[FFmpeg-devel] [PATCH 1/3] avcodec: add siren audio decoder
James Almer
jamrial at gmail.com
Wed Apr 4 18:12:02 EEST 2018
On 4/4/2018 11:09 AM, Paul B Mahol wrote:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/avcodec.h | 1 +
> libavcodec/codec_desc.c | 8 +
> libavcodec/siren.c | 847 ++++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 858 insertions(+)
> create mode 100644 libavcodec/siren.c
[...]
> +static av_cold int siren_init(AVCodecContext *avctx)
> +{
> + SirenContext *s = avctx->priv_data;
> + int i;
> +
> + avctx->channels = 1;
> + avctx->channel_layout = AV_CH_LAYOUT_MONO;
> + avctx->sample_fmt = AV_SAMPLE_FMT_S16;
> +
> + s->number_of_coefs = 320;
> + s->rate_control_bits = 4;
> + s->rate_control_possibilities = 16;
> + s->checksum_bits = 0;
> + s->esf_adjustment = 7;
> + s->number_of_regions = 14;
> + s->scale_factor = 1;
> + s->bits_per_frame = avctx->sample_rate / 50;
> + s->region_size = 20;
> + s->dw1 = s->dw2 = s->dw3 = s->dw4 = 1;
> +
> + for (i = 0; i < 64; i++) {
> + float region_power = powf(10, (i - 24) * STEPSIZE);
> +
> + s->standard_deviation[i] = sqrtf(region_power);
> + s->deviation_inverse[i] = 1.f / s->standard_deviation[i];
> + }
> +
> + for (i = 0; i < 320; i++) {
> + float angle = ((i + 0.5f) * M_PI_2) / 320.f;
> + s->window[i] = sinf(angle);
> + }
> +
> + ff_fft_init(&s->fft_ctx, 10, 0);
Missing fft dependency in configure.
> +
> + return 0;
> +}
[...]
> +
> +static int categorize_regions(int number_of_regions, int number_of_available_bits,
> + int *absolute_region_power_index, int *power_categories,
> + int *category_balance)
> +{
> + int region, delta, i, temp;
> + int expected_number_of_code_bits;
> + int min, max;
> + int offset,
> + num_rate_control_possibilities,
> + raw_value, raw_max_idx = 0, raw_min_idx = 0;
> + int max_rate_categories[28];
> + int min_rate_categories[28];
> + int temp_category_balances[64];
> + int *min_rate_ptr = NULL;
> + int *max_rate_ptr = NULL;
> +
> + if (number_of_regions == 14) {
> + num_rate_control_possibilities = 16;
> + if (number_of_available_bits > 320)
> + number_of_available_bits =
> + ((number_of_available_bits - 320) * 5 / 8) + 320;
> + } else {
> + num_rate_control_possibilities = 32;
> + if (number_of_regions == 28 && number_of_available_bits > 640)
> + number_of_available_bits =
> + ((number_of_available_bits - 640) * 5 / 8) + 640;
> + }
> +
> + offset = -32;
> + for (delta = 32; number_of_regions > 0 && delta > 0; delta /= 2) {
> + expected_number_of_code_bits = 0;
> + for (region = 0; region < number_of_regions; region++) {
> + i = (delta + offset -
> + absolute_region_power_index[region]) >> 1;
> + if (i > 7)
> + i = 7;
> + else if (i < 0)
> + i = 0;
av_clip_uintp2()
> +
> + power_categories[region] = i;
> + expected_number_of_code_bits += expected_bits_table[i];
> +
> + }
> + if (expected_number_of_code_bits >= number_of_available_bits - 32)
> + offset += delta;
> + }
> +
> + expected_number_of_code_bits = 0;
> + for (region = 0; region < number_of_regions; region++) {
> + i = (offset - absolute_region_power_index[region]) >> 1;
> + if (i > 7)
> + i = 7;
> + else if (i < 0)
> + i = 0;
Same.
> + max_rate_categories[region] = min_rate_categories[region] =
> + power_categories[region] = i;
> + expected_number_of_code_bits += expected_bits_table[i];
> + }
[...]
> +static int siren_decode(AVCodecContext *avctx, void *data,
> + int *got_frame, AVPacket *pkt)
> +{
> + SirenContext *s = avctx->priv_data;
> + AVFrame *frame = data;
> + int number_of_valid_coefs = 20 * s->number_of_regions;
> + int number_of_available_bits =
> + s->bits_per_frame - s->sample_rate_bits - s->checksum_bits;
s->checksum_bits seems to always be 0, unless I'm missing something.
> + int envelope_bits, ret;
> + int frame_error = 0, i, rate_control = 0;
> + int checksum, calculated_checksum;
> +
> + if (s->checksum_bits > 0)
> + memcpy(s->input_frame, pkt->data, FFMIN(pkt->size, 80));
sizeof(s->input_frame) instead of 80?
> + if ((ret = init_get_bits8(&s->gb, pkt->data, pkt->size)) < 0)
> + return ret;
> +
> + envelope_bits =
> + decode_envelope(s, &s->gb, s->number_of_regions,
> + s->decoder_standard_deviation,
> + s->absolute_region_power_index, s->esf_adjustment);
> +
> + number_of_available_bits -= envelope_bits;
> +
> + for (i = 0; i < s->rate_control_bits; i++) {
> + rate_control <<= 1;
> + rate_control |= get_bits1(&s->gb);
> + }
> +
> + number_of_available_bits -= s->rate_control_bits;
> +
> + categorize_regions(s->number_of_regions, number_of_available_bits,
> + s->absolute_region_power_index, s->power_categories,
> + s->category_balance);
> +
> + for (i = 0; i < rate_control; i++) {
> + s->power_categories[s->category_balance[i]]++;
> + }
> +
> + number_of_available_bits =
> + decode_vector(s, s->number_of_regions, number_of_available_bits,
> + s->decoder_standard_deviation, s->power_categories,
> + s->coefs, s->scale_factor);
> +
> + if (number_of_available_bits > 0) {
> + for (i = 0; i < number_of_available_bits; i++) {
> + if (!get_bits1(&s->gb))
> + frame_error = 1;
> + }
> + } else if (number_of_available_bits < 0
> + && rate_control + 1 < s->rate_control_possibilities) {
> + frame_error |= 2;
> + }
> +
> + for (i = 0; i < s->number_of_regions; i++) {
> + if (s->absolute_region_power_index[i] > 33
> + || s->absolute_region_power_index[i] < -31)
> + frame_error |= 4;
> + }
> +
> + if (s->checksum_bits > 0) {
> + int idx = 0, sum = 0;
> +
> + s->bits_per_frame >>= 4;
> + checksum = s->input_frame[s->bits_per_frame - 1] & ((1 << s->checksum_bits) - 1);
> + s->input_frame[s->bits_per_frame - 1] &= ~checksum;
> + do {
> + sum ^= (s->input_frame[idx] & 0xFFFF) << (idx % 15);
> + } while (++idx < s->bits_per_frame);
> +
> + sum = (sum >> 15) ^ (sum & 0x7FFF);
> + calculated_checksum = 0;
> + for (i = 0; i < 4; i++) {
> + int j, temp1 = checksum_table[i] & sum;
> + for (j = 8; j > 0; j >>= 1) {
> + int temp2 = temp1 >> j;
> + temp1 ^= temp2;
> + }
> + calculated_checksum <<= 1;
> + calculated_checksum |= temp1 & 1;
> + }
AVCRC?
> +
> + if (checksum != calculated_checksum)
> + frame_error |= 8;
> + }
> +
> + if (frame_error != 0) {
> + for (i = 0; i < number_of_valid_coefs; i++) {
> + s->coefs[i] = s->backup_frame[i];
> + s->backup_frame[i] = 0;
> + }
> + } else {
> + for (i = 0; i < number_of_valid_coefs; i++)
> + s->backup_frame[i] = s->coefs[i];
> + }
> +
> + for (i = number_of_valid_coefs; i < s->number_of_coefs; i++)
> + s->coefs[i] = 0;
> +
> + *got_frame = decode_samples(s, s->coefs, s->context, s->number_of_coefs, s->output_frame);
> + if (*got_frame) {
> + int16_t *dst;
> +
> + frame->nb_samples = 320;
> + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> + return ret;
> + dst = (int16_t *)frame->data[0];
> +
> + for (i = 0; i < frame->nb_samples; i++) {
> + dst[i] = av_clip_int16(s->output_frame[i]);
Can't you clip them in decode_samples() instead, so you can replace this
with a memcpy?
> + }
> + }
> +
> + return pkt->size;
> +}
> +
> +static av_cold int siren_close(AVCodecContext *avctx)
> +{
> + SirenContext *s = avctx->priv_data;
> +
> + ff_fft_end(&s->fft_ctx);
> +
> + return 0;
> +}
> +
> +AVCodec ff_siren_decoder = {
> + .name = "siren",
> + .long_name = NULL_IF_CONFIG_SMALL("Siren"),
> + .priv_data_size = sizeof(SirenContext),
> + .type = AVMEDIA_TYPE_AUDIO,
> + .id = AV_CODEC_ID_SIREN,
> + .init = siren_init,
> + .close = siren_close,
> + .decode = siren_decode,
> + .capabilities = AV_CODEC_CAP_DR1,
> +};
>
More information about the ffmpeg-devel
mailing list