From 7cb27d216d1caa2c6fbd957bc477def6baf2f3cb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 16 Jan 2013 19:58:59 +0100 Subject: oggdec: Support chained streams, support replacing streams in multistream files. Signed-off-by: Michael Niedermayer Conflicts: Changelog --- Changelog | 1 + libavformat/oggdec.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Changelog b/Changelog index 4687cb872e..b4ae07445d 100644 --- a/Changelog +++ b/Changelog @@ -5,6 +5,7 @@ version : - VDPAU hardware acceleration through normal hwaccel - SRTP support - Error diffusion dither in Swscale +- Chained Ogg support version 1.1: diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 3e3be2fb38..55604b4f38 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -57,6 +57,7 @@ static const struct ogg_codec * const ogg_codecs[] = { }; static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts); +static int ogg_new_stream(AVFormatContext *s, uint32_t serial); //FIXME We could avoid some structure duplication static int ogg_save(AVFormatContext *s) @@ -169,30 +170,48 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) * situation where a new audio stream spawn (identified with a new serial) and * must replace the previous one (track switch). */ -static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) +static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs) { struct ogg *ogg = s->priv_data; struct ogg_stream *os; unsigned bufsize; uint8_t *buf; const struct ogg_codec *codec; - - if (ogg->nstreams != 1) { + int i = 0; + + if (s->pb->seekable) { + uint8_t magic[8]; + int64_t pos = avio_tell(s->pb); + avio_skip(s->pb, nsegs); + avio_read(s->pb, magic, sizeof(magic)); + avio_seek(s->pb, pos, SEEK_SET); + codec = ogg_find_codec(magic, sizeof(magic)); + if (!codec) { + av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < ogg->nstreams; i++) { + if (ogg->streams[i].codec == codec) + break; + } + if (i >= ogg->nstreams) + return ogg_new_stream(s, serial); + } else if (ogg->nstreams != 1) { av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0); return AVERROR_PATCHWELCOME; } - os = &ogg->streams[0]; + os = &ogg->streams[i]; os->serial = serial; - return 0; + return i; buf = os->buf; bufsize = os->bufsize; codec = os->codec; - if (!ogg->state || ogg->state->streams[0].private != os->private) - av_freep(&ogg->streams[0].private); + if (!ogg->state || ogg->state->streams[i].private != os->private) + av_freep(&ogg->streams[i].private); /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We * also re-use the ogg_stream allocated buffer */ @@ -203,7 +222,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) os->header = -1; os->codec = codec; - return 0; + return i; } static int ogg_new_stream(AVFormatContext *s, uint32_t serial) @@ -334,7 +353,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) idx = ogg_find_stream(ogg, serial); if (idx < 0) { if (data_packets_seen(ogg)) - idx = ogg_replace_stream(s, serial); + idx = ogg_replace_stream(s, serial, nsegs); else idx = ogg_new_stream(s, serial); -- cgit v1.2.3