History

avcodec: add adpcm_ima_amv encoder

Fixes ticket #747.

Zane van Iperen committed 6 years ago

Commit 555f5c11 parent 8903cb34 files · +60 −2Browse files

Unified · Split

4 files
  1. doc/general_contents.texi +1 −1
  2. libavcodec/adpcmenc.c +57 −1
  3. libavcodec/allcodecs.c +1 −0
  4. libavcodec/utils.c +1 −0
doc/general_contents.texi+1−1
@@ -1106,7 +1106,7 @@ following image formats are supported: · 1105 unmodified lines
11061106 @item ADPCM Electronic Arts XAS @tab @tab X
11071107 @item ADPCM G.722 @tab X @tab X
11081108 @item ADPCM G.726 @tab X @tab X
1109−@item ADPCM IMA AMV @tab @tab X
1109+@item ADPCM IMA AMV @tab X @tab X
11101110 @tab Used in AMV files
11111111 @item ADPCM IMA Cunning Developments @tab @tab X
11121112 @item ADPCM IMA Electronic Arts EACS @tab @tab X
libavcodec/adpcmenc.c+57−1
@@ -74,7 +74,12 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) · 73 unmodified lines
7474 return AVERROR(EINVAL);
7575 }
7676
77− if (s->block_size & (s->block_size - 1)) {
77+ /*
78+ * AMV's block size has to match that of the corresponding video
79+ * stream. Relax the POT requirement.
80+ */
81+ if (avctx->codec->id != AV_CODEC_ID_ADPCM_IMA_AMV &&
82+ (s->block_size & (s->block_size - 1))) {
7883 av_log(avctx, AV_LOG_ERROR, "block size must be power of 2\n");
7984 return AVERROR(EINVAL);
8085 }
@@ -161,6 +166,20 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) · 80 unmodified lines
161166 avctx->frame_size = s->block_size * 2 / avctx->channels;
162167 avctx->block_align = s->block_size;
163168 break;
169+ case AV_CODEC_ID_ADPCM_IMA_AMV:
170+ if (avctx->sample_rate != 22050) {
171+ av_log(avctx, AV_LOG_ERROR, "Sample rate must be 22050\n");
172+ return AVERROR(EINVAL);
173+ }
174+
175+ if (avctx->channels != 1) {
176+ av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n");
177+ return AVERROR(EINVAL);
178+ }
179+
180+ avctx->frame_size = s->block_size;
181+ avctx->block_align = 8 + (FFALIGN(avctx->frame_size, 2) / 2);
182+ break;
164183 case AV_CODEC_ID_ADPCM_IMA_APM:
165184 avctx->frame_size = s->block_size * 2 / avctx->channels;
166185 avctx->block_align = s->block_size;
@@ -338,6 +357,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, · 171 unmodified lines
338357 nodes[0]->sample2 = c->sample2;
339358 if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
340359 version == AV_CODEC_ID_ADPCM_IMA_QT ||
360+ version == AV_CODEC_ID_ADPCM_IMA_AMV ||
341361 version == AV_CODEC_ID_ADPCM_SWF)
342362 nodes[0]->sample1 = c->prev_sample;
343363 if (version == AV_CODEC_ID_ADPCM_MS)
@@ -442,6 +462,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, · 98 unmodified lines
442462 }
443463 } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
444464 version == AV_CODEC_ID_ADPCM_IMA_QT ||
465+ version == AV_CODEC_ID_ADPCM_IMA_AMV ||
445466 version == AV_CODEC_ID_ADPCM_SWF) {
446467 #define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
447468 const int predictor = nodes[j]->sample1;\
@@ -834,6 +855,40 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 386 unmodified lines
834855 flush_put_bits(&pb);
835856 break;
836857 }
858+ case AV_CODEC_ID_ADPCM_IMA_AMV:
859+ {
860+ av_assert0(avctx->channels == 1);
861+
862+ c->status[0].prev_sample = *samples;
863+ bytestream_put_le16(&dst, c->status[0].prev_sample);
864+ bytestream_put_byte(&dst, c->status[0].step_index);
865+ bytestream_put_byte(&dst, 0);
866+ bytestream_put_le32(&dst, avctx->frame_size);
867+
868+ if (avctx->trellis > 0) {
869+ n = frame->nb_samples >> 1;
870+
871+ if (!(buf = av_malloc(2 * n)))
872+ return AVERROR(ENOMEM);
873+
874+ adpcm_compress_trellis(avctx, samples, buf, &c->status[0], 2 * n, avctx->channels);
875+ for (i = 0; i < n; i++)
876+ bytestream_put_byte(&dst, (buf[2 * i] << 4) | buf[2 * i + 1]);
877+
878+ samples += 2 * n;
879+ } else for (n = frame->nb_samples >> 1; n > 0; n--) {
880+ int nibble;
881+ nibble = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4;
882+ nibble |= adpcm_ima_compress_sample(&c->status[0], *samples++) & 0x0F;
883+ bytestream_put_byte(&dst, nibble);
884+ }
885+
886+ if (avctx->frame_size & 1) {
887+ int nibble = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4;
888+ bytestream_put_byte(&dst, nibble);
889+ }
890+ break;
891+ }
837892 case AV_CODEC_ID_ADPCM_ARGO:
838893 {
839894 PutBitContext pb;
@@ -927,6 +982,7 @@ AVCodec ff_ ## name_ ## _encoder = { \ · 87 unmodified lines
927982 }
928983
929984 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_ARGO, adpcm_argo, sample_fmts_p, 0, "ADPCM Argonaut Games");
985+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv, sample_fmts, 0, "ADPCM IMA AMV");
930986 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_APM, adpcm_ima_apm, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Ubisoft APM");
931987 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_ALP, adpcm_ima_alp, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA High Voltage Software ALP");
932988 ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0, "ADPCM IMA QuickTime");
libavcodec/allcodecs.c+1−0
@@ -614,6 +614,7 @@ extern AVCodec ff_adpcm_g726_decoder; · 613 unmodified lines
614614 extern AVCodec ff_adpcm_g726le_encoder;
615615 extern AVCodec ff_adpcm_g726le_decoder;
616616 extern AVCodec ff_adpcm_ima_amv_decoder;
617+extern AVCodec ff_adpcm_ima_amv_encoder;
617618 extern AVCodec ff_adpcm_ima_alp_decoder;
618619 extern AVCodec ff_adpcm_ima_alp_encoder;
619620 extern AVCodec ff_adpcm_ima_apc_decoder;
libavcodec/utils.c+1−0
@@ -1491,6 +1491,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) · 1490 unmodified lines
14911491 case AV_CODEC_ID_ADPCM_ARGO:
14921492 case AV_CODEC_ID_ADPCM_CT:
14931493 case AV_CODEC_ID_ADPCM_IMA_ALP:
1494+ case AV_CODEC_ID_ADPCM_IMA_AMV:
14941495 case AV_CODEC_ID_ADPCM_IMA_APC:
14951496 case AV_CODEC_ID_ADPCM_IMA_APM:
14961497 case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t