[FFmpeg-soc] [soc]: r4544 - als/alsdec.c
thilo.borgmann
subversion at mplayerhq.hu
Sun Jun 28 22:48:05 CEST 2009
Author: thilo.borgmann
Date: Sun Jun 28 22:48:05 2009
New Revision: 4544
Log:
Adds functionality to read the frame data.
Modified:
als/alsdec.c
Modified: als/alsdec.c
==============================================================================
--- als/alsdec.c Sun Jun 28 06:11:53 2009 (r4543)
+++ als/alsdec.c Sun Jun 28 22:48:05 2009 (r4544)
@@ -70,8 +70,11 @@ typedef struct {
typedef struct {
AVCodecContext *avctx;
ALSSpecificConfig sconf;
+ GetBitContext gb; ///< A bit reader context.
unsigned int num_frames; ///< Number of frames to decode. 0 if unknown.
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.
} ALSDecContext;
@@ -259,12 +262,140 @@ static av_cold int read_specific_config(
}
+/** Parses the bs_info item to extract the block partitioning.
+ */
+static void parse_bs_info(uint32_t bs_info, unsigned int n, unsigned int div,
+ unsigned int **div_blocks, unsigned int *num_blocks)
+{
+ if (n < 32 && ((bs_info >> (30 - n)) & 1)) {
+ // if the level is valid and the investigated bit n is set
+ // then recursively check both children at bits (2n+1) and (2n+2)
+ n *= 2;
+ div += 1;
+ parse_bs_info(bs_info, n + 1, div, div_blocks, num_blocks);
+ parse_bs_info(bs_info, n + 2, div, div_blocks, num_blocks);
+ } else {
+ // else the bit is not set or the last level has been reached
+ // (bit implicitly not set)
+ **div_blocks = div;
+ (*div_blocks)++;
+ (*num_blocks)++;
+ }
+}
+
+
+/** Reads the frame data.
+ */
+static int read_frame_data(ALSDecContext *ctx)
+{
+ ALSSpecificConfig *sconf = &ctx->sconf;
+ GetBitContext *gb = &ctx->gb;
+ int c, b;
+ uint32_t bs_info = 0;
+ unsigned int num_blocks;
+ unsigned int div_blocks[32];
+ unsigned int *ptr_div_blocks = &div_blocks[0];
+
+ // skip ra_unit_size if present
+ if (sconf->ra_flag == 1 && !(ctx->frame_id % sconf->random_access))
+ skip_bits_long(gb, 32);
+
+ if (sconf->mc_coding && sconf->joint_stereo) {
+ ctx->js_switch = get_bits1(gb);
+ align_get_bits(gb);
+ }
+
+ if (!sconf->mc_coding || ctx->js_switch) {
+ int independent_bs = !sconf->joint_stereo;
+
+ for (c = 0; c < sconf->channels; c++) {
+ if (sconf->block_switching) {
+ unsigned int bs_info_len = 1 << (sconf->block_switching + 2);
+ bs_info = get_bits_long(gb, bs_info_len);
+ bs_info <<= (32 - bs_info_len);
+ }
+
+ num_blocks = 0;
+ parse_bs_info(bs_info, 0, 0, &ptr_div_blocks, &num_blocks);
+#ifdef DEBUG
+ dprintf(ctx->avctx, "bs_info = %x, block sizes:", bs_info);
+ for (b = 0; b < num_blocks; b++)
+ dprintf(ctx->avctx, " %i", div_blocks[b]);
+ dprintf(ctx->avctx, "\n");
+#endif
+ // if this is the last channel, it has to be decoded independently
+ if (c == sconf->channels - 1)
+ independent_bs = 1;
+
+ // if joint_stereo and block_switching is set, independent decoding
+ // is signaled via the first bit of bs_info
+ if(sconf->joint_stereo && sconf->block_switching)
+ independent_bs = bs_info >> 31;
+
+ if (independent_bs) {
+ for (b = 0; b < num_blocks; b++) {
+ dprintf(ctx->avctx, "reading block A\n");
+ read_block_data(ctx);
+ }
+ } else {
+ for (b = 0; b < num_blocks; b++) {
+ dprintf(ctx->avctx, "reading block B\n");
+ read_block_data(ctx);
+ dprintf(ctx->avctx, "reading block C\n");
+ read_block_data(ctx);
+ }
+ c++;
+ }
+ }
+ } else {
+ if (sconf->block_switching) {
+ unsigned int bs_info_len = 1 << (sconf->block_switching + 2);
+ bs_info = get_bits_long(gb, bs_info_len);
+ bs_info <<= (32 - bs_info_len);
+ }
+
+ num_blocks = 0;
+ parse_bs_info(bs_info, 0, 0, &ptr_div_blocks, &num_blocks);
+#ifdef DEBUG
+ dprintf(ctx->avctx, "bs_info = %x, block sizes:", bs_info);
+ for (b = 0; b < num_blocks; b++)
+ dprintf(ctx->avctx, " %i", div_blocks[b]);
+ dprintf(ctx->avctx, "\n");
+#endif
+
+ for (b = 0; b < num_blocks; b++) {
+ dprintf(ctx->avctx, "reading block D\n");
+ read_block_data(ctx);
+ // TODO: read_channel_data
+ }
+ }
+
+ if (sconf->floating) {
+ unsigned int num_bytes_diff_float = get_bits_long(gb, 32);
+ // TODO: read_diff_float_data
+ }
+
+ return 0;
+}
+
+
/** Decodes an ALS frame.
*/
static int decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
AVPacket *avpkt)
{
+ ALSDecContext *ctx = avctx->priv_data;
+ const uint8_t *buffer = avpkt->data;
+ int buffer_size = avpkt->size;
+
+ init_get_bits(&ctx->gb, buffer, buffer_size * 8);
+
+ if(read_frame_data(ctx)) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "Reading frame data failed.\n");
+ return -1;
+ }
+
return 0;
}
More information about the FFmpeg-soc
mailing list