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

thilo.borgmann subversion at mplayerhq.hu
Thu Jun 18 16:04:42 CEST 2009


Author: thilo.borgmann
Date: Thu Jun 18 16:04:42 2009
New Revision: 4489

Log:
Adds structure and functionality to read and process ALSSpecifigConfig during the initialization.

Modified:
   als/alsdec.c

Modified: als/alsdec.c
==============================================================================
--- als/alsdec.c	Thu Jun 18 07:05:42 2009	(r4488)
+++ als/alsdec.c	Thu Jun 18 16:04:42 2009	(r4489)
@@ -26,13 +26,239 @@
  */
 
 
+//#define DEBUG
+
+
 #include "avcodec.h"
+#include "get_bits.h"
+
+
+typedef struct {
+    uint32_t als_id;                 ///< ALS identifier
+    uint32_t samp_freq;              ///< Sampling frequency in Hz
+    uint32_t samples;                ///< Number of samples (per channel). = 0xFFFFFFFF if unknown.
+    int      channels;               ///< Number of channels
+    int      file_type;              ///< Not used. Provided for debugging.
+    int      resolution;             ///< 000 = 8-bit; 001 = 16-bit; 010 = 24-bit; 011 = 32-bit
+    int      floating;               ///< 1 = IEEE 32-bit floating-point, 0 = integer
+    int      msb_first;              ///< Original byte order of the input audio data
+    int      frame_length;           ///< Frame Length
+    int      random_access;          ///< Distance between RA frames (in frames, 0...255)
+    int      ra_flag;                ///< Indicates where the size of ra units is stored.
+    int      adapt_order;            ///< Adaptive order: 1 = on, 0 = off
+    int      coef_table;             ///< Table index of rice code parameters
+    int      long_term_prediction;   ///< Long term prediction (LTP): 1 = on, 0 = off
+    int      max_order;              ///< Maximum prediction order (0..1023)
+    int      block_switching;        ///< Number of block switching levels
+    int      bgmc_mode;              ///< BGMC Mode: 1 = on, 0 = off (Rice coding only)
+    int      sb_part;                ///< Sub-block partition
+    int      joint_stereo;           ///< Joint Stereo: 1 = on, 0 = off
+    int      mc_coding;              ///< Extended inter-channel coding: 1 = on, 0 = off
+    int      chan_config;            ///< Indicates that a chan_config_info field is present
+    int      chan_sort;              ///< Channel rearrangement: 1 = on, 0 = off
+    int      crc_enabled;            ///< Indicates that the crc field is present
+    int      RLSLMS;                 ///< Use RLS-LMS predictor: 1 = on, 0 = off
+    int      aux_data_enabled;       ///< Indicates that auxiliary data is present
+    int      chan_config_info;       ///< Mapping of channels to loudspeaker locations
+    int      *chan_pos;              ///< Original channel positions
+    uint32_t header_size;            ///< Header size of original audio file in bytes. Provided for debugging.
+    uint32_t trailer_size;           ///< Trailer size of original audio file in bytes. Provided for debugging.
+    uint32_t crc;                    ///< 32-bit CCITT-32 CRC checksum
+} ALSSpecificConfig;
 
 
 typedef struct {
+    AVCodecContext    *avctx;
+    ALSSpecificConfig sconf;
+    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.
 } ALSDecContext;
 
 
+#ifdef DEBUG
+static av_cold void dprint_specific_config(ALSDecContext *ctx)
+{
+    AVCodecContext *avctx    = ctx->avctx;
+    ALSSpecificConfig *sconf = &ctx->sconf;
+
+    dprintf(avctx, "als_id = %x\n",               sconf->als_id);
+    dprintf(avctx, "samp_freq = %i\n",            sconf->samp_freq);
+    dprintf(avctx, "samples = %i\n",              sconf->samples);
+    dprintf(avctx, "channels = %i\n",             sconf->channels);
+    dprintf(avctx, "file_type = %i\n",            sconf->file_type);
+    dprintf(avctx, "resolution = %i\n",           sconf->resolution);
+    dprintf(avctx, "floating = %i\n",             sconf->floating);
+    dprintf(avctx, "msb_first = %i\n",            sconf->msb_first);
+    dprintf(avctx, "frame_length = %i\n",         sconf->frame_length);
+    dprintf(avctx, "ra_flag = %i\n",              sconf->ra_flag);
+    dprintf(avctx, "adapt_order = %i\n",          sconf->adapt_order);
+    dprintf(avctx, "coef_table = %i\n",           sconf->coef_table);
+    dprintf(avctx, "long_term_prediction = %i\n", sconf->long_term_prediction);
+    dprintf(avctx, "max_order = %i\n",            sconf->max_order);
+    dprintf(avctx, "block_switching = %i\n",      sconf->block_switching);
+    dprintf(avctx, "bgmc_mode = %i\n",            sconf->bgmc_mode);
+    dprintf(avctx, "sb_part = %i\n",              sconf->sb_part);
+    dprintf(avctx, "joint_stereo = %i\n",         sconf->joint_stereo);
+    dprintf(avctx, "mc_coding = %i\n",            sconf->mc_coding);
+    dprintf(avctx, "chan_config = %i\n",          sconf->chan_config);
+    dprintf(avctx, "chan_sort = %i\n",            sconf->chan_sort);
+    dprintf(avctx, "crc_enabled = %i\n",          sconf->crc_enabled);
+    dprintf(avctx, "RLSLMS = %i\n",               sconf->RLSLMS);
+    dprintf(avctx, "aux_data_enabled = %i\n",     sconf->aux_data_enabled);
+    dprintf(avctx, "chan_config_info = %i\n",     sconf->chan_config_info);
+    dprintf(avctx, "header_size = %i\n",          sconf->header_size);
+    dprintf(avctx, "trailer_size = %i\n",         sconf->trailer_size);
+    dprintf(avctx, "crc_enabled = %i\n",          sconf->crc_enabled);
+
+    dprintf(avctx, " num_frames = %i\n",          ctx->num_frames);
+    dprintf(avctx, " last_frame_length = %i\n",   ctx->last_frame_length);
+}
+#endif
+
+
+/** Reads an ALSSpecificConfig from a buffer into the output struct.
+ */
+static av_cold int read_specific_config(ALSDecContext *ctx,
+                                        const uint8_t *buffer, int buffer_size,
+                                        ALSSpecificConfig *sconf)
+{
+    GetBitContext gb;
+    uint64_t ht_size;
+    int i;
+
+    if (buffer_size < 22)
+        return -1;
+
+    init_get_bits(&gb, buffer, buffer_size * 8);
+
+    // read the fixed items
+    sconf->als_id               = get_bits_long(&gb, 32);
+    sconf->samp_freq            = get_bits_long(&gb, 32);
+    sconf->samples              = get_bits_long(&gb, 32);
+    sconf->channels             = get_bits(&gb, 16) + 1;
+    sconf->file_type            = get_bits(&gb, 3);
+    sconf->resolution           = get_bits(&gb, 3);
+    sconf->floating             = get_bits1(&gb);
+    sconf->msb_first            = get_bits1(&gb);
+    sconf->frame_length         = get_bits(&gb, 16) + 1;
+    sconf->random_access        = get_bits(&gb, 8);
+    sconf->ra_flag              = get_bits(&gb, 2);
+    sconf->adapt_order          = get_bits1(&gb);
+    sconf->coef_table           = get_bits(&gb, 2);
+    sconf->long_term_prediction = get_bits1(&gb);
+    sconf->max_order            = get_bits(&gb, 10);
+    sconf->block_switching      = get_bits(&gb, 2);
+    sconf->bgmc_mode            = get_bits1(&gb);
+    sconf->sb_part              = get_bits1(&gb);
+    sconf->joint_stereo         = get_bits1(&gb);
+    sconf->mc_coding            = get_bits1(&gb);
+    sconf->chan_config          = get_bits1(&gb);
+    sconf->chan_sort            = get_bits1(&gb);
+    sconf->crc_enabled          = get_bits1(&gb);
+    sconf->RLSLMS               = get_bits1(&gb);
+    skip_bits(&gb, 5);                                      // skip 5 reserved bits
+    sconf->aux_data_enabled     = get_bits1(&gb);
+    buffer_size -= 22;
+
+
+    // check for ALSSpecificConfig struct
+    if (sconf->als_id != MKBETAG('A','L','S','\0'))
+        return -1;
+
+
+    // calculate total number of frames to decode if possible
+    if (sconf->samples != 0xFFFFFFFF) {
+        ctx->num_frames        = ((sconf->samples - 1) / sconf->frame_length) + 1;
+        ctx->last_frame_length = sconf->samples % ctx->sconf.frame_length;
+        if (!ctx->last_frame_length) {
+            ctx->last_frame_length = sconf->frame_length;
+        }
+    } else {
+        ctx->num_frames        = 0;
+        ctx->last_frame_length = 0;
+    }
+
+
+    // read channel config
+    if (sconf->chan_config) {
+        if (buffer_size < 2)
+            return -1;
+
+        sconf->chan_config_info = get_bits(&gb, 16);
+        buffer_size -= 2;
+        // TODO: use this to set avctx->channel_layout
+    }
+
+
+    // read channel sorting
+    if (sconf->chan_sort && sconf->channels > 1) {
+        int chan_pos_bits = av_log2((sconf->channels - 1) << 1);
+        int bytes_needed  = (sconf->channels * chan_pos_bits + 7) / 8;
+        if (buffer_size < bytes_needed)
+            return -1;
+
+        if(!(sconf->chan_pos = av_malloc(sconf->channels * sizeof(int))))
+            return -1;
+
+        for (i = 0; i < sconf->channels; i++) {
+            sconf->chan_pos[i] = get_bits(&gb, chan_pos_bits);
+        }
+
+        align_get_bits(&gb);
+        buffer_size -= bytes_needed;
+    } else {
+        sconf->chan_sort = 0;
+    }
+
+
+    // read fixed header and trailer sizes, if size = 0xFFFFFFFF then there is no data field!
+    if (buffer_size < 8)
+        return -1;
+
+    sconf->header_size  = get_bits_long(&gb, 32);
+    sconf->trailer_size = get_bits_long(&gb, 32);
+    if (sconf->header_size  == 0xFFFFFFFF)
+        sconf->header_size  = 0;
+    if (sconf->trailer_size == 0xFFFFFFFF)
+        sconf->trailer_size = 0;
+
+    ht_size = sconf->header_size + sconf->trailer_size;
+
+    buffer_size -= 8;
+
+
+    // skip the header and trailer data
+    if (buffer_size < ht_size)
+        return -1;
+
+    ht_size *= 8;
+
+    while (ht_size > 0) {
+        int len = FFMIN(ht_size, INT32_MAX);
+        skip_bits_long(&gb, len);
+        ht_size -= len;
+    }
+
+    buffer_size -= ht_size;
+
+
+    // read the crc data
+    if (sconf->crc_enabled) {
+        if (buffer_size < 4)
+            return -1;
+
+        sconf->crc = get_bits_long(&gb, 32);
+    }
+
+
+    // no need to read the rest of ALSSpecificConfig (ra_unit_size & aux data)
+#ifdef DEBUG
+    dprint_specific_config(ctx);
+#endif
+    return 0;
+}
+
+
 /** Decodes an ALS frame.
  */
 static int decode_frame(AVCodecContext *avctx,
@@ -47,6 +273,31 @@ static int decode_frame(AVCodecContext *
  */
 static av_cold int decode_init(AVCodecContext *avctx)
 {
+    ALSDecContext *ctx = avctx->priv_data;
+    ctx->avctx = avctx;
+
+    if (!avctx->extradata) {
+        av_log(avctx, AV_LOG_ERROR, "Missing required ALS extradata.\n");
+        return -1;
+    }
+
+    if (read_specific_config(ctx, avctx->extradata + 6,
+                             avctx->extradata_size - 6, &ctx->sconf)) {
+        av_log(avctx, AV_LOG_ERROR, "Reading ALSSpecificConfig failed.\n");
+        return -1;
+    }
+
+    avctx->sample_rate = ctx->sconf.samp_freq;
+    avctx->channels    = ctx->sconf.channels;
+
+    if (ctx->sconf.floating) {
+        avctx->sample_fmt          = SAMPLE_FMT_FLT;
+        avctx->bits_per_raw_sample = 32;
+    } else {
+        avctx->sample_fmt          = ctx->sconf.resolution > 1 ? SAMPLE_FMT_S32 : SAMPLE_FMT_S16;
+        avctx->bits_per_raw_sample = (ctx->sconf.resolution + 1) * 8;
+    }
+
     return 0;
 }
 
@@ -55,6 +306,10 @@ static av_cold int decode_init(AVCodecCo
  */
 static av_cold int decode_end(AVCodecContext *avctx)
 {
+    ALSDecContext *ctx = avctx->priv_data;
+
+    av_freep(&ctx->sconf.chan_pos);
+
     return 0;
 }
 


More information about the FFmpeg-soc mailing list