avcodec/siren: MSN Siren decoder

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Peter Ross <pross@xvid.org>
This commit is contained in:
Peter Ross 2021-09-04 17:22:19 +10:00
parent b9426f371a
commit c655a734b1
8 changed files with 70 additions and 3 deletions

View File

@ -17,6 +17,7 @@ version <next>:
- grayworld video filter
- AV1 Low overhead bitstream format muxer
- swscale slice threading
- MSN Siren decoder
version 4.4:

View File

@ -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

View File

@ -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;

View File

@ -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 */
{

View File

@ -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.

View File

@ -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,
};

View File

@ -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, \

View File

@ -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 },