Hi,

This patch is the second qualification task of my project.
The patch isn't final yet.
I've got it reviewed by Thilo Borgmann and now sending it here.

Currently, it decodes the floating point data perfectly, and prints
the output to the console.
I matched the output float values with the ones in the original .wav
file and they are same.

Right now, I'm having problem with writing the data to the output
file. The output file generated is almost half the size of what it
should be. I've checked the code and it should work but it doesn't.

I'm also attaching the encoded file having floating point sample data
which I use for testing.

Umair
From cdaf469a9832812755924485e7f83a465652612a Mon Sep 17 00:00:00 2001
From: Umair Khan <omerj...@gmail.com>
Date: Sat, 16 Apr 2016 17:56:13 +0530
Subject: [PATCH] Implement floating point decoding in ALS

Signed-off-by: Umair Khan <omerj...@gmail.com>
---
 libavcodec/alsdec.c | 484 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 479 insertions(+), 5 deletions(-)

diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c
index 1402b00..97f650c 100644
--- a/libavcodec/alsdec.c
+++ b/libavcodec/alsdec.c
@@ -37,6 +37,7 @@
 #include "internal.h"
 #include "libavutil/samplefmt.h"
 #include "libavutil/crc.h"
+#include "libavutil/intfloat.h"
 
 #include <stdint.h>
 
@@ -188,6 +189,14 @@ typedef struct ALSChannelData {
 } ALSChannelData;
 
 
+typedef struct MaskedLZDict {
+    int  string_code;
+    int  parent_code;
+    int  char_code;
+    int  match_len;
+} MaskedLZDict;
+
+
 typedef struct ALSDecContext {
     AVCodecContext *avctx;
     ALSSpecificConfig sconf;
@@ -225,6 +234,15 @@ typedef struct ALSDecContext {
     int32_t **raw_samples;          ///< decoded raw samples for each channel
     int32_t *raw_buffer;            ///< contains all decoded raw samples including carryover samples
     uint8_t *crc_buffer;            ///< buffer of byte order corrected samples used for CRC check
+    //float data
+    MaskedLZDict* dict;
+    float *acf;
+    int *last_acf_mantissa;
+    int *shift_value;
+    int *last_shift_value;
+    int **raw_mantissa;           ///< decoded mantissa bits of the difference signal
+    unsigned char *larray;
+    int **nbits;
 } ALSDecContext;
 
 
@@ -247,6 +265,45 @@ typedef struct ALSBlockData {
 } ALSBlockData;
 
 
+/**
+ * Masked LZ compression/decompression
+ */
+
+#define WORD_SIZE           8
+#define WORD_MASK           0xff
+#define CODE_UNSET          -1
+#define CODE_BIT_INIT       9
+#define CODE_BIT_MAX        15
+#define DIC_INDEX_INIT      512     // 2^9
+#define DIC_INDEX_MAX       32768L  // 2^15
+#define FLUSH_CODE          256
+#define FREEZE_CODE         257
+#define FIRST_CODE          258
+#define MAX_CODE            32767L
+#define TABLE_SIZE          35023L  // TABLE_SIZE must be a prime number
+#define MASK_CODE           0
+#define MAX_SEARCH          4       //(DIC_INDEX_MAX)
+
+#define IEEE754_EXP_BIASED  127     // IEEE754 defines exp to be biased by -127
+
+typedef union {
+  float f;
+  struct {
+    unsigned int mantissa : 23;
+    unsigned int exponent : 8;
+    unsigned int sign : 1;
+  } parts;
+} CFloat;
+
+int              dic_code_bit;
+int              current_dic_index_max;
+unsigned int     bump_code;
+unsigned int     flush_code;
+int              next_code;
+int              freeze_flag;
+//Masked LZ ends
+
+
 static av_cold void dprint_specific_config(ALSDecContext *ctx)
 {
 #ifdef DEBUG
@@ -441,7 +498,6 @@ static int check_specific_config(ALSDecContext *ctx)
         }                                               \
     }
 
-    MISSING_ERR(sconf->floating,  "Floating point decoding",     AVERROR_PATCHWELCOME);
     MISSING_ERR(sconf->rlslms,    "Adaptive RLS-LMS prediction", AVERROR_PATCHWELCOME);
 
     return error;
@@ -867,9 +923,6 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
                 *current_res++ = decode_rice(gb, s[sb]);
      }
 
-    if (!sconf->mc_coding || ctx->js_switch)
-        align_get_bits(gb);
-
     return 0;
 }
 
@@ -1006,6 +1059,9 @@ static int read_block(ALSDecContext *ctx, ALSBlockData *bd)
  */
 static int decode_block(ALSDecContext *ctx, ALSBlockData *bd)
 {
+    ALSSpecificConfig *sconf = &ctx->sconf;
+    GetBitContext *gb        = &ctx->gb;
+
     unsigned int smp;
     int ret = 0;
 
@@ -1024,6 +1080,9 @@ static int decode_block(ALSDecContext *ctx, ALSBlockData *bd)
         for (smp = 0; smp < bd->block_length; smp++)
             bd->raw_samples[smp] <<= *bd->shift_lsbs;
 
+    if (!sconf->mc_coding || ctx->js_switch)
+        align_get_bits(gb);
+
     return 0;
 }
 
@@ -1350,6 +1409,376 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd,
 }
 
 
+//initialize dictionary
+static void init_dict(void) {
+    flush_code               = FLUSH_CODE;
+    current_dic_index_max    = DIC_INDEX_INIT;
+    dic_code_bit             = CODE_BIT_INIT;
+    bump_code                = (DIC_INDEX_INIT - 1);
+    next_code                = FIRST_CODE;
+    freeze_flag              = 0;
+}
+
+
+static int decode_string(unsigned char *buff, int string_code, int *first_char_code, unsigned long bufsize, MaskedLZDict* dict) {
+    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:
+//          printf("Dic Index ERR!!! [stringCode == CODE_UNSET]\n");
+            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 ) ) ) {
+//              printf("Dic Index ERR!!!\n");
+                return count;
+            }
+            if ( current_code > FIRST_CODE ) {
+                parent_code = dict[current_code].parent_code;
+                offset = (dict[current_code].match_len) - 1;
+                if ( parent_code < 0 || parent_code > DIC_INDEX_MAX-1 ) {
+//                  fprintf(stderr,"Dic Index ERR!!!\n");
+                    return count;
+                }
+                if (( offset > (DIC_INDEX_MAX - 1))) {
+//                  printf("Dic offset ERR!!!\n");
+                    return count;
+                }
+            }
+            break;
+        }
+    }
+    return count;
+}
+
+
+static void flush_dict(MaskedLZDict* dict) {
+    int i;
+    for ( i = 0; i < TABLE_SIZE; i++ ) {
+        dict[i].string_code = CODE_UNSET;
+        dict[i].parent_code = CODE_UNSET;
+        dict[i].match_len = 0;
+    }
+    //// read first part
+    // initial DicCodes
+    // $0 - 255 xxxx
+    // $256 FLUSH_CODE
+    // $257 FREEZE_CODE
+    // $258 - $(max-2) code
+    // $(max-1) BUMP_CODE
+    // $(max-1) BumpCode  1st BumpCode = 511
+    // add first entry to dictionary as [$258]
+    current_dic_index_max = DIC_INDEX_INIT;
+    dic_code_bit          = CODE_BIT_INIT;  // DicCodeBitInit;
+    bump_code             = current_dic_index_max - 1;
+    next_code             = FIRST_CODE;
+    freeze_flag           = 0;
+}
+
+
+static void set_new_entry_dict(int string_code, int parent_code, int char_code, MaskedLZDict* dict) {
+    dict[string_code].parent_code = parent_code;
+    dict[string_code].string_code = string_code;
+    dict[string_code].char_code   = char_code;
+    if (parent_code < FIRST_CODE) {
+        dict[string_code].match_len = 2;
+    } else {
+//      if ( pDict[parentCode].stringCode == CODE_UNSET )
+//          fprintf(stderr, "Errr stringCode = CODE_UNSET\n");
+        dict[string_code].match_len = (dict[parent_code].match_len) + 1;
+    }
+}
+
+
+static int masked_lz_decompression(ALSDecContext *ctx, int size, unsigned char *buff) {
+    GetBitContext* gb = &ctx->gb;
+    MaskedLZDict *dict = ctx->dict;
+
+    unsigned long output_chars;
+    int string_code, last_string_code, char_code;
+
+    string_code = 0;
+    char_code   = -1;
+    last_string_code = -1;
+
+    output_chars = 0;
+
+    while (output_chars < size) {
+        string_code = get_bits(gb, dic_code_bit);
+        switch (string_code) {
+            case FLUSH_CODE:
+            case MAX_CODE:
+                flush_dict(dict);
+                char_code = -1;
+                last_string_code = -1;
+                break;
+            case FREEZE_CODE:
+                freeze_flag = 1;
+                break;
+            default:
+                if (string_code > current_dic_index_max) {
+                    av_log(ctx->avctx, AV_LOG_ERROR, "string code %d more than the max value.", string_code);
+                    return output_chars;
+                }
+                if (string_code == (int) bump_code) {
+                    ++dic_code_bit;
+                    current_dic_index_max *= 2;
+                    bump_code = current_dic_index_max - 1;
+                } else {
+                    if (string_code >= next_code) {
+                        output_chars += decode_string(&buff[output_chars], last_string_code, &char_code, size - output_chars, dict);
+                        output_chars += decode_string(&buff[output_chars], char_code, &char_code, size - output_chars, dict);
+                        set_new_entry_dict(next_code, last_string_code, char_code, dict);
+                        ++next_code;
+                    } else {
+                        output_chars += decode_string(&buff[output_chars], string_code, &char_code, size - output_chars, dict);
+                        if ((output_chars <= size) && (freeze_flag == 0)) {
+                            if (last_string_code != -1) {
+                                set_new_entry_dict(next_code, last_string_code, char_code, dict);
+                                ++next_code;
+                            } else {
+                                break;
+                            }
+                        }
+                    }
+                    last_string_code = string_code;
+                }
+                break;
+        }
+    }
+    return output_chars;
+}
+
+
+static float multiply(float a, float b) {
+    uint64_t mantissa_temp;
+    uint64_t mask_64;
+    int bit_count;
+    int cutoff_bit_count;
+    unsigned char   last_2_bits;
+    unsigned int    mantissa;
+    int sign;
+    CFloat f1, f2;
+    uint32_t return_val = 0;
+
+    f1.f = a;
+    f2.f = b;
+
+    sign = f1.parts.sign ^ f2.parts.sign;
+
+    //Multiply mantissa bits in a 64-bit register
+    mantissa_temp = (uint64_t) f1.parts.mantissa * (uint64_t) f2.parts.mantissa;
+
+    // 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 );
+
+    // 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 |= (f1.parts.exponent + f2.parts.exponent + bit_count - 47) << 23;
+    return_val |= mantissa;
+    return av_int2float(return_val);
+}
+
+
+static int read_diff_float_data(ALSDecContext *ctx, unsigned int ra_frame) {
+    AVCodecContext *avctx = ctx->avctx;
+    GetBitContext *gb = &ctx->gb;
+    uint32_t tmp_32, num_bytes_diff_float;
+    int use_acf;
+    float *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;
+    unsigned int partA_flag, highest_byte, shift_amp;
+    int frame_length = ctx->cur_frame_length;
+    int nchars;
+    int i, c;
+    long k, nbits_aligned;
+    unsigned long acc, j;
+    uint32_t e;
+    unsigned int mantissa;
+    uint32_t sign;
+    float scale = (float) (0x1u << 23);
+    CFloat temp_pcm;
+
+    num_bytes_diff_float = get_bits_long(gb, 32); //num_bytes_diff_float
+
+    av_log(avctx, AV_LOG_ERROR, "read_diff_float_data() length = %"PRIu32"\n", num_bytes_diff_float);
+    use_acf = get_bits1(gb);
+    if (ra_frame) {
+        for (int c = 0; c < avctx->channels; ++c) {
+            last_acf_mantissa[c] = 0;
+            last_shift_value[c] = 0;
+        }
+        flush_dict(ctx->dict);
+    }
+    for (c = 0; c < avctx->channels; ++c) {
+        if (use_acf) {
+            if (get_bits1(gb) /*acf_flag*/) {
+                tmp_32 = get_bits(gb, 23);
+                last_acf_mantissa[c] = tmp_32;
+            } else {
+                tmp_32 = last_acf_mantissa[c];
+            }
+            acf[c] = av_int2float(tmp_32);
+        } else {
+            acf[c] = 1.0f;
+        }
+        highest_byte = get_bits(gb, 2);
+        shift_amp = get_bits1(gb);
+        partA_flag = 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)/*compressed_flag*/) { //uncompressed
+                for (i = 0; i < frame_length; ++i) {
+                    if (ctx->raw_samples[c][i] == 0) {
+                        tmp_32 = get_bits_long(gb, 32);
+                        ctx->raw_samples[c][i] = tmp_32;
+                    }
+                }
+            } else { //compressed
+                nchars = 0;
+                for (i = 0; i < frame_length; ++i) {
+                    if (ctx->raw_samples[c][i] == 0) {
+                        nchars += 4;
+                    }
+                }
+                masked_lz_decompression(ctx, nchars, larray);
+                for (i = 0; i < frame_length; ++i) {
+                    tmp_32 = (larray[i] << 24) | larray[i+1] << 16 | larray[i+2] << 8 | larray[i+3];
+                    ctx->raw_samples[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 (acf[c] == 1.0f) {
+                        nbits[c][i] = 23;
+                    } else {
+                        nbits[c][i] = 23 - av_log2(abs(ctx->raw_samples[c][i]));
+                    }
+                    nbits[c][i] = FFMIN(nbits[c][i], highest_byte*8);
+                }
+            }
+            if (!get_bits1(gb)/*compressed_flag*/) { //uncompressed
+                for (i = 0; i < frame_length; ++i) {
+                    if (ctx->raw_samples[c][i] != 0) {
+                        raw_mantissa[c][i] = get_bits(gb, nbits[c][i]);
+                    }
+                }
+                av_log(avctx, AV_LOG_ERROR, "partB uncompressed\n");
+            } else { //compressed
+                nchars = 0;
+                for (i = 0; i < frame_length; ++i) {
+                    if (ctx->raw_samples[c][i]) {
+                        nchars += (int) nbits[c][i] / 8;
+                        if (nbits[c][i] % 8 > 0) {
+                            ++nchars;
+                        }
+                    }
+                }
+                masked_lz_decompression(ctx, nchars, larray);
+                j = 0;
+                for (i = 0; i < frame_length; ++i) {
+                    if (ctx->raw_samples[c][i]) {
+                        if ((nbits[c][i] % 8) > 0) {
+                            nbits_aligned = 8 * ((unsigned int)(nbits[c][i] / 8) + 1);
+                        } else {
+                            nbits_aligned = nbits[c][i];
+                        }
+                        acc = 0;
+                        for (k = 0; nbits_aligned/8; ++k) {
+                            acc = ( acc << 8 ) + larray[j++];
+                        }
+                        acc >>= ( nbits_aligned - nbits[c][i] );
+                        raw_mantissa[c][i] = acc;
+                    }
+                }
+            }
+        } else {
+            // av_log(avctx, AV_LOG_ERROR, "no part B\n");
+        }
+
+        for (i = 0; i < frame_length; ++i) {
+            if (ctx->raw_samples[c][i] != 0) {
+                if (acf[c] == 1.0f) {
+                    temp_pcm.f = (float) (ctx->raw_samples[c][i] / scale);
+                    // av_log(avctx, AV_LOG_ERROR, "float = %f\n", temp_pcm.f);
+                } else {
+                    temp_pcm.f = multiply(acf[c], (float) (ctx->raw_samples[c][i] / scale));
+                }
+                e = temp_pcm.parts.exponent;
+
+                mantissa = (temp_pcm.parts.mantissa | 0x800000) + raw_mantissa[c][i];
+                // av_log(avctx, AV_LOG_ERROR, "mantissa = %d\n", mantissa);
+                // av_log(avctx, AV_LOG_ERROR, "e = %d", e);
+                while( mantissa >= 0x1000000 ) {
+                    e++;
+                    mantissa >>= 1;
+                }
+                // av_log(avctx, AV_LOG_ERROR, "after e = %d", e);
+                if ( mantissa ) e += (shift_value[c] - 127);
+                mantissa = (mantissa & 0x007fffffUL) | 0x00800000UL;
+                // av_log(avctx, AV_LOG_ERROR,  "exponent = %d shift = %d\n", e, shift_value[c]);
+                tmp_32 = (sign << 31) | (e << 23) | (mantissa & 0x007fffffUL);
+                ctx->raw_samples[c][i] = tmp_32;
+                av_log(avctx, AV_LOG_ERROR, "final output = %f\n", av_int2float(ctx->raw_samples[c][i]));
+            }
+        }
+        align_get_bits(gb);
+    }
+    return 0;
+}
+
+
 /** Read the frame data.
  */
 static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
@@ -1491,7 +1920,9 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
                     sizeof(*ctx->raw_samples[c]) * sconf->max_order);
     }
 
-    // TODO: read_diff_float_data
+    if (sconf->floating) {
+        read_diff_float_data(ctx, ra_frame);
+    }
 
     if (get_bits_left(gb) < 0) {
         av_log(ctx->avctx, AV_LOG_ERROR, "Overread %d\n", -get_bits_left(gb));
@@ -1661,6 +2092,14 @@ static av_cold int decode_end(AVCodecContext *avctx)
     av_freep(&ctx->chan_data_buffer);
     av_freep(&ctx->reverted_channels);
     av_freep(&ctx->crc_buffer);
+    av_freep(&ctx->dict);
+    av_freep(&ctx->acf);
+    av_freep(&ctx->last_acf_mantissa);
+    av_freep(&ctx->shift_value);
+    av_freep(&ctx->last_shift_value);
+    av_freep(&ctx->raw_mantissa);
+    av_freep(&ctx->larray);
+    av_freep(&ctx->nbits);
 
     return 0;
 }
@@ -1711,6 +2150,12 @@ static av_cold int decode_init(AVCodecContext *avctx)
         }
     }
 
+    if (sconf->floating) {
+        av_log(avctx, AV_LOG_ERROR, "floating is enabled.\n");
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "floating is NOT enabled.\n");
+    }
+
     // set maximum Rice parameter for progressive decoding based on resolution
     // This is not specified in 14496-3 but actually done by the reference
     // codec RM22 revision 2.
@@ -1797,6 +2242,35 @@ static av_cold int decode_init(AVCodecContext *avctx)
     ctx->raw_buffer       = av_mallocz_array(avctx->channels * channel_size, sizeof(*ctx->raw_buffer));
     ctx->raw_samples      = av_malloc_array(avctx->channels, sizeof(*ctx->raw_samples));
 
+    if (sconf->floating) {
+        ctx->dict = av_malloc_array(TABLE_SIZE, sizeof(*ctx->dict));
+        ctx->acf =  av_malloc_array(avctx->channels, sizeof(*ctx->acf));
+        ctx->shift_value = av_malloc_array(avctx->channels, sizeof(*ctx->shift_value));
+        ctx->last_shift_value = av_malloc_array(avctx->channels, sizeof(*ctx->last_shift_value));
+        ctx->last_acf_mantissa = av_malloc_array(avctx->channels, sizeof(*ctx->last_acf_mantissa));
+
+        ctx->raw_mantissa = av_malloc_array(avctx->channels, sizeof(*ctx->raw_mantissa));
+        for (int c = 0; c < avctx->channels; ++c) {
+            ctx->raw_mantissa[c] = av_malloc_array(ctx->cur_frame_length, sizeof(**ctx->raw_mantissa));
+        }
+
+        ctx->larray = av_malloc_array(ctx->cur_frame_length * 4, sizeof(*ctx->larray));
+
+        ctx->nbits = av_malloc_array(avctx->channels, sizeof(*ctx->nbits));
+        for (int c = 0; c < avctx->channels; ++c) {
+            ctx->nbits[c] = av_malloc_array(ctx->cur_frame_length, sizeof(**ctx->nbits));
+        }
+
+        init_dict();
+
+        if (!ctx->dict || !ctx->acf || !ctx->shift_value || !ctx->last_shift_value
+            || !ctx->last_acf_mantissa || !ctx->raw_mantissa) {
+            av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
     // allocate previous raw sample buffer
     if (!ctx->prev_raw_samples || !ctx->raw_buffer|| !ctx->raw_samples) {
         av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
-- 
2.5.0

Attachment: float.mp4
Description: video/mp4

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to