[FFmpeg-cvslog] avcodec: add ADPCM IMA HVQM4 decoder
Paul B Mahol
git at videolan.org
Wed Feb 23 18:00:43 EET 2022
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Sun Aug 1 21:12:55 2021 +0200| [66aad852aa69e45dd982a310885b08f7e2526115] | committer: Paul B Mahol
avcodec: add ADPCM IMA HVQM4 decoder
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=66aad852aa69e45dd982a310885b08f7e2526115
---
libavcodec/Makefile | 1 +
libavcodec/adpcm.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/allcodecs.c | 1 +
libavcodec/codec_desc.c | 7 ++++++
libavcodec/codec_id.h | 1 +
5 files changed, 74 insertions(+)
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6076b4ad80..276df8ee5b 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -900,6 +900,7 @@ OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_HVQM4_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER) += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index cfde5f58b9..f453628786 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -523,6 +523,49 @@ static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble)
return c->predictor;
}
+static void decode_adpcm_ima_hvqm4(AVCodecContext *avctx, int16_t *outbuf, int samples_to_do,
+ int frame_format, GetByteContext *gb)
+{
+ ADPCMDecodeContext *c = avctx->priv_data;
+ int st = avctx->channels == 2;
+ unsigned tmp;
+
+ for (int ch = 0; ch < avctx->channels; ch++) {
+ switch (frame_format) {
+ case 1: /* combined hist+index */
+ tmp = bytestream2_get_be16(gb);
+ c->status[ch].predictor = sign_extend(tmp & 0xFF80, 16);
+ c->status[ch].step_index = tmp & 0x7f;
+ break;
+ case 2: /* no hist/index (continues from previous frame) */
+ default:
+ break;
+ case 3: /* separate hist+index */
+ tmp = bytestream2_get_be16(gb);
+ c->status[ch].predictor = sign_extend(tmp, 16);
+ c->status[ch].step_index = bytestream2_get_byte(gb);
+ break;
+ }
+
+ c->status[ch].step_index = av_clip(c->status[ch].step_index, 0, 88);
+ }
+
+ if (frame_format == 1 || frame_format == 3) {
+ for (int ch = 0; ch < avctx->channels; ch++)
+ *outbuf++ = (int16_t)c->status[st - ch].predictor;
+ samples_to_do--;
+ }
+
+ for (int i = 0; i < samples_to_do; i++) {
+ uint8_t nibble = bytestream2_get_byte(gb);
+
+ *outbuf++ = adpcm_ima_qt_expand_nibble(&c->status[st], nibble & 0xF);
+ *outbuf++ = adpcm_ima_qt_expand_nibble(&c->status[ 0], nibble >> 4);
+ }
+
+ bytestream2_seek(gb, 0, SEEK_END);
+}
+
static inline int16_t adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble)
{
int predictor;
@@ -910,6 +953,20 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
*coded_samples -= *coded_samples % 28;
nb_samples = (buf_size - 12) / 30 * 28;
break;
+ case AV_CODEC_ID_ADPCM_IMA_HVQM4:
+ {
+ int frame_format = bytestream2_get_be16(gb);
+ int skip = 6;
+
+ if (frame_format == 1)
+ skip += 2 * ch;
+ if (frame_format == 3)
+ skip += 3 * ch;
+
+ nb_samples = (buf_size - skip) * 2 / ch;
+ bytestream2_seek(gb, 0, SEEK_SET);
+ }
+ break;
case AV_CODEC_ID_ADPCM_IMA_EA_EACS:
has_coded_samples = 1;
*coded_samples = bytestream2_get_le32(gb);
@@ -1453,6 +1510,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
}
) /* End of CASE */
+ CASE(ADPCM_IMA_HVQM4,
+ int format = bytestream2_get_be16(&gb);
+
+ bytestream2_skip(&gb, 4);
+ decode_adpcm_ima_hvqm4(avctx, samples, nb_samples, format, &gb);
+ ) /* End of CASE */
CASE(ADPCM_IMA_SSI,
for (int n = nb_samples >> (1 - st); n > 0; n--) {
int v = bytestream2_get_byteu(&gb);
@@ -2322,6 +2385,7 @@ ADPCM_DECODER(ADPCM_IMA_DK3, sample_fmts_s16, adpcm_ima_dk3, "ADPCM IMA
ADPCM_DECODER(ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4, "ADPCM IMA Duck DK4")
ADPCM_DECODER(ADPCM_IMA_EA_EACS, sample_fmts_s16, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS")
ADPCM_DECODER(ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD")
+ADPCM_DECODER(ADPCM_IMA_HVQM4, sample_fmts_s16, adpcm_ima_hvqm4, "ADPCM IMA HVQM4")
ADPCM_DECODER(ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS")
ADPCM_DECODER(ADPCM_IMA_MOFLEX, sample_fmts_s16p, adpcm_ima_moflex, "ADPCM IMA MobiClip MOFLEX")
ADPCM_DECODER(ADPCM_IMA_MTF, sample_fmts_s16, adpcm_ima_mtf, "ADPCM IMA Capcom's MT Framework")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index d1e10197de..89ba205a2f 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -642,6 +642,7 @@ extern const AVCodec ff_adpcm_ima_dk3_decoder;
extern const AVCodec ff_adpcm_ima_dk4_decoder;
extern const AVCodec ff_adpcm_ima_ea_eacs_decoder;
extern const AVCodec ff_adpcm_ima_ea_sead_decoder;
+extern const AVCodec ff_adpcm_ima_hvqm4_decoder;
extern const AVCodec ff_adpcm_ima_iss_decoder;
extern const AVCodec ff_adpcm_ima_moflex_decoder;
extern const AVCodec ff_adpcm_ima_mtf_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 0974ee03de..6deba785dc 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2475,6 +2475,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Acorn Replay"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_ADPCM_IMA_HVQM4,
+ .type = AVMEDIA_TYPE_AUDIO,
+ .name = "adpcm_ima_hvqm4",
+ .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA HVQM4"),
+ .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+ },
/* AMR */
{
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index ab265ec584..f3f262ec75 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -401,6 +401,7 @@ enum AVCodecID {
AV_CODEC_ID_ADPCM_IMA_CUNNING,
AV_CODEC_ID_ADPCM_IMA_MOFLEX,
AV_CODEC_ID_ADPCM_IMA_ACORN,
+ AV_CODEC_ID_ADPCM_IMA_HVQM4,
/* AMR */
AV_CODEC_ID_AMR_NB = 0x12000,
More information about the ffmpeg-cvslog
mailing list