1 /*
2 * Ogg bitstream support
3 * Luca Barbato <lu_zero@gentoo.org>
4 * Based on tcvp implementation
5 */
6
7 /*
8 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
9
10 Permission is hereby granted, free of charge, to any person
11 obtaining a copy of this software and associated documentation
12 files (the "Software"), to deal in the Software without
13 restriction, including without limitation the rights to use, copy,
14 modify, merge, publish, distribute, sublicense, and/or sell copies
15 of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 */
30
31 #include <stdio.h>
32 #include "libavutil/avassert.h"
33 #include "libavutil/intreadwrite.h"
34 #include "oggdec.h"
35 #include "avformat.h"
36 #include "internal.h"
37 #include "vorbiscomment.h"
38
39 #define MAX_PAGE_SIZE 65307
40 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
41
42 static const struct ogg_codec * const ogg_codecs[] = {
43 &ff_skeleton_codec,
44 &ff_daala_codec,
45 &ff_dirac_codec,
46 &ff_speex_codec,
47 &ff_vorbis_codec,
48 &ff_theora_codec,
49 &ff_flac_codec,
50 &ff_celt_codec,
51 &ff_opus_codec,
52 &ff_vp8_codec,
53 &ff_old_dirac_codec,
54 &ff_old_flac_codec,
55 &ff_ogm_video_codec,
56 &ff_ogm_audio_codec,
57 &ff_ogm_text_codec,
58 &ff_ogm_old_codec,
59 NULL
60 };
61
62 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
63 static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
64 static int ogg_restore(AVFormatContext *s);
65
free_stream(AVFormatContext * s,int i)66 static void free_stream(AVFormatContext *s, int i)
67 {
68 struct ogg *ogg = s->priv_data;
69 struct ogg_stream *stream = &ogg->streams[i];
70
71 av_freep(&stream->buf);
72 if (stream->codec &&
73 stream->codec->cleanup) {
74 stream->codec->cleanup(s, i);
75 }
76
77 av_freep(&stream->private);
78 av_freep(&stream->new_metadata);
79 }
80
81 //FIXME We could avoid some structure duplication
ogg_save(AVFormatContext * s)82 static int ogg_save(AVFormatContext *s)
83 {
84 struct ogg *ogg = s->priv_data;
85 struct ogg_state *ost =
86 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
87 int i;
88 int ret = 0;
89
90 if (!ost)
91 return AVERROR(ENOMEM);
92
93 ost->pos = avio_tell(s->pb);
94 ost->curidx = ogg->curidx;
95 ost->next = ogg->state;
96 ost->nstreams = ogg->nstreams;
97 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
98
99 for (i = 0; i < ogg->nstreams; i++) {
100 struct ogg_stream *os = ogg->streams + i;
101 os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
102 if (os->buf)
103 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
104 else
105 ret = AVERROR(ENOMEM);
106 os->new_metadata = NULL;
107 os->new_metadata_size = 0;
108 }
109
110 ogg->state = ost;
111
112 if (ret < 0)
113 ogg_restore(s);
114
115 return ret;
116 }
117
ogg_restore(AVFormatContext * s)118 static int ogg_restore(AVFormatContext *s)
119 {
120 struct ogg *ogg = s->priv_data;
121 AVIOContext *bc = s->pb;
122 struct ogg_state *ost = ogg->state;
123 int i, err;
124
125 if (!ost)
126 return 0;
127
128 ogg->state = ost->next;
129
130 for (i = 0; i < ogg->nstreams; i++) {
131 struct ogg_stream *stream = &ogg->streams[i];
132 av_freep(&stream->buf);
133 av_freep(&stream->new_metadata);
134
135 if (i >= ost->nstreams || !ost->streams[i].private) {
136 free_stream(s, i);
137 }
138 }
139
140 avio_seek(bc, ost->pos, SEEK_SET);
141 ogg->page_pos = -1;
142 ogg->curidx = ost->curidx;
143 ogg->nstreams = ost->nstreams;
144 if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
145 sizeof(*ogg->streams))) < 0) {
146 ogg->nstreams = 0;
147 return err;
148 } else
149 memcpy(ogg->streams, ost->streams,
150 ost->nstreams * sizeof(*ogg->streams));
151
152 av_free(ost);
153
154 return 0;
155 }
156
ogg_reset(AVFormatContext * s)157 static int ogg_reset(AVFormatContext *s)
158 {
159 struct ogg *ogg = s->priv_data;
160 int i;
161 int64_t start_pos = avio_tell(s->pb);
162
163 for (i = 0; i < ogg->nstreams; i++) {
164 struct ogg_stream *os = ogg->streams + i;
165 os->bufpos = 0;
166 os->pstart = 0;
167 os->psize = 0;
168 os->granule = -1;
169 os->lastpts = AV_NOPTS_VALUE;
170 os->lastdts = AV_NOPTS_VALUE;
171 os->sync_pos = -1;
172 os->page_pos = 0;
173 os->nsegs = 0;
174 os->segp = 0;
175 os->incomplete = 0;
176 os->got_data = 0;
177 if (start_pos <= s->internal->data_offset) {
178 os->lastpts = 0;
179 }
180 os->end_trimming = 0;
181 av_freep(&os->new_metadata);
182 os->new_metadata_size = 0;
183 }
184
185 ogg->page_pos = -1;
186 ogg->curidx = -1;
187
188 return 0;
189 }
190
ogg_find_codec(uint8_t * buf,int size)191 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
192 {
193 int i;
194
195 for (i = 0; ogg_codecs[i]; i++)
196 if (size >= ogg_codecs[i]->magicsize &&
197 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
198 return ogg_codecs[i];
199
200 return NULL;
201 }
202
203 /**
204 * Replace the current stream with a new one. This is a typical webradio
205 * situation where a new audio stream spawn (identified with a new serial) and
206 * must replace the previous one (track switch).
207 */
ogg_replace_stream(AVFormatContext * s,uint32_t serial,int nsegs)208 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
209 {
210 struct ogg *ogg = s->priv_data;
211 struct ogg_stream *os;
212 const struct ogg_codec *codec;
213 int i = 0;
214
215 if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
216 uint8_t magic[8];
217 int64_t pos = avio_tell(s->pb);
218 avio_skip(s->pb, nsegs);
219 avio_read(s->pb, magic, sizeof(magic));
220 avio_seek(s->pb, pos, SEEK_SET);
221 codec = ogg_find_codec(magic, sizeof(magic));
222 if (!codec) {
223 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
224 return AVERROR_INVALIDDATA;
225 }
226 for (i = 0; i < ogg->nstreams; i++) {
227 if (ogg->streams[i].codec == codec)
228 break;
229 }
230 if (i >= ogg->nstreams)
231 return ogg_new_stream(s, serial);
232 } else if (ogg->nstreams != 1) {
233 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
234 return AVERROR_PATCHWELCOME;
235 }
236
237 os = &ogg->streams[i];
238
239 os->serial = serial;
240 return i;
241
242 #if 0
243 buf = os->buf;
244 bufsize = os->bufsize;
245 codec = os->codec;
246
247 if (!ogg->state || ogg->state->streams[i].private != os->private)
248 av_freep(&ogg->streams[i].private);
249
250 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
251 * also re-use the ogg_stream allocated buffer */
252 memset(os, 0, sizeof(*os));
253 os->serial = serial;
254 os->bufsize = bufsize;
255 os->buf = buf;
256 os->header = -1;
257 os->codec = codec;
258
259 return i;
260 #endif
261 }
262
ogg_new_stream(AVFormatContext * s,uint32_t serial)263 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
264 {
265 struct ogg *ogg = s->priv_data;
266 int idx = ogg->nstreams;
267 AVStream *st;
268 struct ogg_stream *os;
269 size_t size;
270
271 if (ogg->state) {
272 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
273 "in between Ogg context save/restore operations.\n");
274 return AVERROR_BUG;
275 }
276
277 /* Allocate and init a new Ogg Stream */
278 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
279 !(os = av_realloc(ogg->streams, size)))
280 return AVERROR(ENOMEM);
281 ogg->streams = os;
282 os = ogg->streams + idx;
283 memset(os, 0, sizeof(*os));
284 os->serial = serial;
285 os->bufsize = DECODER_BUFFER_SIZE;
286 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
287 os->header = -1;
288 os->start_granule = OGG_NOGRANULE_VALUE;
289 if (!os->buf)
290 return AVERROR(ENOMEM);
291
292 /* Create the associated AVStream */
293 st = avformat_new_stream(s, NULL);
294 if (!st) {
295 av_freep(&os->buf);
296 return AVERROR(ENOMEM);
297 }
298 st->id = idx;
299 avpriv_set_pts_info(st, 64, 1, 1000000);
300
301 ogg->nstreams++;
302 return idx;
303 }
304
ogg_new_buf(struct ogg * ogg,int idx)305 static int ogg_new_buf(struct ogg *ogg, int idx)
306 {
307 struct ogg_stream *os = ogg->streams + idx;
308 uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
309 int size = os->bufpos - os->pstart;
310
311 if (!nb)
312 return AVERROR(ENOMEM);
313
314 if (os->buf) {
315 memcpy(nb, os->buf + os->pstart, size);
316 av_free(os->buf);
317 }
318
319 os->buf = nb;
320 os->bufpos = size;
321 os->pstart = 0;
322
323 return 0;
324 }
325
data_packets_seen(const struct ogg * ogg)326 static int data_packets_seen(const struct ogg *ogg)
327 {
328 int i;
329
330 for (i = 0; i < ogg->nstreams; i++)
331 if (ogg->streams[i].got_data)
332 return 1;
333 return 0;
334 }
335
ogg_read_page(AVFormatContext * s,int * sid)336 static int ogg_read_page(AVFormatContext *s, int *sid)
337 {
338 AVIOContext *bc = s->pb;
339 struct ogg *ogg = s->priv_data;
340 struct ogg_stream *os;
341 int ret, i = 0;
342 int flags, nsegs;
343 uint64_t gp;
344 uint32_t serial;
345 int size, idx;
346 uint8_t sync[4];
347 int sp = 0;
348
349 ret = avio_read(bc, sync, 4);
350 if (ret < 4)
351 return ret < 0 ? ret : AVERROR_EOF;
352
353 do {
354 int c;
355
356 if (sync[sp & 3] == 'O' &&
357 sync[(sp + 1) & 3] == 'g' &&
358 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
359 break;
360
361 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
362 memset(sync, 0, 4);
363 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
364 ogg->page_pos = -1;
365 }
366
367 c = avio_r8(bc);
368
369 if (avio_feof(bc))
370 return AVERROR_EOF;
371
372 sync[sp++ & 3] = c;
373 } while (i++ < MAX_PAGE_SIZE);
374
375 if (i >= MAX_PAGE_SIZE) {
376 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
377 return AVERROR_INVALIDDATA;
378 }
379
380 if (avio_r8(bc) != 0) { /* version */
381 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
382 return AVERROR_INVALIDDATA;
383 }
384
385 flags = avio_r8(bc);
386 gp = avio_rl64(bc);
387 serial = avio_rl32(bc);
388 avio_skip(bc, 8); /* seq, crc */
389 nsegs = avio_r8(bc);
390
391 idx = ogg_find_stream(ogg, serial);
392 if (idx < 0) {
393 if (data_packets_seen(ogg))
394 idx = ogg_replace_stream(s, serial, nsegs);
395 else
396 idx = ogg_new_stream(s, serial);
397
398 if (idx < 0) {
399 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
400 return idx;
401 }
402 }
403
404 os = ogg->streams + idx;
405 ogg->page_pos =
406 os->page_pos = avio_tell(bc) - 27;
407
408 if (os->psize > 0) {
409 ret = ogg_new_buf(ogg, idx);
410 if (ret < 0)
411 return ret;
412 }
413
414 ret = avio_read(bc, os->segments, nsegs);
415 if (ret < nsegs)
416 return ret < 0 ? ret : AVERROR_EOF;
417
418 os->nsegs = nsegs;
419 os->segp = 0;
420
421 size = 0;
422 for (i = 0; i < nsegs; i++)
423 size += os->segments[i];
424
425 if (!(flags & OGG_FLAG_BOS))
426 os->got_data = 1;
427
428 if (flags & OGG_FLAG_CONT || os->incomplete) {
429 if (!os->psize) {
430 // If this is the very first segment we started
431 // playback in the middle of a continuation packet.
432 // Discard it since we missed the start of it.
433 while (os->segp < os->nsegs) {
434 int seg = os->segments[os->segp++];
435 os->pstart += seg;
436 if (seg < 255)
437 break;
438 }
439 os->sync_pos = os->page_pos;
440 }
441 } else {
442 os->psize = 0;
443 os->sync_pos = os->page_pos;
444 }
445
446 if (os->bufsize - os->bufpos < size) {
447 uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
448 if (!nb)
449 return AVERROR(ENOMEM);
450 memcpy(nb, os->buf, os->bufpos);
451 av_free(os->buf);
452 os->buf = nb;
453 }
454
455 ret = avio_read(bc, os->buf + os->bufpos, size);
456 if (ret < size)
457 return ret < 0 ? ret : AVERROR_EOF;
458
459 os->bufpos += size;
460 os->granule = gp;
461 os->flags = flags;
462
463 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
464 if (sid)
465 *sid = idx;
466
467 return 0;
468 }
469
470 /**
471 * @brief find the next Ogg packet
472 * @param *sid is set to the stream for the packet or -1 if there is
473 * no matching stream, in that case assume all other return
474 * values to be uninitialized.
475 * @return negative value on error or EOF.
476 */
ogg_packet(AVFormatContext * s,int * sid,int * dstart,int * dsize,int64_t * fpos)477 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
478 int64_t *fpos)
479 {
480 struct ogg *ogg = s->priv_data;
481 int idx, i, ret;
482 struct ogg_stream *os;
483 int complete = 0;
484 int segp = 0, psize = 0;
485
486 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
487 if (sid)
488 *sid = -1;
489
490 do {
491 idx = ogg->curidx;
492
493 while (idx < 0) {
494 ret = ogg_read_page(s, &idx);
495 if (ret < 0)
496 return ret;
497 }
498
499 os = ogg->streams + idx;
500
501 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
502 idx, os->pstart, os->psize, os->segp, os->nsegs);
503
504 if (!os->codec) {
505 if (os->header < 0) {
506 os->codec = ogg_find_codec(os->buf, os->bufpos);
507 if (!os->codec) {
508 av_log(s, AV_LOG_WARNING, "Codec not found\n");
509 os->header = 0;
510 return 0;
511 }
512 } else {
513 return 0;
514 }
515 }
516
517 segp = os->segp;
518 psize = os->psize;
519
520 while (os->segp < os->nsegs) {
521 int ss = os->segments[os->segp++];
522 os->psize += ss;
523 if (ss < 255) {
524 complete = 1;
525 break;
526 }
527 }
528
529 if (!complete && os->segp == os->nsegs) {
530 ogg->curidx = -1;
531 // Do not set incomplete for empty packets.
532 // Together with the code in ogg_read_page
533 // that discards all continuation of empty packets
534 // we would get an infinite loop.
535 os->incomplete = !!os->psize;
536 }
537 } while (!complete);
538
539
540 if (os->granule == -1)
541 av_log(s, AV_LOG_WARNING,
542 "Page at %"PRId64" is missing granule\n",
543 os->page_pos);
544
545 ogg->curidx = idx;
546 os->incomplete = 0;
547
548 if (os->header) {
549 if ((ret = os->codec->header(s, idx)) < 0) {
550 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
551 return ret;
552 }
553 os->header = ret;
554 if (!os->header) {
555 os->segp = segp;
556 os->psize = psize;
557
558 // We have reached the first non-header packet in this stream.
559 // Unfortunately more header packets may still follow for others,
560 // but if we continue with header parsing we may lose data packets.
561 ogg->headers = 1;
562
563 // Update the header state for all streams and
564 // compute the data_offset.
565 if (!s->internal->data_offset)
566 s->internal->data_offset = os->sync_pos;
567
568 for (i = 0; i < ogg->nstreams; i++) {
569 struct ogg_stream *cur_os = ogg->streams + i;
570
571 // if we have a partial non-header packet, its start is
572 // obviously at or after the data start
573 if (cur_os->incomplete)
574 s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
575 }
576 } else {
577 os->nb_header++;
578 os->pstart += os->psize;
579 os->psize = 0;
580 }
581 } else {
582 os->pflags = 0;
583 os->pduration = 0;
584 if (os->codec && os->codec->packet) {
585 if ((ret = os->codec->packet(s, idx)) < 0) {
586 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
587 return ret;
588 }
589 }
590 if (sid)
591 *sid = idx;
592 if (dstart)
593 *dstart = os->pstart;
594 if (dsize)
595 *dsize = os->psize;
596 if (fpos)
597 *fpos = os->sync_pos;
598 os->pstart += os->psize;
599 os->psize = 0;
600 if(os->pstart == os->bufpos)
601 os->bufpos = os->pstart = 0;
602 os->sync_pos = os->page_pos;
603 }
604
605 // determine whether there are more complete packets in this page
606 // if not, the page's granule will apply to this packet
607 os->page_end = 1;
608 for (i = os->segp; i < os->nsegs; i++)
609 if (os->segments[i] < 255) {
610 os->page_end = 0;
611 break;
612 }
613
614 if (os->segp == os->nsegs)
615 ogg->curidx = -1;
616
617 return 0;
618 }
619
ogg_get_length(AVFormatContext * s)620 static int ogg_get_length(AVFormatContext *s)
621 {
622 struct ogg *ogg = s->priv_data;
623 int i, ret;
624 int64_t size, end;
625 int streams_left=0;
626
627 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
628 return 0;
629
630 // already set
631 if (s->duration != AV_NOPTS_VALUE)
632 return 0;
633
634 size = avio_size(s->pb);
635 if (size < 0)
636 return 0;
637 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
638
639 ret = ogg_save(s);
640 if (ret < 0)
641 return ret;
642 avio_seek(s->pb, end, SEEK_SET);
643 ogg->page_pos = -1;
644
645 while (!ogg_read_page(s, &i)) {
646 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
647 ogg->streams[i].codec) {
648 s->streams[i]->duration =
649 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
650 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
651 s->streams[i]->duration -= s->streams[i]->start_time;
652 streams_left-= (ogg->streams[i].got_start==-1);
653 ogg->streams[i].got_start= 1;
654 } else if(!ogg->streams[i].got_start) {
655 ogg->streams[i].got_start= -1;
656 streams_left++;
657 }
658 }
659 }
660
661 ogg_restore(s);
662
663 ret = ogg_save(s);
664 if (ret < 0)
665 return ret;
666
667 avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
668 ogg_reset(s);
669 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
670 int64_t pts;
671 if (i < 0) continue;
672 pts = ogg_calc_pts(s, i, NULL);
673 if (s->streams[i]->duration == AV_NOPTS_VALUE)
674 continue;
675 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
676 s->streams[i]->duration -= pts;
677 ogg->streams[i].got_start= 1;
678 streams_left--;
679 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
680 ogg->streams[i].got_start= 1;
681 streams_left--;
682 }
683 }
684 ogg_restore (s);
685
686 return 0;
687 }
688
ogg_read_close(AVFormatContext * s)689 static int ogg_read_close(AVFormatContext *s)
690 {
691 struct ogg *ogg = s->priv_data;
692 int i;
693
694 for (i = 0; i < ogg->nstreams; i++) {
695 free_stream(s, i);
696 }
697
698 ogg->nstreams = 0;
699
700 av_freep(&ogg->streams);
701 return 0;
702 }
703
ogg_read_header(AVFormatContext * s)704 static int ogg_read_header(AVFormatContext *s)
705 {
706 struct ogg *ogg = s->priv_data;
707 int ret, i;
708
709 ogg->curidx = -1;
710
711 //linear headers seek from start
712 do {
713 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
714 if (ret < 0) {
715 ogg_read_close(s);
716 return ret;
717 }
718 } while (!ogg->headers);
719 av_log(s, AV_LOG_TRACE, "found headers\n");
720
721 for (i = 0; i < ogg->nstreams; i++) {
722 struct ogg_stream *os = ogg->streams + i;
723
724 if (ogg->streams[i].header < 0) {
725 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
726 ogg->streams[i].codec = NULL;
727 av_freep(&ogg->streams[i].private);
728 } else if (os->codec && os->nb_header < os->codec->nb_header) {
729 av_log(s, AV_LOG_WARNING,
730 "Headers mismatch for stream %d: "
731 "expected %d received %d.\n",
732 i, os->codec->nb_header, os->nb_header);
733 if (s->error_recognition & AV_EF_EXPLODE) {
734 ogg_read_close(s);
735 return AVERROR_INVALIDDATA;
736 }
737 }
738 if (os->start_granule != OGG_NOGRANULE_VALUE)
739 os->lastpts = s->streams[i]->start_time =
740 ogg_gptopts(s, i, os->start_granule, NULL);
741 }
742
743 //linear granulepos seek from end
744 ret = ogg_get_length(s);
745 if (ret < 0) {
746 ogg_read_close(s);
747 return ret;
748 }
749
750 return 0;
751 }
752
ogg_calc_pts(AVFormatContext * s,int idx,int64_t * dts)753 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
754 {
755 struct ogg *ogg = s->priv_data;
756 struct ogg_stream *os = ogg->streams + idx;
757 int64_t pts = AV_NOPTS_VALUE;
758
759 if (dts)
760 *dts = AV_NOPTS_VALUE;
761
762 if (os->lastpts != AV_NOPTS_VALUE) {
763 pts = os->lastpts;
764 os->lastpts = AV_NOPTS_VALUE;
765 }
766 if (os->lastdts != AV_NOPTS_VALUE) {
767 if (dts)
768 *dts = os->lastdts;
769 os->lastdts = AV_NOPTS_VALUE;
770 }
771 if (os->page_end) {
772 if (os->granule != -1LL) {
773 if (os->codec && os->codec->granule_is_start)
774 pts = ogg_gptopts(s, idx, os->granule, dts);
775 else
776 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
777 os->granule = -1LL;
778 }
779 }
780 return pts;
781 }
782
ogg_validate_keyframe(AVFormatContext * s,int idx,int pstart,int psize)783 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
784 {
785 struct ogg *ogg = s->priv_data;
786 struct ogg_stream *os = ogg->streams + idx;
787 int invalid = 0;
788 if (psize) {
789 switch (s->streams[idx]->codecpar->codec_id) {
790 case AV_CODEC_ID_THEORA:
791 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
792 break;
793 case AV_CODEC_ID_VP8:
794 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
795 }
796 if (invalid) {
797 os->pflags ^= AV_PKT_FLAG_KEY;
798 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
799 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
800 }
801 }
802 }
803
ogg_read_packet(AVFormatContext * s,AVPacket * pkt)804 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
805 {
806 struct ogg *ogg;
807 struct ogg_stream *os;
808 int idx, ret;
809 int pstart, psize;
810 int64_t fpos, pts, dts;
811
812 if (s->io_repositioned) {
813 ogg_reset(s);
814 s->io_repositioned = 0;
815 }
816
817 //Get an ogg packet
818 retry:
819 do {
820 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
821 if (ret < 0)
822 return ret;
823 } while (idx < 0 || !s->streams[idx]);
824
825 ogg = s->priv_data;
826 os = ogg->streams + idx;
827
828 // pflags might not be set until after this
829 pts = ogg_calc_pts(s, idx, &dts);
830 ogg_validate_keyframe(s, idx, pstart, psize);
831
832 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
833 goto retry;
834 os->keyframe_seek = 0;
835
836 //Alloc a pkt
837 ret = av_new_packet(pkt, psize);
838 if (ret < 0)
839 return ret;
840 pkt->stream_index = idx;
841 memcpy(pkt->data, os->buf + pstart, psize);
842
843 pkt->pts = pts;
844 pkt->dts = dts;
845 pkt->flags = os->pflags;
846 pkt->duration = os->pduration;
847 pkt->pos = fpos;
848
849 if (os->end_trimming) {
850 uint8_t *side_data = av_packet_new_side_data(pkt,
851 AV_PKT_DATA_SKIP_SAMPLES,
852 10);
853 if(!side_data)
854 goto fail;
855 AV_WL32(side_data + 4, os->end_trimming);
856 os->end_trimming = 0;
857 }
858
859 if (os->new_metadata) {
860 uint8_t *side_data = av_packet_new_side_data(pkt,
861 AV_PKT_DATA_METADATA_UPDATE,
862 os->new_metadata_size);
863 if(!side_data)
864 goto fail;
865
866 memcpy(side_data, os->new_metadata, os->new_metadata_size);
867 av_freep(&os->new_metadata);
868 os->new_metadata_size = 0;
869 }
870
871 return psize;
872 fail:
873 av_packet_unref(pkt);
874 return AVERROR(ENOMEM);
875 }
876
ogg_read_timestamp(AVFormatContext * s,int stream_index,int64_t * pos_arg,int64_t pos_limit)877 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
878 int64_t *pos_arg, int64_t pos_limit)
879 {
880 struct ogg *ogg = s->priv_data;
881 AVIOContext *bc = s->pb;
882 int64_t pts = AV_NOPTS_VALUE;
883 int64_t keypos = -1;
884 int i;
885 int pstart, psize;
886 avio_seek(bc, *pos_arg, SEEK_SET);
887 ogg_reset(s);
888
889 while ( avio_tell(bc) <= pos_limit
890 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
891 if (i == stream_index) {
892 struct ogg_stream *os = ogg->streams + stream_index;
893 // Do not trust the last timestamps of an ogm video
894 if ( (os->flags & OGG_FLAG_EOS)
895 && !(os->flags & OGG_FLAG_BOS)
896 && os->codec == &ff_ogm_video_codec)
897 continue;
898 pts = ogg_calc_pts(s, i, NULL);
899 ogg_validate_keyframe(s, i, pstart, psize);
900 if (os->pflags & AV_PKT_FLAG_KEY) {
901 keypos = *pos_arg;
902 } else if (os->keyframe_seek) {
903 // if we had a previous keyframe but no pts for it,
904 // return that keyframe with this pts value.
905 if (keypos >= 0)
906 *pos_arg = keypos;
907 else
908 pts = AV_NOPTS_VALUE;
909 }
910 }
911 if (pts != AV_NOPTS_VALUE)
912 break;
913 }
914 ogg_reset(s);
915 return pts;
916 }
917
ogg_read_seek(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)918 static int ogg_read_seek(AVFormatContext *s, int stream_index,
919 int64_t timestamp, int flags)
920 {
921 struct ogg *ogg = s->priv_data;
922 struct ogg_stream *os = ogg->streams + stream_index;
923 int ret;
924
925 av_assert0(stream_index < ogg->nstreams);
926 // Ensure everything is reset even when seeking via
927 // the generated index.
928 ogg_reset(s);
929
930 // Try seeking to a keyframe first. If this fails (very possible),
931 // av_seek_frame will fall back to ignoring keyframes
932 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
933 && !(flags & AVSEEK_FLAG_ANY))
934 os->keyframe_seek = 1;
935
936 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
937 ogg_reset(s);
938 os = ogg->streams + stream_index;
939 if (ret < 0)
940 os->keyframe_seek = 0;
941 return ret;
942 }
943
ogg_probe(AVProbeData * p)944 static int ogg_probe(AVProbeData *p)
945 {
946 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
947 return AVPROBE_SCORE_MAX;
948 return 0;
949 }
950
951 AVInputFormat ff_ogg_demuxer = {
952 .name = "ogg",
953 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
954 .priv_data_size = sizeof(struct ogg),
955 .read_probe = ogg_probe,
956 .read_header = ogg_read_header,
957 .read_packet = ogg_read_packet,
958 .read_close = ogg_read_close,
959 .read_seek = ogg_read_seek,
960 .read_timestamp = ogg_read_timestamp,
961 .extensions = "ogg",
962 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
963 };
964