[FFmpeg-devel] [PATCH 3/3] ADPCM IMA SMJPEG encoder

Paul B Mahol onemda at gmail.com
Wed Nov 7 19:33:33 CET 2012


Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
 libavcodec/Makefile                    |  1 +
 libavcodec/adpcmenc.c                  | 43 ++++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c                 |  2 +-
 tests/fate/acodec.mak                  |  2 ++
 tests/ref/fate/acodec-adpcm-ima_smjpeg |  4 ++++
 5 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 tests/ref/fate/acodec-adpcm-ima_smjpeg

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 5f8776d..d057010 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -577,6 +577,7 @@ OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER)       += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER)   += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_ENCODER)   += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER)      += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_WS_DECODER)       += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 217d165..907cfd0 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -108,6 +108,11 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
         avctx->frame_size  = 64;
         avctx->block_align = 34 * avctx->channels;
         break;
+    case AV_CODEC_ID_ADPCM_IMA_SMJPEG:
+        avctx->frame_size  = 512;
+        avctx->block_align = 260 * avctx->channels;
+        avctx->bits_per_coded_sample = 16;
+        break;
     case AV_CODEC_ID_ADPCM_MS:
         /* each 16 bits sample gives one nibble
            and we have 7 bytes per channel overhead */
@@ -297,6 +302,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx,
     nodes[0]->sample1 = c->sample1;
     nodes[0]->sample2 = c->sample2;
     if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
+        version == AV_CODEC_ID_ADPCM_IMA_SMJPEG ||
         version == AV_CODEC_ID_ADPCM_IMA_QT  ||
         version == AV_CODEC_ID_ADPCM_SWF)
         nodes[0]->sample1 = c->prev_sample;
@@ -401,6 +407,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx,
                                (ff_adpcm_AdaptationTable[nibble] * step) >> 8));
                 }
             } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
+                       version == AV_CODEC_ID_ADPCM_IMA_SMJPEG ||
                        version == AV_CODEC_ID_ADPCM_IMA_QT  ||
                        version == AV_CODEC_ID_ADPCM_SWF) {
 #define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
@@ -576,6 +583,41 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
         flush_put_bits(&pb);
         break;
     }
+    case AV_CODEC_ID_ADPCM_IMA_SMJPEG:
+    {
+        for (ch = 0; ch < avctx->channels; ch++) {
+            ADPCMChannelStatus *status = &c->status[ch];
+            bytestream_put_be16(&dst, status->prev_sample);
+            bytestream_put_byte(&dst, status->step_index);
+            bytestream_put_byte(&dst, 0);
+        }
+
+        if (avctx->trellis > 0) {
+            n = frame->nb_samples;
+            FF_ALLOC_OR_GOTO(avctx, buf, n * 2, error);
+            if (avctx->channels == 1) {
+                adpcm_compress_trellis(avctx, samples, buf,
+                                       &c->status[0], n, avctx->channels);
+                for (i = 0; i < n; i += 2)
+                    bytestream_put_byte(&dst, (buf[i] << 4) | buf[i + 1]);
+            } else {
+                adpcm_compress_trellis(avctx, samples, buf,
+                                       &c->status[0], n, avctx->channels);
+                adpcm_compress_trellis(avctx, samples + 1, buf + n,
+                                       &c->status[1], n, avctx->channels);
+                for (i = 0; i < n; i++)
+                    bytestream_put_byte(&dst, (buf[i] << 4) | buf[n + i]);
+            }
+            av_free(buf);
+        } else {
+            for (i = 0; i < frame->nb_samples >> (1 - st); i++) {
+                int8_t v = adpcm_ima_qt_compress_sample(&c->status[0 ], *samples++) << 4;
+                v       |= adpcm_ima_qt_compress_sample(&c->status[st], *samples++);
+                bytestream_put_byte(&dst, v);
+            }
+        }
+        break;
+    }
     case AV_CODEC_ID_ADPCM_SWF:
     {
         PutBitContext pb;
@@ -729,6 +771,7 @@ AVCodec ff_ ## name_ ## _encoder = {                        \
 
 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT,  adpcm_ima_qt,  sample_fmts_p, "ADPCM IMA QuickTime");
 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, "ADPCM IMA WAV");
+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg, sample_fmts, "ADPCM IMA Loki SDL MJPEG");
 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS,      adpcm_ms,      sample_fmts,   "ADPCM Microsoft");
 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF,     adpcm_swf,     sample_fmts,   "ADPCM Shockwave Flash");
 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA,  adpcm_yamaha,  sample_fmts,   "ADPCM Yamaha");
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 6bad573..b2de67a 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -400,7 +400,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead);
     REGISTER_DECODER (ADPCM_IMA_ISS, adpcm_ima_iss);
     REGISTER_ENCDEC  (ADPCM_IMA_QT, adpcm_ima_qt);
-    REGISTER_DECODER (ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
+    REGISTER_ENCDEC  (ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
     REGISTER_ENCDEC  (ADPCM_IMA_WAV, adpcm_ima_wav);
     REGISTER_DECODER (ADPCM_IMA_WS, adpcm_ima_ws);
     REGISTER_ENCDEC  (ADPCM_MS, adpcm_ms);
diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak
index f1c9f37..8088125 100644
--- a/tests/fate/acodec.mak
+++ b/tests/fate/acodec.mak
@@ -32,6 +32,7 @@ fate-acodec-pcm-f%be: FMT = au
 FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_ADX,     ADX)  += adx
 FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_QT,  AIFF) += ima_qt
 FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_WAV, WAV)  += ima_wav
+FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_SMJPEG, SMJPEG)  += ima_smjpeg
 FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_MS,      WAV)  += ms
 FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_SWF,     FLV)  += swf
 FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_YAMAHA,  WAV)  += yamaha
@@ -45,6 +46,7 @@ fate-acodec-adpcm-%: CODEC = adpcm_$(@:fate-acodec-adpcm-%=%)
 fate-acodec-adpcm-adx:     FMT = adx
 fate-acodec-adpcm-ima_qt:  FMT = aiff
 fate-acodec-adpcm-ima_wav: FMT = wav
+fate-acodec-adpcm-ima_smjpeg: FMT = smjpeg
 fate-acodec-adpcm-ms:      FMT = wav
 fate-acodec-adpcm-swf:     FMT = flv
 fate-acodec-adpcm-yamaha:  FMT = wav
diff --git a/tests/ref/fate/acodec-adpcm-ima_smjpeg b/tests/ref/fate/acodec-adpcm-ima_smjpeg
new file mode 100644
index 0000000..4428a51
--- /dev/null
+++ b/tests/ref/fate/acodec-adpcm-ima_smjpeg
@@ -0,0 +1,4 @@
+87063a56d09563309ddb2f9ed4157209 *tests/data/fate/acodec-adpcm-ima_smjpeg.smjpeg
+275084 tests/data/fate/acodec-adpcm-ima_smjpeg.smjpeg
+1ca3665c65efd6ff480ce4c445dfd32a *tests/data/fate/acodec-adpcm-ima_smjpeg.out.wav
+stddev:  904.76 PSNR: 37.20 MAXDIFF:34029 bytes:  1058400/  1058816
-- 
1.7.11.2



More information about the ffmpeg-devel mailing list