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 avio_read(s->pb, magic, sizeof(magic));
220 avio_seek(s->pb, pos, SEEK_SET);
221 codec = ogg_find_codec(magic, sizeof(magic));
223 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
224 return AVERROR_INVALIDDATA;
226 for (i = 0; i < ogg->nstreams; i++) {
227 if (ogg->streams[i].codec == codec)
230 if (i >= ogg->nstreams)
231 return ogg_new_stream(s, serial);
232 } else if (ogg->nstreams != 1) {
233 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
234 return AVERROR_PATCHWELCOME;
237 os = &ogg->streams[i];
244 bufsize = os->bufsize;
247 if (!ogg->state || ogg->state->streams[i].private != os->private)
248 av_freep(&ogg->streams[i].private);
250 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
251 * also re-use the ogg_stream allocated buffer */
252 memset(os, 0, sizeof(*os));
254 os->bufsize = bufsize;
263 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
265 struct ogg *ogg = s->priv_data;
266 int idx = ogg->nstreams;
268 struct ogg_stream *os;
272 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
273 "in between Ogg context save/restore operations.\n");
277 /* Allocate and init a new Ogg Stream */
278 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
279 !(os = av_realloc(ogg->streams, size)))
280 return AVERROR(ENOMEM);
282 os = ogg->streams + idx;
283 memset(os, 0, sizeof(*os));
285 os->bufsize = DECODER_BUFFER_SIZE;
286 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
288 os->start_granule = OGG_NOGRANULE_VALUE;
290 return AVERROR(ENOMEM);
292 /* Create the associated AVStream */
293 st = avformat_new_stream(s, NULL);
296 return AVERROR(ENOMEM);
299 avpriv_set_pts_info(st, 64, 1, 1000000);
305 static int ogg_new_buf(struct ogg *ogg, int idx)
307 struct ogg_stream *os = ogg->streams + idx;
308 uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
309 int size = os->bufpos - os->pstart;
312 return AVERROR(ENOMEM);
315 memcpy(nb, os->buf + os->pstart, size);
326 static int data_packets_seen(const struct ogg *ogg)
330 for (i = 0; i < ogg->nstreams; i++)
331 if (ogg->streams[i].got_data)
336 static int ogg_read_page(AVFormatContext *s, int *sid)
338 AVIOContext *bc = s->pb;
339 struct ogg *ogg = s->priv_data;
340 struct ogg_stream *os;
349 ret = avio_read(bc, sync, 4);
351 return ret < 0 ? ret : AVERROR_EOF;
356 if (sync[sp & 3] == 'O' &&
357 sync[(sp + 1) & 3] == 'g' &&
358 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
361 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
363 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
373 } while (i++ < MAX_PAGE_SIZE);
375 if (i >= MAX_PAGE_SIZE) {
376 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
377 return AVERROR_INVALIDDATA;
380 if (avio_r8(bc) != 0) { /* version */
381 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
382 return AVERROR_INVALIDDATA;
387 serial = avio_rl32(bc);
388 avio_skip(bc, 8); /* seq, crc */
391 idx = ogg_find_stream(ogg, serial);
393 if (data_packets_seen(ogg))
394 idx = ogg_replace_stream(s, serial, nsegs);
396 idx = ogg_new_stream(s, serial);
399 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
404 os = ogg->streams + idx;
406 os->page_pos = avio_tell(bc) - 27;
409 ret = ogg_new_buf(ogg, idx);
414 ret = avio_read(bc, os->segments, nsegs);
416 return ret < 0 ? ret : AVERROR_EOF;
422 for (i = 0; i < nsegs; i++)
423 size += os->segments[i];
425 if (!(flags & OGG_FLAG_BOS))
428 if (flags & OGG_FLAG_CONT || os->incomplete) {
430 // If this is the very first segment we started
431 // playback in the middle of a continuation packet.
432 // Discard it since we missed the start of it.
433 while (os->segp < os->nsegs) {
434 int seg = os->segments[os->segp++];
439 os->sync_pos = os->page_pos;
443 os->sync_pos = os->page_pos;
446 if (os->bufsize - os->bufpos < size) {
447 uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
449 return AVERROR(ENOMEM);
450 memcpy(nb, os->buf, os->bufpos);
455 ret = avio_read(bc, os->buf + os->bufpos, size);
457 return ret < 0 ? ret : AVERROR_EOF;
463 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
471 * @brief find the next Ogg packet
472 * @param *sid is set to the stream for the packet or -1 if there is
473 * no matching stream, in that case assume all other return
474 * values to be uninitialized.
475 * @return negative value on error or EOF.
477 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
480 struct ogg *ogg = s->priv_data;
482 struct ogg_stream *os;
484 int segp = 0, psize = 0;
486 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
494 ret = ogg_read_page(s, &idx);
499 os = ogg->streams + idx;
501 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
502 idx, os->pstart, os->psize, os->segp, os->nsegs);
505 if (os->header < 0) {
506 os->codec = ogg_find_codec(os->buf, os->bufpos);
508 av_log(s, AV_LOG_WARNING, "Codec not found\n");
520 while (os->segp < os->nsegs) {
521 int ss = os->segments[os->segp++];
529 if (!complete && os->segp == os->nsegs) {
531 // Do not set incomplete for empty packets.
532 // Together with the code in ogg_read_page
533 // that discards all continuation of empty packets
534 // we would get an infinite loop.
535 os->incomplete = !!os->psize;
540 if (os->granule == -1)
541 av_log(s, AV_LOG_WARNING,
542 "Page at %"PRId64" is missing granule\n",
549 if ((ret = os->codec->header(s, idx)) < 0) {
550 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
558 // We have reached the first non-header packet in this stream.
559 // Unfortunately more header packets may still follow for others,
560 // but if we continue with header parsing we may lose data packets.
563 // Update the header state for all streams and
564 // compute the data_offset.
565 if (!s->internal->data_offset)
566 s->internal->data_offset = os->sync_pos;
568 for (i = 0; i < ogg->nstreams; i++) {
569 struct ogg_stream *cur_os = ogg->streams + i;
571 // if we have a partial non-header packet, its start is
572 // obviously at or after the data start
573 if (cur_os->incomplete)
574 s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
578 os->pstart += os->psize;
584 if (os->codec && os->codec->packet) {
585 if ((ret = os->codec->packet(s, idx)) < 0) {
586 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
593 *dstart = os->pstart;
597 *fpos = os->sync_pos;
598 os->pstart += os->psize;
600 if(os->pstart == os->bufpos)
601 os->bufpos = os->pstart = 0;
602 os->sync_pos = os->page_pos;
605 // determine whether there are more complete packets in this page
606 // if not, the page's granule will apply to this packet
608 for (i = os->segp; i < os->nsegs; i++)
609 if (os->segments[i] < 255) {
614 if (os->segp == os->nsegs)
620 static int ogg_get_length(AVFormatContext *s)
622 struct ogg *ogg = s->priv_data;
627 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
631 if (s->duration != AV_NOPTS_VALUE)
634 size = avio_size(s->pb);
637 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
642 avio_seek(s->pb, end, SEEK_SET);
645 while (!ogg_read_page(s, &i)) {
646 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
647 ogg->streams[i].codec) {
648 s->streams[i]->duration =
649 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
650 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
651 s->streams[i]->duration -= s->streams[i]->start_time;
652 streams_left-= (ogg->streams[i].got_start==-1);
653 ogg->streams[i].got_start= 1;
654 } else if(!ogg->streams[i].got_start) {
655 ogg->streams[i].got_start= -1;
667 avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
669 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
672 pts = ogg_calc_pts(s, i, NULL);
673 if (s->streams[i]->duration == AV_NOPTS_VALUE)
675 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
676 s->streams[i]->duration -= pts;
677 ogg->streams[i].got_start= 1;
679 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
680 ogg->streams[i].got_start= 1;
689 static int ogg_read_close(AVFormatContext *s)
691 struct ogg *ogg = s->priv_data;
694 for (i = 0; i < ogg->nstreams; i++) {
700 av_freep(&ogg->streams);
704 static int ogg_read_header(AVFormatContext *s)
706 struct ogg *ogg = s->priv_data;
711 //linear headers seek from start
713 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
718 } while (!ogg->headers);
719 av_log(s, AV_LOG_TRACE, "found headers\n");
721 for (i = 0; i < ogg->nstreams; i++) {
722 struct ogg_stream *os = ogg->streams + i;
724 if (ogg->streams[i].header < 0) {
725 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
726 ogg->streams[i].codec = NULL;
727 av_freep(&ogg->streams[i].private);
728 } else if (os->codec && os->nb_header < os->codec->nb_header) {
729 av_log(s, AV_LOG_WARNING,
730 "Headers mismatch for stream %d: "
731 "expected %d received %d.\n",
732 i, os->codec->nb_header, os->nb_header);
733 if (s->error_recognition & AV_EF_EXPLODE) {
735 return AVERROR_INVALIDDATA;
738 if (os->start_granule != OGG_NOGRANULE_VALUE)
739 os->lastpts = s->streams[i]->start_time =
740 ogg_gptopts(s, i, os->start_granule, NULL);
743 //linear granulepos seek from end
744 ret = ogg_get_length(s);
753 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
755 struct ogg *ogg = s->priv_data;
756 struct ogg_stream *os = ogg->streams + idx;
757 int64_t pts = AV_NOPTS_VALUE;
760 *dts = AV_NOPTS_VALUE;
762 if (os->lastpts != AV_NOPTS_VALUE) {
764 os->lastpts = AV_NOPTS_VALUE;
766 if (os->lastdts != AV_NOPTS_VALUE) {
769 os->lastdts = AV_NOPTS_VALUE;
772 if (os->granule != -1LL) {
773 if (os->codec && os->codec->granule_is_start)
774 pts = ogg_gptopts(s, idx, os->granule, dts);
776 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
783 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
785 struct ogg *ogg = s->priv_data;
786 struct ogg_stream *os = ogg->streams + idx;
789 switch (s->streams[idx]->codecpar->codec_id) {
790 case AV_CODEC_ID_THEORA:
791 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
793 case AV_CODEC_ID_VP8:
794 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
797 os->pflags ^= AV_PKT_FLAG_KEY;
798 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
799 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
804 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
807 struct ogg_stream *os;
810 int64_t fpos, pts, dts;
812 if (s->io_repositioned) {
814 s->io_repositioned = 0;
820 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
823 } while (idx < 0 || !s->streams[idx]);
826 os = ogg->streams + idx;
828 // pflags might not be set until after this
829 pts = ogg_calc_pts(s, idx, &dts);
830 ogg_validate_keyframe(s, idx, pstart, psize);
832 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
834 os->keyframe_seek = 0;
837 ret = av_new_packet(pkt, psize);
840 pkt->stream_index = idx;
841 memcpy(pkt->data, os->buf + pstart, psize);
845 pkt->flags = os->pflags;
846 pkt->duration = os->pduration;
849 if (os->end_trimming) {
850 uint8_t *side_data = av_packet_new_side_data(pkt,
851 AV_PKT_DATA_SKIP_SAMPLES,
855 AV_WL32(side_data + 4, os->end_trimming);
856 os->end_trimming = 0;
859 if (os->new_metadata) {
860 uint8_t *side_data = av_packet_new_side_data(pkt,
861 AV_PKT_DATA_METADATA_UPDATE,
862 os->new_metadata_size);
866 memcpy(side_data, os->new_metadata, os->new_metadata_size);
867 av_freep(&os->new_metadata);
868 os->new_metadata_size = 0;
873 av_packet_unref(pkt);
874 return AVERROR(ENOMEM);
877 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
878 int64_t *pos_arg, int64_t pos_limit)
880 struct ogg *ogg = s->priv_data;
881 AVIOContext *bc = s->pb;
882 int64_t pts = AV_NOPTS_VALUE;
886 avio_seek(bc, *pos_arg, SEEK_SET);
889 while ( avio_tell(bc) <= pos_limit
890 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
891 if (i == stream_index) {
892 struct ogg_stream *os = ogg->streams + stream_index;
893 // Do not trust the last timestamps of an ogm video
894 if ( (os->flags & OGG_FLAG_EOS)
895 && !(os->flags & OGG_FLAG_BOS)
896 && os->codec == &ff_ogm_video_codec)
898 pts = ogg_calc_pts(s, i, NULL);
899 ogg_validate_keyframe(s, i, pstart, psize);
900 if (os->pflags & AV_PKT_FLAG_KEY) {
902 } else if (os->keyframe_seek) {
903 // if we had a previous keyframe but no pts for it,
904 // return that keyframe with this pts value.
908 pts = AV_NOPTS_VALUE;
911 if (pts != AV_NOPTS_VALUE)
918 static int ogg_read_seek(AVFormatContext *s, int stream_index,
919 int64_t timestamp, int flags)
921 struct ogg *ogg = s->priv_data;
922 struct ogg_stream *os = ogg->streams + stream_index;
925 av_assert0(stream_index < ogg->nstreams);
926 // Ensure everything is reset even when seeking via
927 // the generated index.
930 // Try seeking to a keyframe first. If this fails (very possible),
931 // av_seek_frame will fall back to ignoring keyframes
932 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
933 && !(flags & AVSEEK_FLAG_ANY))
934 os->keyframe_seek = 1;
936 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
938 os = ogg->streams + stream_index;
940 os->keyframe_seek = 0;
944 static int ogg_probe(const AVProbeData *p)
946 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
947 return AVPROBE_SCORE_MAX;
951 AVInputFormat ff_ogg_demuxer = {
953 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
954 .priv_data_size = sizeof(struct ogg),
955 .read_probe = ogg_probe,
956 .read_header = ogg_read_header,
957 .read_packet = ogg_read_packet,
958 .read_close = ogg_read_close,
959 .read_seek = ogg_read_seek,
960 .read_timestamp = ogg_read_timestamp,
962 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,