[FFmpeg-devel] [PATCH] avcodec/alsdec: implement floating point decoding
Umair Khan
omerjerk at gmail.com
Fri Jul 22 15:52:30 EEST 2016
On Thu, Jul 21, 2016 at 6:18 PM, Michael Niedermayer
<michael at niedermayer.cc> wrote:
> On Sun, Jul 17, 2016 at 12:06:03AM +0530, Umair Khan wrote:
>> Hi,
>>
>> Patch attached.
>>
>> - Umair
>
>> libavcodec/Makefile | 2
>> libavcodec/alsdec.c | 284 +++++++++++++++++++++++++++++++++++++++++-
>> libavcodec/mlz.c | 171 +++++++++++++++++++++++++
>> libavcodec/mlz.h | 69 ++++++++++
>> libavutil/softfloat_ieee754.h | 115 +++++++++++++++++
>> 5 files changed, 638 insertions(+), 3 deletions(-)
>> 0282267108d74681f1bff6b5e6a85c603ac7052e 0001-avcodec-alsdec-implement-floating-point-decoding.patch
>> From 70e65b26cc3f84c9c664c30808b43a5e1cf16eaa Mon Sep 17 00:00:00 2001
>> From: Umair Khan <omerjerk at gmail.com>
>> Date: Sat, 16 Jul 2016 23:52:39 +0530
>> Subject: [PATCH 1/1] avcodec/alsdec: implement floating point decoding
>>
>> It conforms to RM22 version of the reference codec.
>>
>> Signed-off-by: Umair Khan <omerjerk at gmail.com>
>> ---
>> libavcodec/Makefile | 2 +-
>> libavcodec/alsdec.c | 284 +++++++++++++++++++++++++++++++++++++++++-
>> libavcodec/mlz.c | 171 +++++++++++++++++++++++++
>> libavcodec/mlz.h | 69 ++++++++++
>> libavutil/softfloat_ieee754.h | 115 +++++++++++++++++
>
> missing update to Changelog
>
> [...]
>> @@ -1356,6 +1366,237 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd,
>> }
>>
>>
>> +/** multiply two softfloats and handle the rounding off
>> + */
>> +static SoftFloat_IEEE754 multiply(SoftFloat_IEEE754 a, SoftFloat_IEEE754 b) {
>> + uint64_t mantissa_temp;
>> + uint64_t mask_64;
>> + int bit_count;
>> + int cutoff_bit_count;
>> + unsigned char last_2_bits;
>> + unsigned int mantissa;
>> + uint32_t return_val = 0;
>> + int32_t sign;
>> +
>> + sign = a.sign ^ b.sign;
>> +
>> + // Multiply mantissa bits in a 64-bit register
>> + mantissa_temp = (uint64_t)a.mant * (uint64_t)b.mant;
>> +
>> + // Count the valid bit count
>
>> + for (bit_count=48, mask_64=(uint64_t)0x1 << 47; !(mantissa_temp & mask_64) && mask_64; bit_count--, mask_64>>=1);
>
> this needs some newlines for readability
>
>
>> +
>> + // Round off
>> + cutoff_bit_count = bit_count - 24;
>> + if (cutoff_bit_count > 0) {
>> + last_2_bits = (unsigned char)(((unsigned int)mantissa_temp >> (cutoff_bit_count - 1)) & 0x3 );
>> + if ((last_2_bits == 0x3) || ((last_2_bits == 0x1) && ((unsigned int)mantissa_temp & ((0x1UL << (cutoff_bit_count - 1)) - 1)))) {
>> + // Need to round up
>> + mantissa_temp += (uint64_t)0x1 << cutoff_bit_count;
>> + }
>> + }
>> +
>> + mantissa = (unsigned int)(mantissa_temp >> cutoff_bit_count);
>> +
>> + // Need one more shift?
>> + if (mantissa & 0x01000000ul) {
>> + bit_count++;
>> + mantissa >>= 1;
>> + }
>> +
>> + if (!sign) {
>> + return_val = 0x80000000U;
>> + }
>> +
>> + return_val |= (a.exp + b.exp + bit_count - 47) << 23;
>> + return_val |= mantissa;
>> + return av_bits2sf_ieee754(return_val);
>> +}
>> +
>> +
>> +/** Read and decode the floating point sample data
>> + */
>> +static int read_diff_float_data(ALSDecContext *ctx, unsigned int ra_frame) {
>> + AVCodecContext *avctx = ctx->avctx;
>> + GetBitContext *gb = &ctx->gb;
>> + SoftFloat_IEEE754 *acf = ctx->acf;
>> + int *shift_value = ctx->shift_value;
>> + int *last_shift_value = ctx->last_shift_value;
>> + int *last_acf_mantissa = ctx->last_acf_mantissa;
>> + int **raw_mantissa = ctx->raw_mantissa;
>> + int *nbits = ctx->nbits;
>> + unsigned char *larray = ctx->larray;
>> + int frame_length = ctx->cur_frame_length;
>> + SoftFloat_IEEE754 scale = av_int2sf_ieee754(0x1u, 23);
>> + unsigned int partA_flag;
>> + unsigned int highest_byte;
>> + unsigned int shift_amp;
>> + uint32_t tmp_32;
>> + int use_acf;
>> + int nchars;
>> + int i;
>> + int c;
>> + long k;
>> + long nbits_aligned;
>> + unsigned long acc;
>> + unsigned long j;
>> + uint32_t sign;
>> + uint32_t e;
>> + uint32_t mantissa;
>> +
>> + skip_bits_long(gb, 32); //num_bytes_diff_float
>> + use_acf = get_bits1(gb);
>> +
>> + if (ra_frame) {
>
>> + for (c = 0; c < avctx->channels; ++c) {
>> + last_acf_mantissa[c] = 0;
>> + last_shift_value[c] = 0;
>> + }
>
> memset()
>
>
>> + ff_mlz_flush_dict(ctx->mlz);
>> + }
>> +
>> + for (c = 0; c < avctx->channels; ++c) {
>> + if (use_acf) {
>> + //acf_flag
>> + if (get_bits1(gb)) {
>> + tmp_32 = get_bits(gb, 23);
>> + last_acf_mantissa[c] = tmp_32;
>> + } else {
>> + tmp_32 = last_acf_mantissa[c];
>> + }
>> + acf[c] = av_bits2sf_ieee754(tmp_32);
>> + } else {
>> + acf[c] = FLOAT_1;
>> + }
>> +
>> + highest_byte = get_bits(gb, 2);
>> + partA_flag = get_bits1(gb);
>> + shift_amp = get_bits1(gb);
>> +
>> + if (shift_amp) {
>> + shift_value[c] = get_bits(gb, 8);
>> + last_shift_value[c] = shift_value[c];
>> + } else {
>> + shift_value[c] = last_shift_value[c];
>> + }
>> +
>> + if (partA_flag) {
>> + if (!get_bits1(gb)) { //uncompressed
>> + for (i = 0; i < frame_length; ++i) {
>> + if (ctx->raw_samples[c][i] == 0) {
>> + ctx->raw_mantissa[c][i] = get_bits_long(gb, 32);
>> + }
>> + }
>> + } else { //compressed
>> + nchars = 0;
>> + for (i = 0; i < frame_length; ++i) {
>> + if (ctx->raw_samples[c][i] == 0) {
>> + nchars += 4;
>> + }
>> + }
>> +
>> + tmp_32 = ff_mlz_decompression(ctx->mlz, gb, nchars, larray);
>> + if(tmp_32 != nchars) {
>> + av_log(ctx->avctx, AV_LOG_ERROR, "Error in MLZ decompression (%d, %d).\n", tmp_32, nchars);
>> + return AVERROR_INVALIDDATA;
>> + }
>> +
>> + for (i = 0; i < frame_length; ++i) {
>
>> + tmp_32 = (larray[i] << 24) | larray[i+1] << 16 | larray[i+2] << 8 | larray[i+3];
>
> AV_RB32()
>
>
>> + ctx->raw_mantissa[c][i] = tmp_32;
>> + }
>> + }
>> + }
>> +
>> + //decode part B
>> + if (highest_byte) {
>> + for (i = 0; i < frame_length; ++i) {
>> + if (ctx->raw_samples[c][i] != 0) {
>> + //The following logic is taken from Tabel 14.45 and 14.46 from the ISO spec
>> + if (av_cmp_sf_ieee754(acf[c], FLOAT_1)) {
>> + nbits[i] = 23 - av_log2(abs(ctx->raw_samples[c][i]));
>> + } else {
>> + nbits[i] = 23;
>> + }
>> + nbits[i] = FFMIN(nbits[i], highest_byte*8);
>> + }
>> + }
>> +
>> + if (!get_bits1(gb)) { //uncompressed
>> + for (i = 0; i < frame_length; ++i) {
>> + if (ctx->raw_samples[c][i] != 0) {
>> + raw_mantissa[c][i] = get_bits(gb, nbits[i]);
>> + }
>> + }
>> + } else { //compressed
>> + nchars = 0;
>> + for (i = 0; i < frame_length; ++i) {
>> + if (ctx->raw_samples[c][i]) {
>> + nchars += (int) nbits[i] / 8;
>
>> + if (nbits[i] % 8 > 0) {
>
> can nbits[] be < 0 ?
> if not then &7 is better than %8
>
>
> [...]
>> +static int decode_string(MLZDict *dict, unsigned char *buff, int string_code, int *first_char_code, unsigned long bufsize) {
>> + unsigned long count, offset;
>> + int current_code, parent_code, tmp_code;
>> +
>> + count = 0;
>> + current_code = string_code;
>> + *first_char_code = CODE_UNSET;
>> +
>> + while (count < bufsize) {
>> + switch (current_code) {
>> + case CODE_UNSET:
>> + return count;
>> + break;
>> + default:
>> + if (current_code < FIRST_CODE) {
>> + *first_char_code = current_code;
>> + buff[0] = current_code;
>> + count++;
>> + return count;
>> + } else {
>> + offset = dict[current_code].match_len - 1;
>> + tmp_code = dict[current_code].char_code;
>> + buff[offset] = tmp_code;
>> + count++;
>> + }
>> + current_code = dict[current_code].parent_code;
>> + if ((current_code < 0) || (current_code > (DIC_INDEX_MAX - 1))) {
>
>> + av_log(NULL, AV_LOG_ERROR, "MLZ dic index error.\n");
>
> it would be ideal if all av_log() would have a context instead of NULL
How to go ahead with this? Should I create MLZContext or something? If
yes, could you please tell how?
- Umair
More information about the ffmpeg-devel
mailing list