OSDN Git Service

vqf/twinvq: pass vqf COMM chunk info in extradata
authorJustin Ruggles <justin.ruggles@gmail.com>
Sun, 30 Oct 2011 04:46:16 +0000 (00:46 -0400)
committerJustin Ruggles <justin.ruggles@gmail.com>
Fri, 11 Nov 2011 19:06:14 +0000 (14:06 -0500)
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.

libavcodec/twinvq.c
libavformat/vqf.c

index 174cee7..73eb7c1 100644 (file)
@@ -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;
index 4650a0b..f2c1d8f 100644 (file)
@@ -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;
 }