mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-08 06:09:50 +00:00
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:
parent
b9426f371a
commit
c655a734b1
8 changed files with 70 additions and 3 deletions
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue