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[] = {
61 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
62 static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
64 //FIXME We could avoid some structure duplication
65 static int ogg_save(AVFormatContext *s)
67 struct ogg *ogg = s->priv_data;
68 struct ogg_state *ost =
69 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
73 return AVERROR(ENOMEM);
75 ost->pos = avio_tell(s->pb);
76 ost->curidx = ogg->curidx;
77 ost->next = ogg->state;
78 ost->nstreams = ogg->nstreams;
79 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
81 for (i = 0; i < ogg->nstreams; i++) {
82 struct ogg_stream *os = ogg->streams + i;
83 os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
84 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
85 os->new_metadata = NULL;
86 os->new_metadata_size = 0;
94 static int ogg_restore(AVFormatContext *s, int discard)
96 struct ogg *ogg = s->priv_data;
97 AVIOContext *bc = s->pb;
98 struct ogg_state *ost = ogg->state;
104 ogg->state = ost->next;
108 for (i = 0; i < ogg->nstreams; i++)
109 av_freep(&ogg->streams[i].buf);
111 avio_seek(bc, ost->pos, SEEK_SET);
113 ogg->curidx = ost->curidx;
114 ogg->nstreams = ost->nstreams;
115 if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
116 sizeof(*ogg->streams))) < 0) {
120 memcpy(ogg->streams, ost->streams,
121 ost->nstreams * sizeof(*ogg->streams));
129 static int ogg_reset(AVFormatContext *s)
131 struct ogg *ogg = s->priv_data;
133 int64_t start_pos = avio_tell(s->pb);
135 for (i = 0; i < ogg->nstreams; i++) {
136 struct ogg_stream *os = ogg->streams + i;
141 os->lastpts = AV_NOPTS_VALUE;
142 os->lastdts = AV_NOPTS_VALUE;
149 if (start_pos <= s->internal->data_offset) {
152 os->end_trimming = 0;
153 av_freep(&os->new_metadata);
154 os->new_metadata_size = 0;
163 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
167 for (i = 0; ogg_codecs[i]; i++)
168 if (size >= ogg_codecs[i]->magicsize &&
169 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
170 return ogg_codecs[i];
176 * Replace the current stream with a new one. This is a typical webradio
177 * situation where a new audio stream spawn (identified with a new serial) and
178 * must replace the previous one (track switch).
180 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
182 struct ogg *ogg = s->priv_data;
183 struct ogg_stream *os;
184 const struct ogg_codec *codec;
187 if (s->pb->seekable) {
189 int64_t pos = avio_tell(s->pb);
190 avio_skip(s->pb, nsegs);
191 avio_read(s->pb, magic, sizeof(magic));
192 avio_seek(s->pb, pos, SEEK_SET);
193 codec = ogg_find_codec(magic, sizeof(magic));
195 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
196 return AVERROR_INVALIDDATA;
198 for (i = 0; i < ogg->nstreams; i++) {
199 if (ogg->streams[i].codec == codec)
202 if (i >= ogg->nstreams)
203 return ogg_new_stream(s, serial);
204 } else if (ogg->nstreams != 1) {
205 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
206 return AVERROR_PATCHWELCOME;
209 os = &ogg->streams[i];
216 bufsize = os->bufsize;
219 if (!ogg->state || ogg->state->streams[i].private != os->private)
220 av_freep(&ogg->streams[i].private);
222 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
223 * also re-use the ogg_stream allocated buffer */
224 memset(os, 0, sizeof(*os));
226 os->bufsize = bufsize;
235 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
237 struct ogg *ogg = s->priv_data;
238 int idx = ogg->nstreams;
240 struct ogg_stream *os;
244 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
245 "in between Ogg context save/restore operations.\n");
249 /* Allocate and init a new Ogg Stream */
250 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
251 !(os = av_realloc(ogg->streams, size)))
252 return AVERROR(ENOMEM);
254 os = ogg->streams + idx;
255 memset(os, 0, sizeof(*os));
257 os->bufsize = DECODER_BUFFER_SIZE;
258 os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
260 os->start_granule = OGG_NOGRANULE_VALUE;
262 return AVERROR(ENOMEM);
264 /* Create the associated AVStream */
265 st = avformat_new_stream(s, NULL);
268 return AVERROR(ENOMEM);
271 avpriv_set_pts_info(st, 64, 1, 1000000);
277 static int ogg_new_buf(struct ogg *ogg, int idx)
279 struct ogg_stream *os = ogg->streams + idx;
280 uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
281 int size = os->bufpos - os->pstart;
284 return AVERROR(ENOMEM);
287 memcpy(nb, os->buf + os->pstart, size);
298 static int data_packets_seen(const struct ogg *ogg)
302 for (i = 0; i < ogg->nstreams; i++)
303 if (ogg->streams[i].got_data)
308 static int ogg_read_page(AVFormatContext *s, int *sid)
310 AVIOContext *bc = s->pb;
311 struct ogg *ogg = s->priv_data;
312 struct ogg_stream *os;
321 ret = avio_read(bc, sync, 4);
323 return ret < 0 ? ret : AVERROR_EOF;
328 if (sync[sp & 3] == 'O' &&
329 sync[(sp + 1) & 3] == 'g' &&
330 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
333 if(!i && bc->seekable && ogg->page_pos > 0) {
335 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
345 } while (i++ < MAX_PAGE_SIZE);
347 if (i >= MAX_PAGE_SIZE) {
348 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
349 return AVERROR_INVALIDDATA;
352 if (avio_r8(bc) != 0) { /* version */
353 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
354 return AVERROR_INVALIDDATA;
359 serial = avio_rl32(bc);
360 avio_skip(bc, 8); /* seq, crc */
363 idx = ogg_find_stream(ogg, serial);
365 if (data_packets_seen(ogg))
366 idx = ogg_replace_stream(s, serial, nsegs);
368 idx = ogg_new_stream(s, serial);
371 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
376 os = ogg->streams + idx;
378 os->page_pos = avio_tell(bc) - 27;
381 ret = ogg_new_buf(ogg, idx);
386 ret = avio_read(bc, os->segments, nsegs);
388 return ret < 0 ? ret : AVERROR_EOF;
394 for (i = 0; i < nsegs; i++)
395 size += os->segments[i];
397 if (!(flags & OGG_FLAG_BOS))
400 if (flags & OGG_FLAG_CONT || os->incomplete) {
402 // If this is the very first segment we started
403 // playback in the middle of a continuation packet.
404 // Discard it since we missed the start of it.
405 while (os->segp < os->nsegs) {
406 int seg = os->segments[os->segp++];
411 os->sync_pos = os->page_pos;
415 os->sync_pos = os->page_pos;
418 if (os->bufsize - os->bufpos < size) {
419 uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
421 return AVERROR(ENOMEM);
422 memcpy(nb, os->buf, os->bufpos);
427 ret = avio_read(bc, os->buf + os->bufpos, size);
429 return ret < 0 ? ret : AVERROR_EOF;
435 memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
443 * @brief find the next Ogg packet
444 * @param *sid is set to the stream for the packet or -1 if there is
445 * no matching stream, in that case assume all other return
446 * values to be uninitialized.
447 * @return negative value on error or EOF.
449 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
452 struct ogg *ogg = s->priv_data;
454 struct ogg_stream *os;
456 int segp = 0, psize = 0;
458 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
466 ret = ogg_read_page(s, &idx);
471 os = ogg->streams + idx;
473 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
474 idx, os->pstart, os->psize, os->segp, os->nsegs);
477 if (os->header < 0) {
478 os->codec = ogg_find_codec(os->buf, os->bufpos);
480 av_log(s, AV_LOG_WARNING, "Codec not found\n");
492 while (os->segp < os->nsegs) {
493 int ss = os->segments[os->segp++];
501 if (!complete && os->segp == os->nsegs) {
503 // Do not set incomplete for empty packets.
504 // Together with the code in ogg_read_page
505 // that discards all continuation of empty packets
506 // we would get an infinite loop.
507 os->incomplete = !!os->psize;
512 if (os->granule == -1)
513 av_log(s, AV_LOG_WARNING,
514 "Page at %"PRId64" is missing granule\n",
521 os->header = os->codec->header(s, idx);
526 // We have reached the first non-header packet in this stream.
527 // Unfortunately more header packets may still follow for others,
528 // but if we continue with header parsing we may lose data packets.
531 // Update the header state for all streams and
532 // compute the data_offset.
533 if (!s->internal->data_offset)
534 s->internal->data_offset = os->sync_pos;
536 for (i = 0; i < ogg->nstreams; i++) {
537 struct ogg_stream *cur_os = ogg->streams + i;
539 // if we have a partial non-header packet, its start is
540 // obviously at or after the data start
541 if (cur_os->incomplete)
542 s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
546 os->pstart += os->psize;
552 if (os->codec && os->codec->packet)
553 os->codec->packet(s, idx);
557 *dstart = os->pstart;
561 *fpos = os->sync_pos;
562 os->pstart += os->psize;
564 if(os->pstart == os->bufpos)
565 os->bufpos = os->pstart = 0;
566 os->sync_pos = os->page_pos;
569 // determine whether there are more complete packets in this page
570 // if not, the page's granule will apply to this packet
572 for (i = os->segp; i < os->nsegs; i++)
573 if (os->segments[i] < 255) {
578 if (os->segp == os->nsegs)
584 static int ogg_get_length(AVFormatContext *s)
586 struct ogg *ogg = s->priv_data;
592 if (!s->pb->seekable)
596 if (s->duration != AV_NOPTS_VALUE)
599 size = avio_size(s->pb);
602 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
607 avio_seek(s->pb, end, SEEK_SET);
610 while (!ogg_read_page(s, &i)) {
611 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
612 ogg->streams[i].codec) {
613 s->streams[i]->duration =
614 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
615 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
616 s->streams[i]->duration -= s->streams[i]->start_time;
617 streams_left-= (ogg->streams[i].got_start==-1);
618 ogg->streams[i].got_start= 1;
619 } else if(!ogg->streams[i].got_start) {
620 ogg->streams[i].got_start= -1;
632 avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
634 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
637 pts = ogg_calc_pts(s, i, NULL);
638 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
639 s->streams[i]->duration -= pts;
640 ogg->streams[i].got_start= 1;
642 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
643 ogg->streams[i].got_start= 1;
652 static int ogg_read_close(AVFormatContext *s)
654 struct ogg *ogg = s->priv_data;
657 for (i = 0; i < ogg->nstreams; i++) {
658 av_freep(&ogg->streams[i].buf);
659 if (ogg->streams[i].codec &&
660 ogg->streams[i].codec->cleanup) {
661 ogg->streams[i].codec->cleanup(s, i);
663 av_freep(&ogg->streams[i].private);
664 av_freep(&ogg->streams[i].new_metadata);
669 av_freep(&ogg->streams);
673 static int ogg_read_header(AVFormatContext *s)
675 struct ogg *ogg = s->priv_data;
680 //linear headers seek from start
682 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
687 } while (!ogg->headers);
688 av_log(s, AV_LOG_TRACE, "found headers\n");
690 for (i = 0; i < ogg->nstreams; i++) {
691 struct ogg_stream *os = ogg->streams + i;
693 if (ogg->streams[i].header < 0) {
694 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
695 ogg->streams[i].codec = NULL;
696 } else if (os->codec && os->nb_header < os->codec->nb_header) {
697 av_log(s, AV_LOG_WARNING,
698 "Headers mismatch for stream %d: "
699 "expected %d received %d.\n",
700 i, os->codec->nb_header, os->nb_header);
701 if (s->error_recognition & AV_EF_EXPLODE)
702 return AVERROR_INVALIDDATA;
704 if (os->start_granule != OGG_NOGRANULE_VALUE)
705 os->lastpts = s->streams[i]->start_time =
706 ogg_gptopts(s, i, os->start_granule, NULL);
709 //linear granulepos seek from end
715 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
717 struct ogg *ogg = s->priv_data;
718 struct ogg_stream *os = ogg->streams + idx;
719 int64_t pts = AV_NOPTS_VALUE;
722 *dts = AV_NOPTS_VALUE;
724 if (os->lastpts != AV_NOPTS_VALUE) {
726 os->lastpts = AV_NOPTS_VALUE;
728 if (os->lastdts != AV_NOPTS_VALUE) {
731 os->lastdts = AV_NOPTS_VALUE;
734 if (os->granule != -1LL) {
735 if (os->codec && os->codec->granule_is_start)
736 pts = ogg_gptopts(s, idx, os->granule, dts);
738 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
745 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
747 struct ogg *ogg = s->priv_data;
748 struct ogg_stream *os = ogg->streams + idx;
751 switch (s->streams[idx]->codec->codec_id) {
752 case AV_CODEC_ID_THEORA:
753 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
755 case AV_CODEC_ID_VP8:
756 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
759 os->pflags ^= AV_PKT_FLAG_KEY;
760 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
761 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
766 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
769 struct ogg_stream *os;
772 int64_t fpos, pts, dts;
774 if (s->io_repositioned) {
776 s->io_repositioned = 0;
782 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
785 } while (idx < 0 || !s->streams[idx]);
788 os = ogg->streams + idx;
790 // pflags might not be set until after this
791 pts = ogg_calc_pts(s, idx, &dts);
792 ogg_validate_keyframe(s, idx, pstart, psize);
794 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
796 os->keyframe_seek = 0;
799 ret = av_new_packet(pkt, psize);
802 pkt->stream_index = idx;
803 memcpy(pkt->data, os->buf + pstart, psize);
807 pkt->flags = os->pflags;
808 pkt->duration = os->pduration;
811 if (os->end_trimming) {
812 uint8_t *side_data = av_packet_new_side_data(pkt,
813 AV_PKT_DATA_SKIP_SAMPLES,
817 AV_WL32(side_data + 4, os->end_trimming);
818 os->end_trimming = 0;
821 if (os->new_metadata) {
822 uint8_t *side_data = av_packet_new_side_data(pkt,
823 AV_PKT_DATA_METADATA_UPDATE,
824 os->new_metadata_size);
828 memcpy(side_data, os->new_metadata, os->new_metadata_size);
829 av_freep(&os->new_metadata);
830 os->new_metadata_size = 0;
836 return AVERROR(ENOMEM);
839 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
840 int64_t *pos_arg, int64_t pos_limit)
842 struct ogg *ogg = s->priv_data;
843 AVIOContext *bc = s->pb;
844 int64_t pts = AV_NOPTS_VALUE;
848 avio_seek(bc, *pos_arg, SEEK_SET);
851 while ( avio_tell(bc) <= pos_limit
852 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
853 if (i == stream_index) {
854 struct ogg_stream *os = ogg->streams + stream_index;
855 // Do not trust the last timestamps of a ogm video
856 if ( (os->flags & OGG_FLAG_EOS)
857 && !(os->flags & OGG_FLAG_BOS)
858 && os->codec == &ff_ogm_video_codec)
860 pts = ogg_calc_pts(s, i, NULL);
861 ogg_validate_keyframe(s, i, pstart, psize);
862 if (os->pflags & AV_PKT_FLAG_KEY) {
864 } else if (os->keyframe_seek) {
865 // if we had a previous keyframe but no pts for it,
866 // return that keyframe with this pts value.
870 pts = AV_NOPTS_VALUE;
873 if (pts != AV_NOPTS_VALUE)
880 static int ogg_read_seek(AVFormatContext *s, int stream_index,
881 int64_t timestamp, int flags)
883 struct ogg *ogg = s->priv_data;
884 struct ogg_stream *os = ogg->streams + stream_index;
887 av_assert0(stream_index < ogg->nstreams);
888 // Ensure everything is reset even when seeking via
889 // the generated index.
892 // Try seeking to a keyframe first. If this fails (very possible),
893 // av_seek_frame will fall back to ignoring keyframes
894 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
895 && !(flags & AVSEEK_FLAG_ANY))
896 os->keyframe_seek = 1;
898 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
899 os = ogg->streams + stream_index;
901 os->keyframe_seek = 0;
905 static int ogg_probe(AVProbeData *p)
907 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
908 return AVPROBE_SCORE_MAX;
912 AVInputFormat ff_ogg_demuxer = {
914 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
915 .priv_data_size = sizeof(struct ogg),
916 .read_probe = ogg_probe,
917 .read_header = ogg_read_header,
918 .read_packet = ogg_read_packet,
919 .read_close = ogg_read_close,
920 .read_seek = ogg_read_seek,
921 .read_timestamp = ogg_read_timestamp,
923 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,