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 av_freep(&ogg->streams[i].private);
705 } else if (os->codec && os->nb_header < os->codec->nb_header) {
706 av_log(s, AV_LOG_WARNING,
707 "Headers mismatch for stream %d: "
708 "expected %d received %d.\n",
709 i, os->codec->nb_header, os->nb_header);
710 if (s->error_recognition & AV_EF_EXPLODE)
711 return AVERROR_INVALIDDATA;
713 if (os->start_granule != OGG_NOGRANULE_VALUE)
714 os->lastpts = s->streams[i]->start_time =
715 ogg_gptopts(s, i, os->start_granule, NULL);
718 //linear granulepos seek from end
719 ret = ogg_get_length(s);
728 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
730 struct ogg *ogg = s->priv_data;
731 struct ogg_stream *os = ogg->streams + idx;
732 int64_t pts = AV_NOPTS_VALUE;
735 *dts = AV_NOPTS_VALUE;
737 if (os->lastpts != AV_NOPTS_VALUE) {
739 os->lastpts = AV_NOPTS_VALUE;
741 if (os->lastdts != AV_NOPTS_VALUE) {
744 os->lastdts = AV_NOPTS_VALUE;
747 if (os->granule != -1LL) {
748 if (os->codec && os->codec->granule_is_start)
749 pts = ogg_gptopts(s, idx, os->granule, dts);
751 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
758 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
760 struct ogg *ogg = s->priv_data;
761 struct ogg_stream *os = ogg->streams + idx;
764 switch (s->streams[idx]->codecpar->codec_id) {
765 case AV_CODEC_ID_THEORA:
766 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
768 case AV_CODEC_ID_VP8:
769 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
772 os->pflags ^= AV_PKT_FLAG_KEY;
773 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
774 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
779 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
782 struct ogg_stream *os;
785 int64_t fpos, pts, dts;
787 if (s->io_repositioned) {
789 s->io_repositioned = 0;
795 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
798 } while (idx < 0 || !s->streams[idx]);
801 os = ogg->streams + idx;
803 // pflags might not be set until after this
804 pts = ogg_calc_pts(s, idx, &dts);
805 ogg_validate_keyframe(s, idx, pstart, psize);
807 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
809 os->keyframe_seek = 0;
812 ret = av_new_packet(pkt, psize);
815 pkt->stream_index = idx;
816 memcpy(pkt->data, os->buf + pstart, psize);
820 pkt->flags = os->pflags;
821 pkt->duration = os->pduration;
824 if (os->end_trimming) {
825 uint8_t *side_data = av_packet_new_side_data(pkt,
826 AV_PKT_DATA_SKIP_SAMPLES,
830 AV_WL32(side_data + 4, os->end_trimming);
831 os->end_trimming = 0;
834 if (os->new_metadata) {
835 uint8_t *side_data = av_packet_new_side_data(pkt,
836 AV_PKT_DATA_METADATA_UPDATE,
837 os->new_metadata_size);
841 memcpy(side_data, os->new_metadata, os->new_metadata_size);
842 av_freep(&os->new_metadata);
843 os->new_metadata_size = 0;
848 av_packet_unref(pkt);
849 return AVERROR(ENOMEM);
852 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
853 int64_t *pos_arg, int64_t pos_limit)
855 struct ogg *ogg = s->priv_data;
856 AVIOContext *bc = s->pb;
857 int64_t pts = AV_NOPTS_VALUE;
861 avio_seek(bc, *pos_arg, SEEK_SET);
864 while ( avio_tell(bc) <= pos_limit
865 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
866 if (i == stream_index) {
867 struct ogg_stream *os = ogg->streams + stream_index;
868 // Do not trust the last timestamps of an ogm video
869 if ( (os->flags & OGG_FLAG_EOS)
870 && !(os->flags & OGG_FLAG_BOS)
871 && os->codec == &ff_ogm_video_codec)
873 pts = ogg_calc_pts(s, i, NULL);
874 ogg_validate_keyframe(s, i, pstart, psize);
875 if (os->pflags & AV_PKT_FLAG_KEY) {
877 } else if (os->keyframe_seek) {
878 // if we had a previous keyframe but no pts for it,
879 // return that keyframe with this pts value.
883 pts = AV_NOPTS_VALUE;
886 if (pts != AV_NOPTS_VALUE)
893 static int ogg_read_seek(AVFormatContext *s, int stream_index,
894 int64_t timestamp, int flags)
896 struct ogg *ogg = s->priv_data;
897 struct ogg_stream *os = ogg->streams + stream_index;
900 av_assert0(stream_index < ogg->nstreams);
901 // Ensure everything is reset even when seeking via
902 // the generated index.
905 // Try seeking to a keyframe first. If this fails (very possible),
906 // av_seek_frame will fall back to ignoring keyframes
907 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
908 && !(flags & AVSEEK_FLAG_ANY))
909 os->keyframe_seek = 1;
911 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
913 os = ogg->streams + stream_index;
915 os->keyframe_seek = 0;
919 static int ogg_probe(AVProbeData *p)
921 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
922 return AVPROBE_SCORE_MAX;
926 AVInputFormat ff_ogg_demuxer = {
928 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
929 .priv_data_size = sizeof(struct ogg),
930 .read_probe = ogg_probe,
931 .read_header = ogg_read_header,
932 .read_packet = ogg_read_packet,
933 .read_close = ogg_read_close,
934 .read_seek = ogg_read_seek,
935 .read_timestamp = ogg_read_timestamp,
937 .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,