2 * Ogg bitstream support
3 * Luca Barbato <lu_zero@gentoo.org>
4 * Based on tcvp implementation
8 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
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:
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
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.
32 #include "libavutil/avassert.h"
33 #include "libavutil/intreadwrite.h"
37 #include "vorbiscomment.h"
39 #define MAX_PAGE_SIZE 65307
40 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
42 static const struct ogg_codec * const ogg_codecs[] = {
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);
66 static void free_stream(AVFormatContext *s, int i)
68 struct ogg *ogg = s->priv_data;
69 struct ogg_stream *stream = &ogg->streams[i];
71 av_freep(&stream->buf);
73 stream->codec->cleanup) {
74 stream->codec->cleanup(s, i);
77 av_freep(&stream->private);
78 av_freep(&stream->new_metadata);
81 //FIXME We could avoid some structure duplication
82 static int ogg_save(AVFormatContext *s)
84 struct ogg *ogg = s->priv_data;
85 struct ogg_state *ost =
86 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
91 return AVERROR(ENOMEM);
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));
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);
103 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
105 ret = AVERROR(ENOMEM);
106 os->new_metadata = NULL;
107 os->new_metadata_size = 0;
118 static int ogg_restore(AVFormatContext *s)
120 struct ogg *ogg = s->priv_data;
121 AVIOContext *bc = s->pb;
122 struct ogg_state *ost = ogg->state;
128 ogg->state = ost->next;
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);
135 if (i >= ost->nstreams || !ost->streams[i].private) {
140 avio_seek(bc, ost->pos, SEEK_SET);
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) {
149 memcpy(ogg->streams, ost->streams,
150 ost->nstreams * sizeof(*ogg->streams));
157 static int ogg_reset(AVFormatContext *s)
159 struct ogg *ogg = s->priv_data;
161 int64_t start_pos = avio_tell(s->pb);
163 for (i = 0; i < ogg->nstreams; i++) {
164 struct ogg_stream *os = ogg->streams + i;
169 os->lastpts = AV_NOPTS_VALUE;
170 os->lastdts = AV_NOPTS_VALUE;
177 if (start_pos <= s->internal->data_offset) {
180 os->end_trimming = 0;
181 av_freep(&os->new_metadata);
182 os->new_metadata_size = 0;
191 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
195 for (i = 0; ogg_codecs[i]; i++)
196 if (size >= ogg_codecs[i]->magicsize &&
197 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
198 return ogg_codecs[i];
204 * Replace the current stream with a new one. This is a typical webradio
205 * situation where a new audio stream spawn (identified with a new serial) and
206 * must replace the previous one (track switch).
208 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
210 struct ogg *ogg = s->priv_data;
211 struct ogg_stream *os;
212 const struct ogg_codec *codec;
215 if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
217 int64_t pos = avio_tell(s->pb);
218 avio_skip(s->pb, nsegs);
219 if (avio_read(s->pb, magic, sizeof(magic)) != sizeof(magic))
220 return AVERROR_INVALIDDATA;
221 avio_seek(s->pb, pos, SEEK_SET);
222 codec = ogg_find_codec(magic, sizeof(magic));
224 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
225 return AVERROR_INVALIDDATA;
227 for (i = 0; i < ogg->nstreams; i++) {
228 if (ogg->streams[i].codec == codec)
231 if (i >= ogg->nstreams)
232 return ogg_new_stream(s, serial);
233 } else if (ogg->nstreams != 1) {
234 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
235 return AVERROR_PATCHWELCOME;
238 os = &ogg->streams[i];
245 bufsize = os->bufsize;
248 if (!ogg->state || ogg->state->streams[i].private != os->private)
249 av_freep(&ogg->streams[i].private);
251 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
252 * also re-use the ogg_stream allocated buffer */
253 memset(os, 0, sizeof(*os));
255 os->bufsize = bufsize;
264 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
266 struct ogg *ogg = s->priv_data;
267 int idx = ogg->nstreams;
269 struct ogg_stream *os;
273 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
274 "in between Ogg context save/restore operations.\n");
278 /* Allocate and init a new Ogg Stream */
279 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
280 !(os = av_realloc(ogg->streams, size)))
281 return AVERROR(ENOMEM);
283 os = ogg->streams + idx;
284 memset(os, 0, sizeof(*os));
286 os->bufsize = DECODER_BUFFER_SIZE;
287 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
289 os->start_granule = OGG_NOGRANULE_VALUE;
291 return AVERROR(ENOMEM);
293 /* Create the associated AVStream */
294 st = avformat_new_stream(s, NULL);
297 return AVERROR(ENOMEM);
300 avpriv_set_pts_info(st, 64, 1, 1000000);
306 static int ogg_new_buf(struct ogg *ogg, int idx)
308 struct ogg_stream *os = ogg->streams + idx;
309 uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
310 int size = os->bufpos - os->pstart;
313 return AVERROR(ENOMEM);
316 memcpy(nb, os->buf + os->pstart, size);
327 static int data_packets_seen(const struct ogg *ogg)
331 for (i = 0; i < ogg->nstreams; i++)
332 if (ogg->streams[i].got_data)
337 static int ogg_read_page(AVFormatContext *s, int *sid)
339 AVIOContext *bc = s->pb;
340 struct ogg *ogg = s->priv_data;
341 struct ogg_stream *os;
350 ret = avio_read(bc, sync, 4);
352 return ret < 0 ? ret : AVERROR_EOF;
357 if (sync[sp & 3] == 'O' &&
358 sync[(sp + 1) & 3] == 'g' &&
359 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
362 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
364 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
374 } while (i++ < MAX_PAGE_SIZE);
376 if (i >= MAX_PAGE_SIZE) {
377 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
378 return AVERROR_INVALIDDATA;
381 if (avio_r8(bc) != 0) { /* version */
382 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
383 return AVERROR_INVALIDDATA;
388 serial = avio_rl32(bc);
389 avio_skip(bc, 8); /* seq, crc */
392 idx = ogg_find_stream(ogg, serial);
394 if (data_packets_seen(ogg))
395 idx = ogg_replace_stream(s, serial, nsegs);
397 idx = ogg_new_stream(s, serial);
400 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
405 os = ogg->streams + idx;
407 os->page_pos = avio_tell(bc) - 27;
410 ret = ogg_new_buf(ogg, idx);
415 ret = avio_read(bc, os->segments, nsegs);
417 return ret < 0 ? ret : AVERROR_EOF;
423 for (i = 0; i < nsegs; i++)
424 size += os->segments[i];
426 if (!(flags & OGG_FLAG_BOS))
429 if (flags & OGG_FLAG_CONT || os->incomplete) {
431 // If this is the very first segment we started
432 // playback in the middle of a continuation packet.
433 // Discard it since we missed the start of it.
434 while (os->segp < os->nsegs) {
435 int seg = os->segments[os->segp++];
440 os->sync_pos = os->page_pos;
444 os->sync_pos = os->page_pos;
447 if (os->bufsize - os->bufpos < size) {
448 uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
450 return AVERROR(ENOMEM);
451 memcpy(nb, os->buf, os->bufpos);
456 ret = avio_read(bc, os->buf + os->bufpos, size);
458 return ret < 0 ? ret : AVERROR_EOF;
464 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
472 * @brief find the next Ogg packet
473 * @param *sid is set to the stream for the packet or -1 if there is
474 * no matching stream, in that case assume all other return
475 * values to be uninitialized.
476 * @return negative value on error or EOF.
478 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
481 struct ogg *ogg = s->priv_data;
483 struct ogg_stream *os;
485 int segp = 0, psize = 0;
487 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
495 ret = ogg_read_page(s, &idx);
500 os = ogg->streams + idx;
502 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
503 idx, os->pstart, os->psize, os->segp, os->nsegs);
506 if (os->header < 0) {
507 os->codec = ogg_find_codec(os->buf, os->bufpos);
509 av_log(s, AV_LOG_WARNING, "Codec not found\n");
521 while (os->segp < os->nsegs) {
522 int ss = os->segments[os->segp++];
530 if (!complete && os->segp == os->nsegs) {
532 // Do not set incomplete for empty packets.
533 // Together with the code in ogg_read_page
534 // that discards all continuation of empty packets
535 // we would get an infinite loop.
536 os->incomplete = !!os->psize;
541 if (os->granule == -1)
542 av_log(s, AV_LOG_WARNING,
543 "Page at %"PRId64" is missing granule\n",
550 if ((ret = os->codec->header(s, idx)) < 0) {
551 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
559 // We have reached the first non-header packet in this stream.
560 // Unfortunately more header packets may still follow for others,
561 // but if we continue with header parsing we may lose data packets.
564 // Update the header state for all streams and
565 // compute the data_offset.
566 if (!s->internal->data_offset)
567 s->internal->data_offset = os->sync_pos;
569 for (i = 0; i < ogg->nstreams; i++) {
570 struct ogg_stream *cur_os = ogg->streams + i;
572 // if we have a partial non-header packet, its start is
573 // obviously at or after the data start
574 if (cur_os->incomplete)
575 s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
579 os->pstart += os->psize;
585 if (os->codec && os->codec->packet) {
586 if ((ret = os->codec->packet(s, idx)) < 0) {
587 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
594 *dstart = os->pstart;
598 *fpos = os->sync_pos;
599 os->pstart += os->psize;
601 if(os->pstart == os->bufpos)
602 os->bufpos = os->pstart = 0;
603 os->sync_pos = os->page_pos;
606 // determine whether there are more complete packets in this page
607 // if not, the page's granule will apply to this packet
609 for (i = os->segp; i < os->nsegs; i++)
610 if (os->segments[i] < 255) {
615 if (os->segp == os->nsegs)
621 static int ogg_get_length(AVFormatContext *s)
623 struct ogg *ogg = s->priv_data;
628 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
632 if (s->duration != AV_NOPTS_VALUE)
635 size = avio_size(s->pb);
638 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
643 avio_seek(s->pb, end, SEEK_SET);
646 while (!ogg_read_page(s, &i)) {
647 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
648 ogg->streams[i].codec) {
649 s->streams[i]->duration =
650 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
651 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
652 s->streams[i]->duration -= s->streams[i]->start_time;
653 streams_left-= (ogg->streams[i].got_start==-1);
654 ogg->streams[i].got_start= 1;
655 } else if(!ogg->streams[i].got_start) {
656 ogg->streams[i].got_start= -1;
668 avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
670 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
673 pts = ogg_calc_pts(s, i, NULL);
674 if (s->streams[i]->duration == AV_NOPTS_VALUE)
676 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
677 s->streams[i]->duration -= pts;
678 ogg->streams[i].got_start= 1;
680 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
681 ogg->streams[i].got_start= 1;
690 static int ogg_read_close(AVFormatContext *s)
692 struct ogg *ogg = s->priv_data;
695 for (i = 0; i < ogg->nstreams; i++) {
701 av_freep(&ogg->streams);
705 static int ogg_read_header(AVFormatContext *s)
707 struct ogg *ogg = s->priv_data;
712 //linear headers seek from start
714 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
719 } while (!ogg->headers);
720 av_log(s, AV_LOG_TRACE, "found headers\n");
722 for (i = 0; i < ogg->nstreams; i++) {
723 struct ogg_stream *os = ogg->streams + i;
725 if (ogg->streams[i].header < 0) {
726 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
727 ogg->streams[i].codec = NULL;
728 av_freep(&ogg->streams[i].private);
729 } else if (os->codec && os->nb_header < os->codec->nb_header) {
730 av_log(s, AV_LOG_WARNING,
731 "Headers mismatch for stream %d: "
732 "expected %d received %d.\n",
733 i, os->codec->nb_header, os->nb_header);
734 if (s->error_recognition & AV_EF_EXPLODE) {
736 return AVERROR_INVALIDDATA;
739 if (os->start_granule != OGG_NOGRANULE_VALUE)
740 os->lastpts = s->streams[i]->start_time =
741 ogg_gptopts(s, i, os->start_granule, NULL);
744 //linear granulepos seek from end
745 ret = ogg_get_length(s);
754 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
756 struct ogg *ogg = s->priv_data;
757 struct ogg_stream *os = ogg->streams + idx;
758 int64_t pts = AV_NOPTS_VALUE;
761 *dts = AV_NOPTS_VALUE;
763 if (os->lastpts != AV_NOPTS_VALUE) {
765 os->lastpts = AV_NOPTS_VALUE;
767 if (os->lastdts != AV_NOPTS_VALUE) {
770 os->lastdts = AV_NOPTS_VALUE;
773 if (os->granule != -1LL) {
774 if (os->codec && os->codec->granule_is_start)
775 pts = ogg_gptopts(s, idx, os->granule, dts);
777 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
784 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
786 struct ogg *ogg = s->priv_data;
787 struct ogg_stream *os = ogg->streams + idx;
790 switch (s->streams[idx]->codecpar->codec_id) {
791 case AV_CODEC_ID_THEORA:
792 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
794 case AV_CODEC_ID_VP8:
795 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
798 os->pflags ^= AV_PKT_FLAG_KEY;
799 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
800 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
805 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
808 struct ogg_stream *os;
811 int64_t fpos, pts, dts;
813 if (s->io_repositioned) {
815 s->io_repositioned = 0;
821 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
824 } while (idx < 0 || !s->streams[idx]);
827 os = ogg->streams + idx;
829 // pflags might not be set until after this
830 pts = ogg_calc_pts(s, idx, &dts);
831 ogg_validate_keyframe(s, idx, pstart, psize);
833 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
835 os->keyframe_seek = 0;
838 ret = av_new_packet(pkt, psize);
841 pkt->stream_index = idx;
842 memcpy(pkt->data, os->buf + pstart, psize);
846 pkt->flags = os->pflags;
847 pkt->duration = os->pduration;
850 if (os->end_trimming) {
851 uint8_t *side_data = av_packet_new_side_data(pkt,
852 AV_PKT_DATA_SKIP_SAMPLES,
855 return AVERROR(ENOMEM);
856 AV_WL32(side_data + 4, os->end_trimming);
857 os->end_trimming = 0;
860 if (os->new_metadata) {
861 uint8_t *side_data = av_packet_new_side_data(pkt,
862 AV_PKT_DATA_METADATA_UPDATE,
863 os->new_metadata_size);
865 return AVERROR(ENOMEM);
867 memcpy(side_data, os->new_metadata, os->new_metadata_size);
868 av_freep(&os->new_metadata);
869 os->new_metadata_size = 0;
875 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
876 int64_t *pos_arg, int64_t pos_limit)
878 struct ogg *ogg = s->priv_data;
879 AVIOContext *bc = s->pb;
880 int64_t pts = AV_NOPTS_VALUE;
884 avio_seek(bc, *pos_arg, SEEK_SET);
887 while ( avio_tell(bc) <= pos_limit
888 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
889 if (i == stream_index) {
890 struct ogg_stream *os = ogg->streams + stream_index;
891 // Do not trust the last timestamps of an ogm video
892 if ( (os->flags & OGG_FLAG_EOS)
893 && !(os->flags & OGG_FLAG_BOS)
894 && os->codec == &ff_ogm_video_codec)
896 pts = ogg_calc_pts(s, i, NULL);
897 ogg_validate_keyframe(s, i, pstart, psize);
898 if (os->pflags & AV_PKT_FLAG_KEY) {
900 } else if (os->keyframe_seek) {
901 // if we had a previous keyframe but no pts for it,
902 // return that keyframe with this pts value.
906 pts = AV_NOPTS_VALUE;
909 if (pts != AV_NOPTS_VALUE)
916 static int ogg_read_seek(AVFormatContext *s, int stream_index,
917 int64_t timestamp, int flags)
919 struct ogg *ogg = s->priv_data;
920 struct ogg_stream *os = ogg->streams + stream_index;
923 av_assert0(stream_index < ogg->nstreams);
924 // Ensure everything is reset even when seeking via
925 // the generated index.
928 // Try seeking to a keyframe first. If this fails (very possible),
929 // av_seek_frame will fall back to ignoring keyframes
930 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
931 && !(flags & AVSEEK_FLAG_ANY))
932 os->keyframe_seek = 1;
934 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
936 os = ogg->streams + stream_index;
938 os->keyframe_seek = 0;
942 static int ogg_probe(const AVProbeData *p)
944 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
945 return AVPROBE_SCORE_MAX;
949 AVInputFormat ff_ogg_demuxer = {
951 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
952 .priv_data_size = sizeof(struct ogg),
953 .read_probe = ogg_probe,
954 .read_header = ogg_read_header,
955 .read_packet = ogg_read_packet,
956 .read_close = ogg_read_close,
957 .read_seek = ogg_read_seek,
958 .read_timestamp = ogg_read_timestamp,
960 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,