]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/adpcm.c
avfilter/vf_lenscorrection: add >8 depth support
[ffmpeg] / libavcodec / adpcm.c
index 7b618dba17f4c0e3721e84cd2a8cf7792f393c63..eb228cc47afe288fc8081ff35484324cf7aeb637 100644 (file)
@@ -775,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)
@@ -783,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);
@@ -1684,6 +1690,16 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
     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);
@@ -1699,6 +1715,17 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
             *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++) {
@@ -2115,6 +2142,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. */