[FFmpeg-devel] [PATCH] Bink file demuxer and audio decoder

Michael Niedermayer michaelni
Wed Jun 24 21:41:54 CEST 2009


On Sat, Jun 20, 2009 at 11:49:05PM +1000, Peter Ross wrote:
> On Mon, Jan 19, 2009 at 02:34:07PM +0100, Michael Niedermayer wrote:
[...]
>  wma.c     |    4 ++--
>  wmadata.h |    2 +-
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 4e273d25638cdacdd14133a23502611fe418f12b  export-wma-critial-freqs.diff

ok


[...]

>  configure            |    2 +
>  libavcodec/Makefile  |    1 
>  libavcodec/dct.c     |   95 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/dsputil.h |   18 +++++++++
>  4 files changed, 116 insertions(+)
> 10b581a1c87d332f4600553bc521d351f4a8f8f5  dct-r201.diff
> Index: configure
> ===================================================================
> --- configure	(revision 19182)
> +++ configure	(working copy)
> @@ -97,6 +97,7 @@
>    echo "  --disable-fastdiv        disable table-based division"
>    echo "  --enable-small           optimize for size instead of speed"
>    echo "  --disable-aandct         disable AAN DCT code"
> +  echo "  --disable-dct            disable DCT code"

this is confusing considering that video encoders use DCTs too but they
arent disabled

[...]
> +#define ROTATE(i,n) (-M_PI*((n)-0.5f)*(i)/(n))

i would factor M_PI*((n)-0.5f)/n out
because its not easy for gcc to do, it requires the associative law, which
doesnt hold for floats ...


> +    if (s->inverse) {
> +        for(i=0; i < n; i++) {
> +            s->data[i].re = 2 * data[i] * cos(ROTATE(i,n));
> +            s->data[i].im = 2 * data[i] * sin(ROTATE(i,n));
> +        }
> +        s->data[n].re = 0;
> +        s->data[n].im = 0;
> +        for(i=0; i<n-1; i++) {
> +            s->data[n+i+1].re = -2 * data[n - (i+1)] * cos(ROTATE(n+i+1,n));
> +            s->data[n+i+1].im = -2 * data[n - (i+1)] * sin(ROTATE(n+i+1,n));
> +        }
> +    }else{

> +        for(i=0; i < n; i++) {
> +            s->data[i].re = data[n - (i+1)];
> +            s->data[i].im = 0;
> +            s->data[n+i].re = data[i];
> +            s->data[n+i].im = 0;
> +        }

This way of calculating the DCT isnt efficient, better variants
exist in "numerical recipes" available freely online (at least last i
checked)


[...]
> +static av_cold int decode_init(AVCodecContext *avctx)
> +{
> +    BinkAudioContext *s = avctx->priv_data;
> +    int sample_rate = avctx->sample_rate;
> +    int sample_rate_half;
> +    int i;
> +    int frame_len_bits;
> +
> +    s->avctx = avctx;
> +    dsputil_init(&s->dsp, avctx);
> +
> +    /* determine frame length */
> +    if (avctx->sample_rate < 22050) {
> +        frame_len_bits = 9;
> +    } else if (avctx->sample_rate < 44100) {
> +        frame_len_bits = 10;
> +    } else {
> +        frame_len_bits = 11;
> +    }
> +    s->frame_len = 1 << frame_len_bits;
> +
> +    if (s->channels > MAX_CHANNELS) {
> +        av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels);
> +        return -1;
> +    }
> +
> +    s->use_dct = (avctx->codec->id == CODEC_ID_BINKAUDIO2);
> +
> +    if (s->use_dct) {
> +        s->channels = avctx->channels;
> +    } else {
> +        // audio is already interleaved for the RDFT format variant
> +        sample_rate  *= avctx->channels;
> +        s->frame_len *= avctx->channels;
> +        s->channels = 1;
> +        if (avctx->channels == 2)
> +            frame_len_bits++;
> +    }
> +
> +    s->overlap_len   = s->frame_len / 16;
> +    s->block_size    = (s->frame_len - s->overlap_len) * s->channels;
> +    sample_rate_half = (sample_rate + 1) / 2;
> +    s->root          = 2.0 / sqrt(s->frame_len);
> +
> +    /* calculate number of bands */
> +    for (s->num_bands = 1; s->num_bands < 25; s->num_bands++)
> +        if (sample_rate_half <= ff_wma_critical_freqs[s->num_bands - 1])
> +            break;
> +
> +    s->bands = av_malloc((s->num_bands + 1) * sizeof(*s->bands));
> +    if (!s->bands)
> +        return AVERROR(ENOMEM);
> +
> +    /* populate bands data */
> +    s->bands[0] = 1;
> +    for (i = 1; i < s->num_bands; i++)
> +        s->bands[i] = ff_wma_critical_freqs[i - 1] * (s->frame_len / 2) / sample_rate_half;
> +    s->bands[s->num_bands] = s->frame_len / 2;
> +
> +    s->first = 1;
> +    avctx->sample_fmt = SAMPLE_FMT_S16;
> +
> +    for (i = 0; i < s->channels; i++)
> +        s->coeffs_ptr[i] = s->coeffs + i * s->frame_len;
> +

> +    if (s->use_dct)
> +        ff_dct_init(&s->trans.dct, frame_len_bits, 0);
> +    else

if(){
}else
to make possible future patches smaller


[...]
> +/**
> + * Decode Bink Audio block
> + * @param[out] out Output buffer (must contain s->block_size elements)
> + */
> +static void decode_block(BinkAudioContext *s, short *out)
> +{
> +    int ch, i, j, k;
> +    float q, quant[25];
> +    int width, coeff;
> +    GetBitContext *gb = &s->gb;
> +
> +    if (s->use_dct) {
> +        skip_bits(gb, 2);
> +    }
> +
> +    for (ch = 0; ch < s->channels; ch++) {
> +        FFTSample *coeffs = s->coeffs_ptr[ch];

> +        q = 0.0;

declaration & init can be merged


> +        coeffs[0] = get_float(gb);
> +        coeffs[1] = get_float(gb);
> +
> +        for (i = 0; i < s->num_bands; i++) {
> +            int value = get_bits(gb, 8);
> +            quant[i] = pow(10.0, FFMIN(value, 95) * 0.066399999);

pow(pow(10.0, 0.066399999), FFMIN(value, 95));


> +        }
> +
> +        // find band (k)
> +        for (k = 0; s->bands[k] * 2 < 2; k++) {
> +            q = quant[k];
> +        }
> +

> +        // parse coefficients
> +        i = 2;
> +        while (i < s->frame_len) {
> +            if (get_bits1(gb)) {
> +                j = i + rle_length_tab[get_bits(gb, 4)] * 8;
> +            } else {
> +                j = i + 8;
> +            }
> +

> +            if (j > s->frame_len)
> +                j = s->frame_len;

this is not an error ?


> +
> +            width = get_bits(gb, 4);
> +            if (width == 0) {
> +                memset(coeffs + i, 0, (j - i) * sizeof(*coeffs));
> +                i = j;
> +                while (s->bands[k] * 2 < i)
> +                    q = quant[k++];
> +            } else {
> +                while (i < j) {
> +                    if (s->bands[k] * 2 == i)
> +                        q = quant[k++];
> +                    coeff = get_bits(gb, width);
> +                    if (coeff) {
> +                        if (get_bits1(gb))
> +                            coeffs[i] = -q * coeff;
> +                        else
> +                            coeffs[i] =  q * coeff;
> +                    } else {
> +                        coeffs[i] = 0.0;
> +                    }
> +                    i++;
> +                }
> +            }
> +        }
> +
> +        if (s->use_dct)
> +            ff_dct_calc (&s->trans.dct,  coeffs);
> +        else
> +            ff_rdft_calc(&s->trans.rdft, coeffs);
> +

> +        for (i = 0; i < s->frame_len; i++)
> +            coeffs[i] *= s->root;

this can be merged into quant i think


[...]
> +static int read_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> +    BinkDemuxContext *bink = s->priv_data;
> +    ByteIOContext *pb = s->pb;
> +    int ret;
> +
> +    if (bink->current_track < 0) {
> +        int index_entry;
> +        AVStream *st = s->streams[0]; // stream 0 is video stream with index
> +
> +        if (bink->video_pts >= bink->total_frames)
> +            return AVERROR(EIO);
> +
> +        index_entry = av_index_search_timestamp(st, bink->video_pts,
> +                                                AVSEEK_FLAG_ANY);
> +        if (index_entry < 0) {
> +            av_log(s, AV_LOG_ERROR,
> +                   "could not find index entry for frame %"PRId64"\n",
> +                   bink->video_pts);
> +            return AVERROR(EIO);
> +        }
> +
> +        bink->remain_packet_size = st->index_entries[index_entry].size;
> +        bink->current_track = 0;
> +    }
> +
> +    if (bink->current_track < bink->num_audio_tracks) {
> +        uint32_t audio_size = get_le32(pb);

> +        if (audio_size > bink->remain_packet_size - 4) {

the subtraction can overflow

[...]

>  smacker.c |   14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 35c4d928a5245a41d669ad2baa261044e7423496  smacker-decoder-r300.diff

ok
[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Avoid a single point of failure, be that a person or equipment.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090624/b00beefc/attachment.pgp>



More information about the ffmpeg-devel mailing list