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, int discard);
66 //FIXME We could avoid some structure duplication
67 static int ogg_save(AVFormatContext *s)
69 struct ogg *ogg = s->priv_data;
70 struct ogg_state *ost =
71 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
76 return AVERROR(ENOMEM);
78 ost->pos = avio_tell(s->pb);
79 ost->curidx = ogg->curidx;
80 ost->next = ogg->state;
81 ost->nstreams = ogg->nstreams;
82 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
84 for (i = 0; i < ogg->nstreams; i++) {
85 struct ogg_stream *os = ogg->streams + i;
86 os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
88 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
90 ret = AVERROR(ENOMEM);
91 os->new_metadata = NULL;
92 os->new_metadata_size = 0;
103 static int ogg_restore(AVFormatContext *s, int discard)
105 struct ogg *ogg = s->priv_data;
106 AVIOContext *bc = s->pb;
107 struct ogg_state *ost = ogg->state;
113 ogg->state = ost->next;
117 for (i = 0; i < ogg->nstreams; i++)
118 av_freep(&ogg->streams[i].buf);
120 avio_seek(bc, ost->pos, SEEK_SET);
122 ogg->curidx = ost->curidx;
123 ogg->nstreams = ost->nstreams;
124 if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
125 sizeof(*ogg->streams))) < 0) {
129 memcpy(ogg->streams, ost->streams,
130 ost->nstreams * sizeof(*ogg->streams));
138 static int ogg_reset(AVFormatContext *s)
140 struct ogg *ogg = s->priv_data;
142 int64_t start_pos = avio_tell(s->pb);
144 for (i = 0; i < ogg->nstreams; i++) {
145 struct ogg_stream *os = ogg->streams + i;
150 os->lastpts = AV_NOPTS_VALUE;
151 os->lastdts = AV_NOPTS_VALUE;
158 if (start_pos <= s->internal->data_offset) {
161 os->end_trimming = 0;
162 av_freep(&os->new_metadata);
163 os->new_metadata_size = 0;
172 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
176 for (i = 0; ogg_codecs[i]; i++)
177 if (size >= ogg_codecs[i]->magicsize &&
178 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
179 return ogg_codecs[i];
185 * Replace the current stream with a new one. This is a typical webradio
186 * situation where a new audio stream spawn (identified with a new serial) and
187 * must replace the previous one (track switch).
189 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
191 struct ogg *ogg = s->priv_data;
192 struct ogg_stream *os;
193 const struct ogg_codec *codec;
196 if (s->pb->seekable) {
198 int64_t pos = avio_tell(s->pb);
199 avio_skip(s->pb, nsegs);
200 avio_read(s->pb, magic, sizeof(magic));
201 avio_seek(s->pb, pos, SEEK_SET);
202 codec = ogg_find_codec(magic, sizeof(magic));
204 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
205 return AVERROR_INVALIDDATA;
207 for (i = 0; i < ogg->nstreams; i++) {
208 if (ogg->streams[i].codec == codec)
211 if (i >= ogg->nstreams)
212 return ogg_new_stream(s, serial);
213 } else if (ogg->nstreams != 1) {
214 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
215 return AVERROR_PATCHWELCOME;
218 os = &ogg->streams[i];
225 bufsize = os->bufsize;
228 if (!ogg->state || ogg->state->streams[i].private != os->private)
229 av_freep(&ogg->streams[i].private);
231 /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
232 * also re-use the ogg_stream allocated buffer */
233 memset(os, 0, sizeof(*os));
235 os->bufsize = bufsize;
244 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
246 struct ogg *ogg = s->priv_data;
247 int idx = ogg->nstreams;
249 struct ogg_stream *os;
253 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
254 "in between Ogg context save/restore operations.\n");
258 /* Allocate and init a new Ogg Stream */
259 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
260 !(os = av_realloc(ogg->streams, size)))
261 return AVERROR(ENOMEM);
263 os = ogg->streams + idx;
264 memset(os, 0, sizeof(*os));
266 os->bufsize = DECODER_BUFFER_SIZE;
267 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
269 os->start_granule = OGG_NOGRANULE_VALUE;
271 return AVERROR(ENOMEM);
273 /* Create the associated AVStream */
274 st = avformat_new_stream(s, NULL);
277 return AVERROR(ENOMEM);
280 avpriv_set_pts_info(st, 64, 1, 1000000);
286 static int ogg_new_buf(struct ogg *ogg, int idx)
288 struct ogg_stream *os = ogg->streams + idx;
289 uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
290 int size = os->bufpos - os->pstart;
293 return AVERROR(ENOMEM);
296 memcpy(nb, os->buf + os->pstart, size);
307 static int data_packets_seen(const struct ogg *ogg)
311 for (i = 0; i < ogg->nstreams; i++)
312 if (ogg->streams[i].got_data)
317 static int ogg_read_page(AVFormatContext *s, int *sid)
319 AVIOContext *bc = s->pb;
320 struct ogg *ogg = s->priv_data;
321 struct ogg_stream *os;
330 ret = avio_read(bc, sync, 4);
332 return ret < 0 ? ret : AVERROR_EOF;
337 if (sync[sp & 3] == 'O' &&
338 sync[(sp + 1) & 3] == 'g' &&
339 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
342 if(!i && bc->seekable && ogg->page_pos > 0) {
344 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
354 } while (i++ < MAX_PAGE_SIZE);
356 if (i >= MAX_PAGE_SIZE) {
357 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
358 return AVERROR_INVALIDDATA;
361 if (avio_r8(bc) != 0) { /* version */
362 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
363 return AVERROR_INVALIDDATA;
368 serial = avio_rl32(bc);
369 avio_skip(bc, 8); /* seq, crc */
372 idx = ogg_find_stream(ogg, serial);
374 if (data_packets_seen(ogg))
375 idx = ogg_replace_stream(s, serial, nsegs);
377 idx = ogg_new_stream(s, serial);
380 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
385 os = ogg->streams + idx;
387 os->page_pos = avio_tell(bc) - 27;
390 ret = ogg_new_buf(ogg, idx);
395 ret = avio_read(bc, os->segments, nsegs);
397 return ret < 0 ? ret : AVERROR_EOF;
403 for (i = 0; i < nsegs; i++)
404 size += os->segments[i];
406 if (!(flags & OGG_FLAG_BOS))
409 if (flags & OGG_FLAG_CONT || os->incomplete) {
411 // If this is the very first segment we started
412 // playback in the middle of a continuation packet.
413 // Discard it since we missed the start of it.
414 while (os->segp < os->nsegs) {
415 int seg = os->segments[os->segp++];
420 os->sync_pos = os->page_pos;
424 os->sync_pos = os->page_pos;
427 if (os->bufsize - os->bufpos < size) {
428 uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
430 return AVERROR(ENOMEM);
431 memcpy(nb, os->buf, os->bufpos);
436 ret = avio_read(bc, os->buf + os->bufpos, size);
438 return ret < 0 ? ret : AVERROR_EOF;
444 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
452 * @brief find the next Ogg packet
453 * @param *sid is set to the stream for the packet or -1 if there is
454 * no matching stream, in that case assume all other return
455 * values to be uninitialized.
456 * @return negative value on error or EOF.
458 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
461 struct ogg *ogg = s->priv_data;
463 struct ogg_stream *os;
465 int segp = 0, psize = 0;
467 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
475 ret = ogg_read_page(s, &idx);
480 os = ogg->streams + idx;
482 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
483 idx, os->pstart, os->psize, os->segp, os->nsegs);
486 if (os->header < 0) {
487 os->codec = ogg_find_codec(os->buf, os->bufpos);
489 av_log(s, AV_LOG_WARNING, "Codec not found\n");
501 while (os->segp < os->nsegs) {
502 int ss = os->segments[os->segp++];
510 if (!complete && os->segp == os->nsegs) {
512 // Do not set incomplete for empty packets.
513 // Together with the code in ogg_read_page
514 // that discards all continuation of empty packets
515 // we would get an infinite loop.
516 os->incomplete = !!os->psize;
521 if (os->granule == -1)
522 av_log(s, AV_LOG_WARNING,
523 "Page at %"PRId64" is missing granule\n",
530 os->header = os->codec->header(s, idx);
535 // We have reached the first non-header packet in this stream.
536 // Unfortunately more header packets may still follow for others,
537 // but if we continue with header parsing we may lose data packets.
540 // Update the header state for all streams and
541 // compute the data_offset.
542 if (!s->internal->data_offset)
543 s->internal->data_offset = os->sync_pos;
545 for (i = 0; i < ogg->nstreams; i++) {
546 struct ogg_stream *cur_os = ogg->streams + i;
548 // if we have a partial non-header packet, its start is
549 // obviously at or after the data start
550 if (cur_os->incomplete)
551 s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
555 os->pstart += os->psize;
561 if (os->codec && os->codec->packet)
562 os->codec->packet(s, idx);
566 *dstart = os->pstart;
570 *fpos = os->sync_pos;
571 os->pstart += os->psize;
573 if(os->pstart == os->bufpos)
574 os->bufpos = os->pstart = 0;
575 os->sync_pos = os->page_pos;
578 // determine whether there are more complete packets in this page
579 // if not, the page's granule will apply to this packet
581 for (i = os->segp; i < os->nsegs; i++)
582 if (os->segments[i] < 255) {
587 if (os->segp == os->nsegs)
593 static int ogg_get_length(AVFormatContext *s)
595 struct ogg *ogg = s->priv_data;
600 if (!s->pb->seekable)
604 if (s->duration != AV_NOPTS_VALUE)
607 size = avio_size(s->pb);
610 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
615 avio_seek(s->pb, end, SEEK_SET);
618 while (!ogg_read_page(s, &i)) {
619 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
620 ogg->streams[i].codec) {
621 s->streams[i]->duration =
622 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
623 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
624 s->streams[i]->duration -= s->streams[i]->start_time;
625 streams_left-= (ogg->streams[i].got_start==-1);
626 ogg->streams[i].got_start= 1;
627 } else if(!ogg->streams[i].got_start) {
628 ogg->streams[i].got_start= -1;
640 avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
642 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
645 pts = ogg_calc_pts(s, i, NULL);
646 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
647 s->streams[i]->duration -= pts;
648 ogg->streams[i].got_start= 1;
650 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
651 ogg->streams[i].got_start= 1;
660 static int ogg_read_close(AVFormatContext *s)
662 struct ogg *ogg = s->priv_data;
665 for (i = 0; i < ogg->nstreams; i++) {
666 av_freep(&ogg->streams[i].buf);
667 if (ogg->streams[i].codec &&
668 ogg->streams[i].codec->cleanup) {
669 ogg->streams[i].codec->cleanup(s, i);
671 av_freep(&ogg->streams[i].private);
672 av_freep(&ogg->streams[i].new_metadata);
677 av_freep(&ogg->streams);
681 static int ogg_read_header(AVFormatContext *s)
683 struct ogg *ogg = s->priv_data;
688 //linear headers seek from start
690 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
695 } while (!ogg->headers);
696 av_log(s, AV_LOG_TRACE, "found headers\n");
698 for (i = 0; i < ogg->nstreams; i++) {
699 struct ogg_stream *os = ogg->streams + i;
701 if (ogg->streams[i].header < 0) {
702 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
703 ogg->streams[i].codec = NULL;
704 } else if (os->codec && os->nb_header < os->codec->nb_header) {
705 av_log(s, AV_LOG_WARNING,
706 "Headers mismatch for stream %d: "
707 "expected %d received %d.\n",
708 i, os->codec->nb_header, os->nb_header);
709 if (s->error_recognition & AV_EF_EXPLODE)
710 return AVERROR_INVALIDDATA;
712 if (os->start_granule != OGG_NOGRANULE_VALUE)
713 os->lastpts = s->streams[i]->start_time =
714 ogg_gptopts(s, i, os->start_granule, NULL);
717 //linear granulepos seek from end
718 ret = ogg_get_length(s);
727 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
729 struct ogg *ogg = s->priv_data;
730 struct ogg_stream *os = ogg->streams + idx;
731 int64_t pts = AV_NOPTS_VALUE;
734 *dts = AV_NOPTS_VALUE;
736 if (os->lastpts != AV_NOPTS_VALUE) {
738 os->lastpts = AV_NOPTS_VALUE;
740 if (os->lastdts != AV_NOPTS_VALUE) {
743 os->lastdts = AV_NOPTS_VALUE;
746 if (os->granule != -1LL) {
747 if (os->codec && os->codec->granule_is_start)
748 pts = ogg_gptopts(s, idx, os->granule, dts);
750 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
757 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
759 struct ogg *ogg = s->priv_data;
760 struct ogg_stream *os = ogg->streams + idx;
763 switch (s->streams[idx]->codecpar->codec_id) {
764 case AV_CODEC_ID_THEORA:
765 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
767 case AV_CODEC_ID_VP8:
768 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
771 os->pflags ^= AV_PKT_FLAG_KEY;
772 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
773 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
778 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
781 struct ogg_stream *os;
784 int64_t fpos, pts, dts;
786 if (s->io_repositioned) {
788 s->io_repositioned = 0;
794 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
797 } while (idx < 0 || !s->streams[idx]);
800 os = ogg->streams + idx;
802 // pflags might not be set until after this
803 pts = ogg_calc_pts(s, idx, &dts);
804 ogg_validate_keyframe(s, idx, pstart, psize);
806 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
808 os->keyframe_seek = 0;
811 ret = av_new_packet(pkt, psize);
814 pkt->stream_index = idx;
815 memcpy(pkt->data, os->buf + pstart, psize);
819 pkt->flags = os->pflags;
820 pkt->duration = os->pduration;
823 if (os->end_trimming) {
824 uint8_t *side_data = av_packet_new_side_data(pkt,
825 AV_PKT_DATA_SKIP_SAMPLES,
829 AV_WL32(side_data + 4, os->end_trimming);
830 os->end_trimming = 0;
833 if (os->new_metadata) {
834 uint8_t *side_data = av_packet_new_side_data(pkt,
835 AV_PKT_DATA_METADATA_UPDATE,
836 os->new_metadata_size);
840 memcpy(side_data, os->new_metadata, os->new_metadata_size);
841 av_freep(&os->new_metadata);
842 os->new_metadata_size = 0;
847 av_packet_unref(pkt);
848 return AVERROR(ENOMEM);
851 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
852 int64_t *pos_arg, int64_t pos_limit)
854 struct ogg *ogg = s->priv_data;
855 AVIOContext *bc = s->pb;
856 int64_t pts = AV_NOPTS_VALUE;
860 avio_seek(bc, *pos_arg, SEEK_SET);
863 while ( avio_tell(bc) <= pos_limit
864 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
865 if (i == stream_index) {
866 struct ogg_stream *os = ogg->streams + stream_index;
867 // Do not trust the last timestamps of an ogm video
868 if ( (os->flags & OGG_FLAG_EOS)
869 && !(os->flags & OGG_FLAG_BOS)
870 && os->codec == &ff_ogm_video_codec)
872 pts = ogg_calc_pts(s, i, NULL);
873 ogg_validate_keyframe(s, i, pstart, psize);
874 if (os->pflags & AV_PKT_FLAG_KEY) {
876 } else if (os->keyframe_seek) {
877 // if we had a previous keyframe but no pts for it,
878 // return that keyframe with this pts value.
882 pts = AV_NOPTS_VALUE;
885 if (pts != AV_NOPTS_VALUE)
892 static int ogg_read_seek(AVFormatContext *s, int stream_index,
893 int64_t timestamp, int flags)
895 struct ogg *ogg = s->priv_data;
896 struct ogg_stream *os = ogg->streams + stream_index;
899 av_assert0(stream_index < ogg->nstreams);
900 // Ensure everything is reset even when seeking via
901 // the generated index.
904 // Try seeking to a keyframe first. If this fails (very possible),
905 // av_seek_frame will fall back to ignoring keyframes
906 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
907 && !(flags & AVSEEK_FLAG_ANY))
908 os->keyframe_seek = 1;
910 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
912 os = ogg->streams + stream_index;
914 os->keyframe_seek = 0;
918 static int ogg_probe(AVProbeData *p)
920 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
921 return AVPROBE_SCORE_MAX;
925 AVInputFormat ff_ogg_demuxer = {
927 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
928 .priv_data_size = sizeof(struct ogg),
929 .read_probe = ogg_probe,
930 .read_header = ogg_read_header,
931 .read_packet = ogg_read_packet,
932 .read_close = ogg_read_close,
933 .read_seek = ogg_read_seek,
934 .read_timestamp = ogg_read_timestamp,
936 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,