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 = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
308 if (!nb)
309 return AVERROR(ENOMEM);
310 os->buf = nb;
311 os->bufsize *= 2;
312 }
313
314 return 0;
315}
316
317static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
318{
319 AVIOContext *bc = s->pb;
320 struct ogg *ogg = s->priv_data;
321 struct ogg_stream *os;
322 int ret, i = 0;
323 int flags, nsegs;
324 uint64_t gp;
325 uint32_t serial;
326 uint32_t crc, crc_tmp;
327 int size = 0, idx;
329 int64_t start_pos;
330 uint8_t sync[4];
331 uint8_t segments[255];
332 uint8_t *readout_buf;
333 int sp = 0;
334
335 ret = avio_read(bc, sync, 4);
336 if (ret < 4)
337 return ret < 0 ? ret : AVERROR_EOF;
338
339 do {
340 int c;
341
342 if (sync[sp & 3] == 'O' &&
343 sync[(sp + 1) & 3] == 'g' &&
344 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
345 break;
346
347 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
348 memset(sync, 0, 4);
349 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
350 ogg->page_pos = -1;
351 }
352
353 c = avio_r8(bc);
354
355 if (avio_feof(bc))
356 return AVERROR_EOF;
357
358 sync[sp++ & 3] = c;
359 } while (i++ < MAX_PAGE_SIZE);
360
361 if (i >= MAX_PAGE_SIZE) {
362 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
363 return AVERROR_INVALIDDATA;
364 }
365
366 /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
368
369 /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
371 if (ret < 0)
372 return ret;
373 start_pos = avio_tell(bc);
374
375 version = avio_r8(bc);
376 flags = avio_r8(bc);
377 gp = avio_rl64(bc);
378 serial = avio_rl32(bc);
379 avio_rl32(bc); /* seq */
380
381 crc_tmp = ffio_get_checksum(bc);
382 crc = avio_rb32(bc);
383 crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
385
386 nsegs = avio_r8(bc);
387 page_pos = avio_tell(bc) - 27;
388
389 ret = avio_read(bc, segments, nsegs);
390 if (ret < nsegs)
391 return ret < 0 ? ret : AVERROR_EOF;
392
393 for (i = 0; i < nsegs; i++)
394 size += segments[i];
395
396 idx = ogg_find_stream(ogg, serial);
397 if (idx >= 0) {
398 os = ogg->streams + idx;
399
400 ret = buf_realloc(os, size);
401 if (ret < 0)
402 return ret;
403
404 readout_buf = os->buf + os->bufpos;
405 } else {
406 readout_buf = av_malloc(size);
407 }
408
409 ret = avio_read(bc, readout_buf, size);
410 if (ret < size) {
411 if (idx < 0)
412 av_free(readout_buf);
413 return ret < 0 ? ret : AVERROR_EOF;
414 }
415
416 if (crc ^ ffio_get_checksum(bc)) {
417 av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
418 if (idx < 0)
419 av_free(readout_buf);
420 avio_seek(bc, start_pos, SEEK_SET);
421 *sid = -1;
422 return 0;
423 }
424
425 /* Since we're almost sure its a valid packet, checking the version after
426 * the checksum lets the demuxer be more tolerant */
427 if (version) {
428 av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
429 if (idx < 0)
430 av_free(readout_buf);
431 avio_seek(bc, start_pos, SEEK_SET);
432 *sid = -1;
433 return 0;
434 }
435
436 /* CRC is correct so we can be 99% sure there's an actual change here */
437 if (idx < 0) {
439 idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
440 else
441 idx = ogg_new_stream(s, serial);
442
443 if (idx < 0) {
444 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
445 av_free(readout_buf);
446 return idx;
447 }
448
449 os = ogg->streams + idx;
450
451 ret = buf_realloc(os, size);
452 if (ret < 0) {
453 av_free(readout_buf);
454 return ret;
455 }
456
457 memcpy(os->buf + os->bufpos, readout_buf, size);
458 av_free(readout_buf);
459 }
460
462 os->page_pos = page_pos;
463 os->nsegs = nsegs;
464 os->segp = 0;
465 os->got_data = !(flags & OGG_FLAG_BOS);
466 os->bufpos += size;
467 os->granule = gp;
468 os->flags = flags;
469 memcpy(os->segments, segments, nsegs);
470 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
471
472 if (flags & OGG_FLAG_CONT || os->incomplete) {
473 if (!os->psize) {
474 // If this is the very first segment we started
475 // playback in the middle of a continuation packet.
476 // Discard it since we missed the start of it.
477 while (os->segp < os->nsegs) {
478 int seg = os->segments[os->segp++];
479 os->pstart += seg;
480 if (seg < 255)
481 break;
482 }
483 os->sync_pos = os->page_pos;
484 }
485 } else {
486 os->psize = 0;
487 os->sync_pos = os->page_pos;
488 }
489
490 /* This function is always called with sid != NULL */
491 *sid = idx;
492
493 return 0;
494}
495
496/**
497 * @brief find the next Ogg packet
498 * @param *sid is set to the stream for the packet or -1 if there is
499 * no matching stream, in that case assume all other return
500 * values to be uninitialized.
501 * @return negative value on error or EOF.
502 */
503static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
504 int64_t *fpos)
505{
506 FFFormatContext *const si = ffformatcontext(s);
507 struct ogg *ogg = s->priv_data;
508 int idx, i, ret;
509 struct ogg_stream *os;
510 int complete = 0;
511 int segp = 0, psize = 0;
512
513 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
514 if (sid)
515 *sid = -1;
516
517 do {
518 idx = ogg->curidx;
519
520 while (idx < 0) {
521 ret = ogg_read_page(s, &idx, 0);
522 if (ret < 0)
523 return ret;
524 }
525
526 os = ogg->streams + idx;
527
528 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
529 idx, os->pstart, os->psize, os->segp, os->nsegs);
530
531 if (!os->codec) {
532 if (os->header < 0) {
533 os->codec = ogg_find_codec(os->buf, os->bufpos);
534 if (!os->codec) {
535 av_log(s, AV_LOG_WARNING, "Codec not found\n");
536 os->header = 0;
537 return 0;
538 }
539 } else {
540 return 0;
541 }
542 }
543
544 segp = os->segp;
545 psize = os->psize;
546
547 while (os->segp < os->nsegs) {
548 int ss = os->segments[os->segp++];
549 os->psize += ss;
550 if (ss < 255) {
551 complete = 1;
552 break;
553 }
554 }
555
556 if (!complete && os->segp == os->nsegs) {
557 ogg->curidx = -1;
558 // Do not set incomplete for empty packets.
559 // Together with the code in ogg_read_page
560 // that discards all continuation of empty packets
561 // we would get an infinite loop.
562 os->incomplete = !!os->psize;
563 }
564 } while (!complete);
565
566
567 if (os->granule == -1)
569 "Page at %"PRId64" is missing granule\n",
570 os->page_pos);
571
572 ogg->curidx = idx;
573 os->incomplete = 0;
574
575 // the packet started at the first segment of the page it completes on
576 os->page_start = segp == 0;
577
578 if (os->header) {
579 if ((ret = os->codec->header(s, idx)) < 0) {
580 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
581 return ret;
582 }
583 os->header = ret;
584 if (!os->header) {
585 os->segp = segp;
586 os->psize = psize;
587
588 // We have reached the first non-header packet in this stream.
589 // Unfortunately more header packets may still follow for others,
590 // but if we continue with header parsing we may lose data packets.
591 ogg->headers = 1;
592
593 // Update the header state for all streams and
594 // compute the data_offset.
595 if (!si->data_offset)
596 si->data_offset = os->sync_pos;
597
598 for (i = 0; i < ogg->nstreams; i++) {
599 struct ogg_stream *cur_os = ogg->streams + i;
600
601 // if we have a partial non-header packet, its start is
602 // obviously at or after the data start
603 if (cur_os->incomplete)
604 si->data_offset = FFMIN(si->data_offset, cur_os->sync_pos);
605 }
606 } else {
607 os->nb_header++;
608 os->pstart += os->psize;
609 os->psize = 0;
610 }
611 } else {
612 os->pflags = 0;
613 os->pduration = 0;
614
615 ret = 0;
616 if (os->codec && os->codec->packet) {
617 if ((ret = os->codec->packet(s, idx)) < 0) {
618 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
619 return ret;
620 }
621 }
622
623 if (!ret) {
624 if (sid)
625 *sid = idx;
626 if (dstart)
627 *dstart = os->pstart;
628 if (dsize)
629 *dsize = os->psize;
630 if (fpos)
631 *fpos = os->sync_pos;
632 }
633
634 os->pstart += os->psize;
635 os->psize = 0;
636 if(os->pstart == os->bufpos)
637 os->bufpos = os->pstart = 0;
638 os->sync_pos = os->page_pos;
639 }
640
641 // determine whether there are more complete packets in this page
642 // if not, the page's granule will apply to this packet
643 os->page_end = 1;
644 for (i = os->segp; i < os->nsegs; i++)
645 if (os->segments[i] < 255) {
646 os->page_end = 0;
647 break;
648 }
649
650 if (os->segp == os->nsegs)
651 ogg->curidx = -1;
652
653 return 0;
654}
655
657{
658 struct ogg *ogg = s->priv_data;
659 int i, ret;
660 int64_t size, end;
661 int streams_left=0;
662
663 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
664 return 0;
665
666// already set
667 if (s->duration != AV_NOPTS_VALUE)
668 return 0;
669
670 size = avio_size(s->pb);
671 if (size < 0)
672 return 0;
673 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
674
675 ret = ogg_save(s);
676 if (ret < 0)
677 return ret;
678 avio_seek(s->pb, end, SEEK_SET);
679 ogg->page_pos = -1;
680
681 while (!ogg_read_page(s, &i, 1)) {
682 if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
683 ogg->streams[i].codec) {
684 s->streams[i]->duration =
686 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
687 s->streams[i]->duration -= s->streams[i]->start_time;
688 streams_left-= (ogg->streams[i].got_start==-1);
689 ogg->streams[i].got_start= 1;
690 } else if(!ogg->streams[i].got_start) {
691 ogg->streams[i].got_start= -1;
692 streams_left++;
693 }
694 }
695 }
696
697 ogg_restore(s);
698
699 ret = ogg_save(s);
700 if (ret < 0)
701 return ret;
702
703 avio_seek (s->pb, ffformatcontext(s)->data_offset, SEEK_SET);
704 ogg_reset(s);
705 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
706 int64_t pts;
707 if (i < 0) continue;
708 pts = ogg_calc_pts(s, i, NULL);
709 if (s->streams[i]->duration == AV_NOPTS_VALUE)
710 continue;
711 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
712 s->streams[i]->duration -= pts;
713 ogg->streams[i].got_start= 1;
714 streams_left--;
715 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
716 ogg->streams[i].got_start= 1;
717 streams_left--;
718 }
719 }
720 ogg_restore (s);
721
722 return 0;
723}
724
726{
727 struct ogg *ogg = s->priv_data;
728 int i;
729
730 for (i = 0; i < ogg->nstreams; i++) {
731 free_stream(s, i);
732 }
733
734 ogg->nstreams = 0;
735
737 return 0;
738}
739
741{
742 struct ogg *ogg = s->priv_data;
743 int ret, i;
744
745 ogg->curidx = -1;
746
747 //linear headers seek from start
748 do {
749 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
750 if (ret < 0)
751 return ret;
752 } while (!ogg->headers);
753 av_log(s, AV_LOG_TRACE, "found headers\n");
754
755 for (i = 0; i < ogg->nstreams; i++) {
756 struct ogg_stream *os = ogg->streams + i;
757
758 if (ogg->streams[i].header < 0) {
759 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
760 ogg->streams[i].codec = NULL;
762 } else if (os->codec && os->nb_header < os->codec->nb_header) {
764 "Headers mismatch for stream %d: "
765 "expected %d received %d.\n",
766 i, os->codec->nb_header, os->nb_header);
767 if (s->error_recognition & AV_EF_EXPLODE)
768 return AVERROR_INVALIDDATA;
769 }
771 os->lastpts = s->streams[i]->start_time =
773 }
774
775 //linear granulepos seek from end
776 ret = ogg_get_length(s);
777 if (ret < 0)
778 return ret;
779
780 return 0;
781}
782
784{
785 struct ogg *ogg = s->priv_data;
786 struct ogg_stream *os = ogg->streams + idx;
788
789 if (dts)
790 *dts = AV_NOPTS_VALUE;
791
792 if (os->lastpts != AV_NOPTS_VALUE) {
793 pts = os->lastpts;
795 }
796 if (os->lastdts != AV_NOPTS_VALUE) {
797 if (dts)
798 *dts = os->lastdts;
800 }
801 if (os->page_end) {
802 if (os->granule != -1LL) {
803 if (os->codec && os->codec->granule_is_start)
804 pts = ogg_gptopts(s, idx, os->granule, dts);
805 else
806 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
807 os->granule = -1LL;
808 }
809 }
810 return pts;
811}
812
813static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
814{
815 struct ogg *ogg = s->priv_data;
816 struct ogg_stream *os = ogg->streams + idx;
817 int invalid = 0;
818 if (psize) {
819 switch (s->streams[idx]->codecpar->codec_id) {
821 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
822 break;
823 case AV_CODEC_ID_VP8:
824 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
825 }
826 if (invalid) {
827 os->pflags ^= AV_PKT_FLAG_KEY;
828 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
829 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
830 }
831 }
832}
833
835{
836 struct ogg *ogg;
837 struct ogg_stream *os;
838 int idx, ret;
839 int pstart, psize;
840 int64_t fpos, pts, dts;
841
842 if (s->io_repositioned) {
843 ogg_reset(s);
844 s->io_repositioned = 0;
845 }
846
847 //Get an ogg packet
848retry:
849 do {
850 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
851 if (ret < 0)
852 return ret;
853 } while (idx < 0 || !s->streams[idx]);
854
855 ogg = s->priv_data;
856 os = ogg->streams + idx;
857
858 // pflags might not be set until after this
859 pts = ogg_calc_pts(s, idx, &dts);
861
862 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
863 goto retry;
864 os->keyframe_seek = 0;
865
866 //Alloc a pkt
867 ret = av_new_packet(pkt, psize);
868 if (ret < 0)
869 return ret;
870 pkt->stream_index = idx;
871 memcpy(pkt->data, os->buf + pstart, psize);
872
873 pkt->pts = pts;
874 pkt->dts = dts;
875 pkt->flags = os->pflags;
876 pkt->duration = os->pduration;
877 pkt->pos = fpos;
878
879 if (os->start_trimming || os->end_trimming) {
880 uint8_t *side_data = av_packet_new_side_data(pkt,
882 10);
883 if(!side_data)
884 return AVERROR(ENOMEM);
885 AV_WL32(side_data + 0, os->start_trimming);
886 AV_WL32(side_data + 4, os->end_trimming);
887 os->start_trimming = 0;
888 os->end_trimming = 0;
889 }
890
891 if (os->replace) {
892 os->replace = 0;
893 pkt->dts = pkt->pts = AV_NOPTS_VALUE;
894 }
895
896 if (os->new_metadata) {
899 if (ret < 0)
900 return ret;
901
902 os->new_metadata = NULL;
903 os->new_metadata_size = 0;
904 }
905
906 if (os->new_extradata) {
909 if (ret < 0)
910 return ret;
911
912 os->new_extradata = NULL;
913 os->new_extradata_size = 0;
914 }
915
916 return psize;
917}
918
919static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
920 int64_t *pos_arg, int64_t pos_limit)
921{
922 struct ogg *ogg = s->priv_data;
923 AVIOContext *bc = s->pb;
925 int64_t keypos = -1;
926 int i;
927 int pstart, psize;
928 avio_seek(bc, *pos_arg, SEEK_SET);
929 ogg_reset(s);
930
931 while ( avio_tell(bc) <= pos_limit
932 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
933 if (i == stream_index) {
934 struct ogg_stream *os = ogg->streams + stream_index;
935 // Do not trust the last timestamps of an ogm video
936 if ( (os->flags & OGG_FLAG_EOS)
937 && !(os->flags & OGG_FLAG_BOS)
938 && os->codec == &ff_ogm_video_codec)
939 continue;
940 pts = ogg_calc_pts(s, i, NULL);
942 if (os->pflags & AV_PKT_FLAG_KEY) {
943 keypos = *pos_arg;
944 } else if (os->keyframe_seek) {
945 // if we had a previous keyframe but no pts for it,
946 // return that keyframe with this pts value.
947 if (keypos >= 0)
948 *pos_arg = keypos;
949 else
951 }
952 }
953 if (pts != AV_NOPTS_VALUE)
954 break;
955 }
956 ogg_reset(s);
957 return pts;
958}
959
960static int ogg_read_seek(AVFormatContext *s, int stream_index,
961 int64_t timestamp, int flags)
962{
963 struct ogg *ogg = s->priv_data;
964 struct ogg_stream *os = ogg->streams + stream_index;
965 int ret;
966
967 av_assert0(stream_index < ogg->nstreams);
968 // Ensure everything is reset even when seeking via
969 // the generated index.
970 ogg_reset(s);
971
972 // Try seeking to a keyframe first. If this fails (very possible),
973 // av_seek_frame will fall back to ignoring keyframes
974 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
975 && !(flags & AVSEEK_FLAG_ANY))
976 os->keyframe_seek = 1;
977
978 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
979 ogg_reset(s);
980 os = ogg->streams + stream_index;
981 if (ret < 0)
982 os->keyframe_seek = 0;
983 return ret;
984}
985
986static int ogg_probe(const AVProbeData *p)
987{
988 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
989 return AVPROBE_SCORE_MAX;
990 return 0;
991}
992
994 .p.name = "ogg",
995 .p.long_name = NULL_IF_CONFIG_SMALL("Ogg"),
996 .p.extensions = "ogg",
998 .priv_data_size = sizeof(struct ogg),
999 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
1000 .read_probe = ogg_probe,
1001 .read_header = ogg_read_header,
1002 .read_packet = ogg_read_packet,
1003 .read_close = ogg_read_close,
1004 .read_seek = ogg_read_seek,
1005 .read_timestamp = ogg_read_timestamp,
1006};
const FFInputFormat ff_ogg_demuxer
Definition oggdec.c:993
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:656
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:986
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:740
static int ogg_restore(AVFormatContext *s)
Definition oggdec.c:121
static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition oggdec.c:834
static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, int64_t *fpos)
find the next Ogg packet
Definition oggdec.c:503
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:919
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
Definition oggdec.c:783
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:725
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition oggdec.c:960
static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
Definition oggdec.c:317
static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
Definition oggdec.c:813
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]