2
* Ogg bitstream support
3
* Luca Barbato <lu_zero@gentoo.org>
4
* Based on tcvp implementation
9
Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
11
Permission is hereby granted, free of charge, to any person
12
obtaining a copy of this software and associated documentation
13
files (the "Software"), to deal in the Software without
14
restriction, including without limitation the rights to use, copy,
15
modify, merge, publish, distribute, sublicense, and/or sell copies
16
of the Software, and to permit persons to whom the Software is
17
furnished to do so, subject to the following conditions:
19
The above copyright notice and this permission notice shall be
20
included in all copies or substantial portions of the Software.
22
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
DEALINGS IN THE SOFTWARE.
37
#define MAX_PAGE_SIZE 65307
38
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40
static ogg_codec_t *ogg_codecs[] = {
50
#if 0 // CONFIG_MUXERS
52
ogg_write_header (AVFormatContext * avfcontext)
57
ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
63
ogg_write_trailer (AVFormatContext * avfcontext)
68
AVOutputFormat ogg_muxer = {
80
#endif //CONFIG_MUXERS
82
//FIXME We could avoid some structure duplication
84
ogg_save (AVFormatContext * s)
86
ogg_t *ogg = s->priv_data;
88
av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
90
ost->pos = url_ftell (&s->pb);;
91
ost->curidx = ogg->curidx;
92
ost->next = ogg->state;
93
ost->nstreams = ogg->nstreams;
94
memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
96
for (i = 0; i < ogg->nstreams; i++){
97
ogg_stream_t *os = ogg->streams + i;
98
os->buf = av_malloc (os->bufsize);
99
memset (os->buf, 0, os->bufsize);
100
memcpy (os->buf, ost->streams[i].buf, os->bufpos);
109
ogg_restore (AVFormatContext * s, int discard)
111
ogg_t *ogg = s->priv_data;
112
ByteIOContext *bc = &s->pb;
113
ogg_state_t *ost = ogg->state;
119
ogg->state = ost->next;
122
for (i = 0; i < ogg->nstreams; i++)
123
av_free (ogg->streams[i].buf);
125
url_fseek (bc, ost->pos, SEEK_SET);
126
ogg->curidx = ost->curidx;
127
ogg->nstreams = ost->nstreams;
128
memcpy(ogg->streams, ost->streams,
129
ost->nstreams * sizeof(*ogg->streams));
138
ogg_reset (ogg_t * ogg)
142
for (i = 0; i < ogg->nstreams; i++){
143
ogg_stream_t *os = ogg->streams + i;
159
ogg_find_codec (uint8_t * buf, int size)
163
for (i = 0; ogg_codecs[i]; i++)
164
if (size >= ogg_codecs[i]->magicsize &&
165
!memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
166
return ogg_codecs[i];
172
ogg_find_stream (ogg_t * ogg, int serial)
176
for (i = 0; i < ogg->nstreams; i++)
177
if (ogg->streams[i].serial == serial)
184
ogg_new_stream (AVFormatContext * s, uint32_t serial)
187
ogg_t *ogg = s->priv_data;
188
int idx = ogg->nstreams++;
192
ogg->streams = av_realloc (ogg->streams,
193
ogg->nstreams * sizeof (*ogg->streams));
194
memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
195
os = ogg->streams + idx;
197
os->bufsize = DECODER_BUFFER_SIZE;
198
os->buf = av_malloc(os->bufsize);
201
st = av_new_stream (s, idx);
203
return AVERROR_NOMEM;
205
av_set_pts_info(st, 64, 1, 1000000);
211
ogg_new_buf(ogg_t *ogg, int idx)
213
ogg_stream_t *os = ogg->streams + idx;
214
uint8_t *nb = av_malloc(os->bufsize);
215
int size = os->bufpos - os->pstart;
217
memcpy(nb, os->buf + os->pstart, size);
228
ogg_read_page (AVFormatContext * s, int *str)
230
ByteIOContext *bc = &s->pb;
231
ogg_t *ogg = s->priv_data;
243
if (get_buffer (bc, sync, 4) < 4)
249
if (sync[sp & 3] == 'O' &&
250
sync[(sp + 1) & 3] == 'g' &&
251
sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
258
}while (i++ < MAX_PAGE_SIZE);
260
if (i >= MAX_PAGE_SIZE){
261
av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
265
if (url_fgetc (bc) != 0) /* version */
268
flags = url_fgetc (bc);
270
serial = get_le32 (bc);
273
nsegs = url_fgetc (bc);
275
idx = ogg_find_stream (ogg, serial);
277
idx = ogg_new_stream (s, serial);
282
os = ogg->streams + idx;
285
ogg_new_buf(ogg, idx);
287
if (get_buffer (bc, os->segments, nsegs) < nsegs)
294
for (i = 0; i < nsegs; i++)
295
size += os->segments[i];
297
if (flags & OGG_FLAG_CONT){
299
while (os->segp < os->nsegs){
300
int seg = os->segments[os->segp++];
310
if (os->bufsize - os->bufpos < size){
311
uint8_t *nb = av_malloc (os->bufsize *= 2);
312
memcpy (nb, os->buf, os->bufpos);
317
if (get_buffer (bc, os->buf + os->bufpos, size) < size)
320
os->lastgp = os->granule;
332
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
334
ogg_t *ogg = s->priv_data;
338
int segp = 0, psize = 0;
341
av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
348
if (ogg_read_page (s, &idx) < 0)
352
os = ogg->streams + idx;
355
av_log (s, AV_LOG_DEBUG,
356
"ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
357
idx, os->pstart, os->psize, os->segp, os->nsegs);
362
os->codec = ogg_find_codec (os->buf, os->bufpos);
375
while (os->segp < os->nsegs){
376
int ss = os->segments[os->segp++];
384
if (!complete && os->segp == os->nsegs){
390
av_log (s, AV_LOG_DEBUG,
391
"ogg_packet: idx %i, frame size %i, start %i\n",
392
idx, os->psize, os->pstart);
398
int hdr = os->codec->header (s, idx);
400
os->header = os->seq;
405
os->pstart += os->psize;
410
if (os->header > -1 && os->seq > os->header){
411
if (os->codec && os->codec->packet)
412
os->codec->packet (s, idx);
416
*dstart = os->pstart;
419
os->pstart += os->psize;
424
if (os->segp == os->nsegs)
431
ogg_get_headers (AVFormatContext * s)
433
ogg_t *ogg = s->priv_data;
436
if (ogg_packet (s, NULL, NULL, NULL) < 0)
438
}while (!ogg->headers);
441
av_log (s, AV_LOG_DEBUG, "found headers\n");
448
ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
450
ogg_t *ogg = s->priv_data;
451
ogg_stream_t *os = ogg->streams + i;
452
uint64_t pts = AV_NOPTS_VALUE;
454
if(os->codec->gptopts){
455
pts = os->codec->gptopts(s, i, gp);
465
ogg_get_length (AVFormatContext * s)
467
ogg_t *ogg = s->priv_data;
471
if(s->pb.is_streamed)
475
if (s->duration != AV_NOPTS_VALUE)
478
size = url_fsize(&s->pb);
481
end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
484
url_fseek (&s->pb, end, SEEK_SET);
486
while (!ogg_read_page (s, &i)){
487
if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
488
ogg->streams[i].codec)
493
s->streams[idx]->duration =
494
ogg_gptopts (s, idx, ogg->streams[idx].granule);
500
while (!ogg_read_page (s, &i)) {
501
if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
505
s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
506
s->streams[idx]->duration -= s->streams[idx]->start_time;
515
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
517
ogg_t *ogg = s->priv_data;
519
//linear headers seek from start
520
if (ogg_get_headers (s) < 0){
524
//linear granulepos seek from end
527
//fill the extradata in the per codec callbacks
533
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
542
if (ogg_packet (s, &idx, &pstart, &psize) < 0)
544
}while (idx < 0 || !s->streams[idx]);
547
os = ogg->streams + idx;
550
if (av_new_packet (pkt, psize) < 0)
552
pkt->stream_index = idx;
553
memcpy (pkt->data, os->buf + pstart, psize);
554
if (os->lastgp != -1LL){
555
pkt->pts = ogg_gptopts (s, idx, os->lastgp);
564
ogg_read_close (AVFormatContext * s)
566
ogg_t *ogg = s->priv_data;
569
for (i = 0; i < ogg->nstreams; i++){
570
av_free (ogg->streams[i].buf);
571
av_free (ogg->streams[i].private);
573
av_free (ogg->streams);
579
ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
582
AVStream *st = s->streams[stream_index];
583
ogg_t *ogg = s->priv_data;
584
ByteIOContext *bc = &s->pb;
585
uint64_t min = 0, max = ogg->size;
586
uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
587
int64_t pts = AV_NOPTS_VALUE;
591
if ((uint64_t)target_ts < tmin || target_ts < 0)
593
while (min <= max && tmin < tmax){
594
uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
597
url_fseek (bc, p, SEEK_SET);
599
while (!ogg_read_page (s, &i)){
600
if (i == stream_index && ogg->streams[i].granule != 0 &&
601
ogg->streams[i].granule != -1)
608
pts = ogg_gptopts (s, i, ogg->streams[i].granule);
611
if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den)
614
if (pts > target_ts){
615
if (max == p && tmax == pts) {
616
// probably our tmin is wrong, causing us to always end up too late in the file
617
tmin = (target_ts + tmin + 1) / 2;
618
if (tmin == target_ts) {
619
url_fseek(bc, min, SEEK_SET);
626
if (min == p && tmin == pts) {
627
// probably our tmax is wrong, causing us to always end up too early in the file
628
tmax = (target_ts + tmax) / 2;
629
if (tmax == target_ts) {
630
url_fseek(bc, max, SEEK_SET);
639
if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den){
644
pts = AV_NOPTS_VALUE;
647
av_update_cur_dts(s, st, pts);
653
if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
655
pos = url_ftell (&s->pb);
656
ogg_read_timestamp (s, stream_index, &pos, pos - 1);
663
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
666
ogg_t *ogg = s->priv_data;
667
ByteIOContext *bc = &s->pb;
671
return AV_NOPTS_VALUE;
677
static int ogg_probe(AVProbeData *p)
681
if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
682
p->buf[2] == 'g' && p->buf[3] == 'S' &&
683
p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
684
return AVPROBE_SCORE_MAX;
689
AVInputFormat ogg_demuxer = {
698
// ogg_read_timestamp,