FFmpeg
Loading...
Searching...
No Matches
oggdec.c
Go to the documentation of this file.
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"
34#include "libavutil/mem.h"
35#include "avio_internal.h"
36#include "demux.h"
37#include "oggdec.h"
38#include "avformat.h"
39#include "internal.h"
40
41#define MAX_PAGE_SIZE 65307
42#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
43
61
62static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
63static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
64static int ogg_restore(AVFormatContext *s);
65
66static 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 av_freep(&stream->new_extradata);
80}
81
82//FIXME We could avoid some structure duplication
84{
85 struct ogg *ogg = s->priv_data;
86 struct ogg_state *ost =
87 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
88 int i;
89 int ret = 0;
90
91 if (!ost)
92 return AVERROR(ENOMEM);
93
94 ost->pos = avio_tell(s->pb);
95 ost->curidx = ogg->curidx;
96 ost->next = ogg->state;
97 ost->nstreams = ogg->nstreams;
98 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
99
100 for (i = 0; i < ogg->nstreams; i++) {
101 struct ogg_stream *os = ogg->streams + i;
103 if (os->buf)
104 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
105 else
106 ret = AVERROR(ENOMEM);
107 os->new_metadata = NULL;
108 os->new_metadata_size = 0;
109 os->new_extradata = NULL;
110 os->new_extradata_size = 0;
111 }
112
113 ogg->state = ost;
114
115 if (ret < 0)
116 ogg_restore(s);
117
118 return ret;
119}
120
122{
123 struct ogg *ogg = s->priv_data;
124 AVIOContext *bc = s->pb;
125 struct ogg_state *ost = ogg->state;
126 int i, err;
127
128 if (!ost)
129 return 0;
130
131 ogg->state = ost->next;
132
133 for (i = 0; i < ogg->nstreams; i++) {
134 struct ogg_stream *stream = &ogg->streams[i];
135 av_freep(&stream->buf);
136 av_freep(&stream->new_metadata);
137 av_freep(&stream->new_extradata);
138
139 if (i >= ost->nstreams || !ost->streams[i].private) {
140 free_stream(s, i);
141 }
142 }
143
144 avio_seek(bc, ost->pos, SEEK_SET);
145 ogg->page_pos = -1;
146 ogg->curidx = ost->curidx;
147 ogg->nstreams = ost->nstreams;
149 sizeof(*ogg->streams))) < 0) {
150 ogg->nstreams = 0;
151 return err;
152 } else
153 memcpy(ogg->streams, ost->streams,
154 ost->nstreams * sizeof(*ogg->streams));
155
156 av_free(ost);
157
158 return 0;
159}
160
162{
163 struct ogg *ogg = s->priv_data;
164 int i;
165 int64_t start_pos = avio_tell(s->pb);
166
167 for (i = 0; i < ogg->nstreams; i++) {
168 struct ogg_stream *os = ogg->streams + i;
169 os->bufpos = 0;
170 os->pstart = 0;
171 os->psize = 0;
172 os->granule = -1;
175 os->sync_pos = -1;
176 os->page_pos = 0;
177 os->nsegs = 0;
178 os->segp = 0;
179 os->incomplete = 0;
180 os->got_data = 0;
181 if (start_pos <= ffformatcontext(s)->data_offset) {
182 os->lastpts = 0;
183 }
184 os->start_trimming = 0;
185 os->end_trimming = 0;
187 os->new_metadata_size = 0;
189 os->new_extradata_size = 0;
190 }
191
192 ogg->page_pos = -1;
193 ogg->curidx = -1;
194
195 return 0;
196}
197
198static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
199{
200 int i;
201
202 for (i = 0; ogg_codecs[i]; i++)
203 if (size >= ogg_codecs[i]->magicsize &&
204 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
205 return ogg_codecs[i];
206
207 return NULL;
208}
209
210/**
211 * Replace the current stream with a new one. This is a typical webradio
212 * situation where a new audio stream spawn (identified with a new serial) and
213 * must replace the previous one (track switch).
214 */
215static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, int page_size,
216 int probing)
217{
218 struct ogg *ogg = s->priv_data;
219 struct ogg_stream *os;
220 const struct ogg_codec *codec;
221 int i = 0;
222
223 if (ogg->nstreams != 1) {
224 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
226 }
227
228 /* Check for codecs */
229 codec = ogg_find_codec(magic, page_size);
230 if (!codec && !probing) {
231 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
232 return AVERROR_INVALIDDATA;
233 }
234
235 os = &ogg->streams[0];
236 if (os->codec != codec)
237 return AVERROR(EINVAL);
238
239 os->serial = serial;
240 os->codec = codec;
241 os->serial = serial;
242 os->lastpts = 0;
243 os->lastdts = 0;
244 os->flags = 0;
245 os->start_trimming = 0;
246 os->end_trimming = 0;
247 os->replace = 1;
248
249 return i;
250}
251
252static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
253{
254 struct ogg *ogg = s->priv_data;
255 int idx = ogg->nstreams;
256 AVStream *st;
257 struct ogg_stream *os;
258
259 if (ogg->state) {
260 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
261 "in between Ogg context save/restore operations.\n");
262 return AVERROR_BUG;
263 }
264
265 /* Allocate and init a new Ogg Stream */
266 if (!(os = av_realloc_array(ogg->streams, ogg->nstreams + 1,
267 sizeof(*ogg->streams))))
268 return AVERROR(ENOMEM);
269 ogg->streams = os;
270 os = ogg->streams + idx;
271 memset(os, 0, sizeof(*os));
272 os->serial = serial;
275 os->header = -1;
277 if (!os->buf)
278 return AVERROR(ENOMEM);
279
280 /* Create the associated AVStream */
282 if (!st) {
283 av_freep(&os->buf);
284 return AVERROR(ENOMEM);
285 }
286 st->id = idx;
287 avpriv_set_pts_info(st, 64, 1, 1000000);
288
289 ogg->nstreams++;
290 return idx;
291}
292
293static int data_packets_seen(const struct ogg *ogg)
294{
295 int i;
296
297 for (i = 0; i < ogg->nstreams; i++)
298 if (ogg->streams[i].got_data)
299 return 1;
300 return 0;
301}
302
303static int buf_realloc(struct ogg_stream *os, int size)
304{
305 /* Even if invalid guarantee there's enough memory to read the page */
306 if (os->bufsize - os->bufpos < size) {
307 uint8_t *nb;
308 if (os->bufsize > (UINT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) / 2)
309 return AVERROR(ENOMEM);
311 if (!nb)
312 return AVERROR(ENOMEM);
313 os->buf = nb;
314 os->bufsize *= 2;
315 }
316
317 return 0;
318}
319
320static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
321{
322 AVIOContext *bc = s->pb;
323 struct ogg *ogg = s->priv_data;
324 struct ogg_stream *os;
325 int ret, i = 0;
326 int flags, nsegs;
327 uint64_t gp;
328 uint32_t serial;
329 uint32_t crc, crc_tmp;
330 int size = 0, idx;
332 int64_t start_pos;
333 uint8_t sync[4];
334 uint8_t segments[255];
335 uint8_t *readout_buf;
336 int sp = 0;
337
338 ret = avio_read(bc, sync, 4);
339 if (ret < 4)
340 return ret < 0 ? ret : AVERROR_EOF;
341
342 do {
343 int c;
344
345 if (sync[sp & 3] == 'O' &&
346 sync[(sp + 1) & 3] == 'g' &&
347 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
348 break;
349
350 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
351 memset(sync, 0, 4);
352 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
353 ogg->page_pos = -1;
354 }
355
356 c = avio_r8(bc);
357
358 if (avio_feof(bc))
359 return AVERROR_EOF;
360
361 sync[sp++ & 3] = c;
362 } while (i++ < MAX_PAGE_SIZE);
363
364 if (i >= MAX_PAGE_SIZE) {
365 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
366 return AVERROR_INVALIDDATA;
367 }
368
369 /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
371
372 /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
374 if (ret < 0)
375 return ret;
376 start_pos = avio_tell(bc);
377
378 version = avio_r8(bc);
379 flags = avio_r8(bc);
380 gp = avio_rl64(bc);
381 serial = avio_rl32(bc);
382 avio_rl32(bc); /* seq */
383
384 crc_tmp = ffio_get_checksum(bc);
385 crc = avio_rb32(bc);
386 crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
388
389 nsegs = avio_r8(bc);
390 page_pos = avio_tell(bc) - 27;
391
392 ret = avio_read(bc, segments, nsegs);
393 if (ret < nsegs)
394 return ret < 0 ? ret : AVERROR_EOF;
395
396 for (i = 0; i < nsegs; i++)
397 size += segments[i];
398
399 idx = ogg_find_stream(ogg, serial);
400 if (idx >= 0) {
401 os = ogg->streams + idx;
402
403 ret = buf_realloc(os, size);
404 if (ret < 0)
405 return ret;
406
407 readout_buf = os->buf + os->bufpos;
408 } else {
409 readout_buf = av_malloc(size);
410 }
411
412 ret = avio_read(bc, readout_buf, size);
413 if (ret < size) {
414 if (idx < 0)
415 av_free(readout_buf);
416 return ret < 0 ? ret : AVERROR_EOF;
417 }
418
419 if (crc ^ ffio_get_checksum(bc)) {
420 av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
421 if (idx < 0)
422 av_free(readout_buf);
423 avio_seek(bc, start_pos, SEEK_SET);
424 *sid = -1;
425 return 0;
426 }
427
428 /* Since we're almost sure its a valid packet, checking the version after
429 * the checksum lets the demuxer be more tolerant */
430 if (version) {
431 av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
432 if (idx < 0)
433 av_free(readout_buf);
434 avio_seek(bc, start_pos, SEEK_SET);
435 *sid = -1;
436 return 0;
437 }
438
439 /* CRC is correct so we can be 99% sure there's an actual change here */
440 if (idx < 0) {
442 idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
443 else
444 idx = ogg_new_stream(s, serial);
445
446 if (idx < 0) {
447 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
448 av_free(readout_buf);
449 return idx;
450 }
451
452 os = ogg->streams + idx;
453
454 ret = buf_realloc(os, size);
455 if (ret < 0) {
456 av_free(readout_buf);
457 return ret;
458 }
459
460 memcpy(os->buf + os->bufpos, readout_buf, size);
461 av_free(readout_buf);
462 }
463
465 os->page_pos = page_pos;
466 os->nsegs = nsegs;
467 os->segp = 0;
468 os->got_data = !(flags & OGG_FLAG_BOS);
469 os->bufpos += size;
470 os->granule = gp;
471 os->flags = flags;
472 memcpy(os->segments, segments, nsegs);
473 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
474
475 if (flags & OGG_FLAG_CONT || os->incomplete) {
476 if (!os->psize) {
477 // If this is the very first segment we started
478 // playback in the middle of a continuation packet.
479 // Discard it since we missed the start of it.
480 while (os->segp < os->nsegs) {
481 int seg = os->segments[os->segp++];
482 os->pstart += seg;
483 if (seg < 255)
484 break;
485 }
486 os->sync_pos = os->page_pos;
487 }
488 } else {
489 os->psize = 0;
490 os->sync_pos = os->page_pos;
491 }
492
493 /* This function is always called with sid != NULL */
494 *sid = idx;
495
496 return 0;
497}
498
499/**
500 * @brief find the next Ogg packet
501 * @param *sid is set to the stream for the packet or -1 if there is
502 * no matching stream, in that case assume all other return
503 * values to be uninitialized.
504 * @return negative value on error or EOF.
505 */
506static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
507 int64_t *fpos)
508{
509 FFFormatContext *const si = ffformatcontext(s);
510 struct ogg *ogg = s->priv_data;
511 int idx, i, ret;
512 struct ogg_stream *os;
513 int complete = 0;
514 int segp = 0, psize = 0;
515
516 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
517 if (sid)
518 *sid = -1;
519
520 do {
521 idx = ogg->curidx;
522
523 while (idx < 0) {
524 ret = ogg_read_page(s, &idx, 0);
525 if (ret < 0)
526 return ret;
527 }
528
529 os = ogg->streams + idx;
530
531 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
532 idx, os->pstart, os->psize, os->segp, os->nsegs);
533
534 if (!os->codec) {
535 if (os->header < 0) {
536 os->codec = ogg_find_codec(os->buf, os->bufpos);
537 if (!os->codec) {
538 av_log(s, AV_LOG_WARNING, "Codec not found\n");
539 os->header = 0;
540 return 0;
541 }
542 } else {
543 return 0;
544 }
545 }
546
547 segp = os->segp;
548 psize = os->psize;
549
550 while (os->segp < os->nsegs) {
551 int ss = os->segments[os->segp++];
552 os->psize += ss;
553 if (ss < 255) {
554 complete = 1;
555 break;
556 }
557 }
558
559 if (!complete && os->segp == os->nsegs) {
560 ogg->curidx = -1;
561 // Do not set incomplete for empty packets.
562 // Together with the code in ogg_read_page
563 // that discards all continuation of empty packets
564 // we would get an infinite loop.
565 os->incomplete = !!os->psize;
566 }
567 } while (!complete);
568
569
570 if (os->granule == -1)
572 "Page at %"PRId64" is missing granule\n",
573 os->page_pos);
574
575 ogg->curidx = idx;
576 os->incomplete = 0;
577
578 // the packet started at the first segment of the page it completes on
579 os->page_start = segp == 0;
580
581 if (os->header) {
582 if ((ret = os->codec->header(s, idx)) < 0) {
583 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
584 return ret;
585 }
586 os->header = ret;
587 if (!os->header) {
588 os->segp = segp;
589 os->psize = psize;
590
591 // We have reached the first non-header packet in this stream.
592 // Unfortunately more header packets may still follow for others,
593 // but if we continue with header parsing we may lose data packets.
594 ogg->headers = 1;
595
596 // Update the header state for all streams and
597 // compute the data_offset.
598 if (!si->data_offset)
599 si->data_offset = os->sync_pos;
600
601 for (i = 0; i < ogg->nstreams; i++) {
602 struct ogg_stream *cur_os = ogg->streams + i;
603
604 // if we have a partial non-header packet, its start is
605 // obviously at or after the data start
606 if (cur_os->incomplete)
607 si->data_offset = FFMIN(si->data_offset, cur_os->sync_pos);
608 }
609 } else {
610 os->nb_header++;
611 os->pstart += os->psize;
612 os->psize = 0;
613 }
614 } else {
615 os->pflags = 0;
616 os->pduration = 0;
617
618 ret = 0;
619 if (os->codec && os->codec->packet) {
620 if ((ret = os->codec->packet(s, idx)) < 0) {
621 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
622 return ret;
623 }
624 }
625
626 if (!ret) {
627 if (sid)
628 *sid = idx;
629 if (dstart)
630 *dstart = os->pstart;
631 if (dsize)
632 *dsize = os->psize;
633 if (fpos)
634 *fpos = os->sync_pos;
635 }
636
637 os->pstart += os->psize;
638 os->psize = 0;
639 if(os->pstart == os->bufpos)
640 os->bufpos = os->pstart = 0;
641 os->sync_pos = os->page_pos;
642 }
643
644 // determine whether there are more complete packets in this page
645 // if not, the page's granule will apply to this packet
646 os->page_end = 1;
647 for (i = os->segp; i < os->nsegs; i++)
648 if (os->segments[i] < 255) {
649 os->page_end = 0;
650 break;
651 }
652
653 if (os->segp == os->nsegs)
654 ogg->curidx = -1;
655
656 return 0;
657}
658
660{
661 struct ogg *ogg = s->priv_data;
662 int i, ret;
663 int64_t size, end;
664 int streams_left=0;
665
666 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
667 return 0;
668
669// already set
670 if (s->duration != AV_NOPTS_VALUE)
671 return 0;
672
673 size = avio_size(s->pb);
674 if (size < 0)
675 return 0;
676 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
677
678 ret = ogg_save(s);
679 if (ret < 0)
680 return ret;
681 avio_seek(s->pb, end, SEEK_SET);
682 ogg->page_pos = -1;
683
684 while (!ogg_read_page(s, &i, 1)) {
685 if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
686 ogg->streams[i].codec) {
687 s->streams[i]->duration =
689 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
690 s->streams[i]->duration -= s->streams[i]->start_time;
691 streams_left-= (ogg->streams[i].got_start==-1);
692 ogg->streams[i].got_start= 1;
693 } else if(!ogg->streams[i].got_start) {
694 ogg->streams[i].got_start= -1;
695 streams_left++;
696 }
697 }
698 }
699
700 ogg_restore(s);
701
702 ret = ogg_save(s);
703 if (ret < 0)
704 return ret;
705
706 avio_seek (s->pb, ffformatcontext(s)->data_offset, SEEK_SET);
707 ogg_reset(s);
708 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
709 int64_t pts;
710 if (i < 0) continue;
711 pts = ogg_calc_pts(s, i, NULL);
712 if (s->streams[i]->duration == AV_NOPTS_VALUE)
713 continue;
714 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
715 s->streams[i]->duration -= pts;
716 ogg->streams[i].got_start= 1;
717 streams_left--;
718 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
719 ogg->streams[i].got_start= 1;
720 streams_left--;
721 }
722 }
723 ogg_restore (s);
724
725 return 0;
726}
727
729{
730 struct ogg *ogg = s->priv_data;
731 int i;
732
733 for (i = 0; i < ogg->nstreams; i++) {
734 free_stream(s, i);
735 }
736
737 ogg->nstreams = 0;
738
740 return 0;
741}
742
744{
745 struct ogg *ogg = s->priv_data;
746 int ret, i;
747
748 ogg->curidx = -1;
749
750 //linear headers seek from start
751 do {
752 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
753 if (ret < 0)
754 return ret;
755 } while (!ogg->headers);
756 av_log(s, AV_LOG_TRACE, "found headers\n");
757
758 for (i = 0; i < ogg->nstreams; i++) {
759 struct ogg_stream *os = ogg->streams + i;
760
761 if (ogg->streams[i].header < 0) {
762 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
763 ogg->streams[i].codec = NULL;
765 } else if (os->codec && os->nb_header < os->codec->nb_header) {
767 "Headers mismatch for stream %d: "
768 "expected %d received %d.\n",
769 i, os->codec->nb_header, os->nb_header);
770 if (s->error_recognition & AV_EF_EXPLODE)
771 return AVERROR_INVALIDDATA;
772 }
774 os->lastpts = s->streams[i]->start_time =
776 }
777
778 //linear granulepos seek from end
779 ret = ogg_get_length(s);
780 if (ret < 0)
781 return ret;
782
783 return 0;
784}
785
787{
788 struct ogg *ogg = s->priv_data;
789 struct ogg_stream *os = ogg->streams + idx;
791
792 if (dts)
793 *dts = AV_NOPTS_VALUE;
794
795 if (os->lastpts != AV_NOPTS_VALUE) {
796 pts = os->lastpts;
798 }
799 if (os->lastdts != AV_NOPTS_VALUE) {
800 if (dts)
801 *dts = os->lastdts;
803 }
804 if (os->page_end) {
805 if (os->granule != -1LL) {
806 if (os->codec && os->codec->granule_is_start)
807 pts = ogg_gptopts(s, idx, os->granule, dts);
808 else
809 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
810 os->granule = -1LL;
811 }
812 }
813 return pts;
814}
815
816static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
817{
818 struct ogg *ogg = s->priv_data;
819 struct ogg_stream *os = ogg->streams + idx;
820 int invalid = 0;
821 if (psize) {
822 switch (s->streams[idx]->codecpar->codec_id) {
824 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
825 break;
826 case AV_CODEC_ID_VP8:
827 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
828 }
829 if (invalid) {
830 os->pflags ^= AV_PKT_FLAG_KEY;
831 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
832 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
833 }
834 }
835}
836
838{
839 struct ogg *ogg;
840 struct ogg_stream *os;
841 int idx, ret;
842 int pstart, psize;
843 int64_t fpos, pts, dts;
844
845 if (s->io_repositioned) {
846 ogg_reset(s);
847 s->io_repositioned = 0;
848 }
849
850 //Get an ogg packet
851retry:
852 do {
853 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
854 if (ret < 0)
855 return ret;
856 } while (idx < 0 || !s->streams[idx]);
857
858 ogg = s->priv_data;
859 os = ogg->streams + idx;
860
861 // pflags might not be set until after this
862 pts = ogg_calc_pts(s, idx, &dts);
864
865 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
866 goto retry;
867 os->keyframe_seek = 0;
868
869 //Alloc a pkt
870 ret = av_new_packet(pkt, psize);
871 if (ret < 0)
872 return ret;
873 pkt->stream_index = idx;
874 memcpy(pkt->data, os->buf + pstart, psize);
875
876 pkt->pts = pts;
877 pkt->dts = dts;
878 pkt->flags = os->pflags;
879 pkt->duration = os->pduration;
880 pkt->pos = fpos;
881
882 if (os->start_trimming || os->end_trimming) {
883 uint8_t *side_data = av_packet_new_side_data(pkt,
885 10);
886 if(!side_data)
887 return AVERROR(ENOMEM);
888 AV_WL32(side_data + 0, os->start_trimming);
889 AV_WL32(side_data + 4, os->end_trimming);
890 os->start_trimming = 0;
891 os->end_trimming = 0;
892 }
893
894 if (os->replace) {
895 os->replace = 0;
896 pkt->dts = pkt->pts = AV_NOPTS_VALUE;
897 }
898
899 if (os->new_metadata) {
902 if (ret < 0)
903 return ret;
904
905 os->new_metadata = NULL;
906 os->new_metadata_size = 0;
907 }
908
909 if (os->new_extradata) {
912 if (ret < 0)
913 return ret;
914
915 os->new_extradata = NULL;
916 os->new_extradata_size = 0;
917 }
918
919 return psize;
920}
921
922static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
923 int64_t *pos_arg, int64_t pos_limit)
924{
925 struct ogg *ogg = s->priv_data;
926 AVIOContext *bc = s->pb;
928 int64_t keypos = -1;
929 int i;
930 int pstart, psize;
931 avio_seek(bc, *pos_arg, SEEK_SET);
932 ogg_reset(s);
933
934 while ( avio_tell(bc) <= pos_limit
935 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
936 if (i == stream_index) {
937 struct ogg_stream *os = ogg->streams + stream_index;
938 // Do not trust the last timestamps of an ogm video
939 if ( (os->flags & OGG_FLAG_EOS)
940 && !(os->flags & OGG_FLAG_BOS)
941 && os->codec == &ff_ogm_video_codec)
942 continue;
943 pts = ogg_calc_pts(s, i, NULL);
945 if (os->pflags & AV_PKT_FLAG_KEY) {
946 keypos = *pos_arg;
947 } else if (os->keyframe_seek) {
948 // if we had a previous keyframe but no pts for it,
949 // return that keyframe with this pts value.
950 if (keypos >= 0)
951 *pos_arg = keypos;
952 else
954 }
955 }
956 if (pts != AV_NOPTS_VALUE)
957 break;
958 }
959 ogg_reset(s);
960 return pts;
961}
962
963static int ogg_read_seek(AVFormatContext *s, int stream_index,
964 int64_t timestamp, int flags)
965{
966 struct ogg *ogg = s->priv_data;
967 struct ogg_stream *os = ogg->streams + stream_index;
968 int ret;
969
970 av_assert0(stream_index < ogg->nstreams);
971 // Ensure everything is reset even when seeking via
972 // the generated index.
973 ogg_reset(s);
974
975 // Try seeking to a keyframe first. If this fails (very possible),
976 // av_seek_frame will fall back to ignoring keyframes
977 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
978 && !(flags & AVSEEK_FLAG_ANY))
979 os->keyframe_seek = 1;
980
981 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
982 ogg_reset(s);
983 os = ogg->streams + stream_index;
984 if (ret < 0)
985 os->keyframe_seek = 0;
986 return ret;
987}
988
989static int ogg_probe(const AVProbeData *p)
990{
991 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
992 return AVPROBE_SCORE_MAX;
993 return 0;
994}
995
997 .p.name = "ogg",
998 .p.long_name = NULL_IF_CONFIG_SMALL("Ogg"),
999 .p.extensions = "ogg",
1001 .priv_data_size = sizeof(struct ogg),
1002 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
1003 .read_probe = ogg_probe,
1004 .read_header = ogg_read_header,
1005 .read_packet = ogg_read_packet,
1006 .read_close = ogg_read_close,
1007 .read_seek = ogg_read_seek,
1008 .read_timestamp = ogg_read_timestamp,
1009};
const FFInputFormat ff_ogg_demuxer
Definition oggdec.c:996
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVPROBE_SCORE_MAX
maximum score
Definition avformat.h:483
#define AVFMT_TS_DISCONT
Format allows timestamp discontinuities.
Definition avformat.h:500
#define AVFMT_NOBINSEARCH
Format does not allow to fall back on binary search via read_timestamp.
Definition avformat.h:504
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition avformat.h:2618
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition avformat.h:499
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
Definition avio.h:41
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition aviobuf.c:326
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition aviobuf.c:615
unsigned int avio_rl32(AVIOContext *s)
Definition aviobuf.c:733
unsigned int avio_rb32(AVIOContext *s)
Definition aviobuf.c:764
int avio_r8(AVIOContext *s)
Definition aviobuf.c:606
uint64_t avio_rl64(AVIOContext *s)
Definition aviobuf.c:741
void ffio_init_checksum(AVIOContext *s, unsigned long(*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum)
Definition aviobuf.c:594
unsigned long ffio_get_checksum(AVIOContext *s)
Definition aviobuf.c:586
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
Definition aviobuf.c:1026
unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len)
Definition aviobuf.c:568
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define ss(width, name, subs,...)
Definition cbs_vp9.c:202
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
#define AV_EF_EXPLODE
abort decoding on minor error detection
Definition defs.h:51
int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
Perform a binary search using av_index_search_timestamp() and FFInputFormat.read_timestamp().
Definition seek.c:290
#define FF_INFMT_FLAG_INIT_CLEANUP
For an FFInputFormat with this flag set read_close() needs to be called by the caller upon read_heade...
Definition demux.h:35
static AVPacket * pkt
@ AV_CODEC_ID_VP8
Definition codec_id.h:190
@ AV_CODEC_ID_THEORA
Definition codec_id.h:80
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
@ AV_PKT_DATA_STRINGS_METADATA
A list of zero terminated key/value strings.
Definition packet.h:169
@ AV_PKT_DATA_SKIP_SAMPLES
Recommends skipping the specified number of samples.
Definition packet.h:153
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition packet.h:56
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, size_t size)
Allocate new information of a packet.
Definition packet.c:231
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, uint8_t *data, size_t size)
Wrap an existing array as a packet side data.
Definition packet.c:197
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition packet.c:98
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:217
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
Definition mem.c:225
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_WL32(p, v)
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition internal.h:130
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
version
Definition libkvazaar.c:313
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
static int ogg_get_length(AVFormatContext *s)
Definition oggdec.c:659
static int ogg_save(AVFormatContext *s)
Definition oggdec.c:83
static const struct ogg_codec *const ogg_codecs[]
Definition oggdec.c:44
static int ogg_probe(const AVProbeData *p)
Definition oggdec.c:989
static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, int page_size, int probing)
Replace the current stream with a new one.
Definition oggdec.c:215
static int ogg_read_header(AVFormatContext *s)
Definition oggdec.c:743
static int ogg_restore(AVFormatContext *s)
Definition oggdec.c:121
static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition oggdec.c:837
static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, int64_t *fpos)
find the next Ogg packet
Definition oggdec.c:506
static int buf_realloc(struct ogg_stream *os, int size)
Definition oggdec.c:303
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit)
Definition oggdec.c:922
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
Definition oggdec.c:786
static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
Definition oggdec.c:252
#define DECODER_BUFFER_SIZE
Definition oggdec.c:42
#define MAX_PAGE_SIZE
Definition oggdec.c:41
static int ogg_reset(AVFormatContext *s)
Definition oggdec.c:161
static const struct ogg_codec * ogg_find_codec(uint8_t *buf, int size)
Definition oggdec.c:198
static void free_stream(AVFormatContext *s, int i)
Definition oggdec.c:66
static int data_packets_seen(const struct ogg *ogg)
Definition oggdec.c:293
static int ogg_read_close(AVFormatContext *s)
Definition oggdec.c:728
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition oggdec.c:963
static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
Definition oggdec.c:320
static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
Definition oggdec.c:816
const struct ogg_codec ff_skeleton_codec
const struct ogg_codec ff_flac_codec
#define OGG_NOGRANULE_VALUE
Definition oggdec.h:125
const struct ogg_codec ff_ogm_old_codec
const struct ogg_codec ff_opus_codec
const struct ogg_codec ff_vp8_codec
#define OGG_FLAG_BOS
Definition oggdec.h:122
const struct ogg_codec ff_ogm_video_codec
static uint64_t ogg_gptopts(AVFormatContext *s, int i, uint64_t gp, int64_t *dts)
Definition oggdec.h:191
const struct ogg_codec ff_speex_codec
const struct ogg_codec ff_old_dirac_codec
const struct ogg_codec ff_old_flac_codec
const struct ogg_codec ff_ogm_audio_codec
const struct ogg_codec ff_dirac_codec
const struct ogg_codec ff_vorbis_codec
static int ogg_find_stream(struct ogg *ogg, int serial)
Definition oggdec.h:179
#define OGG_FLAG_EOS
Definition oggdec.h:123
const struct ogg_codec ff_ogm_text_codec
#define OGG_FLAG_CONT
Definition oggdec.h:121
const struct ogg_codec ff_theora_codec
#define av_realloc(p, s)
Definition ops_static.c:54
#define av_malloc(s)
Definition ops_static.c:52
Format I/O context.
Definition avformat.h:1333
Bytestream IO Context.
Definition avio.h:160
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition avio.h:261
This structure stores compressed data.
Definition packet.h:580
This structure contains the data a format has to probe a file.
Definition avformat.h:471
Stream structure.
Definition avformat.h:766
int id
Format-specific stream ID.
Definition avformat.h:778
int64_t data_offset
offset of the first packet
Definition internal.h:89
Copyright (C) 2005 Michael Ahlberg, Måns Rullgård.
Definition oggdec.h:30
int(* header)(AVFormatContext *, int)
Attempt to process a packet as a header.
Definition oggdec.h:40
void(* cleanup)(AVFormatContext *s, int idx)
Definition oggdec.h:64
int granule_is_start
1 if granule is the start time of the associated packet.
Definition oggdec.h:59
int nb_header
Number of expected headers.
Definition oggdec.h:63
int(* packet)(AVFormatContext *, int)
Attempt to process a packet as a data packet.
Definition oggdec.h:48
const int8_t * magic
Definition oggdec.h:31
uint8_t magicsize
Definition oggdec.h:32
unsigned int pduration
Definition oggdec.h:74
int incomplete
whether we're expecting a continuation in the next page
Definition oggdec.h:87
uint8_t * new_extradata
Definition oggdec.h:99
size_t new_metadata_size
Definition oggdec.h:98
uint64_t start_granule
Definition oggdec.h:77
size_t new_extradata_size
Definition oggdec.h:100
int end_trimming
set the number of packets to drop from the end
Definition oggdec.h:95
unsigned int pflags
Definition oggdec.h:73
int nb_header
set to the number of parsed headers
Definition oggdec.h:93
uint8_t * new_metadata
Definition oggdec.h:97
int nsegs
Definition oggdec.h:85
unsigned int bufpos
Definition oggdec.h:70
int start_trimming
set the number of packets to drop from the start
Definition oggdec.h:94
int keyframe_seek
Definition oggdec.h:90
uint8_t segments[255]
Definition oggdec.h:86
int page_start
current packet is the first one starting in the page
Definition oggdec.h:88
unsigned int bufsize
Definition oggdec.h:69
uint64_t granule
Definition oggdec.h:76
int64_t lastdts
Definition oggdec.h:79
unsigned int pstart
Definition oggdec.h:71
int replace
Definition oggdec.h:96
unsigned int psize
Definition oggdec.h:72
void * private
Definition oggdec.h:101
uint8_t * buf
Definition oggdec.h:68
int page_end
current packet is the last one completed in the page
Definition oggdec.h:89
int header
Definition oggdec.h:84
int64_t page_pos
file offset of the current page
Definition oggdec.h:81
const struct ogg_codec * codec
Definition oggdec.h:83
int64_t lastpts
Definition oggdec.h:78
int got_start
Definition oggdec.h:91
int segp
Definition oggdec.h:85
int64_t sync_pos
file offset of the first page needed to reconstruct the current packet
Definition oggdec.h:80
uint32_t serial
Definition oggdec.h:75
int flags
Definition oggdec.h:82
int got_data
1 if the stream got some data (non-initial packets), 0 otherwise
Definition oggdec.h:92
Definition oggdec.h:112
int64_t page_pos
file offset of the current page
Definition oggdec.h:117
int nstreams
Definition oggdec.h:114
struct ogg_stream * streams
Definition oggdec.h:113
int headers
Definition oggdec.h:115
int curidx
Definition oggdec.h:116
struct ogg_state * state
Definition oggdec.h:118
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static int64_t pts
int size
static AVStream * ost
static double c[64]