[FFmpeg-soc] [soc]: r2276 - in wmapro: . wma3dec.c

faust3 subversion at mplayerhq.hu
Fri May 30 17:25:21 CEST 2008


Author: faust3
Date: Fri May 30 17:25:21 2008
New Revision: 2276

Log:
imported wmapro packet parser from the codecs repository

Added:
   wmapro/
   wmapro/wma3dec.c

Added: wmapro/wma3dec.c
==============================================================================
--- (empty file)
+++ wmapro/wma3dec.c	Fri May 30 17:25:21 2008
@@ -0,0 +1,244 @@
+/*
+ * WMA 9/3/PRO compatible decoder
+ * Copyright (c) 2007 The FFmpeg Project.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+#include "bitstream.h"
+
+typedef struct WMA3DecodeContext {
+    AVCodecContext*     avctx;
+    GetBitContext       gb;
+
+    // Packet info
+    int                 packet_sequence_number;
+    int                 bit5;   // might be that packet contains padding data, last packet in some cbr files have it
+    int                 bit6;
+
+    // Stream info
+    unsigned int        samples_per_frame;
+    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;
+    unsigned int        dwChannelMask;
+    unsigned int        sample_bit_depth;
+
+    // Packet loss variables
+    unsigned int        packet_loss;
+} WMA3DecodeContext;
+
+
+static void dump_context(WMA3DecodeContext *s)
+{
+#define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b);
+#define PRINT_HEX(a,b) av_log(NULL,AV_LOG_ERROR," %s = %x\n", a, b);
+
+    PRINT_HEX("ed channelmask",s->dwChannelMask);
+    PRINT("ed sample bit depth",s->sample_bit_depth);
+    PRINT_HEX("ed decode flags",s->decode_flags);
+    PRINT("samples per frame",s->samples_per_frame);
+    PRINT("log2 frame size",s->log2_frame_size);
+}
+
+
+/**
+ *  Get the samples per frame for this stream
+ */
+static int get_samples_per_frame(int sample_rate, unsigned int decode_flags) {
+
+    int samples_per_frame;
+    int tmp;
+
+    if (sample_rate <= 16000)
+        samples_per_frame = 512;
+    else if (sample_rate <= 22050)
+        samples_per_frame = 1024;
+    else if (sample_rate <= 48000)
+        samples_per_frame = 2048;
+    else if (sample_rate <= 96000)
+        samples_per_frame = 4096;
+    else
+        samples_per_frame = 8192;
+
+ /* wma voice code  if (decode_flags & 0x800) {
+        tmp = ((decode_flags & 6) >> 1) | ((decode_flags & 0x600) >> 7);
+        samples_per_frame = (tmp+1)*160;
+    } else { */
+
+    tmp = decode_flags & 0x6;
+    if (tmp == 0x2)
+        samples_per_frame <<= 1;
+    else if (tmp == 0x4)
+        samples_per_frame >>= 1;
+    else if (tmp == 0x6)
+        samples_per_frame >>= 2;
+
+
+    return samples_per_frame;
+}
+
+static int wma3_decode_init(AVCodecContext *avctx)
+{
+    WMA3DecodeContext *s = avctx->priv_data;
+    uint8_t *edata_ptr = avctx->extradata;
+    int i;
+
+    s->avctx = avctx;
+
+    if (avctx->extradata_size >= 18) {
+        s->decode_flags     = AV_RL16(edata_ptr+14);
+        s->dwChannelMask    = AV_RL32(edata_ptr+2);
+        s->sample_bit_depth = AV_RL16(edata_ptr);
+
+        /* Dump the extradata */
+        for (i=0 ; i<avctx->extradata_size ; i++)
+            av_log(avctx, AV_LOG_ERROR, "[%x] ",avctx->extradata[i]);
+        av_log(avctx, AV_LOG_ERROR, "\n");
+
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "Unknown extradata size %d.\n",avctx->extradata_size);
+        return -1;
+    }
+
+    s->samples_per_frame = get_samples_per_frame(avctx->sample_rate, s->decode_flags);
+
+    /* Generic init */
+    s->packet_loss = 0;
+    s->log2_block_align = av_log2(avctx->block_align);
+    s->log2_block_align_bits = av_log2(avctx->block_align*8);
+    s->log2_frame_size = s->log2_block_align_bits + 1;
+
+    dump_context(s);
+
+    return 0;
+}
+
+static int wma3_decode_packet(AVCodecContext *avctx,
+                             void *data, int *data_size,
+                             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;
+
+    /* Parse packet header */
+    init_get_bits(&s->gb, buf, 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 */
+    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);
+
+
+    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 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 (sum)
+            av_log(avctx, AV_LOG_ERROR, "!!Non crossing frame contains %x non zero bits!\n",sum);
+    }
+
+    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);
+    }
+
+    return avctx->block_align;
+}
+
+static int wma3_decode_end(AVCodecContext *avctx)
+{
+    return 0;
+}
+
+AVCodec wmav3pro_decoder =
+{
+    "wmav3Pro",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_WMAV3PRO,
+    sizeof(WMA3DecodeContext),
+    wma3_decode_init,
+    NULL,
+    wma3_decode_end,
+    wma3_decode_packet,
+};



More information about the FFmpeg-soc mailing list