From c655a734b1f799e4c41349e99b0e85c5b6e1045c Mon Sep 17 00:00:00 2001 From: Peter Ross Date: Sat, 4 Sep 2021 17:22:19 +1000 Subject: [PATCH] avcodec/siren: MSN Siren decoder Reviewed-by: Paul B Mahol Signed-off-by: Peter Ross --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 +++++ libavcodec/codec_id.h | 1 + libavcodec/siren.c | 59 +++++++++++++++++++++++++++++++++++++++-- libavcodec/version.h | 2 +- libavformat/riff.c | 1 + 8 files changed, 70 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index f66f47b6cb..df24c69a69 100644 --- a/Changelog +++ b/Changelog @@ -17,6 +17,7 @@ version : - grayworld video filter - AV1 Low overhead bitstream format muxer - swscale slice threading +- MSN Siren decoder version 4.4: diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 68d808de42..11873eecae 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -508,6 +508,7 @@ OBJS-$(CONFIG_MSMPEG4V2_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V2_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V3_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o +OBJS-$(CONFIG_MSNSIREN_DECODER) += siren.o OBJS-$(CONFIG_MSP2_DECODER) += msp2dec.o OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index c087b91148..c42aba140d 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -479,6 +479,7 @@ extern const AVCodec ff_mp3on4float_decoder; extern const AVCodec ff_mp3on4_decoder; extern const AVCodec ff_mpc7_decoder; extern const AVCodec ff_mpc8_decoder; +extern const AVCodec ff_msnsiren_decoder; extern const AVCodec ff_nellymoser_encoder; extern const AVCodec ff_nellymoser_decoder; extern const AVCodec ff_on2avc_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 674f4bf8c3..a06992fce8 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3222,6 +3222,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_MSNSIREN, + .type = AVMEDIA_TYPE_AUDIO, + .name = "msnsiren", + .long_name = NULL_IF_CONFIG_SMALL("MSN Siren"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index d49f9af36c..446bb2c2fb 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -514,6 +514,7 @@ enum AVCodecID { AV_CODEC_ID_SIREN, AV_CODEC_ID_HCA, AV_CODEC_ID_FASTAUDIO, + AV_CODEC_ID_MSNSIREN, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/siren.c b/libavcodec/siren.c index 87464808a4..0675fbaffd 100644 --- a/libavcodec/siren.c +++ b/libavcodec/siren.c @@ -359,11 +359,13 @@ static const float noise_category6[21] = { typedef struct SirenContext { GetBitContext gb; + int microsoft; int rate_control_possibilities; int esf_adjustment; int number_of_regions; int scale_factor; int sample_rate_bits; + int checksum_bits; unsigned dw1, dw2, dw3, dw4; @@ -421,6 +423,15 @@ static av_cold int siren_init(AVCodecContext *avctx) if (!s->fdsp) return AVERROR(ENOMEM); + s->microsoft = avctx->codec->id == AV_CODEC_ID_MSNSIREN; + if (s->microsoft) { + s->esf_adjustment = -2; + s->number_of_regions = 14; + s->scale_factor = 1; + s->sample_rate_bits = 2; + s->checksum_bits = 4; + } + return av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_MDCT, 1, FRAME_SIZE, &scale, 0); } @@ -626,6 +637,20 @@ static int decode_vector(SirenContext *s, int number_of_regions, coefs_ptr = coefs + (region * REGION_SIZE); + if (category == 5 && s->microsoft) { + i = 0; + for (j = 0; j < REGION_SIZE; j++) { + if (*coefs_ptr != 0) { + i++; + if (fabs(*coefs_ptr) > 2.0 * decoder_standard_deviation[region]) { + i += 3; + } + } + coefs_ptr++; + } + + noise = decoder_standard_deviation[region] * noise_category5[i]; + } else if (category == 5 || category == 6) { i = 0; for (j = 0; j < REGION_SIZE; j++) { @@ -675,10 +700,22 @@ static int siren_decode(AVCodecContext *avctx, void *data, AVFrame *frame = data; int ret, number_of_valid_coefs = 20 * s->number_of_regions; int frame_error = 0, rate_control = 0; + int bits_per_frame; + if (s->microsoft) { + bits_per_frame = avctx->sample_rate / 50; + + if (avpkt->size < bits_per_frame / 8) + return AVERROR_INVALIDDATA; + + if ((ret = init_get_bits(gb, avpkt->data, bits_per_frame - s->checksum_bits)) < 0) + return ret; + } else if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0) return ret; + skip_bits(gb, s->sample_rate_bits); + decode_envelope(s, gb, s->number_of_regions, s->decoder_standard_deviation, s->absolute_region_power_index, s->esf_adjustment); @@ -697,7 +734,7 @@ static int siren_decode(AVCodecContext *avctx, void *data, ret = decode_vector(s, s->number_of_regions, get_bits_left(gb), s->decoder_standard_deviation, s->power_categories, s->imdct_in, s->scale_factor); - if (ret < 0) + if (ret < 0 && !s->microsoft) return ret; if (get_bits_left(gb) > 0) { @@ -715,6 +752,8 @@ static int siren_decode(AVCodecContext *avctx, void *data, frame_error = 1; } + skip_bits(gb, s->checksum_bits); + if (frame_error) { memcpy(s->imdct_in, s->backup_frame, number_of_valid_coefs * sizeof(float)); memset(s->backup_frame, 0, number_of_valid_coefs * sizeof(float)); @@ -738,7 +777,7 @@ static int siren_decode(AVCodecContext *avctx, void *data, *got_frame = 1; - return avpkt->size; + return s->microsoft ? bits_per_frame / 8 : avpkt->size; } static av_cold void siren_flush(AVCodecContext *avctx) @@ -775,3 +814,19 @@ const AVCodec ff_siren_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; + +const AVCodec ff_msnsiren_decoder = { + .name = "msnsiren", + .long_name = NULL_IF_CONFIG_SMALL("MSN Siren"), + .priv_data_size = sizeof(SirenContext), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MSNSIREN, + .init = siren_init, + .close = siren_close, + .decode = siren_decode, + .flush = siren_flush, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 7839bf945d..83db2b242a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 59 #define LIBAVCODEC_VERSION_MINOR 7 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 423926e3bd..27a9706510 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -560,6 +560,7 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_DVAUDIO, 0x0215 }, { AV_CODEC_ID_DVAUDIO, 0x0216 }, { AV_CODEC_ID_ATRAC3, 0x0270 }, + { AV_CODEC_ID_MSNSIREN, 0x028E }, { AV_CODEC_ID_ADPCM_G722, 0x028F }, { AV_CODEC_ID_IMC, 0x0401 }, { AV_CODEC_ID_IAC, 0x0402 },