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;
179 const struct ogg_codec *codec;
182 if (s->pb->seekable) {
184 int64_t pos = avio_tell(s->pb);
185 avio_skip(s->pb, nsegs);
186 avio_read(s->pb, magic, sizeof(magic));
187 avio_seek(s->pb, pos, SEEK_SET);
188 codec = ogg_find_codec(magic, sizeof(magic));
190 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
191 return AVERROR_INVALIDDATA;
193 for (i = 0; i < ogg->nstreams; i++) {
194 if (ogg->streams[i].codec == codec)
197 if (i >= ogg->nstreams)
198 return ogg_new_stream(s, serial);
199 } else if (ogg->nstreams != 1) {
200 av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0);
201 return AVERROR_PATCHWELCOME;
204 os = &ogg->streams[i];
211 bufsize = os->bufsize;
214 if (!ogg->state || ogg->state->streams[i].private != os->private)
215 av_freep(&ogg->streams[i].private);
217 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
218 * also re-use the ogg_stream allocated buffer */
219 memset(os, 0, sizeof(*os));
221 os->bufsize = bufsize;
230 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
232 struct ogg *ogg = s->priv_data;
233 int idx = ogg->nstreams;
235 struct ogg_stream *os;
239 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
240 "in between Ogg context save/restore operations.\n");
244 /* Allocate and init a new Ogg Stream */
245 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
246 !(os = av_realloc(ogg->streams, size)))
247 return AVERROR(ENOMEM);
249 os = ogg->streams + idx;
250 memset(os, 0, sizeof(*os));
252 os->bufsize = DECODER_BUFFER_SIZE;
253 os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
255 os->start_granule = OGG_NOGRANULE_VALUE;
257 return AVERROR(ENOMEM);
259 /* Create the associated AVStream */
260 st = avformat_new_stream(s, NULL);
263 return AVERROR(ENOMEM);
266 avpriv_set_pts_info(st, 64, 1, 1000000);
272 static int ogg_new_buf(struct ogg *ogg, int idx)
274 struct ogg_stream *os = ogg->streams + idx;
275 uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
276 int size = os->bufpos - os->pstart;
279 memcpy(nb, os->buf + os->pstart, size);
290 static int data_packets_seen(const struct ogg *ogg)
294 for (i = 0; i < ogg->nstreams; i++)
295 if (ogg->streams[i].got_data)
300 static int ogg_read_page(AVFormatContext *s, int *sid)
302 AVIOContext *bc = s->pb;
303 struct ogg *ogg = s->priv_data;
304 struct ogg_stream *os;
313 ret = avio_read(bc, sync, 4);
315 return ret < 0 ? ret : AVERROR_EOF;
320 if (sync[sp & 3] == 'O' &&
321 sync[(sp + 1) & 3] == 'g' &&
322 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
325 if(!i && bc->seekable && ogg->page_pos > 0) {
327 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
337 } while (i++ < MAX_PAGE_SIZE);
339 if (i >= MAX_PAGE_SIZE) {
340 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
341 return AVERROR_INVALIDDATA;
344 if (avio_r8(bc) != 0) { /* version */
345 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
346 return AVERROR_INVALIDDATA;
351 serial = avio_rl32(bc);
352 avio_skip(bc, 8); /* seq, crc */
355 idx = ogg_find_stream(ogg, serial);
357 if (data_packets_seen(ogg))
358 idx = ogg_replace_stream(s, serial, nsegs);
360 idx = ogg_new_stream(s, serial);
363 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
368 os = ogg->streams + idx;
370 os->page_pos = avio_tell(bc) - 27;
373 ogg_new_buf(ogg, idx);
375 ret = avio_read(bc, os->segments, nsegs);
377 return ret < 0 ? ret : AVERROR_EOF;
383 for (i = 0; i < nsegs; i++)
384 size += os->segments[i];
386 if (!(flags & OGG_FLAG_BOS))
389 if (flags & OGG_FLAG_CONT || os->incomplete) {
391 // If this is the very first segment we started
392 // playback in the middle of a continuation packet.
393 // Discard it since we missed the start of it.
394 while (os->segp < os->nsegs) {
395 int seg = os->segments[os->segp++];
400 os->sync_pos = os->page_pos;
404 os->sync_pos = os->page_pos;
407 if (os->bufsize - os->bufpos < size) {
408 uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
410 return AVERROR(ENOMEM);
411 memcpy(nb, os->buf, os->bufpos);
416 ret = avio_read(bc, os->buf + os->bufpos, size);
418 return ret < 0 ? ret : AVERROR_EOF;
424 memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
432 * @brief find the next Ogg packet
433 * @param *sid is set to the stream for the packet or -1 if there is
434 * no matching stream, in that case assume all other return
435 * values to be uninitialized.
436 * @return negative value on error or EOF.
438 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
441 struct ogg *ogg = s->priv_data;
443 struct ogg_stream *os;
445 int segp = 0, psize = 0;
447 av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
455 ret = ogg_read_page(s, &idx);
460 os = ogg->streams + idx;
462 av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
463 idx, os->pstart, os->psize, os->segp, os->nsegs);
466 if (os->header < 0) {
467 os->codec = ogg_find_codec(os->buf, os->bufpos);
469 av_log(s, AV_LOG_WARNING, "Codec not found\n");
481 while (os->segp < os->nsegs) {
482 int ss = os->segments[os->segp++];
490 if (!complete && os->segp == os->nsegs) {
492 // Do not set incomplete for empty packets.
493 // Together with the code in ogg_read_page
494 // that discards all continuation of empty packets
495 // we would get an infinite loop.
496 os->incomplete = !!os->psize;
501 if (os->granule == -1)
502 av_log(s, AV_LOG_WARNING,
503 "Page at %"PRId64" is missing granule\n",
510 os->header = os->codec->header(s, idx);
515 // We have reached the first non-header packet in this stream.
516 // Unfortunately more header packets may still follow for others,
517 // but if we continue with header parsing we may lose data packets.
520 // Update the header state for all streams and
521 // compute the data_offset.
523 s->data_offset = os->sync_pos;
525 for (i = 0; i < ogg->nstreams; i++) {
526 struct ogg_stream *cur_os = ogg->streams + i;
528 // if we have a partial non-header packet, its start is
529 // obviously at or after the data start
530 if (cur_os->incomplete)
531 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
535 os->pstart += os->psize;
541 if (os->codec && os->codec->packet)
542 os->codec->packet(s, idx);
546 *dstart = os->pstart;
550 *fpos = os->sync_pos;
551 os->pstart += os->psize;
553 if(os->pstart == os->bufpos)
554 os->bufpos = os->pstart = 0;
555 os->sync_pos = os->page_pos;
558 // determine whether there are more complete packets in this page
559 // if not, the page's granule will apply to this packet
561 for (i = os->segp; i < os->nsegs; i++)
562 if (os->segments[i] < 255) {
567 if (os->segp == os->nsegs)
573 static int ogg_get_length(AVFormatContext *s)
575 struct ogg *ogg = s->priv_data;
580 if (!s->pb->seekable)
584 if (s->duration != AV_NOPTS_VALUE)
587 size = avio_size(s->pb);
590 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
593 avio_seek(s->pb, end, SEEK_SET);
596 while (!ogg_read_page(s, &i)) {
597 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
598 ogg->streams[i].codec) {
599 s->streams[i]->duration =
600 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
601 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
602 s->streams[i]->duration -= s->streams[i]->start_time;
603 streams_left-= (ogg->streams[i].got_start==-1);
604 ogg->streams[i].got_start= 1;
605 } else if(!ogg->streams[i].got_start) {
606 ogg->streams[i].got_start= -1;
615 avio_seek (s->pb, s->data_offset, SEEK_SET);
617 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
620 pts = ogg_calc_pts(s, i, NULL);
621 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
622 s->streams[i]->duration -= pts;
623 ogg->streams[i].got_start= 1;
625 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
626 ogg->streams[i].got_start= 1;
635 static int ogg_read_close(AVFormatContext *s)
637 struct ogg *ogg = s->priv_data;
640 for (i = 0; i < ogg->nstreams; i++) {
641 av_free(ogg->streams[i].buf);
642 if (ogg->streams[i].codec &&
643 ogg->streams[i].codec->cleanup) {
644 ogg->streams[i].codec->cleanup(s, i);
646 av_free(ogg->streams[i].private);
648 av_free(ogg->streams);
652 static int ogg_read_header(AVFormatContext *s)
654 struct ogg *ogg = s->priv_data;
659 //linear headers seek from start
661 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
666 } while (!ogg->headers);
667 av_dlog(s, "found headers\n");
669 for (i = 0; i < ogg->nstreams; i++) {
670 struct ogg_stream *os = ogg->streams + i;
672 if (ogg->streams[i].header < 0) {
673 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
674 ogg->streams[i].codec = NULL;
675 } else if (os->codec && os->nb_header < os->codec->nb_header) {
676 av_log(s, AV_LOG_WARNING, "Number of headers (%d) mismatch for stream %d\n", os->nb_header, i);
678 if (os->start_granule != OGG_NOGRANULE_VALUE)
679 os->lastpts = s->streams[i]->start_time =
680 ogg_gptopts(s, i, os->start_granule, NULL);
683 //linear granulepos seek from end
689 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
691 struct ogg *ogg = s->priv_data;
692 struct ogg_stream *os = ogg->streams + idx;
693 int64_t pts = AV_NOPTS_VALUE;
696 *dts = AV_NOPTS_VALUE;
698 if (os->lastpts != AV_NOPTS_VALUE) {
700 os->lastpts = AV_NOPTS_VALUE;
702 if (os->lastdts != AV_NOPTS_VALUE) {
705 os->lastdts = AV_NOPTS_VALUE;
708 if (os->granule != -1LL) {
709 if (os->codec && os->codec->granule_is_start)
710 pts = ogg_gptopts(s, idx, os->granule, dts);
712 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
719 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
721 struct ogg *ogg = s->priv_data;
722 struct ogg_stream *os = ogg->streams + idx;
723 if (psize && s->streams[idx]->codec->codec_id == AV_CODEC_ID_THEORA) {
724 if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
725 os->pflags ^= AV_PKT_FLAG_KEY;
726 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
727 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
732 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
735 struct ogg_stream *os;
738 int64_t fpos, pts, dts;
743 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
746 } while (idx < 0 || !s->streams[idx]);
749 os = ogg->streams + idx;
751 // pflags might not be set until after this
752 pts = ogg_calc_pts(s, idx, &dts);
753 ogg_validate_keyframe(s, idx, pstart, psize);
755 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
757 os->keyframe_seek = 0;
760 ret = av_new_packet(pkt, psize);
763 pkt->stream_index = idx;
764 memcpy(pkt->data, os->buf + pstart, psize);
768 pkt->flags = os->pflags;
769 pkt->duration = os->pduration;
775 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
776 int64_t *pos_arg, int64_t pos_limit)
778 struct ogg *ogg = s->priv_data;
779 AVIOContext *bc = s->pb;
780 int64_t pts = AV_NOPTS_VALUE;
784 avio_seek(bc, *pos_arg, SEEK_SET);
787 while ( avio_tell(bc) <= pos_limit
788 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
789 if (i == stream_index) {
790 struct ogg_stream *os = ogg->streams + stream_index;
791 pts = ogg_calc_pts(s, i, NULL);
792 ogg_validate_keyframe(s, i, pstart, psize);
793 if (os->pflags & AV_PKT_FLAG_KEY) {
795 } else if (os->keyframe_seek) {
796 // if we had a previous keyframe but no pts for it,
797 // return that keyframe with this pts value.
801 pts = AV_NOPTS_VALUE;
804 if (pts != AV_NOPTS_VALUE)
811 static int ogg_read_seek(AVFormatContext *s, int stream_index,
812 int64_t timestamp, int flags)
814 struct ogg *ogg = s->priv_data;
815 struct ogg_stream *os = ogg->streams + stream_index;
818 av_assert0(stream_index < ogg->nstreams);
819 // Ensure everything is reset even when seeking via
820 // the generated index.
823 // Try seeking to a keyframe first. If this fails (very possible),
824 // av_seek_frame will fall back to ignoring keyframes
825 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
826 && !(flags & AVSEEK_FLAG_ANY))
827 os->keyframe_seek = 1;
829 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
830 os = ogg->streams + stream_index;
832 os->keyframe_seek = 0;
836 static int ogg_probe(AVProbeData *p)
838 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
839 return AVPROBE_SCORE_MAX;
843 AVInputFormat ff_ogg_demuxer = {
845 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
846 .priv_data_size = sizeof(struct ogg),
847 .read_probe = ogg_probe,
848 .read_header = ogg_read_header,
849 .read_packet = ogg_read_packet,
850 .read_close = ogg_read_close,
851 .read_seek = ogg_read_seek,
852 .read_timestamp = ogg_read_timestamp,
854 .flags = AVFMT_GENERIC_INDEX,