[FFmpeg-devel] [PATCH] avcodec/alsdec: implement floating point decoding

Michael Niedermayer michael at niedermayer.cc
Thu Jul 21 15:48:30 EEST 2016


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

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If you fake or manipulate statistics in a paper in physics you will never
get a job again.
If you fake or manipulate statistics in a paper in medicin you will get
a job for life at the pharma industry.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20160721/62843384/attachment.sig>


More information about the ffmpeg-devel mailing list