[FFmpeg-devel] [PATCH 1/3] avcodec: add siren audio decoder

Paul B Mahol onemda at gmail.com
Wed Apr 4 18:20:31 EEST 2018


On 4/4/18, James Almer <jamrial at gmail.com> wrote:
> 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.

ok


>
>> +
>> +    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()

ok


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

ok

>
>> +        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?
>

ok


>> +    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?

What?

>
>> +
>> +        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?

I do not think so.

>
>> +        }
>> +    }
>> +
>> +    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,
>> +};
>>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list