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 "demux.h"
36 #include "oggdec.h"
37 #include "avformat.h"
38 #include "internal.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 <= ffformatcontext(s)->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
255 if (ogg->state) {
256 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
257 "in between Ogg context save/restore operations.\n");
258 return AVERROR_BUG;
259 }
260
261 /* Allocate and init a new Ogg Stream */
262 if (!(os = av_realloc_array(ogg->streams, ogg->nstreams + 1,
263 sizeof(*ogg->streams))))
264 return AVERROR(ENOMEM);
265 ogg->streams = os;
266 os = ogg->streams + idx;
267 memset(os, 0, sizeof(*os));
268 os->serial = serial;
269 os->bufsize = DECODER_BUFFER_SIZE;
270 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
271 os->header = -1;
272 os->start_granule = OGG_NOGRANULE_VALUE;
273 if (!os->buf)
274 return AVERROR(ENOMEM);
275
276 /* Create the associated AVStream */
277 st = avformat_new_stream(s, NULL);
278 if (!st) {
279 av_freep(&os->buf);
280 return AVERROR(ENOMEM);
281 }
282 st->id = idx;
283 avpriv_set_pts_info(st, 64, 1, 1000000);
284
285 ogg->nstreams++;
286 return idx;
287 }
288
data_packets_seen(const struct ogg * ogg)289 static int data_packets_seen(const struct ogg *ogg)
290 {
291 int i;
292
293 for (i = 0; i < ogg->nstreams; i++)
294 if (ogg->streams[i].got_data)
295 return 1;
296 return 0;
297 }
298
buf_realloc(struct ogg_stream * os,int size)299 static int buf_realloc(struct ogg_stream *os, int size)
300 {
301 /* Even if invalid guarantee there's enough memory to read the page */
302 if (os->bufsize - os->bufpos < size) {
303 uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
304 if (!nb)
305 return AVERROR(ENOMEM);
306 os->buf = nb;
307 os->bufsize *= 2;
308 }
309
310 return 0;
311 }
312
ogg_read_page(AVFormatContext * s,int * sid,int probing)313 static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
314 {
315 AVIOContext *bc = s->pb;
316 struct ogg *ogg = s->priv_data;
317 struct ogg_stream *os;
318 int ret, i = 0;
319 int flags, nsegs;
320 uint64_t gp;
321 uint32_t serial;
322 uint32_t crc, crc_tmp;
323 int size = 0, idx;
324 int64_t version, page_pos;
325 int64_t start_pos;
326 uint8_t sync[4];
327 uint8_t segments[255];
328 uint8_t *readout_buf;
329 int sp = 0;
330
331 ret = avio_read(bc, sync, 4);
332 if (ret < 4)
333 return ret < 0 ? ret : AVERROR_EOF;
334
335 do {
336 int c;
337
338 if (sync[sp & 3] == 'O' &&
339 sync[(sp + 1) & 3] == 'g' &&
340 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
341 break;
342
343 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
344 memset(sync, 0, 4);
345 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
346 ogg->page_pos = -1;
347 }
348
349 c = avio_r8(bc);
350
351 if (avio_feof(bc))
352 return AVERROR_EOF;
353
354 sync[sp++ & 3] = c;
355 } while (i++ < MAX_PAGE_SIZE);
356
357 if (i >= MAX_PAGE_SIZE) {
358 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
359 return AVERROR_INVALIDDATA;
360 }
361
362 /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
363 ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
364
365 /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
366 ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
367 start_pos = avio_tell(bc);
368
369 version = avio_r8(bc);
370 flags = avio_r8(bc);
371 gp = avio_rl64(bc);
372 serial = avio_rl32(bc);
373 avio_skip(bc, 4); /* seq */
374
375 crc_tmp = ffio_get_checksum(bc);
376 crc = avio_rb32(bc);
377 crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
378 ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
379
380 nsegs = avio_r8(bc);
381 page_pos = avio_tell(bc) - 27;
382
383 ret = avio_read(bc, segments, nsegs);
384 if (ret < nsegs)
385 return ret < 0 ? ret : AVERROR_EOF;
386
387 for (i = 0; i < nsegs; i++)
388 size += segments[i];
389
390 idx = ogg_find_stream(ogg, serial);
391 if (idx >= 0) {
392 os = ogg->streams + idx;
393
394 ret = buf_realloc(os, size);
395 if (ret < 0)
396 return ret;
397
398 readout_buf = os->buf + os->bufpos;
399 } else {
400 readout_buf = av_malloc(size);
401 }
402
403 ret = avio_read(bc, readout_buf, size);
404 if (ret < size) {
405 if (idx < 0)
406 av_free(readout_buf);
407 return ret < 0 ? ret : AVERROR_EOF;
408 }
409
410 if (crc ^ ffio_get_checksum(bc)) {
411 av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
412 if (idx < 0)
413 av_free(readout_buf);
414 avio_seek(bc, start_pos, SEEK_SET);
415 *sid = -1;
416 return 0;
417 }
418
419 /* Since we're almost sure its a valid packet, checking the version after
420 * the checksum lets the demuxer be more tolerant */
421 if (version) {
422 av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
423 if (idx < 0)
424 av_free(readout_buf);
425 avio_seek(bc, start_pos, SEEK_SET);
426 *sid = -1;
427 return 0;
428 }
429
430 /* CRC is correct so we can be 99% sure there's an actual change here */
431 if (idx < 0) {
432 if (data_packets_seen(ogg))
433 idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
434 else
435 idx = ogg_new_stream(s, serial);
436
437 if (idx < 0) {
438 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
439 av_free(readout_buf);
440 return idx;
441 }
442
443 os = ogg->streams + idx;
444
445 ret = buf_realloc(os, size);
446 if (ret < 0) {
447 av_free(readout_buf);
448 return ret;
449 }
450
451 memcpy(os->buf + os->bufpos, readout_buf, size);
452 av_free(readout_buf);
453 }
454
455 ogg->page_pos = page_pos;
456 os->page_pos = page_pos;
457 os->nsegs = nsegs;
458 os->segp = 0;
459 os->got_data = !(flags & OGG_FLAG_BOS);
460 os->bufpos += size;
461 os->granule = gp;
462 os->flags = flags;
463 memcpy(os->segments, segments, nsegs);
464 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
465
466 if (flags & OGG_FLAG_CONT || os->incomplete) {
467 if (!os->psize) {
468 // If this is the very first segment we started
469 // playback in the middle of a continuation packet.
470 // Discard it since we missed the start of it.
471 while (os->segp < os->nsegs) {
472 int seg = os->segments[os->segp++];
473 os->pstart += seg;
474 if (seg < 255)
475 break;
476 }
477 os->sync_pos = os->page_pos;
478 }
479 } else {
480 os->psize = 0;
481 os->sync_pos = os->page_pos;
482 }
483
484 /* This function is always called with sid != NULL */
485 *sid = idx;
486
487 return 0;
488 }
489
490 /**
491 * @brief find the next Ogg packet
492 * @param *sid is set to the stream for the packet or -1 if there is
493 * no matching stream, in that case assume all other return
494 * values to be uninitialized.
495 * @return negative value on error or EOF.
496 */
ogg_packet(AVFormatContext * s,int * sid,int * dstart,int * dsize,int64_t * fpos)497 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
498 int64_t *fpos)
499 {
500 FFFormatContext *const si = ffformatcontext(s);
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 (!si->data_offset)
587 si->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 si->data_offset = FFMIN(si->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, ffformatcontext(s)->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 return ret;
737 } while (!ogg->headers);
738 av_log(s, AV_LOG_TRACE, "found headers\n");
739
740 for (i = 0; i < ogg->nstreams; i++) {
741 struct ogg_stream *os = ogg->streams + i;
742
743 if (ogg->streams[i].header < 0) {
744 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
745 ogg->streams[i].codec = NULL;
746 av_freep(&ogg->streams[i].private);
747 } else if (os->codec && os->nb_header < os->codec->nb_header) {
748 av_log(s, AV_LOG_WARNING,
749 "Headers mismatch for stream %d: "
750 "expected %d received %d.\n",
751 i, os->codec->nb_header, os->nb_header);
752 if (s->error_recognition & AV_EF_EXPLODE)
753 return AVERROR_INVALIDDATA;
754 }
755 if (os->start_granule != OGG_NOGRANULE_VALUE)
756 os->lastpts = s->streams[i]->start_time =
757 ogg_gptopts(s, i, os->start_granule, NULL);
758 }
759
760 //linear granulepos seek from end
761 ret = ogg_get_length(s);
762 if (ret < 0)
763 return ret;
764
765 return 0;
766 }
767
ogg_calc_pts(AVFormatContext * s,int idx,int64_t * dts)768 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
769 {
770 struct ogg *ogg = s->priv_data;
771 struct ogg_stream *os = ogg->streams + idx;
772 int64_t pts = AV_NOPTS_VALUE;
773
774 if (dts)
775 *dts = AV_NOPTS_VALUE;
776
777 if (os->lastpts != AV_NOPTS_VALUE) {
778 pts = os->lastpts;
779 os->lastpts = AV_NOPTS_VALUE;
780 }
781 if (os->lastdts != AV_NOPTS_VALUE) {
782 if (dts)
783 *dts = os->lastdts;
784 os->lastdts = AV_NOPTS_VALUE;
785 }
786 if (os->page_end) {
787 if (os->granule != -1LL) {
788 if (os->codec && os->codec->granule_is_start)
789 pts = ogg_gptopts(s, idx, os->granule, dts);
790 else
791 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
792 os->granule = -1LL;
793 }
794 }
795 return pts;
796 }
797
ogg_validate_keyframe(AVFormatContext * s,int idx,int pstart,int psize)798 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
799 {
800 struct ogg *ogg = s->priv_data;
801 struct ogg_stream *os = ogg->streams + idx;
802 int invalid = 0;
803 if (psize) {
804 switch (s->streams[idx]->codecpar->codec_id) {
805 case AV_CODEC_ID_THEORA:
806 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
807 break;
808 case AV_CODEC_ID_VP8:
809 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
810 }
811 if (invalid) {
812 os->pflags ^= AV_PKT_FLAG_KEY;
813 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
814 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
815 }
816 }
817 }
818
ogg_read_packet(AVFormatContext * s,AVPacket * pkt)819 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
820 {
821 struct ogg *ogg;
822 struct ogg_stream *os;
823 int idx, ret;
824 int pstart, psize;
825 int64_t fpos, pts, dts;
826
827 if (s->io_repositioned) {
828 ogg_reset(s);
829 s->io_repositioned = 0;
830 }
831
832 //Get an ogg packet
833 retry:
834 do {
835 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
836 if (ret < 0)
837 return ret;
838 } while (idx < 0 || !s->streams[idx]);
839
840 ogg = s->priv_data;
841 os = ogg->streams + idx;
842
843 // pflags might not be set until after this
844 pts = ogg_calc_pts(s, idx, &dts);
845 ogg_validate_keyframe(s, idx, pstart, psize);
846
847 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
848 goto retry;
849 os->keyframe_seek = 0;
850
851 //Alloc a pkt
852 ret = av_new_packet(pkt, psize);
853 if (ret < 0)
854 return ret;
855 pkt->stream_index = idx;
856 memcpy(pkt->data, os->buf + pstart, psize);
857
858 pkt->pts = pts;
859 pkt->dts = dts;
860 pkt->flags = os->pflags;
861 pkt->duration = os->pduration;
862 pkt->pos = fpos;
863
864 if (os->start_trimming || os->end_trimming) {
865 uint8_t *side_data = av_packet_new_side_data(pkt,
866 AV_PKT_DATA_SKIP_SAMPLES,
867 10);
868 if(!side_data)
869 return AVERROR(ENOMEM);
870 AV_WL32(side_data + 0, os->start_trimming);
871 AV_WL32(side_data + 4, os->end_trimming);
872 os->start_trimming = 0;
873 os->end_trimming = 0;
874 }
875
876 if (os->new_metadata) {
877 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE,
878 os->new_metadata, os->new_metadata_size);
879 if (ret < 0)
880 return ret;
881
882 os->new_metadata = NULL;
883 os->new_metadata_size = 0;
884 }
885
886 return psize;
887 }
888
ogg_read_timestamp(AVFormatContext * s,int stream_index,int64_t * pos_arg,int64_t pos_limit)889 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
890 int64_t *pos_arg, int64_t pos_limit)
891 {
892 struct ogg *ogg = s->priv_data;
893 AVIOContext *bc = s->pb;
894 int64_t pts = AV_NOPTS_VALUE;
895 int64_t keypos = -1;
896 int i;
897 int pstart, psize;
898 avio_seek(bc, *pos_arg, SEEK_SET);
899 ogg_reset(s);
900
901 while ( avio_tell(bc) <= pos_limit
902 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
903 if (i == stream_index) {
904 struct ogg_stream *os = ogg->streams + stream_index;
905 // Do not trust the last timestamps of an ogm video
906 if ( (os->flags & OGG_FLAG_EOS)
907 && !(os->flags & OGG_FLAG_BOS)
908 && os->codec == &ff_ogm_video_codec)
909 continue;
910 pts = ogg_calc_pts(s, i, NULL);
911 ogg_validate_keyframe(s, i, pstart, psize);
912 if (os->pflags & AV_PKT_FLAG_KEY) {
913 keypos = *pos_arg;
914 } else if (os->keyframe_seek) {
915 // if we had a previous keyframe but no pts for it,
916 // return that keyframe with this pts value.
917 if (keypos >= 0)
918 *pos_arg = keypos;
919 else
920 pts = AV_NOPTS_VALUE;
921 }
922 }
923 if (pts != AV_NOPTS_VALUE)
924 break;
925 }
926 ogg_reset(s);
927 return pts;
928 }
929
ogg_read_seek(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)930 static int ogg_read_seek(AVFormatContext *s, int stream_index,
931 int64_t timestamp, int flags)
932 {
933 struct ogg *ogg = s->priv_data;
934 struct ogg_stream *os = ogg->streams + stream_index;
935 int ret;
936
937 av_assert0(stream_index < ogg->nstreams);
938 // Ensure everything is reset even when seeking via
939 // the generated index.
940 ogg_reset(s);
941
942 // Try seeking to a keyframe first. If this fails (very possible),
943 // av_seek_frame will fall back to ignoring keyframes
944 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
945 && !(flags & AVSEEK_FLAG_ANY))
946 os->keyframe_seek = 1;
947
948 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
949 ogg_reset(s);
950 os = ogg->streams + stream_index;
951 if (ret < 0)
952 os->keyframe_seek = 0;
953 return ret;
954 }
955
ogg_probe(const AVProbeData * p)956 static int ogg_probe(const AVProbeData *p)
957 {
958 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
959 return AVPROBE_SCORE_MAX;
960 return 0;
961 }
962
963 const AVInputFormat ff_ogg_demuxer = {
964 .name = "ogg",
965 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
966 .priv_data_size = sizeof(struct ogg),
967 .flags_internal = FF_FMT_INIT_CLEANUP,
968 .read_probe = ogg_probe,
969 .read_header = ogg_read_header,
970 .read_packet = ogg_read_packet,
971 .read_close = ogg_read_close,
972 .read_seek = ogg_read_seek,
973 .read_timestamp = ogg_read_timestamp,
974 .extensions = "ogg",
975 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
976 };
977