[FFmpeg-soc] [soc]: r2404 - wmapro/wma3dec.c
faust3
subversion at mplayerhq.hu
Sun Jun 8 16:22:58 CEST 2008
Author: faust3
Date: Sun Jun 8 16:22:58 2008
New Revision: 2404
Log:
almost complete rewrite
the packet splitting code should be a lot easier to understand now
also added a wma_decode_frame dummy function
Modified:
wmapro/wma3dec.c
Modified: wmapro/wma3dec.c
==============================================================================
--- wmapro/wma3dec.c (original)
+++ wmapro/wma3dec.c Sun Jun 8 16:22:58 2008
@@ -23,6 +23,7 @@
typedef struct WMA3DecodeContext {
AVCodecContext* avctx;
GetBitContext gb;
+ int buf_bit_size;
// Packet info
int packet_sequence_number;
@@ -34,11 +35,6 @@ typedef struct WMA3DecodeContext {
unsigned int log2_block_align;
unsigned int log2_block_align_bits;
unsigned int log2_frame_size;
- unsigned int num_bits_prev_frame;
- unsigned int num_bits_curr_frame;
- unsigned int cross_frame_needed_bits;
- unsigned int cross_length_prev_bits;
- unsigned int cross_length_prev;
// Extradata
unsigned int decode_flags;
@@ -47,6 +43,13 @@ typedef struct WMA3DecodeContext {
// Packet loss variables
unsigned int packet_loss;
+
+
+
+ // Buffered frame data
+ int prev_frame_bit_size;
+ uint8_t* prev_frame;
+
} WMA3DecodeContext;
@@ -135,99 +138,132 @@ static av_cold int wma3_decode_init(AVCo
return 0;
}
+
+
+/* decode one wma frame */
+static int wma_decode_frame(WMA3DecodeContext *s,GetBitContext* gb){
+ int more_frames = 0;
+ /* get frame length */
+ int len = get_bits(gb,s->log2_frame_size);
+ av_log(s->avctx,AV_LOG_INFO,"decoding frame with len %x\n",len);
+
+ /* decode frame data */
+ skip_bits_long(gb,len - s->log2_frame_size - 1);
+
+ /* decode trailer bit */
+ more_frames = get_bits1(gb);
+ return more_frames;
+}
+
+
+/* calculate remaining bits from the input buffer */
+static int remaining_bits(WMA3DecodeContext *s){
+ return s->buf_bit_size - get_bits_count(&s->gb);
+}
+
+/* store bits from the prev frame into a temporary buffer */
+static void save_bits(WMA3DecodeContext *s,int len){
+ int buflen = (s->prev_frame_bit_size + len + 8) / 8;
+ int bit_offset = s->prev_frame_bit_size % 8;
+ int pos = (s->prev_frame_bit_size - bit_offset) / 8;
+ s->prev_frame_bit_size += len;
+
+ if(len <= 0)
+ return;
+
+ s->prev_frame = av_realloc(s->prev_frame,buflen + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ /* byte align prev_frame buffer */
+ if(bit_offset){
+ if(len > bit_offset)
+ s->prev_frame[pos++] |= get_bits(&s->gb,bit_offset);
+ else
+ s->prev_frame[pos++] |= get_bits(&s->gb,len) << (bit_offset - len);
+ len -= bit_offset;
+ }
+
+ /* copy full bytes */
+ while(len > 7){
+ s->prev_frame[pos++] = get_bits(&s->gb,8);
+ len -= 8;
+ }
+
+ /* copy remaining bits */
+ if(len > 0){
+ s->prev_frame[pos++] |= get_bits(&s->gb,len) << (8 - len);
+ }
+}
+
static int wma3_decode_packet(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
WMA3DecodeContext *s = avctx->priv_data;
int more_frames=1;
- int num_bits_curr_frame, num_bits_prev_frame;
- int i=0, sum=0, cross_frame = 0, buf_bit_size = buf_size << 3;
+ int num_bits_prev_frame;
+ s->buf_bit_size = buf_size << 3;
+
+ *data_size = 0;
+
+ //FIXME check minimum buffer size and check for security problems!!!
+ if(buf_size < avctx->block_align)
+ return 0;
/* Parse packet header */
- init_get_bits(&s->gb, buf, buf_bit_size);
+ init_get_bits(&s->gb, buf, s->buf_bit_size);
s->packet_sequence_number = get_bits(&s->gb, 4);
s->bit5 = get_bits1(&s->gb);
s->bit6 = get_bits1(&s->gb);
- /* Parse frames */
+ /* get number of bits that need to be added to the previous frame */
num_bits_prev_frame = get_bits(&s->gb, s->log2_frame_size);
- av_log(avctx, AV_LOG_ERROR, "[%d]: nbpf %x\n", avctx->frame_number, num_bits_prev_frame);
- if (num_bits_prev_frame) {
- if (s->cross_length_prev_bits) {
- int num_bits_cross_frame = s->cross_length_prev | get_bits(&s->gb, s->log2_frame_size - s->cross_length_prev_bits);
- av_log(avctx, AV_LOG_ERROR, "[%d]: cross length field nbpf %x, %x\n", avctx->frame_number, num_bits_prev_frame + s->cross_length_prev_bits, num_bits_cross_frame);
- skip_bits_long(&s->gb, num_bits_cross_frame - s->log2_frame_size);
- }
- else
- skip_bits_long(&s->gb, num_bits_prev_frame);
- more_frames = 1;
- }
- s->cross_length_prev_bits = 0;
- s->cross_length_prev = 0;
- i = 0;
- do {
- num_bits_curr_frame = get_bits(&s->gb, s->log2_frame_size);
- av_log(avctx, AV_LOG_ERROR, "[%d]:%d nbcf %x ", avctx->frame_number,i, num_bits_curr_frame);
- if (num_bits_curr_frame >= s->log2_frame_size) {
- //Check if the next frame will need data from the next packet
- if (num_bits_curr_frame - s->log2_frame_size <= buf_bit_size - get_bits_count(&s->gb)) {
- int left_bits = buf_bit_size - get_bits_count(&s->gb) - (num_bits_curr_frame - s->log2_frame_size);
- if (left_bits == 0) {
- skip_bits_long(&s->gb, num_bits_curr_frame - s->log2_frame_size);
- more_frames = 0;
- av_log(avctx, AV_LOG_ERROR, "\tfull end\n");
- }
- else {
- skip_bits_long(&s->gb, num_bits_curr_frame - s->log2_frame_size - 1);
- more_frames = get_bits1(&s->gb);
- av_log(avctx, AV_LOG_ERROR, "\tlast bit %d \t lastbit align pos %d\n", more_frames,get_bits_count(&s->gb)%8);
- // Need to save the bits to be handled in next packet?
- if (more_frames && left_bits < s->log2_frame_size) {
- s->cross_length_prev_bits = left_bits;
- s->cross_length_prev = get_bits(&s->gb, left_bits);
- s->cross_length_prev <<= s->log2_frame_size - left_bits;
- more_frames = 0;
- av_log(avctx, AV_LOG_ERROR, "cross length field found: %x/%x, %x\n", left_bits, s->log2_frame_size, s->cross_length_prev);
- }
- }
- } else {
- more_frames = 0;
- cross_frame = 1;
- av_log(avctx, AV_LOG_ERROR, "\tlast bit: cross_frame %x \tleft_bit_size %x\n", num_bits_curr_frame, buf_bit_size - get_bits_count(&s->gb) + s->log2_frame_size);
- s->cross_frame_needed_bits = num_bits_curr_frame - s->log2_frame_size - (buf_bit_size - get_bits_count(&s->gb));
- av_log(avctx, AV_LOG_ERROR, " Not available needed bits %x\n",s->cross_frame_needed_bits);
- }
- } else
- av_log(avctx, AV_LOG_ERROR, "\n");
- i++;
- } while(more_frames);
-
+ av_log(avctx, AV_LOG_INFO, "[%d]: nbpf %x\n", avctx->frame_number, num_bits_prev_frame);
- if (!cross_frame) {
- av_log(avctx, AV_LOG_ERROR, " Available bits %x - Consumed bits %x \t diff %x\n",buf_bit_size, get_bits_count(&s->gb),buf_bit_size-get_bits_count(&s->gb));
- s->cross_frame_needed_bits = buf_bit_size-get_bits_count(&s->gb);
+ /* check for packet loss */
+ if (s->packet_sequence_number != (avctx->frame_number&0xF)) {
+ s->packet_loss = 1;
+ av_log(avctx, AV_LOG_ERROR, "!!Packet loss detected! seq %x vs %x\n",s->packet_sequence_number,avctx->frame_number&0xF);
}
- //Check amount of non zero bits in non crossing frames
- if (!cross_frame) {
- for (i=0 ; i<buf_bit_size-get_bits_count(&s->gb) ; i++) {
- sum+=get_bits1(&s->gb);
+ if (num_bits_prev_frame > 0) {
+ /* append the prev frame data to the remaining data from the previous packet to create a full frame */
+ save_bits(s,num_bits_prev_frame);
+ av_log(avctx, AV_LOG_INFO, "accumulated %x bits of frame data\n",s->prev_frame_bit_size);
+
+ /* decode the cross packet frame if it is valid */
+ if(!s->packet_loss){
+ GetBitContext gb_prev;
+ init_get_bits(&gb_prev, s->prev_frame, s->prev_frame_bit_size);
+ wma_decode_frame(s,&gb_prev);
}
- if (sum)
- av_log(avctx, AV_LOG_ERROR, "!!Non crossing frame contains %x non zero bits!\n",sum);
+
+ /* reset prev frame buffer */
+ s->prev_frame_bit_size = 0;
}
- if (s->packet_sequence_number != (avctx->frame_number&0xF)) {
- s->packet_loss = 1;
- av_log(avctx, AV_LOG_ERROR, "!!Packet loss detected! seq %x vs %x\n",s->packet_sequence_number,avctx->frame_number&0xF);
+ /* 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);
+
+ /* there is enough data for a full frame */
+ if(remaining_bits(s) >= frame_size){
+ /* decode the frame */
+ more_frames = wma_decode_frame(s,&s->gb);
+ }else
+ more_frames = 0;
}
+ /* save the rest of the data so that it can be decoded with the next packet */
+ save_bits(s,remaining_bits(s));
+
return avctx->block_align;
}
static av_cold int wma3_decode_end(AVCodecContext *avctx)
{
+ WMA3DecodeContext *s = avctx->priv_data;
+ if(s->prev_frame)
+ av_free(s->prev_frame);
return 0;
}
More information about the FFmpeg-soc
mailing list