diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-01-16 19:58:59 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-01-20 17:53:51 +0100 |
commit | 7cb27d216d1caa2c6fbd957bc477def6baf2f3cb (patch) | |
tree | b5d89915b42399b646816b108269541de1bfd4bf /libavformat/oggdec.c | |
parent | 6136b989f658fff68e2b758db583f04358d3d412 (diff) | |
download | ffmpeg-7cb27d216d1caa2c6fbd957bc477def6baf2f3cb.tar.gz |
oggdec: Support chained streams, support replacing streams in multistream files.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Conflicts:
Changelog
Diffstat (limited to 'libavformat/oggdec.c')
-rw-r--r-- | libavformat/oggdec.c | 37 |
1 files changed, 28 insertions, 9 deletions
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); |