[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