[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