diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-10-30 00:46:16 -0400 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2011-11-11 14:06:14 -0500 |
commit | 7b966566da24598a636a433a75a7842e272b18f6 (patch) | |
tree | f1a779535c5be39993775c95a639c411ac6846e3 | |
parent | ca482ce4204fe198b2df1b41f3d15e883f3f1f0d (diff) | |
download | ffmpeg-7b966566da24598a636a433a75a7842e272b18f6.tar.gz |
vqf/twinvq: pass vqf COMM chunk info in extradata
This is needed because the twinvq decoder cannot rely on bit_rate to be set.
The API documentation says that bit_rate is set by libavcodec, not by the
user.
-rw-r--r-- | libavcodec/twinvq.c | 18 | ||||
-rw-r--r-- | libavformat/vqf.c | 14 |
2 files changed, 27 insertions, 5 deletions
diff --git a/libavcodec/twinvq.c b/libavcodec/twinvq.c index 174cee7424..73eb7c1499 100644 --- a/libavcodec/twinvq.c +++ b/libavcodec/twinvq.c @@ -1104,17 +1104,31 @@ static av_cold int twin_decode_init(AVCodecContext *avctx) { int ret; TwinContext *tctx = avctx->priv_data; - int isampf = avctx->sample_rate/1000; - int ibps = avctx->bit_rate/(1000 * avctx->channels); + int isampf, ibps; tctx->avctx = avctx; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + if (!avctx->extradata || avctx->extradata_size < 12) { + av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n"); + return AVERROR_INVALIDDATA; + } + avctx->channels = AV_RB32(avctx->extradata ) + 1; + avctx->bit_rate = AV_RB32(avctx->extradata + 4) * 1000; + isampf = AV_RB32(avctx->extradata + 8); + switch (isampf) { + case 44: avctx->sample_rate = 44100; break; + case 22: avctx->sample_rate = 22050; break; + case 11: avctx->sample_rate = 11025; break; + default: avctx->sample_rate = isampf * 1000; break; + } + if (avctx->channels > CHANNELS_MAX) { av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n", avctx->channels); return -1; } + ibps = avctx->bit_rate / (1000 * avctx->channels); switch ((isampf << 8) + ibps) { case (8 <<8) + 8: tctx->mtab = &mode_08_08; break; diff --git a/libavformat/vqf.c b/libavformat/vqf.c index 4650a0b500..f2c1d8f146 100644 --- a/libavformat/vqf.c +++ b/libavformat/vqf.c @@ -70,6 +70,7 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) int header_size; int read_bitrate = 0; int size; + uint8_t comm_chunk[12]; if (!st) return AVERROR(ENOMEM); @@ -100,9 +101,10 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) switch(chunk_tag){ case MKTAG('C','O','M','M'): - st->codec->channels = avio_rb32(s->pb) + 1; - read_bitrate = avio_rb32(s->pb); - rate_flag = avio_rb32(s->pb); + avio_read(s->pb, comm_chunk, 12); + st->codec->channels = AV_RB32(comm_chunk ) + 1; + read_bitrate = AV_RB32(comm_chunk + 4); + rate_flag = AV_RB32(comm_chunk + 8); avio_skip(s->pb, len-12); st->codec->bit_rate = read_bitrate*1000; @@ -192,6 +194,12 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) c->frame_bit_len = st->codec->bit_rate*size/st->codec->sample_rate; av_set_pts_info(st, 64, 1, st->codec->sample_rate); + /* put first 12 bytes of COMM chunk in extradata */ + if (!(st->codec->extradata = av_malloc(12 + FF_INPUT_BUFFER_PADDING_SIZE))) + return AVERROR(ENOMEM); + st->codec->extradata_size = 12; + memcpy(st->codec->extradata, comm_chunk, 12); + return 0; } |