[FFmpeg-soc] [soc]: r2529 - wmapro/wma3dec.c
faust3
subversion at mplayerhq.hu
Sun Jun 22 11:55:33 CEST 2008
Author: faust3
Date: Sun Jun 22 11:55:33 2008
New Revision: 2529
Log:
decode tiling information
Modified:
wmapro/wma3dec.c
Modified: wmapro/wma3dec.c
==============================================================================
--- wmapro/wma3dec.c (original)
+++ wmapro/wma3dec.c Sun Jun 22 11:55:33 2008
@@ -51,6 +51,7 @@ typedef struct WMA3DecodeContext {
int lossless;
int nb_channels;
wma_channel_t channel[MAX_CHANNELS];
+ int no_tiling;
// Extradata
unsigned int decode_flags;
@@ -65,6 +66,7 @@ typedef struct WMA3DecodeContext {
int len_prefix; //< true if the frame is prefixed with its len
int allow_subframes;
int max_num_subframes;
+ int min_samples_per_subframe;
// Buffered frame data
int prev_frame_bit_size;
@@ -170,6 +172,7 @@ static av_cold int wma3_decode_init(AVCo
log2_max_num_subframes = (s->decode_flags & 0x38) >> 3;
s->max_num_subframes = 1 << log2_max_num_subframes;
s->allow_subframes = s->max_num_subframes > 1;
+ s->min_samples_per_subframe = s->samples_per_frame / s->max_num_subframes;
if(s->max_num_subframes > MAX_SUBFRAMES){
av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n",s->max_num_subframes);
@@ -190,7 +193,174 @@ static av_cold int wma3_decode_init(AVCo
-/* decode one wma frame */
+/**
+ *@brief decode how the data in the frame is split into subframes
+ *@param s context
+ *@param gb current get bit context
+ *@return 0 on success < 0 in case of an error
+ */
+static int wma_decode_tilehdr(WMA3DecodeContext *s, GetBitContext* gb){
+ int c;
+ int missing_samples = s->nb_channels * s->samples_per_frame;
+
+ /** reset tiling information */
+ for(c=0;c<s->nb_channels;c++){
+ s->channel[c].num_subframes = 0;
+ s->channel[c].channel_len = 0;
+ }
+
+ /** handle the easy case whith one constant sized subframe per channel */
+ if(s->max_num_subframes == 1){
+ for(c=0;c<s->nb_channels;c++){
+ s->channel[c].num_subframes = 1;
+ s->channel[c].subframe_len[0] = s->samples_per_frame;
+ s->channel[c].channel_len = 0;
+ }
+ }else{ /** subframe len and number of subframes is not constant */
+ int subframe_len_bits = 0; /** bits needed for the subframe len */
+ int subframe_len_zero_bit = 0; /** how many of the len bits indicate
+ if the subframe is zero */
+
+ /** calculate subframe len bits */
+ if(s->lossless)
+ subframe_len_bits = av_log2(s->max_num_subframes - 1) + 1;
+ else if(s->max_num_subframes == 16){
+ subframe_len_zero_bit = 1;
+ subframe_len_bits = 3;
+ }else
+ subframe_len_bits = av_log2(s->max_num_subframes) + 1;
+
+ /** loop until the frame data is split between the subframes */
+ while(missing_samples > 0){
+ int64_t tileinfo = -1;
+ int min_channel_len = s->samples_per_frame;
+ int num_subframes_per_channel = 0;
+ int num_channels = 0;
+ int subframe_len = s->samples_per_frame / s->max_num_subframes;
+
+ /** find channel with the smallest overall len */
+ for(c=0;c<s->nb_channels;c++){
+ if(min_channel_len > s->channel[c].channel_len)
+ min_channel_len = s->channel[c].channel_len;
+ }
+
+ /** check if this is the start of a new frame */
+ if(missing_samples == s->nb_channels * s->samples_per_frame){
+ s->no_tiling = get_bits1(gb);
+ }
+
+ if(s->no_tiling){
+ num_subframes_per_channel = 1;
+ num_channels = s->nb_channels;
+ }else{
+ /** count how many channels have the minimum len */
+ for(c=0;c<s->nb_channels;c++){
+ if(min_channel_len == s->channel[c].channel_len){
+ ++num_channels;
+ }
+ }
+ if(num_channels <= 1)
+ num_subframes_per_channel = 1;
+ }
+
+ /** maximum number of subframes, evenly split */
+ if(subframe_len == missing_samples / num_channels){
+ num_subframes_per_channel = 1;
+ }
+
+ /** if there might be multiple subframes per channel */
+ if(num_subframes_per_channel != 1){
+ int total_num_bits = num_channels;
+ tileinfo = 0;
+ /** for every channel with the minimum len 1 bit is transmitted that
+ informs us if the channel
+ contains a subframe with the next subframe_len */
+ while(total_num_bits){
+ int num_bits = total_num_bits;
+ if(num_bits > 24)
+ num_bits = 24;
+ tileinfo |= get_bits(gb,num_bits);
+ total_num_bits -= num_bits;
+ num_bits = total_num_bits;
+ tileinfo <<= (num_bits > 24)? 24 : num_bits;
+ }
+ }
+
+
+ /** if the frames are not evenly split get the next subframe len from the bitstream */
+ if(subframe_len != missing_samples / num_channels){
+ int log2_subframe_len;
+ /* 1 bit indicates if the subframe len is zero */
+ if(subframe_len_zero_bit){
+ log2_subframe_len = get_bits1(gb);
+ if(log2_subframe_len){
+ log2_subframe_len = get_bits(gb,subframe_len_bits-1) + 1;
+ }
+ }else
+ log2_subframe_len = get_bits(gb,subframe_len_bits);
+
+ if(s->lossless)
+ subframe_len = s->samples_per_frame / s->max_num_subframes * (log2_subframe_len + 1);
+ else
+ subframe_len = s->samples_per_frame / (1 << log2_subframe_len);
+
+ }
+
+ /** sanity check the len */
+ if(subframe_len < s->min_samples_per_subframe || subframe_len > s->samples_per_frame){
+ av_log(s->avctx, AV_LOG_ERROR, "broken frame: subframe_len %i\n",subframe_len);
+ return -1;
+ }
+ for(c=0; c<s->nb_channels;c++){
+ if(s->channel[c].num_subframes > 32){
+ av_log(s->avctx, AV_LOG_ERROR, "broken frame: num subframes %i\n",s->channel[c].num_subframes);
+ return -1;
+ }
+
+ /** add subframes to the individual channels */
+ if(min_channel_len == s->channel[c].channel_len){
+ --num_channels;
+ if(tileinfo & (1<<num_channels)){
+ if(s->channel[c].num_subframes > 31){
+ av_log(s->avctx, AV_LOG_ERROR, "broken frame: num subframes > 31\n");
+ return -1;
+ }
+ s->channel[c].subframe_len[s->channel[c].num_subframes] = subframe_len;
+ s->channel[c].channel_len += subframe_len;
+ missing_samples -= subframe_len;
+ ++s->channel[c].num_subframes;
+ if(missing_samples < 0 || s->channel[c].channel_len > s->samples_per_frame){
+ av_log(s->avctx, AV_LOG_ERROR, "broken frame: channel len > samples_per_frame\n");
+ return -1;
+ }
+ }
+ }
+ }
+ }
+
+ }
+#if 0
+#undef printf
+
+ for(c=0;c<s->nb_channels;c++){
+ int i;
+ for(i=0;i<s->channel[c].num_subframes;i++){
+ printf("frame[%i] channel[%i] subframe[%i] len %i\n",s->frame_num,c,i,s->channel[c].subframe_len[i]);
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+/**
+ *@brief decode one wma frame
+ *@param s context
+ *@param gb current get bit context
+ *@return 0 if the trailer bit indicates that this is the last frame
+ * 1 if there are more frames
+ */
static int wma_decode_frame(WMA3DecodeContext *s,GetBitContext* gb){
unsigned int gb_start_count = get_bits_count(gb);
int more_frames = 0;
@@ -202,6 +372,12 @@ static int wma_decode_frame(WMA3DecodeCo
av_log(s->avctx,AV_LOG_INFO,"decoding frame with len %x\n",len);
+ /** decode tile information */
+ if(wma_decode_tilehdr(s,gb)){
+ s->packet_loss = 1;
+ return 0;
+ }
+
/* skip the rest of the frame data */
skip_bits_long(gb,len - (get_bits_count(gb) - gb_start_count) - 1);
@@ -292,11 +468,14 @@ static int wma3_decode_packet(AVCodecCon
init_get_bits(&gb_prev, s->prev_frame, s->prev_frame_bit_size);
wma_decode_frame(s,&gb_prev);
}
+ }else if(s->prev_frame_bit_size){
+ av_log(avctx, AV_LOG_ERROR, "ignoring %x previously saved bits\n",s->prev_frame_bit_size);
- /* reset prev frame buffer */
- s->prev_frame_bit_size = 0;
}
+ /* reset prev frame buffer */
+ s->prev_frame_bit_size = 0;
+ s->packet_loss = 0;
/* decode the rest of the packet */
while(more_frames && remaining_bits(s) > s->log2_frame_size){
int frame_size = show_bits(&s->gb, s->log2_frame_size);
@@ -306,6 +485,8 @@ static int wma3_decode_packet(AVCodecCon
/* decode the frame */
more_frames = wma_decode_frame(s,&s->gb);
+ /** the linspire wma decoder does not decode the last frames from the last
+ packet when more_frames is false */
if(!more_frames){
av_log(avctx, AV_LOG_ERROR, "no more frames\n");
}
More information about the FFmpeg-soc
mailing list