[FFmpeg-devel] [PATCH] MSN Siren decoder
Peter Ross
pross at xvid.org
Sat Sep 4 10:30:06 EEST 2021
---
Sample: http://samples.ffmpeg.org/A-codecs/msnsiren/msnsiren.wav
Changelog | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/codec_desc.c | 7 +++++
libavcodec/codec_id.h | 1 +
libavcodec/siren.c | 60 +++++++++++++++++++++++++++++++++++++++--
libavformat/riff.c | 1 +
7 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/Changelog b/Changelog
index 5b58401183..0044462bf4 100644
--- a/Changelog
+++ b/Changelog
@@ -16,6 +16,7 @@ version <next>:
- atilt audio filter
- grayworld video filter
- AV1 Low overhead bitstream format muxer
+- 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..df45054a36 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,23 @@ 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 +735,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 +753,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 +778,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 +815,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/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 },
--
2.33.0
-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20210904/cdf23f09/attachment.sig>
More information about the ffmpeg-devel
mailing list