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"
36 #include "vorbiscomment.h"
38 #define MAX_PAGE_SIZE 65307
39 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
41 static const struct ogg_codec * const ogg_codecs[] = {
59 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
60 static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
62 //FIXME We could avoid some structure duplication
63 static int ogg_save(AVFormatContext *s)
65 struct ogg *ogg = s->priv_data;
66 struct ogg_state *ost =
67 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
69 ost->pos = avio_tell(s->pb);
70 ost->curidx = ogg->curidx;
71 ost->next = ogg->state;
72 ost->nstreams = ogg->nstreams;
73 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
75 for (i = 0; i < ogg->nstreams; i++) {
76 struct ogg_stream *os = ogg->streams + i;
77 os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
78 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
86 static int ogg_restore(AVFormatContext *s, int discard)
88 struct ogg *ogg = s->priv_data;
89 AVIOContext *bc = s->pb;
90 struct ogg_state *ost = ogg->state;
96 ogg->state = ost->next;
99 struct ogg_stream *old_streams = ogg->streams;
101 for (i = 0; i < ogg->nstreams; i++)
102 av_free(ogg->streams[i].buf);
104 avio_seek(bc, ost->pos, SEEK_SET);
106 ogg->curidx = ost->curidx;
107 ogg->nstreams = ost->nstreams;
108 ogg->streams = av_realloc(ogg->streams,
109 ogg->nstreams * sizeof(*ogg->streams));
112 memcpy(ogg->streams, ost->streams,
113 ost->nstreams * sizeof(*ogg->streams));
115 av_free(old_streams);
125 static int ogg_reset(AVFormatContext *s)
127 struct ogg *ogg = s->priv_data;
129 int64_t start_pos = avio_tell(s->pb);
131 for (i = 0; i < ogg->nstreams; i++) {
132 struct ogg_stream *os = ogg->streams + i;
137 os->lastpts = AV_NOPTS_VALUE;
138 os->lastdts = AV_NOPTS_VALUE;
145 if (start_pos <= s->data_offset) {
156 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
160 for (i = 0; ogg_codecs[i]; i++)
161 if (size >= ogg_codecs[i]->magicsize &&
162 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
163 return ogg_codecs[i];
169 * Replace the current stream with a new one. This is a typical webradio
170 * situation where a new audio stream spawn (identified with a new serial) and
171 * must replace the previous one (track switch).
173 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
175 struct ogg *ogg = s->priv_data;
176 struct ogg_stream *os;
177 const struct ogg_codec *codec;
180 if (s->pb->seekable) {
182 int64_t pos = avio_tell(s->pb);
183 avio_skip(s->pb, nsegs);
184 avio_read(s->pb, magic, sizeof(magic));
185 avio_seek(s->pb, pos, SEEK_SET);
186 codec = ogg_find_codec(magic, sizeof(magic));
188 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
189 return AVERROR_INVALIDDATA;
191 for (i = 0; i < ogg->nstreams; i++) {
192 if (ogg->streams[i].codec == codec)
195 if (i >= ogg->nstreams)
196 return ogg_new_stream(s, serial);
197 } else if (ogg->nstreams != 1) {
198 av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0);
199 return AVERROR_PATCHWELCOME;
202 os = &ogg->streams[i];
209 bufsize = os->bufsize;
212 if (!ogg->state || ogg->state->streams[i].private != os->private)
213 av_freep(&ogg->streams[i].private);
215 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
216 * also re-use the ogg_stream allocated buffer */
217 memset(os, 0, sizeof(*os));
219 os->bufsize = bufsize;
228 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
230 struct ogg *ogg = s->priv_data;
231 int idx = ogg->nstreams;
233 struct ogg_stream *os;
237 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
238 "in between Ogg context save/restore operations.\n");
242 /* Allocate and init a new Ogg Stream */
243 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
244 !(os = av_realloc(ogg->streams, size)))
245 return AVERROR(ENOMEM);
247 os = ogg->streams + idx;
248 memset(os, 0, sizeof(*os));
250 os->bufsize = DECODER_BUFFER_SIZE;
251 os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
253 os->start_granule = OGG_NOGRANULE_VALUE;
255 return AVERROR(ENOMEM);
257 /* Create the associated AVStream */
258 st = avformat_new_stream(s, NULL);
261 return AVERROR(ENOMEM);
264 avpriv_set_pts_info(st, 64, 1, 1000000);
270 static int ogg_new_buf(struct ogg *ogg, int idx)
272 struct ogg_stream *os = ogg->streams + idx;
273 uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
274 int size = os->bufpos - os->pstart;
277 memcpy(nb, os->buf + os->pstart, size);
288 static int data_packets_seen(const struct ogg *ogg)
292 for (i = 0; i < ogg->nstreams; i++)
293 if (ogg->streams[i].got_data)
298 static int ogg_read_page(AVFormatContext *s, int *sid)
300 AVIOContext *bc = s->pb;
301 struct ogg *ogg = s->priv_data;
302 struct ogg_stream *os;
311 ret = avio_read(bc, sync, 4);
313 return ret < 0 ? ret : AVERROR_EOF;
318 if (sync[sp & 3] == 'O' &&
319 sync[(sp + 1) & 3] == 'g' &&
320 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
323 if(!i && bc->seekable && ogg->page_pos > 0) {
325 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
335 } while (i++ < MAX_PAGE_SIZE);
337 if (i >= MAX_PAGE_SIZE) {
338 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
339 return AVERROR_INVALIDDATA;
342 if (avio_r8(bc) != 0) { /* version */
343 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
344 return AVERROR_INVALIDDATA;
349 serial = avio_rl32(bc);
350 avio_skip(bc, 8); /* seq, crc */
353 idx = ogg_find_stream(ogg, serial);
355 if (data_packets_seen(ogg))
356 idx = ogg_replace_stream(s, serial, nsegs);
358 idx = ogg_new_stream(s, serial);
361 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
366 os = ogg->streams + idx;
368 os->page_pos = avio_tell(bc) - 27;
371 ogg_new_buf(ogg, idx);
373 ret = avio_read(bc, os->segments, nsegs);
375 return ret < 0 ? ret : AVERROR_EOF;
381 for (i = 0; i < nsegs; i++)
382 size += os->segments[i];
384 if (!(flags & OGG_FLAG_BOS))
387 if (flags & OGG_FLAG_CONT || os->incomplete) {
389 // If this is the very first segment we started
390 // playback in the middle of a continuation packet.
391 // Discard it since we missed the start of it.
392 while (os->segp < os->nsegs) {
393 int seg = os->segments[os->segp++];
398 os->sync_pos = os->page_pos;
402 os->sync_pos = os->page_pos;
405 if (os->bufsize - os->bufpos < size) {
406 uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
408 return AVERROR(ENOMEM);
409 memcpy(nb, os->buf, os->bufpos);
414 ret = avio_read(bc, os->buf + os->bufpos, size);
416 return ret < 0 ? ret : AVERROR_EOF;
422 memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
430 * @brief find the next Ogg packet
431 * @param *sid is set to the stream for the packet or -1 if there is
432 * no matching stream, in that case assume all other return
433 * values to be uninitialized.
434 * @return negative value on error or EOF.
436 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
439 struct ogg *ogg = s->priv_data;
441 struct ogg_stream *os;
443 int segp = 0, psize = 0;
445 av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
453 ret = ogg_read_page(s, &idx);
458 os = ogg->streams + idx;
460 av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
461 idx, os->pstart, os->psize, os->segp, os->nsegs);
464 if (os->header < 0) {
465 os->codec = ogg_find_codec(os->buf, os->bufpos);
467 av_log(s, AV_LOG_WARNING, "Codec not found\n");
479 while (os->segp < os->nsegs) {
480 int ss = os->segments[os->segp++];
488 if (!complete && os->segp == os->nsegs) {
490 // Do not set incomplete for empty packets.
491 // Together with the code in ogg_read_page
492 // that discards all continuation of empty packets
493 // we would get an infinite loop.
494 os->incomplete = !!os->psize;
499 if (os->granule == -1)
500 av_log(s, AV_LOG_WARNING,
501 "Page at %"PRId64" is missing granule\n",
508 os->header = os->codec->header(s, idx);
513 // We have reached the first non-header packet in this stream.
514 // Unfortunately more header packets may still follow for others,
515 // but if we continue with header parsing we may lose data packets.
518 // Update the header state for all streams and
519 // compute the data_offset.
521 s->data_offset = os->sync_pos;
523 for (i = 0; i < ogg->nstreams; i++) {
524 struct ogg_stream *cur_os = ogg->streams + i;
526 // if we have a partial non-header packet, its start is
527 // obviously at or after the data start
528 if (cur_os->incomplete)
529 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
533 os->pstart += os->psize;
539 if (os->codec && os->codec->packet)
540 os->codec->packet(s, idx);
544 *dstart = os->pstart;
548 *fpos = os->sync_pos;
549 os->pstart += os->psize;
551 if(os->pstart == os->bufpos)
552 os->bufpos = os->pstart = 0;
553 os->sync_pos = os->page_pos;
556 // determine whether there are more complete packets in this page
557 // if not, the page's granule will apply to this packet
559 for (i = os->segp; i < os->nsegs; i++)
560 if (os->segments[i] < 255) {
565 if (os->segp == os->nsegs)
571 static int ogg_get_length(AVFormatContext *s)
573 struct ogg *ogg = s->priv_data;
578 if (!s->pb->seekable)
582 if (s->duration != AV_NOPTS_VALUE)
585 size = avio_size(s->pb);
588 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
591 avio_seek(s->pb, end, SEEK_SET);
594 while (!ogg_read_page(s, &i)) {
595 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
596 ogg->streams[i].codec) {
597 s->streams[i]->duration =
598 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
599 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
600 s->streams[i]->duration -= s->streams[i]->start_time;
601 streams_left-= (ogg->streams[i].got_start==-1);
602 ogg->streams[i].got_start= 1;
603 } else if(!ogg->streams[i].got_start) {
604 ogg->streams[i].got_start= -1;
613 avio_seek (s->pb, s->data_offset, SEEK_SET);
615 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
618 pts = ogg_calc_pts(s, i, NULL);
619 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
620 s->streams[i]->duration -= pts;
621 ogg->streams[i].got_start= 1;
623 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
624 ogg->streams[i].got_start= 1;
633 static int ogg_read_close(AVFormatContext *s)
635 struct ogg *ogg = s->priv_data;
638 for (i = 0; i < ogg->nstreams; i++) {
639 av_free(ogg->streams[i].buf);
640 if (ogg->streams[i].codec &&
641 ogg->streams[i].codec->cleanup) {
642 ogg->streams[i].codec->cleanup(s, i);
644 av_free(ogg->streams[i].private);
646 av_free(ogg->streams);
650 static int ogg_read_header(AVFormatContext *s)
652 struct ogg *ogg = s->priv_data;
657 //linear headers seek from start
659 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
664 } while (!ogg->headers);
665 av_dlog(s, "found headers\n");
667 for (i = 0; i < ogg->nstreams; i++) {
668 struct ogg_stream *os = ogg->streams + i;
670 if (ogg->streams[i].header < 0) {
671 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
672 ogg->streams[i].codec = NULL;
673 } else if (os->codec && os->nb_header < os->codec->nb_header) {
674 av_log(s, AV_LOG_WARNING, "Number of headers (%d) mismatch for stream %d\n", os->nb_header, i);
676 if (os->start_granule != OGG_NOGRANULE_VALUE)
677 os->lastpts = s->streams[i]->start_time =
678 ogg_gptopts(s, i, os->start_granule, NULL);
681 //linear granulepos seek from end
687 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
689 struct ogg *ogg = s->priv_data;
690 struct ogg_stream *os = ogg->streams + idx;
691 int64_t pts = AV_NOPTS_VALUE;
694 *dts = AV_NOPTS_VALUE;
696 if (os->lastpts != AV_NOPTS_VALUE) {
698 os->lastpts = AV_NOPTS_VALUE;
700 if (os->lastdts != AV_NOPTS_VALUE) {
703 os->lastdts = AV_NOPTS_VALUE;
706 if (os->granule != -1LL) {
707 if (os->codec && os->codec->granule_is_start)
708 pts = ogg_gptopts(s, idx, os->granule, dts);
710 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
717 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
719 struct ogg *ogg = s->priv_data;
720 struct ogg_stream *os = ogg->streams + idx;
721 if (psize && s->streams[idx]->codec->codec_id == AV_CODEC_ID_THEORA) {
722 if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
723 os->pflags ^= AV_PKT_FLAG_KEY;
724 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
725 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
730 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
733 struct ogg_stream *os;
736 int64_t fpos, pts, dts;
741 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
744 } while (idx < 0 || !s->streams[idx]);
747 os = ogg->streams + idx;
749 // pflags might not be set until after this
750 pts = ogg_calc_pts(s, idx, &dts);
751 ogg_validate_keyframe(s, idx, pstart, psize);
753 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
755 os->keyframe_seek = 0;
758 ret = av_new_packet(pkt, psize);
761 pkt->stream_index = idx;
762 memcpy(pkt->data, os->buf + pstart, psize);
766 pkt->flags = os->pflags;
767 pkt->duration = os->pduration;
773 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
774 int64_t *pos_arg, int64_t pos_limit)
776 struct ogg *ogg = s->priv_data;
777 AVIOContext *bc = s->pb;
778 int64_t pts = AV_NOPTS_VALUE;
782 avio_seek(bc, *pos_arg, SEEK_SET);
785 while ( avio_tell(bc) <= pos_limit
786 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
787 if (i == stream_index) {
788 struct ogg_stream *os = ogg->streams + stream_index;
789 pts = ogg_calc_pts(s, i, NULL);
790 ogg_validate_keyframe(s, i, pstart, psize);
791 if (os->pflags & AV_PKT_FLAG_KEY) {
793 } else if (os->keyframe_seek) {
794 // if we had a previous keyframe but no pts for it,
795 // return that keyframe with this pts value.
799 pts = AV_NOPTS_VALUE;
802 if (pts != AV_NOPTS_VALUE)
809 static int ogg_read_seek(AVFormatContext *s, int stream_index,
810 int64_t timestamp, int flags)
812 struct ogg *ogg = s->priv_data;
813 struct ogg_stream *os = ogg->streams + stream_index;
816 av_assert0(stream_index < ogg->nstreams);
817 // Ensure everything is reset even when seeking via
818 // the generated index.
821 // Try seeking to a keyframe first. If this fails (very possible),
822 // av_seek_frame will fall back to ignoring keyframes
823 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
824 && !(flags & AVSEEK_FLAG_ANY))
825 os->keyframe_seek = 1;
827 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
828 os = ogg->streams + stream_index;
830 os->keyframe_seek = 0;
834 static int ogg_probe(AVProbeData *p)
836 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
837 return AVPROBE_SCORE_MAX;
841 AVInputFormat ff_ogg_demuxer = {
843 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
844 .priv_data_size = sizeof(struct ogg),
845 .read_probe = ogg_probe,
846 .read_header = ogg_read_header,
847 .read_packet = ogg_read_packet,
848 .read_close = ogg_read_close,
849 .read_seek = ogg_read_seek,
850 .read_timestamp = ogg_read_timestamp,
852 .flags = AVFMT_GENERIC_INDEX,