summaryrefslogtreecommitdiff
path: root/libavcodec/siren.c
diff options
context:
space:
mode:
authorPeter Ross <pross@xvid.org>2021-09-04 17:22:19 +1000
committerPeter Ross <pross@xvid.org>2021-09-07 18:07:11 +1000
commitc655a734b1f799e4c41349e99b0e85c5b6e1045c (patch)
tree560419ce96c55ea02ea5bf7fd7ba4fdd0b874df5 /libavcodec/siren.c
parentb9426f371a153d4340cbed0e61e8aed8b5f760f1 (diff)
avcodec/siren: MSN Siren decoder
Reviewed-by: Paul B Mahol <onemda@gmail.com> Signed-off-by: Peter Ross <pross@xvid.org>
Diffstat (limited to 'libavcodec/siren.c')
-rw-r--r--libavcodec/siren.c59
1 files changed, 57 insertions, 2 deletions
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,
+};