]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/adpcm.c
avcodec/adpcm_ima_alp: reset state on flush
[ffmpeg] / libavcodec / adpcm.c
index d018c1f91bbe012c3ae702ad6afa75dde4a073e4..f154188b5d2c64f13ef94ba528dcdef444e6262d 100644 (file)
@@ -100,7 +100,7 @@ static const int8_t mtf_index_table[16] = {
 typedef struct ADPCMDecodeContext {
     ADPCMChannelStatus status[14];
     int vqa_version;                /**< VQA version. Used for ADPCM_IMA_WS */
-    int has_status;
+    int has_status;                 /**< Status flag. Reset to 0 after a flush. */
 } ADPCMDecodeContext;
 
 static av_cold int adpcm_decode_init(AVCodecContext * avctx)
@@ -110,7 +110,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     unsigned int max_channels = 2;
 
     switch(avctx->codec->id) {
-    case AV_CODEC_ID_ADPCM_IMA_CUNNING:
+    case AV_CODEC_ID_ADPCM_IMA_AMV:
         max_channels = 1;
         break;
     case AV_CODEC_ID_ADPCM_DTK:
@@ -196,6 +196,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
 
     switch (avctx->codec->id) {
     case AV_CODEC_ID_ADPCM_AICA:
+    case AV_CODEC_ID_ADPCM_IMA_CUNNING:
     case AV_CODEC_ID_ADPCM_IMA_DAT4:
     case AV_CODEC_ID_ADPCM_IMA_QT:
     case AV_CODEC_ID_ADPCM_IMA_WAV:
@@ -774,7 +775,6 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
         case AV_CODEC_ID_ADPCM_IMA_DAT4:
         case AV_CODEC_ID_ADPCM_IMA_MOFLEX:
         case AV_CODEC_ID_ADPCM_IMA_ISS:     header_size = 4 * ch;      break;
-        case AV_CODEC_ID_ADPCM_IMA_AMV:     header_size = 8;           break;
         case AV_CODEC_ID_ADPCM_IMA_SMJPEG:  header_size = 4 * ch;      break;
     }
     if (header_size > 0)
@@ -782,6 +782,13 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
 
     /* more complex formats */
     switch (avctx->codec->id) {
+    case AV_CODEC_ID_ADPCM_IMA_AMV:
+        bytestream2_skip(gb, 4);
+        has_coded_samples  = 1;
+        *coded_samples     = bytestream2_get_le32u(gb);
+        nb_samples         = FFMIN((buf_size - 8) * 2, *coded_samples);
+        bytestream2_seek(gb, -8, SEEK_CUR);
+        break;
     case AV_CODEC_ID_ADPCM_EA:
         has_coded_samples = 1;
         *coded_samples  = bytestream2_get_le32(gb);
@@ -1370,10 +1377,13 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     case AV_CODEC_ID_ADPCM_IMA_CUNNING:
-        for (n = 0; n < nb_samples / 2; n++) {
-            int v = bytestream2_get_byteu(&gb);
-            *samples++ = adpcm_ima_cunning_expand_nibble(&c->status[0], v & 0x0F);
-            *samples++ = adpcm_ima_cunning_expand_nibble(&c->status[0], v >> 4);
+        for (channel = 0; channel < avctx->channels; channel++) {
+            int16_t *smp = samples_p[channel];
+            for (n = 0; n < nb_samples / 2; n++) {
+                int v = bytestream2_get_byteu(&gb);
+                *smp++ = adpcm_ima_cunning_expand_nibble(&c->status[channel], v & 0x0F);
+                *smp++ = adpcm_ima_cunning_expand_nibble(&c->status[channel], v >> 4);
+            }
         }
         break;
     case AV_CODEC_ID_ADPCM_IMA_OKI:
@@ -1681,6 +1691,18 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     case AV_CODEC_ID_ADPCM_IMA_AMV:
+        av_assert0(avctx->channels == 1);
+
+        /*
+         * Header format:
+         *   int16_t  predictor;
+         *   uint8_t  step_index;
+         *   uint8_t  reserved;
+         *   uint32_t frame_size;
+         *
+         * Some implementations have step_index as 16-bits, but others
+         * only use the lower 8 and store garbage in the upper 8.
+         */
         c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
         c->status[0].step_index = bytestream2_get_byteu(&gb);
         bytestream2_skipu(&gb, 5);
@@ -1690,12 +1712,23 @@ 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; 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[0], v & 0xf, 3);
         }
+
+        if (nb_samples & 1) {
+            int v = bytestream2_get_byteu(&gb);
+            *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4, 3);
+
+            if (v & 0x0F) {
+                /* Holds true on all the http://samples.mplayerhq.hu/amv samples. */
+                av_log(avctx, AV_LOG_WARNING, "Last nibble set on packet with odd sample count.\n");
+                av_log(avctx, AV_LOG_WARNING, "Sample will be skipped.\n");
+            }
+        }
         break;
     case AV_CODEC_ID_ADPCM_IMA_SMJPEG:
         for (i = 0; i < avctx->channels; i++) {
@@ -1778,11 +1811,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     case AV_CODEC_ID_ADPCM_AICA:
-        if (!c->has_status) {
-            for (channel = 0; channel < avctx->channels; channel++)
-                c->status[channel].step = 0;
-            c->has_status = 1;
-        }
         for (channel = 0; channel < avctx->channels; channel++) {
             samples = samples_p[channel];
             for (n = nb_samples >> 1; n > 0; n--) {
@@ -2044,13 +2072,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     case AV_CODEC_ID_ADPCM_ZORK:
-        if (!c->has_status) {
-            for (channel = 0; channel < avctx->channels; channel++) {
-                c->status[channel].predictor  = 0;
-                c->status[channel].step_index = 0;
-            }
-            c->has_status = 1;
-        }
         for (n = 0; n < nb_samples * avctx->channels; n++) {
             int v = bytestream2_get_byteu(&gb);
             *samples++ = adpcm_zork_expand_nibble(&c->status[n % avctx->channels], v);
@@ -2088,7 +2109,36 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 static void adpcm_flush(AVCodecContext *avctx)
 {
     ADPCMDecodeContext *c = avctx->priv_data;
-    c->has_status = 0;
+
+    switch(avctx->codec_id) {
+    case AV_CODEC_ID_ADPCM_AICA:
+        for (int channel = 0; channel < avctx->channels; channel++)
+            c->status[channel].step = 0;
+        break;
+
+    case AV_CODEC_ID_ADPCM_ARGO:
+        for (int channel = 0; channel < avctx->channels; channel++) {
+            c->status[channel].sample1 = 0;
+            c->status[channel].sample2 = 0;
+        }
+        break;
+
+    case AV_CODEC_ID_ADPCM_IMA_ALP:
+    case AV_CODEC_ID_ADPCM_IMA_SSI:
+    case AV_CODEC_ID_ADPCM_ZORK:
+        for (int channel = 0; channel < avctx->channels; channel++) {
+            c->status[channel].predictor  = 0;
+            c->status[channel].step_index = 0;
+        }
+        break;
+
+    default:
+        /* Other codecs may want to handle this during decoding. */
+        c->has_status = 0;
+        return;
+    }
+
+    c->has_status = 1;
 }
 
 
@@ -2112,6 +2162,7 @@ AVCodec ff_ ## name_ ## _decoder = {                        \
     .flush          = adpcm_flush,                          \
     .capabilities   = AV_CODEC_CAP_DR1,                     \
     .sample_fmts    = sample_fmts_,                         \
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,         \
 }
 
 /* Note: Do not forget to add new entries to the Makefile as well. */
@@ -2131,7 +2182,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS,      sample_fmts_s16p, adpcm_ea_xas,
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_AMV,     sample_fmts_s16,  adpcm_ima_amv,     "ADPCM IMA AMV");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APC,     sample_fmts_s16,  adpcm_ima_apc,     "ADPCM IMA CRYO APC");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APM,     sample_fmts_s16,  adpcm_ima_apm,     "ADPCM IMA Ubisoft APM");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_CUNNING, sample_fmts_s16 adpcm_ima_cunning, "ADPCM IMA Cunning Developments");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_CUNNING, sample_fmts_s16p, adpcm_ima_cunning, "ADPCM IMA Cunning Developments");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DAT4,    sample_fmts_s16,  adpcm_ima_dat4,    "ADPCM IMA Eurocom DAT4");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK3,     sample_fmts_s16,  adpcm_ima_dk3,     "ADPCM IMA Duck DK3");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4,     sample_fmts_s16,  adpcm_ima_dk4,     "ADPCM IMA Duck DK4");