[FFmpeg-soc] [soc]: r5014 - als/alsdec.c

thilo.borgmann subversion at mplayerhq.hu
Mon Aug 10 00:45:16 CEST 2009


Author: thilo.borgmann
Date: Mon Aug 10 00:45:15 2009
New Revision: 5014

Log:
Added functionality for undocumented last frame handling if block switching is enabled.

Modified:
   als/alsdec.c

Modified: als/alsdec.c
==============================================================================
--- als/alsdec.c	Mon Aug 10 00:08:46 2009	(r5013)
+++ als/alsdec.c	Mon Aug 10 00:45:15 2009	(r5014)
@@ -74,6 +74,7 @@ typedef struct {
     ALSSpecificConfig sconf;
     GetBitContext     gb;                ///< A bit reader context.
     unsigned int      num_frames;        ///< Number of frames to decode. 0 if unknown.
+    unsigned int      cur_frame_length;  ///< Length of the current frame to decode.
     unsigned int      last_frame_length; ///< Length of the last frame to decode. 0 if unknown.
     unsigned int      frame_id;          ///< The frame id / number of the current frame.
     unsigned int      js_switch;         ///< If true, joint-stereo decoding is enforced.
@@ -184,6 +185,7 @@ static av_cold int read_specific_config(
     if (sconf->als_id != MKBETAG('A','L','S','\0'))
         return -1;
 
+    ctx->cur_frame_length = sconf->frame_length;
 
     // calculate total number of frames to decode if possible
     if (sconf->samples != 0xFFFFFFFF) {
@@ -357,6 +359,36 @@ static void all_parcor_to_lpc(unsigned i
 }
 
 
+/** Convert block sizes from log2 format into direct form with respect to
+ *  the actual number of samples in the frame.
+ */
+static void reconstruct_block_sizes(ALSDecContext *ctx, uint32_t *div_blocks)
+{
+    unsigned int b;
+
+    // The last frame may have an overdetermined block structure given in
+    // the bitstream which can not be filled with samples completely
+    if (ctx->cur_frame_length == ctx->last_frame_length) {
+        unsigned int remaining = ctx->cur_frame_length;
+
+        for (b = 0; b < ctx->num_blocks; b++) {
+            div_blocks[b] = ctx->sconf.frame_length >> div_blocks[b];
+
+            if (remaining < div_blocks[b]) {
+                div_blocks[b] = remaining;
+                ctx->num_blocks = b + 1;
+                break;
+            } else {
+                remaining -= div_blocks[b];
+            }
+        }
+    } else {
+        for (b = 0; b < ctx->num_blocks; b++)
+            div_blocks[b] = ctx->sconf.frame_length >> div_blocks[b];
+    }
+}
+
+
 /** Reads the block data.
  */
 static int read_block_data(ALSDecContext *ctx, unsigned int ra_block,
@@ -621,7 +653,7 @@ static int read_frame_data(ALSDecContext
     ALSSpecificConfig *sconf = &ctx->sconf;
     GetBitContext *gb = &ctx->gb;
     unsigned int div_blocks[32];                ///< Block sizes.
-    unsigned int c, b, ra_block, block_length;
+    unsigned int c, b, ra_block;
     int64_t *raw_samples;
     uint32_t js_blocks[2];
 
@@ -652,6 +684,7 @@ static int read_frame_data(ALSDecContext
 
             ctx->num_blocks = 0;
             parse_bs_info(bs_info, 0, 0, &ptr_div_blocks, &ctx->num_blocks);
+            reconstruct_block_sizes(ctx, div_blocks);
 
             // if this is the last channel, it has to be decoded independently
             if (c == sconf->channels - 1)
@@ -667,10 +700,9 @@ static int read_frame_data(ALSDecContext
 
                 for (b = 0; b < ctx->num_blocks; b++) {
                     ra_block = !b && ra_frame;
-                    block_length = sconf->frame_length >> div_blocks[b];
-                    read_block_data(ctx, ra_block, raw_samples, block_length,
+                    read_block_data(ctx, ra_block, raw_samples, div_blocks[b],
                                     &js_blocks[0], NULL);
-                    raw_samples += block_length;
+                    raw_samples += div_blocks[b];
                 }
 
                 // store carryover raw samples
@@ -683,17 +715,16 @@ static int read_frame_data(ALSDecContext
                 // decode all blocks
                 for (b = 0; b < ctx->num_blocks; b++) {
                     ra_block = !b && ra_frame;
-                    block_length = sconf->frame_length >> div_blocks[b];
 
                     raw_samples = ctx->raw_samples[c] + offset;
-                    read_block_data(ctx, ra_block, raw_samples, block_length,
+                    read_block_data(ctx, ra_block, raw_samples, div_blocks[b],
                                     &js_blocks[0], ctx->raw_samples[c + 1] + offset);
 
                     raw_samples = ctx->raw_samples[c + 1] + offset;
-                    read_block_data(ctx, ra_block, raw_samples, block_length,
+                    read_block_data(ctx, ra_block, raw_samples, div_blocks[b],
                                     &js_blocks[1], ctx->raw_samples[c] + offset);
 
-                    offset += block_length;
+                    offset += div_blocks[b];
                 }
 
                 // reconstruct joint-stereo blocks
@@ -707,9 +738,8 @@ static int read_frame_data(ALSDecContext
 
                     while (js_blocks[0] || js_blocks[1]) {
                         unsigned int diff_l, diff_r;
-                        block_length   = sconf->frame_length >> div_blocks[b];
-                        raw_samples_L -= block_length;
-                        raw_samples_R -= block_length;
+                        raw_samples_L -= div_blocks[b];
+                        raw_samples_R -= div_blocks[b];
 
                         diff_l = js_blocks[0] & 1;
                         diff_r = js_blocks[1] & 1;
@@ -718,10 +748,10 @@ static int read_frame_data(ALSDecContext
                             if (diff_r)
                                 av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel pair!");
 
-                            for (s = 0; s < block_length; s++)
+                            for (s = 0; s < div_blocks[b]; s++)
                                 raw_samples_L[s] = raw_samples_R[s] - raw_samples_L[s];
                         } else if (diff_r) {                // R = D + L
-                            for (s = 0; s < block_length; s++)
+                            for (s = 0; s < div_blocks[b]; s++)
                                 raw_samples_R[s] = raw_samples_R[s] + raw_samples_L[s];
                         }
 
@@ -752,6 +782,7 @@ static int read_frame_data(ALSDecContext
 
         ctx->num_blocks = 0;
         parse_bs_info(bs_info, 0, 0, &ptr_div_blocks, &ctx->num_blocks);
+        reconstruct_block_sizes(ctx, div_blocks);
 
         // TODO: multi channel coding might use a temporary buffer instead as
         //       the actual channel is not known when read_block-data is called
@@ -759,10 +790,9 @@ static int read_frame_data(ALSDecContext
 
         for (b = 0; b < ctx->num_blocks; b++) {
             ra_block = !b && ra_frame;
-            block_length = sconf->frame_length >> div_blocks[b];
-            read_block_data(ctx, ra_block, raw_samples, block_length,
+            read_block_data(ctx, ra_block, raw_samples, div_blocks[b],
                             &js_blocks[0], NULL);
-            raw_samples += block_length;
+            raw_samples += div_blocks[b];
             // TODO: read_channel_data
         }
     }
@@ -795,7 +825,7 @@ static int decode_frame(AVCodecContext *
 
     // the last frame to decode might have a different length
     if (ctx->num_frames && ctx->num_frames - 1 == ctx->frame_id) {
-        sconf->frame_length = ctx->last_frame_length;
+        ctx->cur_frame_length = ctx->last_frame_length;
     }
 
     // decode the frame data
@@ -809,13 +839,13 @@ static int decode_frame(AVCodecContext *
 
     // transform decoded frame into output format
     // TODO: Support other resolutions than 16 bit
-    for (sample = 0; sample < sconf->frame_length; sample++) {
+    for (sample = 0; sample < ctx->cur_frame_length; sample++) {
         for (c = 0; c < sconf->channels; c++) {
             *(dest++) = (int16_t) (ctx->raw_samples[c][sample]);
         }
     }
 
-    *data_size = sconf->frame_length * sconf->channels
+    *data_size = ctx->cur_frame_length * sconf->channels
                                      * (avctx->sample_fmt == SAMPLE_FMT_S16 ?
                                         2 : 4);
 


More information about the FFmpeg-soc mailing list