]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/adpcm.c
lavfi/avfilter.h: clarify doxy for AVFilterLink.out_buf
[ffmpeg] / libavcodec / adpcm.c
index 62e03e52bebfc1166ee6c566a415caf91c9d70db..cd682572569493a2c5b9de84e200c2cb9a6133c0 100644 (file)
@@ -23,6 +23,7 @@
 #include "bytestream.h"
 #include "adpcm.h"
 #include "adpcm_data.h"
+#include "internal.h"
 
 /**
  * @file
@@ -99,10 +100,12 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     case AV_CODEC_ID_ADPCM_EA:
         min_channels = 2;
         break;
+    case AV_CODEC_ID_ADPCM_AFC:
     case AV_CODEC_ID_ADPCM_EA_R1:
     case AV_CODEC_ID_ADPCM_EA_R2:
     case AV_CODEC_ID_ADPCM_EA_R3:
     case AV_CODEC_ID_ADPCM_EA_XAS:
+    case AV_CODEC_ID_ADPCM_THP:
         max_channels = 6;
         break;
     }
@@ -596,7 +599,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
         bytestream2_skip(gb, 4); // channel size
         *coded_samples  = bytestream2_get_be32(gb);
         *coded_samples -= *coded_samples % 14;
-        nb_samples      = (buf_size - 80) / (8 * ch) * 14;
+        nb_samples      = (buf_size - (8 + 36 * ch)) / (8 * ch) * 14;
         break;
     case AV_CODEC_ID_ADPCM_AFC:
         nb_samples = buf_size / (9 * ch) * 16;
@@ -637,7 +640,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 
     /* get output buffer */
     c->frame.nb_samples = nb_samples;
-    if ((ret = avctx->get_buffer(avctx, &c->frame)) < 0) {
+    if ((ret = ff_get_buffer(avctx, &c->frame)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
@@ -798,7 +801,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
                 return AVERROR_INVALIDDATA;
             }
         }
-        for (n = nb_samples >> (1 - st); n > 0; n--) {
+        for (n = (nb_samples - 1) >> (1 - st); n > 0; n--) {
             int v = bytestream2_get_byteu(&gb);
             *samples++ = adpcm_ima_expand_nibble(&c->status[0 ], v >> 4  , 3);
             *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
@@ -1266,13 +1269,26 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     case AV_CODEC_ID_ADPCM_AFC:
+    {
+        int samples_per_block;
+        int blocks;
+
+        if (avctx->extradata && avctx->extradata_size == 1 && avctx->extradata[0]) {
+            samples_per_block = avctx->extradata[0] / 16;
+            blocks = nb_samples / avctx->extradata[0];
+        } else {
+            samples_per_block = nb_samples / 16;
+            blocks = 1;
+        }
+
+        for (m = 0; m < blocks; m++) {
         for (channel = 0; channel < avctx->channels; channel++) {
             int prev1 = c->status[channel].sample1;
             int prev2 = c->status[channel].sample2;
 
-            samples = samples_p[channel];
+            samples = samples_p[channel] + m * 16;
             /* Read in every sample for this channel.  */
-            for (i = 0; i < nb_samples / 16; i++) {
+            for (i = 0; i < samples_per_block; i++) {
                 int byte = bytestream2_get_byteu(&gb);
                 int scale = 1 << (byte >> 4);
                 int index = byte & 0xf;
@@ -1301,24 +1317,26 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
             c->status[channel].sample1 = prev1;
             c->status[channel].sample2 = prev2;
         }
+        }
         bytestream2_seek(&gb, 0, SEEK_END);
         break;
+    }
     case AV_CODEC_ID_ADPCM_THP:
     {
-        int table[2][16];
+        int table[6][16];
         int ch;
 
-        for (i = 0; i < 2; i++)
+        for (i = 0; i < avctx->channels; i++)
             for (n = 0; n < 16; n++)
                 table[i][n] = sign_extend(bytestream2_get_be16u(&gb), 16);
 
         /* Initialize the previous sample.  */
-        for (i = 0; i < 2; i++) {
-                c->status[i].sample1 = sign_extend(bytestream2_get_be16u(&gb), 16);
-                c->status[i].sample2 = sign_extend(bytestream2_get_be16u(&gb), 16);
+        for (i = 0; i < avctx->channels; i++) {
+            c->status[i].sample1 = sign_extend(bytestream2_get_be16u(&gb), 16);
+            c->status[i].sample2 = sign_extend(bytestream2_get_be16u(&gb), 16);
         }
 
-        for (ch = 0; ch <= st; ch++) {
+        for (ch = 0; ch < avctx->channels; ch++) {
             samples = samples_p[ch];
 
             /* Read in every sample for this channel.  */