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 "avio_internal.h"
35 #include "oggdec.h"
36 #include "avformat.h"
37 #include "internal.h"
38 #include "vorbiscomment.h"
39
40 #define MAX_PAGE_SIZE 65307
41 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
42
43 static const struct ogg_codec * const ogg_codecs[] = {
44 &ff_skeleton_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->start_trimming = 0;
181 os->end_trimming = 0;
182 av_freep(&os->new_metadata);
183 os->new_metadata_size = 0;
184 }
185
186 ogg->page_pos = -1;
187 ogg->curidx = -1;
188
189 return 0;
190 }
191
ogg_find_codec(uint8_t * buf,int size)192 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
193 {
194 int i;
195
196 for (i = 0; ogg_codecs[i]; i++)
197 if (size >= ogg_codecs[i]->magicsize &&
198 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
199 return ogg_codecs[i];
200
201 return NULL;
202 }
203
204 /**
205 * Replace the current stream with a new one. This is a typical webradio
206 * situation where a new audio stream spawn (identified with a new serial) and
207 * must replace the previous one (track switch).
208 */
ogg_replace_stream(AVFormatContext * s,uint32_t serial,char * magic,int page_size,int probing)209 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, int page_size,
210 int probing)
211 {
212 struct ogg *ogg = s->priv_data;
213 struct ogg_stream *os;
214 const struct ogg_codec *codec;
215 int i = 0;
216
217 if (ogg->nstreams != 1) {
218 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
219 return AVERROR_PATCHWELCOME;
220 }
221
222 /* Check for codecs */
223 codec = ogg_find_codec(magic, page_size);
224 if (!codec && !probing) {
225 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
226 return AVERROR_INVALIDDATA;
227 }
228
229 os = &ogg->streams[0];
230 if (os->codec != codec)
231 return AVERROR(EINVAL);
232
233 os->serial = serial;
234 os->codec = codec;
235 os->serial = serial;
236 os->lastpts = 0;
237 os->lastdts = 0;
238 os->start_trimming = 0;
239 os->end_trimming = 0;
240
241 /* Chained files have extradata as a new packet */
242 if (codec == &ff_opus_codec)
243 os->header = -1;
244
245 return i;
246 }
247
ogg_new_stream(AVFormatContext * s,uint32_t serial)248 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
249 {
250 struct ogg *ogg = s->priv_data;
251 int idx = ogg->nstreams;
252 AVStream *st;
253 struct ogg_stream *os;
254 size_t size;
255
256 if (ogg->state) {
257 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
258 "in between Ogg context save/restore operations.\n");
259 return AVERROR_BUG;
260 }
261
262 /* Allocate and init a new Ogg Stream */
263 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
264 !(os = av_realloc(ogg->streams, size)))
265 return AVERROR(ENOMEM);
266 ogg->streams = os;
267 os = ogg->streams + idx;
268 memset(os, 0, sizeof(*os));
269 os->serial = serial;
270 os->bufsize = DECODER_BUFFER_SIZE;
271 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
272 os->header = -1;
273 os->start_granule = OGG_NOGRANULE_VALUE;
274 if (!os->buf)
275 return AVERROR(ENOMEM);
276
277 /* Create the associated AVStream */
278 st = avformat_new_stream(s, NULL);
279 if (!st) {
280 av_freep(&os->buf);
281 return AVERROR(ENOMEM);
282 }
283 st->id = idx;
284 avpriv_set_pts_info(st, 64, 1, 1000000);
285
286 ogg->nstreams++;
287 return idx;
288 }
289
data_packets_seen(const struct ogg * ogg)290 static int data_packets_seen(const struct ogg *ogg)
291 {
292 int i;
293
294 for (i = 0; i < ogg->nstreams; i++)
295 if (ogg->streams[i].got_data)
296 return 1;
297 return 0;
298 }
299
buf_realloc(struct ogg_stream * os,int size)300 static int buf_realloc(struct ogg_stream *os, int size)
301 {
302 /* Even if invalid guarantee there's enough memory to read the page */
303 if (os->bufsize - os->bufpos < size) {
304 uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
305 if (!nb)
306 return AVERROR(ENOMEM);
307 os->buf = nb;
308 os->bufsize *= 2;
309 }
310
311 return 0;
312 }
313
ogg_read_page(AVFormatContext * s,int * sid,int probing)314 static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
315 {
316 AVIOContext *bc = s->pb;
317 struct ogg *ogg = s->priv_data;
318 struct ogg_stream *os;
319 int ret, i = 0;
320 int flags, nsegs;
321 uint64_t gp;
322 uint32_t serial;
323 uint32_t crc, crc_tmp;
324 int size = 0, idx;
325 int64_t version, page_pos;
326 int64_t start_pos;
327 uint8_t sync[4];
328 uint8_t segments[255];
329 uint8_t *readout_buf;
330 int sp = 0;
331
332 ret = avio_read(bc, sync, 4);
333 if (ret < 4)
334 return ret < 0 ? ret : AVERROR_EOF;
335
336 do {
337 int c;
338
339 if (sync[sp & 3] == 'O' &&
340 sync[(sp + 1) & 3] == 'g' &&
341 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
342 break;
343
344 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
345 memset(sync, 0, 4);
346 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
347 ogg->page_pos = -1;
348 }
349
350 c = avio_r8(bc);
351
352 if (avio_feof(bc))
353 return AVERROR_EOF;
354
355 sync[sp++ & 3] = c;
356 } while (i++ < MAX_PAGE_SIZE);
357
358 if (i >= MAX_PAGE_SIZE) {
359 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
360 return AVERROR_INVALIDDATA;
361 }
362
363 /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
364 ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
365
366 /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
367 ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
368 start_pos = avio_tell(bc);
369
370 version = avio_r8(bc);
371 flags = avio_r8(bc);
372 gp = avio_rl64(bc);
373 serial = avio_rl32(bc);
374 avio_skip(bc, 4); /* seq */
375
376 crc_tmp = ffio_get_checksum(bc);
377 crc = avio_rb32(bc);
378 crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
379 ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
380
381 nsegs = avio_r8(bc);
382 page_pos = avio_tell(bc) - 27;
383
384 ret = avio_read(bc, segments, nsegs);
385 if (ret < nsegs)
386 return ret < 0 ? ret : AVERROR_EOF;
387
388 for (i = 0; i < nsegs; i++)
389 size += segments[i];
390
391 idx = ogg_find_stream(ogg, serial);
392 if (idx >= 0) {
393 os = ogg->streams + idx;
394
395 ret = buf_realloc(os, size);
396 if (ret < 0)
397 return ret;
398
399 readout_buf = os->buf + os->bufpos;
400 } else {
401 readout_buf = av_malloc(size);
402 }
403
404 ret = avio_read(bc, readout_buf, size);
405 if (ret < size) {
406 if (idx < 0)
407 av_free(readout_buf);
408 return ret < 0 ? ret : AVERROR_EOF;
409 }
410
411 if (crc ^ ffio_get_checksum(bc)) {
412 av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
413 if (idx < 0)
414 av_free(readout_buf);
415 avio_seek(bc, start_pos, SEEK_SET);
416 *sid = -1;
417 return 0;
418 }
419
420 /* Since we're almost sure its a valid packet, checking the version after
421 * the checksum lets the demuxer be more tolerant */
422 if (version) {
423 av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
424 if (idx < 0)
425 av_free(readout_buf);
426 avio_seek(bc, start_pos, SEEK_SET);
427 *sid = -1;
428 return 0;
429 }
430
431 /* CRC is correct so we can be 99% sure there's an actual change here */
432 if (idx < 0) {
433 if (data_packets_seen(ogg))
434 idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
435 else
436 idx = ogg_new_stream(s, serial);
437
438 if (idx < 0) {
439 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
440 av_free(readout_buf);
441 return idx;
442 }
443
444 os = ogg->streams + idx;
445
446 ret = buf_realloc(os, size);
447 if (ret < 0) {
448 av_free(readout_buf);
449 return ret;
450 }
451
452 memcpy(os->buf + os->bufpos, readout_buf, size);
453 av_free(readout_buf);
454 }
455
456 ogg->page_pos = page_pos;
457 os->page_pos = page_pos;
458 os->nsegs = nsegs;
459 os->segp = 0;
460 os->got_data = !(flags & OGG_FLAG_BOS);
461 os->bufpos += size;
462 os->granule = gp;
463 os->flags = flags;
464 memcpy(os->segments, segments, nsegs);
465 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
466
467 if (flags & OGG_FLAG_CONT || os->incomplete) {
468 if (!os->psize) {
469 // If this is the very first segment we started
470 // playback in the middle of a continuation packet.
471 // Discard it since we missed the start of it.
472 while (os->segp < os->nsegs) {
473 int seg = os->segments[os->segp++];
474 os->pstart += seg;
475 if (seg < 255)
476 break;
477 }
478 os->sync_pos = os->page_pos;
479 }
480 } else {
481 os->psize = 0;
482 os->sync_pos = os->page_pos;
483 }
484
485 /* This function is always called with sid != NULL */
486 *sid = idx;
487
488 return 0;
489 }
490
491 /**
492 * @brief find the next Ogg packet
493 * @param *sid is set to the stream for the packet or -1 if there is
494 * no matching stream, in that case assume all other return
495 * values to be uninitialized.
496 * @return negative value on error or EOF.
497 */
ogg_packet(AVFormatContext * s,int * sid,int * dstart,int * dsize,int64_t * fpos)498 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
499 int64_t *fpos)
500 {
501 struct ogg *ogg = s->priv_data;
502 int idx, i, ret;
503 struct ogg_stream *os;
504 int complete = 0;
505 int segp = 0, psize = 0;
506
507 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
508 if (sid)
509 *sid = -1;
510
511 do {
512 idx = ogg->curidx;
513
514 while (idx < 0) {
515 ret = ogg_read_page(s, &idx, 0);
516 if (ret < 0)
517 return ret;
518 }
519
520 os = ogg->streams + idx;
521
522 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
523 idx, os->pstart, os->psize, os->segp, os->nsegs);
524
525 if (!os->codec) {
526 if (os->header < 0) {
527 os->codec = ogg_find_codec(os->buf, os->bufpos);
528 if (!os->codec) {
529 av_log(s, AV_LOG_WARNING, "Codec not found\n");
530 os->header = 0;
531 return 0;
532 }
533 } else {
534 return 0;
535 }
536 }
537
538 segp = os->segp;
539 psize = os->psize;
540
541 while (os->segp < os->nsegs) {
542 int ss = os->segments[os->segp++];
543 os->psize += ss;
544 if (ss < 255) {
545 complete = 1;
546 break;
547 }
548 }
549
550 if (!complete && os->segp == os->nsegs) {
551 ogg->curidx = -1;
552 // Do not set incomplete for empty packets.
553 // Together with the code in ogg_read_page
554 // that discards all continuation of empty packets
555 // we would get an infinite loop.
556 os->incomplete = !!os->psize;
557 }
558 } while (!complete);
559
560
561 if (os->granule == -1)
562 av_log(s, AV_LOG_WARNING,
563 "Page at %"PRId64" is missing granule\n",
564 os->page_pos);
565
566 ogg->curidx = idx;
567 os->incomplete = 0;
568
569 if (os->header) {
570 if ((ret = os->codec->header(s, idx)) < 0) {
571 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
572 return ret;
573 }
574 os->header = ret;
575 if (!os->header) {
576 os->segp = segp;
577 os->psize = psize;
578
579 // We have reached the first non-header packet in this stream.
580 // Unfortunately more header packets may still follow for others,
581 // but if we continue with header parsing we may lose data packets.
582 ogg->headers = 1;
583
584 // Update the header state for all streams and
585 // compute the data_offset.
586 if (!s->internal->data_offset)
587 s->internal->data_offset = os->sync_pos;
588
589 for (i = 0; i < ogg->nstreams; i++) {
590 struct ogg_stream *cur_os = ogg->streams + i;
591
592 // if we have a partial non-header packet, its start is
593 // obviously at or after the data start
594 if (cur_os->incomplete)
595 s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
596 }
597 } else {
598 os->nb_header++;
599 os->pstart += os->psize;
600 os->psize = 0;
601 }
602 } else {
603 os->pflags = 0;
604 os->pduration = 0;
605 if (os->codec && os->codec->packet) {
606 if ((ret = os->codec->packet(s, idx)) < 0) {
607 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
608 return ret;
609 }
610 }
611 if (sid)
612 *sid = idx;
613 if (dstart)
614 *dstart = os->pstart;
615 if (dsize)
616 *dsize = os->psize;
617 if (fpos)
618 *fpos = os->sync_pos;
619 os->pstart += os->psize;
620 os->psize = 0;
621 if(os->pstart == os->bufpos)
622 os->bufpos = os->pstart = 0;
623 os->sync_pos = os->page_pos;
624 }
625
626 // determine whether there are more complete packets in this page
627 // if not, the page's granule will apply to this packet
628 os->page_end = 1;
629 for (i = os->segp; i < os->nsegs; i++)
630 if (os->segments[i] < 255) {
631 os->page_end = 0;
632 break;
633 }
634
635 if (os->segp == os->nsegs)
636 ogg->curidx = -1;
637
638 return 0;
639 }
640
ogg_get_length(AVFormatContext * s)641 static int ogg_get_length(AVFormatContext *s)
642 {
643 struct ogg *ogg = s->priv_data;
644 int i, ret;
645 int64_t size, end;
646 int streams_left=0;
647
648 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
649 return 0;
650
651 // already set
652 if (s->duration != AV_NOPTS_VALUE)
653 return 0;
654
655 size = avio_size(s->pb);
656 if (size < 0)
657 return 0;
658 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
659
660 ret = ogg_save(s);
661 if (ret < 0)
662 return ret;
663 avio_seek(s->pb, end, SEEK_SET);
664 ogg->page_pos = -1;
665
666 while (!ogg_read_page(s, &i, 1)) {
667 if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
668 ogg->streams[i].codec) {
669 s->streams[i]->duration =
670 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
671 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
672 s->streams[i]->duration -= s->streams[i]->start_time;
673 streams_left-= (ogg->streams[i].got_start==-1);
674 ogg->streams[i].got_start= 1;
675 } else if(!ogg->streams[i].got_start) {
676 ogg->streams[i].got_start= -1;
677 streams_left++;
678 }
679 }
680 }
681
682 ogg_restore(s);
683
684 ret = ogg_save(s);
685 if (ret < 0)
686 return ret;
687
688 avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
689 ogg_reset(s);
690 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
691 int64_t pts;
692 if (i < 0) continue;
693 pts = ogg_calc_pts(s, i, NULL);
694 if (s->streams[i]->duration == AV_NOPTS_VALUE)
695 continue;
696 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
697 s->streams[i]->duration -= pts;
698 ogg->streams[i].got_start= 1;
699 streams_left--;
700 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
701 ogg->streams[i].got_start= 1;
702 streams_left--;
703 }
704 }
705 ogg_restore (s);
706
707 return 0;
708 }
709
ogg_read_close(AVFormatContext * s)710 static int ogg_read_close(AVFormatContext *s)
711 {
712 struct ogg *ogg = s->priv_data;
713 int i;
714
715 for (i = 0; i < ogg->nstreams; i++) {
716 free_stream(s, i);
717 }
718
719 ogg->nstreams = 0;
720
721 av_freep(&ogg->streams);
722 return 0;
723 }
724
ogg_read_header(AVFormatContext * s)725 static int ogg_read_header(AVFormatContext *s)
726 {
727 struct ogg *ogg = s->priv_data;
728 int ret, i;
729
730 ogg->curidx = -1;
731
732 //linear headers seek from start
733 do {
734 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
735 if (ret < 0) {
736 ogg_read_close(s);
737 return ret;
738 }
739 } while (!ogg->headers);
740 av_log(s, AV_LOG_TRACE, "found headers\n");
741
742 for (i = 0; i < ogg->nstreams; i++) {
743 struct ogg_stream *os = ogg->streams + i;
744
745 if (ogg->streams[i].header < 0) {
746 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
747 ogg->streams[i].codec = NULL;
748 av_freep(&ogg->streams[i].private);
749 } else if (os->codec && os->nb_header < os->codec->nb_header) {
750 av_log(s, AV_LOG_WARNING,
751 "Headers mismatch for stream %d: "
752 "expected %d received %d.\n",
753 i, os->codec->nb_header, os->nb_header);
754 if (s->error_recognition & AV_EF_EXPLODE) {
755 ogg_read_close(s);
756 return AVERROR_INVALIDDATA;
757 }
758 }
759 if (os->start_granule != OGG_NOGRANULE_VALUE)
760 os->lastpts = s->streams[i]->start_time =
761 ogg_gptopts(s, i, os->start_granule, NULL);
762 }
763
764 //linear granulepos seek from end
765 ret = ogg_get_length(s);
766 if (ret < 0) {
767 ogg_read_close(s);
768 return ret;
769 }
770
771 return 0;
772 }
773
ogg_calc_pts(AVFormatContext * s,int idx,int64_t * dts)774 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
775 {
776 struct ogg *ogg = s->priv_data;
777 struct ogg_stream *os = ogg->streams + idx;
778 int64_t pts = AV_NOPTS_VALUE;
779
780 if (dts)
781 *dts = AV_NOPTS_VALUE;
782
783 if (os->lastpts != AV_NOPTS_VALUE) {
784 pts = os->lastpts;
785 os->lastpts = AV_NOPTS_VALUE;
786 }
787 if (os->lastdts != AV_NOPTS_VALUE) {
788 if (dts)
789 *dts = os->lastdts;
790 os->lastdts = AV_NOPTS_VALUE;
791 }
792 if (os->page_end) {
793 if (os->granule != -1LL) {
794 if (os->codec && os->codec->granule_is_start)
795 pts = ogg_gptopts(s, idx, os->granule, dts);
796 else
797 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
798 os->granule = -1LL;
799 }
800 }
801 return pts;
802 }
803
ogg_validate_keyframe(AVFormatContext * s,int idx,int pstart,int psize)804 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
805 {
806 struct ogg *ogg = s->priv_data;
807 struct ogg_stream *os = ogg->streams + idx;
808 int invalid = 0;
809 if (psize) {
810 switch (s->streams[idx]->codecpar->codec_id) {
811 case AV_CODEC_ID_THEORA:
812 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
813 break;
814 case AV_CODEC_ID_VP8:
815 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
816 }
817 if (invalid) {
818 os->pflags ^= AV_PKT_FLAG_KEY;
819 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
820 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
821 }
822 }
823 }
824
ogg_read_packet(AVFormatContext * s,AVPacket * pkt)825 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
826 {
827 struct ogg *ogg;
828 struct ogg_stream *os;
829 int idx, ret;
830 int pstart, psize;
831 int64_t fpos, pts, dts;
832
833 if (s->io_repositioned) {
834 ogg_reset(s);
835 s->io_repositioned = 0;
836 }
837
838 //Get an ogg packet
839 retry:
840 do {
841 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
842 if (ret < 0)
843 return ret;
844 } while (idx < 0 || !s->streams[idx]);
845
846 ogg = s->priv_data;
847 os = ogg->streams + idx;
848
849 // pflags might not be set until after this
850 pts = ogg_calc_pts(s, idx, &dts);
851 ogg_validate_keyframe(s, idx, pstart, psize);
852
853 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
854 goto retry;
855 os->keyframe_seek = 0;
856
857 //Alloc a pkt
858 ret = av_new_packet(pkt, psize);
859 if (ret < 0)
860 return ret;
861 pkt->stream_index = idx;
862 memcpy(pkt->data, os->buf + pstart, psize);
863
864 pkt->pts = pts;
865 pkt->dts = dts;
866 pkt->flags = os->pflags;
867 pkt->duration = os->pduration;
868 pkt->pos = fpos;
869
870 if (os->start_trimming || os->end_trimming) {
871 uint8_t *side_data = av_packet_new_side_data(pkt,
872 AV_PKT_DATA_SKIP_SAMPLES,
873 10);
874 if(!side_data)
875 return AVERROR(ENOMEM);
876 AV_WL32(side_data + 0, os->start_trimming);
877 AV_WL32(side_data + 4, os->end_trimming);
878 os->start_trimming = 0;
879 os->end_trimming = 0;
880 }
881
882 if (os->new_metadata) {
883 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE,
884 os->new_metadata, os->new_metadata_size);
885 if (ret < 0)
886 return ret;
887
888 os->new_metadata = NULL;
889 os->new_metadata_size = 0;
890 }
891
892 return psize;
893 }
894
ogg_read_timestamp(AVFormatContext * s,int stream_index,int64_t * pos_arg,int64_t pos_limit)895 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
896 int64_t *pos_arg, int64_t pos_limit)
897 {
898 struct ogg *ogg = s->priv_data;
899 AVIOContext *bc = s->pb;
900 int64_t pts = AV_NOPTS_VALUE;
901 int64_t keypos = -1;
902 int i;
903 int pstart, psize;
904 avio_seek(bc, *pos_arg, SEEK_SET);
905 ogg_reset(s);
906
907 while ( avio_tell(bc) <= pos_limit
908 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
909 if (i == stream_index) {
910 struct ogg_stream *os = ogg->streams + stream_index;
911 // Do not trust the last timestamps of an ogm video
912 if ( (os->flags & OGG_FLAG_EOS)
913 && !(os->flags & OGG_FLAG_BOS)
914 && os->codec == &ff_ogm_video_codec)
915 continue;
916 pts = ogg_calc_pts(s, i, NULL);
917 ogg_validate_keyframe(s, i, pstart, psize);
918 if (os->pflags & AV_PKT_FLAG_KEY) {
919 keypos = *pos_arg;
920 } else if (os->keyframe_seek) {
921 // if we had a previous keyframe but no pts for it,
922 // return that keyframe with this pts value.
923 if (keypos >= 0)
924 *pos_arg = keypos;
925 else
926 pts = AV_NOPTS_VALUE;
927 }
928 }
929 if (pts != AV_NOPTS_VALUE)
930 break;
931 }
932 ogg_reset(s);
933 return pts;
934 }
935
ogg_read_seek(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)936 static int ogg_read_seek(AVFormatContext *s, int stream_index,
937 int64_t timestamp, int flags)
938 {
939 struct ogg *ogg = s->priv_data;
940 struct ogg_stream *os = ogg->streams + stream_index;
941 int ret;
942
943 av_assert0(stream_index < ogg->nstreams);
944 // Ensure everything is reset even when seeking via
945 // the generated index.
946 ogg_reset(s);
947
948 // Try seeking to a keyframe first. If this fails (very possible),
949 // av_seek_frame will fall back to ignoring keyframes
950 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
951 && !(flags & AVSEEK_FLAG_ANY))
952 os->keyframe_seek = 1;
953
954 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
955 ogg_reset(s);
956 os = ogg->streams + stream_index;
957 if (ret < 0)
958 os->keyframe_seek = 0;
959 return ret;
960 }
961
ogg_probe(const AVProbeData * p)962 static int ogg_probe(const AVProbeData *p)
963 {
964 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
965 return AVPROBE_SCORE_MAX;
966 return 0;
967 }
968
969 AVInputFormat ff_ogg_demuxer = {
970 .name = "ogg",
971 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
972 .priv_data_size = sizeof(struct ogg),
973 .read_probe = ogg_probe,
974 .read_header = ogg_read_header,
975 .read_packet = ogg_read_packet,
976 .read_close = ogg_read_close,
977 .read_seek = ogg_read_seek,
978 .read_timestamp = ogg_read_timestamp,
979 .extensions = "ogg",
980 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
981 };
982