[FFmpeg-devel] [PATCH/DRAFT] MonkeyAudio Demuxer/Decoder

Benjamin Zores ben
Tue Jun 19 23:50:06 CEST 2007


Hi there,

As recently stated on Kostya's blog, a light GPL (plain C) decoder has
been written by Dave Chapman for Rockbox project.
I've started porting it to FFMpeg to have a native demuxer/decoder for
this audio format.

Good news is that demuxer seems _almost_ okay by now.
Not so bad news is that decoder seems to work a bit: it decodes a few
samples (too slow however) but then crashes before the end of the
first frame, and here's where I need a few help.

Well, first thing that bugs me is that MonkeyAudio uses really HUUUUGE frames.
Though, I redefined the following in avcodec.h:


-#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
+#define AVCODEC_MAX_AUDIO_FRAME_SIZE 384000 // 1 second of 96khz 32bit audio

In order to at least have enough space in buffer to decode all samples
from one frame. Is this the best way to do (I really doubt so) or what
else can be done ?

By the way, FFMpeg only supports 16bits audio samples right ? So if
anything else in found by demuxer (8/24 bits, I can just drop the
file, right ?)

Then, I'll be glad if someone could review this patch (quickly, no
need to be exhaustive) to help me find out what can cause the decoder
to crash after a few samples.

For the record, in its current form, the decoder's implementation
nearly is a copy/paste from original libdemac.
That's why it uses a new RangeCoder implementation, makes uses of some
already existing defines/macros and so on ... it'll be changed later
on, but first step is to be able to decode with original libdemac
code.

For those who may wanna test, you can find a MA sample here:
http://geexbox.org/~ben/test.ape

Thx to whoever can help me out ;-)

Ben

-- 
"My life, and by extension everyone else's is meaningless."
Bender, Futurama
-------------- next part --------------
Index: libavcodec/Makefile
===================================================================
--- libavcodec/Makefile	(revision 9370)
+++ libavcodec/Makefile	(working copy)
@@ -38,6 +38,7 @@
 OBJS-$(CONFIG_AASC_DECODER)            += aasc.o
 OBJS-$(CONFIG_AC3_ENCODER)             += ac3enc.o ac3tab.o ac3.o
 OBJS-$(CONFIG_ALAC_DECODER)            += alac.o
+OBJS-$(CONFIG_APE_DECODER)             += apedec.o
 OBJS-$(CONFIG_ASV1_DECODER)            += asv1.o
 OBJS-$(CONFIG_ASV1_ENCODER)            += asv1.o
 OBJS-$(CONFIG_ASV2_DECODER)            += asv1.o
Index: libavcodec/apedec.c
===================================================================
--- libavcodec/apedec.c	(revision 0)
+++ libavcodec/apedec.c	(revision 0)
@@ -0,0 +1,1308 @@
+/*
+ * Monkey's Audio lossless audio decoder
+ * Copyright (c) 2007 Benjamin Zores.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define ALT_BITSTREAM_READER_LE
+#include "avcodec.h"
+#include "bitstream.h"
+#include "bytestream.h"
+
+/**
+ * @file apedec.c
+ * Monkey's Audio lossless audio decoder
+ */
+
+#define BLOCKS_PER_LOOP     4608
+#define MAX_CHANNELS        2
+#define MAX_BYTESPERSAMPLE  3
+
+#define INPUT_CHUNKSIZE     (32*1024)
+
+#define APE_FRAMECODE_MONO_SILENCE    1
+#define APE_FRAMECODE_STEREO_SILENCE  3
+#define APE_FRAMECODE_PSEUDO_STEREO   4
+
+#define HISTORY_SIZE 512
+#define PREDICTOR_ORDER 8
+
+struct filter_t {
+  int16_t* coeffs; /* ORDER entries */
+
+  /* We store all the filter delays in a single buffer */
+  int16_t* historybuffer;  /* ORDER*2 + HISTORY_SIZE entries */
+  
+  int16_t* delay;
+  int16_t* adaptcoeffs;
+  
+  int avg;
+};
+
+struct rice_t
+{
+  uint32_t k;
+  uint32_t ksum;
+};
+
+struct rangecoder_t
+{
+  uint32_t low;        /* low end of interval */
+  uint32_t range;      /* length of interval */
+  uint32_t help;       /* bytes_to_follow resp. intermediate value */
+  unsigned int buffer; /* buffer for input/output */
+};
+
+struct predictor_t
+{
+  /* Adaption co-efficients */
+  int32_t coeffsA[4];
+  int32_t coeffsB[5];
+
+  /* Filter histories */
+  int32_t historybuffer[HISTORY_SIZE + PREDICTOR_ORDER * 4];
+  int32_t* delayA;
+  int32_t* delayB;
+  int32_t* adaptcoeffsA;
+  int32_t* adaptcoeffsB;
+
+  int32_t lastA;
+
+  int32_t filterA;
+  int32_t filterB;
+};
+
+typedef struct {
+  int16_t fileversion;
+  uint16_t compression;
+  uint16_t flags;
+} APECodecInfo;
+
+typedef struct APEContext {
+  AVCodecContext *avctx;
+  int channels;
+  int samples;
+
+  /* from demuxer */
+  int16_t fileversion;
+  uint16_t compression_level;
+  uint16_t flags;
+
+  /* Decoder state */
+  uint32_t      CRC;
+  int           frameflags;
+  int           currentframeblocks;
+  int           blocksdecoded;
+  struct predictor_t predictorY;
+  struct predictor_t predictorX;
+  
+  /* 4608*2*3 = 27648 bytes */
+  unsigned char wavbuffer[BLOCKS_PER_LOOP*MAX_CHANNELS*MAX_BYTESPERSAMPLE];
+
+  /* 4608*4 = 18432 bytes per channel */
+  int32_t decoded0[BLOCKS_PER_LOOP];
+  int32_t decoded1[BLOCKS_PER_LOOP];
+
+  /* Statically allocate the filter buffers */
+
+  int16_t filterbuf32[(32*3 + HISTORY_SIZE) * 2];   /* 4480 bytes */
+  int16_t filterbuf256[(256*3 + HISTORY_SIZE) * 2];  /* 5120 bytes */
+
+  /* This is only needed for "insane" files */
+  int16_t filterbuf1280[(1280*3 + HISTORY_SIZE) * 2]; /* 17408 bytes */
+
+  int firstbyte;
+  int bytesconsumed;
+  unsigned int bytesinbuffer;
+
+  /* We assume that 32KB of compressed data is enough to extract up to
+     27648 bytes of decompressed data. */
+  unsigned char inbuffer[INPUT_CHUNKSIZE];
+
+  unsigned char* bytebuffer;
+  int bytebufferoffset;
+
+  struct rangecoder_t rc;
+  struct rice_t riceX;
+  struct rice_t riceY;
+  int32_t X;
+  struct filter_t filter0;
+  struct filter_t filter1;
+  
+} APEContext;
+
+/* Some macros to handle the fixed-point stuff */
+
+#define FP_HALF(y)  (1 << (y - 1))   /* 0.5 in fixed-point format. */
+#define FP_TO_INT(x,y) ((x + FP_HALF(y)) >> y);  /* round(x) */
+
+#define SATURATE(x) (int16_t)(((x) == (int16_t)(x)) ? (x) : ((x) >> 31) ^ 0x7FFF);
+
+static inline void vector_add (int16_t* v1, int16_t* v2, int order)
+{
+  int or = 1;
+  if (order > 32)
+    or = (order >> 5);
+  
+  while (or--)
+  {
+    int i;
+
+    for (i = 0; i < 16; i++)
+      *v1++ += *v2++;
+
+    if (order > 16)
+      for (i = 0; i < 16; i++)
+        *v1++ += *v2++;
+  }
+}
+
+static inline void vector_sub(int16_t* v1, int16_t* v2, int order)
+{
+  int or = 1;
+  if (order > 32)
+    or = (order >> 5);
+
+  while (or--)
+  {
+    int i;
+
+    for (i = 0; i < 16; i++)
+      *v1++ -= *v2++;
+    
+    if (order > 16)
+      for (i = 0; i < 16; i++)
+        *v1++ -= *v2++;
+  }
+}
+
+static inline int32_t scalarproduct(int16_t* v1, int16_t* v2, int order)
+{
+  int res = 0;
+  int or = 1;
+  
+  if (order > 16)
+    or = (order >> 4);
+  
+  while (or--)
+  {
+    int i;
+
+    for (i = 0; i < 16; i++)
+      res += *v1++ * *v2++;
+  }
+
+  return res;
+}
+
+/* 32-bit vector math functions */
+
+#define scalarproduct4_rev32(x,y) ((x[0]  * y[0]) + (x[1] * y[-1]) + \
+                                   (x[2] * y[-2]) + (x[3] * y[-3]))
+
+#define scalarproduct5_rev32(x,y) ((x[0]  * y[0]) + (x[1] * y[-1]) + \
+                                   (x[2] * y[-2]) + (x[3] * y[-3]) + \
+                                   (x[4] * y[-4]))
+
+#define vector_sub4_rev32(x, y) { x[0] -= y[0]; \
+                                  x[1] -= y[-1]; \
+                                  x[2] -= y[-2]; \
+                                  x[3] -= y[-3]; }
+
+#define vector_sub5_rev32(x, y) { x[0] -= y[0]; \
+                                  x[1] -= y[-1]; \
+                                  x[2] -= y[-2]; \
+                                  x[3] -= y[-3]; \
+                                  x[4] -= y[-4]; }
+
+#define vector_add4_rev32(x, y) { x[0] += y[0]; \
+                                  x[1] += y[-1]; \
+                                  x[2] += y[-2]; \
+                                  x[3] += y[-3]; }
+
+#define vector_add5_rev32(x, y) { x[0] += y[0]; \
+                                  x[1] += y[-1]; \
+                                  x[2] += y[-2]; \
+                                  x[3] += y[-3]; \
+                                  x[4] += y[-4]; }
+
+static int ape_decode_init(AVCodecContext *avctx)
+{
+  APEContext *s = avctx->priv_data;
+  APECodecInfo *data = (APECodecInfo *) avctx->extradata;
+  
+  s->avctx = avctx;
+  s->channels = avctx->channels;
+  s->fileversion = data->fileversion;
+  s->compression_level = data->compression;
+  s->flags = data->flags;
+
+  av_log (avctx, AV_LOG_INFO, "%s:%d\n", __FUNCTION__, __LINE__);
+  av_log (avctx, AV_LOG_INFO, "Compression Level: %d - Flags: %d\n",
+          s->compression_level, s->flags);
+  
+  return 0;
+}
+
+static int ape_decode_close(AVCodecContext *avctx)
+{
+  av_log (avctx, AV_LOG_INFO, "%s:%d\n", __FUNCTION__, __LINE__);
+  return 0;
+}
+
+static inline void skip_byte(APEContext *ctx)
+{
+  if (ctx->bytebufferoffset)
+    ctx->bytebufferoffset--;
+  else
+  {
+    ctx->bytebufferoffset = 3;
+    ctx->bytebuffer += 4;
+  }
+}
+
+static inline int read_byte(APEContext *ctx)
+{
+  int ch = ctx->bytebuffer[ctx->bytebufferoffset];
+    
+  skip_byte (ctx);
+
+  return ch;
+}
+
+/* RANGE DECODING FUNCTIONS */
+
+/* SIZE OF RANGE ENCODING CODE VALUES. */
+
+#define CODE_BITS 32
+#define TOP_VALUE ((unsigned int)1 << (CODE_BITS-1))
+#define SHIFT_BITS (CODE_BITS - 9)
+#define EXTRA_BITS ((CODE_BITS-2) % 8 + 1)
+#define BOTTOM_VALUE (TOP_VALUE >> 8)
+
+/* Start the decoder */
+static inline void range_start_decoding(APEContext *ctx)
+{
+    ctx->rc.buffer = read_byte(ctx);
+    ctx->rc.low = ctx->rc.buffer >> (8 - EXTRA_BITS);
+    ctx->rc.range = (uint32_t) 1 << EXTRA_BITS;
+}
+
+static inline void range_dec_normalize(APEContext *ctx)
+{
+    while (ctx->rc.range <= BOTTOM_VALUE)
+    {   
+        ctx->rc.buffer = (ctx->rc.buffer << 8) | read_byte(ctx);
+        ctx->rc.low = (ctx->rc.low << 8) | ((ctx->rc.buffer >> 1) & 0xff);
+        ctx->rc.range <<= 8;
+    }
+}
+
+/* Calculate culmulative frequency for next symbol. Does NO update!*/
+/* tot_f is the total frequency                              */
+/* or: totf is (code_value)1<<shift                                      */
+/* returns the culmulative frequency                         */
+static inline int range_decode_culfreq(APEContext *ctx, int tot_f)
+{   int tmp;
+
+    range_dec_normalize(ctx);
+
+    ctx->rc.help = ctx->rc.range / tot_f;
+    tmp = ctx->rc.low / ctx->rc.help;
+
+    return tmp;
+}
+
+static inline int range_decode_culshift(APEContext *ctx, int shift)
+{
+    int tmp;
+    range_dec_normalize(ctx);
+    ctx->rc.help = ctx->rc.range>>shift;
+    tmp = ctx->rc.low / ctx->rc.help;
+    return tmp;
+}
+
+
+/* Update decoding state                                     */
+/* sy_f is the interval length (frequency of the symbol)     */
+/* lt_f is the lower end (frequency sum of < symbols)        */
+static inline void range_decode_update(APEContext *ctx, int sy_f, int lt_f)
+{
+  int tmp;
+  tmp = ctx->rc.help * lt_f;
+  ctx->rc.low -= tmp;
+  ctx->rc.range = ctx->rc.help * sy_f;
+}
+
+
+/* Decode a byte/short without modelling                     */
+static inline unsigned char decode_byte(APEContext *ctx)
+{   int tmp = range_decode_culshift(ctx, 8);
+    range_decode_update (ctx, 1,tmp);
+    return tmp;
+}
+
+static inline int short range_decode_short(APEContext *ctx)
+{   int tmp = range_decode_culshift(ctx,16);
+    range_decode_update(ctx, 1,tmp);
+    return tmp;
+}
+
+/* Decode n bits (n <= 16) without modelling - based on range_decode_short */
+static inline int range_decode_bits(APEContext *ctx, int n)
+{   int tmp = range_decode_culshift(ctx, n);
+    range_decode_update(ctx, 1,tmp);
+    return tmp;
+}
+
+
+/* Finish decoding                                           */
+static inline void range_done_decoding(APEContext *ctx)
+{   range_dec_normalize(ctx);      /* normalize to use up all bytes */
+}
+
+#define MODEL_ELEMENTS 64
+
+/*
+  The following counts arrays for use with the range decoder are
+  hard-coded in the Monkey's Audio decoder.
+*/
+
+static const int counts_3970[65] =
+{
+        0,14824,28224,39348,47855,53994,58171,60926,
+    62682,63786,64463,64878,65126,65276,65365,65419,
+    65450,65469,65480,65487,65491,65493,65494,65495,
+    65496,65497,65498,65499,65500,65501,65502,65503,
+    65504,65505,65506,65507,65508,65509,65510,65511,
+    65512,65513,65514,65515,65516,65517,65518,65519,
+    65520,65521,65522,65523,65524,65525,65526,65527,
+    65528,65529,65530,65531,65532,65533,65534,65535,
+    65536
+};
+
+/* counts_diff_3970[i] = counts_3970[i+1] - counts_3970[i] */
+static const int counts_diff_3970[64] =
+{
+    14824,13400,11124,8507,6139,4177,2755,1756,
+    1104,677,415,248,150,89,54,31,
+    19,11,7,4,2,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1
+};
+
+static const int counts_3980[65] =
+{
+        0,19578,36160,48417,56323,60899,63265,64435,
+    64971,65232,65351,65416,65447,65466,65476,65482,
+    65485,65488,65490,65491,65492,65493,65494,65495,
+    65496,65497,65498,65499,65500,65501,65502,65503,
+    65504,65505,65506,65507,65508,65509,65510,65511,
+    65512,65513,65514,65515,65516,65517,65518,65519,
+    65520,65521,65522,65523,65524,65525,65526,65527,
+    65528,65529,65530,65531,65532,65533,65534,65535,
+    65536
+};
+
+/* counts_diff_3980[i] = counts_3980[i+1] - counts_3980[i] */
+
+static const int counts_diff_3980[64] =
+{
+    19578,16582,12257,7906,4576,2366,1170,536,
+    261,119,65,31,19,10,6,3,
+    3,2,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1
+};
+
+/*
+  range_get_symbol_* functions based on main decoding loop in simple_d.c from
+  http://www.compressconsult.com/rangecoder/rngcod13.zip
+  (c) Michael Schindler
+*/
+
+static inline int range_get_symbol_3980(APEContext *ctx)
+{
+    int symbol, cf;
+
+    cf = range_decode_culshift(ctx,16);
+
+    /* figure out the symbol inefficiently; a binary search would be much better */
+    for (symbol = 0; counts_3980[symbol+1] <= cf; symbol++);
+
+    range_decode_update(ctx,counts_diff_3980[symbol],counts_3980[symbol]);
+
+    return symbol;
+}
+
+static inline int range_get_symbol_3970(APEContext *ctx)
+{
+    int symbol, cf;
+
+    cf = range_decode_culshift(ctx,16);
+
+    /* figure out the symbol inefficiently; a binary search would be much better */
+    for (symbol = 0; counts_3970[symbol+1] <= cf; symbol++);
+
+    range_decode_update(ctx,counts_diff_3970[symbol],counts_3970[symbol]);
+
+    return symbol;
+}
+
+static inline void update_rice(struct rice_t* rice, int x)
+{
+  rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5);
+
+  if (rice->k == 0) {
+    rice->k = 1;
+  } else if (rice->ksum < ((uint32_t)1 << (rice->k + 4))) {
+    rice->k--;
+  } else if (rice->ksum >= ((uint32_t)1 << (rice->k + 5))) {
+    rice->k++;
+  }
+}
+
+static inline int entropy_decode3980(APEContext *ctx, struct rice_t* rice)
+{
+  int base, x, pivot, overflow;
+
+  pivot = rice->ksum >> 5;
+  if (pivot == 0) pivot=1;
+
+  overflow = range_get_symbol_3980(ctx);
+
+  if (overflow == (MODEL_ELEMENTS-1)) {
+    overflow = range_decode_short(ctx) << 16;
+    overflow |= range_decode_short(ctx);
+  }
+
+  if (pivot >= 0x10000) {
+    /* Codepath for 24-bit streams */
+    int nbits, lo_bits, base_hi, base_lo;
+
+    /* Count the number of bits in pivot */
+    nbits = 17; /* We know there must be at least 17 bits */
+    while ((pivot >> nbits) > 0) { nbits++; }
+
+    /* base_lo is the low (nbits-16) bits of base
+       base_hi is the high 16 bits of base
+    */
+    lo_bits = (nbits - 16);
+
+    base_hi = range_decode_culfreq(ctx, (pivot >> lo_bits) + 1);
+    range_decode_update(ctx, 1, base_hi);
+
+    base_lo = range_decode_culfreq(ctx, 1 << lo_bits);
+    range_decode_update(ctx, 1, base_lo);
+
+    base = (base_hi << lo_bits) + base_lo;
+  } else {
+    /* Codepath for 16-bit streams */
+    base = range_decode_culfreq(ctx, pivot);
+    range_decode_update(ctx, 1, base);
+  }
+
+  x = base + (overflow * pivot);
+  update_rice(rice, x);
+
+  /* Convert to signed */
+  if (x & 1)
+    return (x >> 1) + 1;
+  else
+    return -(x >> 1);
+}
+
+static inline int entropy_decode3970(APEContext *ctx, struct rice_t* rice)
+{
+    int x, tmpk;
+
+    int overflow = range_get_symbol_3970(ctx);
+
+    if (overflow == (MODEL_ELEMENTS - 1)) {
+        tmpk = range_decode_bits(ctx,5);
+        overflow = 0;
+    } else {
+        tmpk = (rice->k < 1) ? 0 : rice->k - 1;
+    }
+
+    if (tmpk <= 16) {
+        x = range_decode_bits(ctx,tmpk);
+    } else {
+        x = range_decode_short(ctx);
+        x |= (range_decode_bits(ctx, tmpk - 16) << 16);
+    }
+    x += (overflow << tmpk);
+
+    update_rice(rice, x);
+
+    /* Convert to signed */
+    if (x & 1)
+        return (x >> 1) + 1;
+    else
+        return -(x >> 1);
+}
+
+void init_entropy_decoder (APEContext *ctx,
+                           unsigned char *inbuffer, int *firstbyte,
+                           int *bytesconsumed)
+{
+  ctx->bytebuffer = inbuffer;
+  ctx->bytebufferoffset = *firstbyte;
+
+  /* Read the CRC */
+  ctx->CRC = read_byte (ctx);
+  ctx->CRC = (ctx->CRC << 8) | read_byte (ctx);
+  ctx->CRC = (ctx->CRC << 8) | read_byte (ctx);
+  ctx->CRC = (ctx->CRC << 8) | read_byte (ctx);
+  
+  /* Read the frame flags if they exist */
+  ctx->frameflags = 0;
+  if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000))
+  {
+    ctx->CRC &= ~0x80000000;
+
+    ctx->frameflags = read_byte (ctx);
+    ctx->frameflags = (ctx->frameflags << 8) | read_byte (ctx);
+    ctx->frameflags = (ctx->frameflags << 8) | read_byte (ctx);
+    ctx->frameflags = (ctx->frameflags << 8) | read_byte (ctx);
+  }
+
+  /* Keep a count of the blocks decoded in this frame */
+  ctx->blocksdecoded = 0;
+
+  /* Initialise the rice structs */
+  ctx->riceX.k = 10;
+  ctx->riceX.ksum = (1 << ctx->riceX.k) * 16;
+  ctx->riceY.k = 10;
+  ctx->riceY.ksum = (1 << ctx->riceY.k) * 16;
+
+  /* The first 8 bits of input are ignored. */
+  skip_byte (ctx);
+
+  range_start_decoding (ctx);
+
+  /* Return the new state of the buffer */
+  *bytesconsumed = (intptr_t) ctx->bytebuffer - (intptr_t) inbuffer;
+  *firstbyte = ctx->bytebufferoffset;
+}
+
+int entropy_decode (APEContext *ctx,
+                   unsigned char* inbuffer, int* firstbyte,
+                   int* bytesconsumed,
+                   int32_t* decoded0, int32_t* decoded1,
+                   int blockstodecode)
+{
+  ctx->bytebuffer = inbuffer;
+  ctx->bytebufferoffset = *firstbyte;
+
+  ctx->blocksdecoded += blockstodecode;
+
+  av_log (NULL, AV_LOG_INFO, "%s\n", __FUNCTION__);
+  
+  if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
+    /* We are pure silence, just memset the output buffer. */
+    memset(decoded0, 0, blockstodecode * sizeof(int32_t));
+    memset(decoded1, 0, blockstodecode * sizeof(int32_t));
+  } else {
+    if (ctx->fileversion > 3970) {
+      while (blockstodecode--) {
+        *(decoded0++) = entropy_decode3980 (ctx,&(ctx->riceY));
+        if (decoded1 != NULL)
+          *(decoded1++) = entropy_decode3980 (ctx,&(ctx->riceX));
+      }
+    } else {
+      while (blockstodecode--) {
+        *(decoded0++) = entropy_decode3970(ctx,&(ctx->riceY));
+        if (decoded1 != NULL)
+          *(decoded1++) = entropy_decode3970(ctx,&(ctx->riceX));
+      }
+    }
+  }
+
+  if (ctx->blocksdecoded == ctx->currentframeblocks)
+  {
+    av_log (NULL, AV_LOG_INFO, "range_stop_decoding\n");
+    range_done_decoding (ctx);
+  }
+
+  /* Return the new state of the buffer */
+  *bytesconsumed = ctx->bytebuffer - inbuffer;
+  *firstbyte = ctx->bytebufferoffset;
+  
+  return 0;
+}
+
+static const int32_t initial_coeffs[4] = {
+  360, 317, -109, 98
+};
+
+static void init_predictor (struct predictor_t* p)
+{
+  /* Zero the history buffers */
+  memset(p->historybuffer, 0, (PREDICTOR_ORDER*4) * sizeof(int32_t));
+  p->delayA = p->historybuffer + PREDICTOR_ORDER*4;
+  p->delayB = p->historybuffer + PREDICTOR_ORDER*3;
+  p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2;
+  p->adaptcoeffsB = p->historybuffer + PREDICTOR_ORDER;
+  
+  /* Initialise and zero the co-efficients */
+  memcpy(p->coeffsA, initial_coeffs, sizeof(initial_coeffs));
+  memset(p->coeffsB, 0, sizeof(p->coeffsB));
+  
+  p->filterA = 0;
+  p->filterB = 0;
+  
+  p->lastA = 0;
+}
+
+/* Return 0 if x is zero, -1 if x is positive, 1 if x is negative */
+#define SIGN(x) (x) ? (((x) > 0) ? -1 : 1) : 0
+
+static int do_predictor_decode(struct predictor_t* p, int32_t A, int32_t nB)
+{
+  int32_t predictionA, predictionB, currentA;
+
+  p->delayA[0] = p->lastA;
+  p->delayA[-1] = p->delayA[0] - p->delayA[-1];
+
+  predictionA = scalarproduct4_rev32(p->coeffsA,p->delayA);
+
+  /*  Apply a scaled first-order filter compression */
+  p->delayB[0] = nB - ((p->filterB * 31) >> 5);
+  p->filterB = nB;
+
+  p->delayB[-1] = p->delayB[0] - p->delayB[-1];
+
+  predictionB = scalarproduct5_rev32(p->coeffsB,p->delayB);
+
+  currentA = A + ((predictionA + (predictionB >> 1)) >> 10);
+
+  p->adaptcoeffsA[0] = SIGN(p->delayA[0]);
+  p->adaptcoeffsA[-1] = SIGN(p->delayA[-1]);
+
+  p->adaptcoeffsB[0] = SIGN(p->delayB[0]);
+  p->adaptcoeffsB[-1] = SIGN(p->delayB[-1]);
+
+  if (A > 0) 
+  {
+    vector_sub4_rev32(p->coeffsA, p->adaptcoeffsA);
+    vector_sub5_rev32(p->coeffsB, p->adaptcoeffsB);
+  }
+  else if (A < 0) 
+  {
+    vector_add4_rev32(p->coeffsA, p->adaptcoeffsA);
+    vector_add5_rev32(p->coeffsB, p->adaptcoeffsB);
+  }
+
+  p->delayA++;
+  p->delayB++;
+  p->adaptcoeffsA++;
+  p->adaptcoeffsB++;
+
+  /* Have we filled the history buffer? */
+  if (p->delayA == p->historybuffer + HISTORY_SIZE + (PREDICTOR_ORDER*4)) {
+    memmove(p->historybuffer, p->delayA - (PREDICTOR_ORDER*4), 
+            (PREDICTOR_ORDER*4) * sizeof(int32_t));
+    p->delayA = p->historybuffer + PREDICTOR_ORDER*4;
+    p->delayB = p->historybuffer + PREDICTOR_ORDER*3;
+    p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2;
+    p->adaptcoeffsB = p->historybuffer + PREDICTOR_ORDER;
+  }
+
+  p->lastA = currentA;
+  p->filterA =  currentA + ((p->filterA * 31) >> 5);
+
+  return p->filterA;
+}
+
+void init_predictor_decoder(APEContext *ctx)
+{
+  ctx->X = 0;
+
+  init_predictor (&(ctx->predictorY));
+  init_predictor (&(ctx->predictorX));
+}
+
+int predictor_decode_stereo (APEContext *ctx, int32_t* decoded0, int32_t* decoded1, int count)
+{
+  while (count--)
+  {
+    *decoded0 = do_predictor_decode(&(ctx->predictorY), *decoded0, ctx->X);
+    ctx->X = do_predictor_decode(&(ctx->predictorX), *decoded1, *(decoded0)++);
+    *(decoded1++) = ctx->X;
+  }
+
+  return 0;
+}
+
+int predictor_decode_mono(APEContext *ctx, int32_t* decoded0, int count)
+{
+  struct predictor_t* p = &ctx->predictorY;
+  int32_t predictionA, currentA, A;
+
+  currentA = p->lastA;
+
+  while (count--)
+  {
+    A = *decoded0;
+
+    p->delayA[0] = currentA;
+    p->delayA[-1] = p->delayA[0] - p->delayA[-1];
+
+    predictionA = (p->delayA[0] * p->coeffsA[0]) +
+      (p->delayA[-1] * p->coeffsA[1]) +
+      (p->delayA[-2] * p->coeffsA[2]) +
+      (p->delayA[-3] * p->coeffsA[3]);
+
+    currentA = A + (predictionA >> 10);
+
+    p->adaptcoeffsA[0] = (p->delayA[0]) ? ((p->delayA[0] >> 30) & 2) - 1 : 0;
+    p->adaptcoeffsA[-1] = (p->delayA[-1]) ? ((p->delayA[-1] >> 30) & 2) - 1 : 0;
+        
+    if (A > 0)
+    {
+      p->coeffsA[0] -= p->adaptcoeffsA[0];
+      p->coeffsA[1] -= p->adaptcoeffsA[-1];
+      p->coeffsA[2] -= p->adaptcoeffsA[-2];
+      p->coeffsA[3] -= p->adaptcoeffsA[-3];
+    }
+    else if (A < 0)
+    {
+      p->coeffsA[0] += p->adaptcoeffsA[0];
+      p->coeffsA[1] += p->adaptcoeffsA[-1];
+      p->coeffsA[2] += p->adaptcoeffsA[-2];
+      p->coeffsA[3] += p->adaptcoeffsA[-3];
+    }
+
+    p->delayA++;
+    p->adaptcoeffsA++;
+
+    /* Have we filled the history buffer? */
+    if (p->delayA == p->historybuffer + HISTORY_SIZE + (PREDICTOR_ORDER*4)) {
+      memmove(p->historybuffer, p->delayA - (PREDICTOR_ORDER*4),
+              (PREDICTOR_ORDER*4) * sizeof(int32_t));
+      p->delayA = p->historybuffer + PREDICTOR_ORDER*4;
+      p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2;
+    }
+
+    p->filterA =  currentA + ((p->filterA * 31) >> 5);
+    *(decoded0++) = p->filterA;
+  }
+
+  p->lastA = currentA;
+
+  return 0;
+}
+
+static void do_init_filter (struct filter_t* f, int16_t* buf, int order)
+{
+  f->coeffs = buf;
+  f->historybuffer = buf + order;
+
+  /* Zero the output history buffer */
+  memset(f->historybuffer, 0 , (order*2) * sizeof(int16_t));
+  f->delay = f->historybuffer + order*2;
+  f->adaptcoeffs = f->historybuffer + order;
+  
+  /* Zero the co-efficients  */
+  memset(f->coeffs, 0, order * sizeof(int16_t));
+  
+  /* Zero the running average */
+  f->avg = 0;
+}
+
+void init_filter (APEContext *ctx, int16_t* buf, int order)
+{
+  do_init_filter (&ctx->filter0, buf, order);
+  do_init_filter (&ctx->filter1, buf + order * 3 + HISTORY_SIZE, order);
+}
+                  
+void init_filter_16_11 (APEContext *ctx, int16_t* buf)
+{
+  init_filter (ctx, buf, 16);
+}
+
+void init_filter_64_11 (APEContext *ctx, int16_t* buf)
+{
+  init_filter (ctx, buf, 64);
+}
+
+void init_filter_32_10 (APEContext *ctx, int16_t* buf)
+{
+  init_filter (ctx, buf, 32);
+}
+
+void init_filter_256_13 (APEContext *ctx, int16_t* buf)
+{
+  init_filter (ctx, buf, 256);
+}
+
+void init_filter_1280_15 (APEContext *ctx, int16_t* buf)
+{
+  init_filter (ctx, buf, 1280);
+}
+
+/* Apply the filter with state f to count entries in data[] */
+static inline void do_apply_filter_3980 (struct filter_t* f, int32_t* data, int count, int order, int fracbits)
+{
+  int res;
+  int absres;
+
+  while(count--)
+  {
+    res = FP_TO_INT(scalarproduct(f->delay - order, f->coeffs, order), fracbits);
+
+    if (*data < 0)
+      vector_add(f->coeffs, f->adaptcoeffs - order, order);
+    else if (*data > 0)
+      vector_sub(f->coeffs, f->adaptcoeffs - order, order);
+
+    /* Convert res from (32-FRACBITS).FRACBITS fixed-point format to an
+       integer (rounding to nearest) and add the input value to
+       it */
+    res += *data;
+
+    *data++ = res;
+
+    /* Update the output history */
+    *f->delay++ = SATURATE(res);
+
+    /* Version 3.98 and later files */
+
+    /* Update the adaption coefficients */
+    absres = (res < 0 ? -res : res);
+
+    if (absres > (f->avg * 3))
+      *f->adaptcoeffs = ((res >> 25) & 64) - 32;
+    else if (absres > (f->avg * 4) / 3)
+      *f->adaptcoeffs = ((res >> 26) & 32) - 16;
+    else if (absres > 0)
+      *f->adaptcoeffs = ((res >> 27) & 16) - 8;
+    else
+      *f->adaptcoeffs = 0;
+
+    f->avg += (absres - f->avg) / 16;
+
+    f->adaptcoeffs[-1] >>= 1;
+    f->adaptcoeffs[-2] >>= 1;
+    f->adaptcoeffs[-8] >>= 1;
+
+    f->adaptcoeffs++;
+
+    /* Have we filled the history buffer? */
+    if (f->delay == f->historybuffer + HISTORY_SIZE + (order*2)) {
+      memmove(f->historybuffer, f->delay - (order*2), 
+              (order*2) * sizeof(int16_t));
+      f->delay = f->historybuffer + order*2;
+      f->adaptcoeffs = f->historybuffer + order;
+    }
+  }
+}
+
+static inline void do_apply_filter_3970(struct filter_t* f, int32_t* data, int count, int order, int fracbits)
+{
+  int res;
+
+  while(count--)
+  {
+    res = FP_TO_INT(scalarproduct(f->delay - order, f->coeffs, order), fracbits);
+
+    if (*data < 0)
+      vector_add(f->coeffs, f->adaptcoeffs - order, order);
+    else if (*data > 0)
+      vector_sub(f->coeffs, f->adaptcoeffs - order, order);
+
+    /* Convert res from (32-FRACBITS).FRACBITS fixed-point format to an
+       integer (rounding to nearest) and add the input value to
+       it */
+    res += *data;
+
+    *data++ = res;
+
+    /* Update the output history */
+    *f->delay++ = SATURATE(res);
+
+    /* Version ??? to < 3.98 files (untested) */
+    f->adaptcoeffs[0] = (res == 0) ? 0 : ((res >> 28) & 8) - 4;
+    f->adaptcoeffs[-4] >>= 1;
+    f->adaptcoeffs[-8] >>= 1;
+
+    f->adaptcoeffs++;
+
+    /* Have we filled the history buffer? */
+    if (f->delay == f->historybuffer + HISTORY_SIZE + (order*2)) {
+      memmove(f->historybuffer, f->delay - (order*2), 
+              (order*2) * sizeof(int16_t));
+      f->delay = f->historybuffer + order*2;
+      f->adaptcoeffs = f->historybuffer + order;
+    }
+  }
+}
+
+int apply_filter (APEContext *ctx, int fileversion, int32_t* data0, int32_t* data1, int count, int order, int fracbits)
+{
+  if (fileversion >= 3980) {
+    do_apply_filter_3980 (&ctx->filter0, data0, count, order, fracbits);
+    if (data1 != NULL)
+      do_apply_filter_3980 (&ctx->filter1, data1, count, order, fracbits);
+  } else {
+    do_apply_filter_3970 (&ctx->filter0, data0, count, order, fracbits);
+    if (data1 != NULL)
+      do_apply_filter_3970 (&ctx->filter1, data1, count, order, fracbits);
+  }
+  
+  return 0;
+}
+
+int apply_filter_16_11 (APEContext *ctx, int fileversion, int32_t* decoded0, int32_t* decoded1, int count)
+{
+  return apply_filter (ctx, fileversion, decoded0, decoded1, count, 16, 11);
+}
+
+int apply_filter_64_11(APEContext *ctx, int fileversion, int32_t* decoded0, int32_t* decoded1, int count)
+{
+  return apply_filter (ctx, fileversion, decoded0, decoded1, count, 64, 11);
+}
+
+int apply_filter_32_10(APEContext *ctx, int fileversion, int32_t* decoded0, int32_t* decoded1, int count)
+{
+  return apply_filter (ctx, fileversion, decoded0, decoded1, count, 32, 10);
+}
+
+int apply_filter_256_13(APEContext *ctx, int fileversion, int32_t* decoded0, int32_t* decoded1, int count)
+{
+  return apply_filter (ctx, fileversion, decoded0, decoded1, count, 256, 13);
+}
+
+int apply_filter_1280_15(APEContext *ctx, int fileversion, int32_t* decoded0, int32_t* decoded1, int count)
+{
+  return apply_filter (ctx, fileversion, decoded0, decoded1, count, 1280, 15);
+}
+
+void init_frame_decoder(APEContext *ctx,
+                        unsigned char* inbuffer, int* firstbyte,
+                        int* bytesconsumed)
+{
+  init_entropy_decoder (ctx, inbuffer, firstbyte, bytesconsumed);
+
+  av_log (NULL, AV_LOG_INFO, "CRC=0x%08x\n", ctx->CRC);
+  av_log (NULL, AV_LOG_INFO, "Flags=0x%08x\n", ctx->frameflags);
+
+  init_predictor_decoder (ctx);
+
+  switch (ctx->compression_level)
+  {
+  case 2000:
+    init_filter_16_11 (ctx, ctx->filterbuf32);
+    break;
+
+  case 3000:
+    init_filter_64_11 (ctx, ctx->filterbuf256);
+    break;
+
+  case 4000:
+    init_filter_256_13 (ctx, ctx->filterbuf256);
+    init_filter_32_10 (ctx, ctx->filterbuf32);
+    break;
+
+  case 5000:
+    init_filter_1280_15 (ctx, ctx->filterbuf1280);
+    init_filter_256_13 (ctx, ctx->filterbuf256);
+    init_filter_16_11 (ctx, ctx->filterbuf32);
+  }
+}
+
+int decode_chunk (APEContext *ctx,
+                  unsigned char *inbuffer, int *firstbyte,
+                  int *bytesconsumed,
+                  int32_t *decoded_left, int32_t *decoded_right, 
+                  int count)
+{
+  int res = 0;
+  int32_t left, right;
+
+  if ((ctx->channels == 1) || (ctx->frameflags & APE_FRAMECODE_PSEUDO_STEREO))
+  {
+    if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE)
+    {
+      res = entropy_decode (ctx, inbuffer, firstbyte, bytesconsumed,
+                            decoded_left, decoded_right, count);
+      /* We are pure silence, so we're done. */
+      av_log (ctx, AV_LOG_ERROR, "%s (pure silence mono)\n", __FUNCTION__);
+      return 0;
+    }
+    else
+    {
+      res = entropy_decode (ctx, inbuffer, firstbyte, bytesconsumed,
+                            decoded_left, NULL, count);
+    }
+    
+    switch (ctx->compression_level)
+    {
+    case 2000:
+      apply_filter_16_11 (ctx, ctx->fileversion, decoded_left, NULL, count);
+      break;
+    
+    case 3000:
+      apply_filter_64_11 (ctx, ctx->fileversion, decoded_left, NULL, count);
+      break;
+    
+    case 4000:
+      apply_filter_32_10 (ctx, ctx->fileversion,decoded_left,NULL,count);
+      apply_filter_256_13 (ctx, ctx->fileversion,decoded_left,NULL,count);
+      break;
+      
+    case 5000:
+      apply_filter_16_11 (ctx, ctx->fileversion,decoded_left,NULL,count);
+      apply_filter_256_13 (ctx, ctx->fileversion,decoded_left,NULL,count);
+      apply_filter_1280_15 (ctx, ctx->fileversion,decoded_left,NULL,count);
+      break;
+    }
+    
+    /* Now apply the predictor decoding */
+    predictor_decode_mono (ctx, decoded_left, count);
+
+    if (ctx->channels == 2)
+    {
+      /* Pseudo-stereo - just copy left channel to right channel */
+      while (count--)
+      {
+        left = *decoded_left;
+        *(decoded_right++) = *(decoded_left++) = left;
+      }
+    }
+    else
+    {
+      /* Mono - do nothing unless it's 8-bit audio */
+      if (ctx->avctx->bits_per_sample == 8)
+      {
+        /* TODO: Handle 8-bit streams */
+      }
+    }
+  }
+  else
+  { /* Stereo */
+    if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE)
+    {
+      /* We are pure silence, so we're done. */
+      av_log (NULL, AV_LOG_ERROR, "%s (pure silence stereo)\n", __FUNCTION__);
+      return 0;
+    }
+
+    av_log (NULL, AV_LOG_INFO, "Start decoding entropy\n");
+    res = entropy_decode (ctx, inbuffer, firstbyte, bytesconsumed,
+                          decoded_left, decoded_right, count);
+    
+    /* Apply filters - compression type 1000 doesn't have any */
+    switch (ctx->compression_level)
+    {
+    case 2000:
+      apply_filter_16_11 (ctx, ctx->fileversion, decoded_left, decoded_right, count);
+      break;
+    
+    case 3000:
+      apply_filter_64_11 (ctx, ctx->fileversion,decoded_left,decoded_right,count);
+      break;
+    
+    case 4000:
+      apply_filter_32_10 (ctx, ctx->fileversion,decoded_left,decoded_right,count);
+      apply_filter_256_13 (ctx, ctx->fileversion,decoded_left,decoded_right,count);
+      break;
+    
+    case 5000:
+      apply_filter_16_11 (ctx, ctx->fileversion,decoded_left,decoded_right,count);
+      apply_filter_256_13 (ctx, ctx->fileversion,decoded_left,decoded_right,count);
+      apply_filter_1280_15 (ctx, ctx->fileversion,decoded_left,decoded_right,count);
+      break;
+    }
+
+    /* Now apply the predictor decoding */
+    predictor_decode_stereo (ctx, decoded_left, decoded_right, count);
+
+    if (ctx->avctx->bits_per_sample == 8)
+    {
+      /* TODO: Handle 8-bit streams */
+    }
+    else
+    {
+      /* Decorrelate and scale to output depth */
+      while (count--)
+      {
+        left = *decoded_right - (*decoded_left / 2);
+        right = left + *decoded_left;
+
+        *(decoded_left++) = left;
+        *(decoded_right++) = right;
+      }
+    }
+  }
+
+  av_log (NULL, AV_LOG_INFO, "%s (%d)\n", __FUNCTION__, res);
+  return res;
+}
+
+
+static int ape_decode_frame(AVCodecContext *avctx,
+                            void *data, int *data_size,
+                            uint8_t *buf, int buf_size)
+{
+  static int frame = 0;
+  APEContext *s = avctx->priv_data;
+  int16_t *samples = data;
+  int nblocks;
+  int decoded_offset = 0;
+  int n;
+  int once = 0;
+  int blockstodecode;
+  int res;
+  unsigned char* p;
+  int16_t  sample16;
+  int32_t  sample32;
+
+  if (buf_size == 0)
+  {
+    *data_size = 0;
+    return 0;
+  }
+
+  nblocks = s->samples = AV_RL32 (buf);
+  s->currentframeblocks = nblocks;
+  buf += 4;
+  if(!s->samples)
+  {
+    *data_size = 0;
+    return buf_size;
+  }
+
+  /* should not happen but who knows */
+  if (s->samples * 2 * avctx->channels > *data_size)
+  {
+    av_log (avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc! (max is %d where you have %d)\n", *data_size, s->samples * 2 * avctx->channels);
+    return -1;
+  }
+
+  if (!once)
+  {
+    s->bytesinbuffer = bytestream_get_buffer (&buf, s->inbuffer, INPUT_CHUNKSIZE);
+    s->firstbyte = 3;  /* Take account of the little-endian 32-bit byte ordering */
+    once++;
+  }
+  
+  av_log (avctx, AV_LOG_INFO, "*** Decoding frame %d - %s:%d - data_size: %d, buf_size: %d - nr_blocks: %d ***\n", frame, __FUNCTION__, __LINE__, *data_size, buf_size, s->samples);
+
+  /* Initialize the frame decoder */
+  init_frame_decoder (s, s->inbuffer, &(s->firstbyte), &(s->bytesconsumed));
+  //av_log (avctx, AV_LOG_INFO, "First byte: %d - Bytes in buffer: %d - Bytes consumed: %d\n",
+  //      firstbyte, bytesinbuffer, bytesconsumed);
+
+  /* Update buffer */
+  memmove(s->inbuffer,s->inbuffer + s->bytesconsumed, s->bytesinbuffer - s->bytesconsumed);
+  s->bytesinbuffer -= s->bytesconsumed;
+
+  n = bytestream_get_buffer (&buf, s->inbuffer + s->bytesinbuffer, INPUT_CHUNKSIZE - s->bytesinbuffer);
+  s->bytesinbuffer += n;
+  
+  //av_log (avctx, AV_LOG_INFO, "First byte: %d - Bytes in buffer: %d - Bytes consumed: %d\n",
+  //      firstbyte, bytesinbuffer, bytesconsumed);
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+  while (nblocks > 0)
+  {
+    blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);
+    av_log (avctx, AV_LOG_INFO, "*** Total blocks: %d - Blocks to decode: %d\n", nblocks, blockstodecode);
+    if ((res = decode_chunk (s, s->inbuffer, &(s->firstbyte),
+                             &(s->bytesconsumed),
+                             s->decoded0, s->decoded1,
+                             blockstodecode)) < 0)
+      return buf_size;
+
+    p = s->wavbuffer;
+    if (avctx->bits_per_sample == 16)
+    {
+      int i;
+      for (i = 0 ; i < blockstodecode ; i++)
+      {
+        sample16 = s->decoded0[i];
+        *(p++) = sample16 & 0xff;
+        *(p++) = (sample16&0xff00) >> 8;
+        
+        if (s->channels == 2)
+        {
+          sample16 = s->decoded1[i];
+          *(p++) = sample16 & 0xff;
+          *(p++) = (sample16&0xff00) >> 8;
+        }
+      }
+    } else if (avctx->bits_per_sample == 24) {
+      int i;
+      for (i = 0 ; i < blockstodecode ; i++)
+      {
+        sample32 = s->decoded0[i];
+        *(p++) = sample32 & 0xff;
+        *(p++) = (sample32&0xff00) >> 8;
+        *(p++) = (sample32&0xff0000) >> 16;
+
+        if (s->channels == 2) {
+          sample32 = s->decoded1[i];
+          *(p++) = sample32 & 0xff;
+          *(p++) = (sample32&0xff00) >> 8;
+          *(p++) = (sample32&0xff0000) >> 16;
+        }
+      }
+    }
+
+    memcpy (samples + decoded_offset, s->wavbuffer, p - s->wavbuffer);
+    decoded_offset += p - s->wavbuffer;
+
+    /* Update the buffer */
+    memmove (s->inbuffer, s->inbuffer + s->bytesconsumed,
+             s->bytesinbuffer - s->bytesconsumed);
+    s->bytesinbuffer -= s->bytesconsumed;
+    n = bytestream_get_buffer (&buf, s->inbuffer + s->bytesinbuffer, INPUT_CHUNKSIZE - s->bytesinbuffer);
+    s->bytesinbuffer += n;
+    av_log (avctx, AV_LOG_INFO, "*** Frame: %d - Decoded offset: %d - n: %d - size: %d\n",
+            frame, decoded_offset, n, p - s->wavbuffer);
+    
+    *data_size += p - s->wavbuffer;
+    nblocks -= blockstodecode;
+  }
+
+  frame++;
+  av_log (avctx, AV_LOG_INFO, "*** Decoded Data Size %d \n", *data_size);
+  return buf_size;
+}
+
+AVCodec ape_decoder = {
+    "ape",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_APE,
+    sizeof(APEContext),
+    ape_decode_init,
+    NULL,
+    ape_decode_close,
+    ape_decode_frame,
+};
Index: libavcodec/allcodecs.c
===================================================================
--- libavcodec/allcodecs.c	(revision 9370)
+++ libavcodec/allcodecs.c	(working copy)
@@ -167,6 +167,7 @@
     REGISTER_DECODER(MPEG4AAC, mpeg4aac);
     REGISTER_ENCODER(AC3, ac3);
     REGISTER_DECODER(ALAC, alac);
+    REGISTER_DECODER(APE, ape);
     REGISTER_DECODER(ATRAC3, atrac3);
     REGISTER_DECODER(COOK, cook);
     REGISTER_DECODER(DCA, dca);
Index: libavcodec/allcodecs.h
===================================================================
--- libavcodec/allcodecs.h	(revision 9370)
+++ libavcodec/allcodecs.h	(working copy)
@@ -76,6 +76,7 @@
 
 extern AVCodec aasc_decoder;
 extern AVCodec alac_decoder;
+extern AVCodec ape_decoder;
 extern AVCodec asv1_decoder;
 extern AVCodec asv2_decoder;
 extern AVCodec atrac3_decoder;
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h	(revision 9370)
+++ libavcodec/avcodec.h	(working copy)
@@ -258,6 +258,7 @@
     CODEC_ID_MLP,
     CODEC_ID_GSM_MS, /* as found in WAV */
     CODEC_ID_ATRAC3,
+    CODEC_ID_APE,
 
     /* subtitle codecs */
     CODEC_ID_DVD_SUBTITLE= 0x17000,
@@ -294,7 +295,7 @@
 };
 
 /* in bytes */
-#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
+#define AVCODEC_MAX_AUDIO_FRAME_SIZE 384000 // 1 second of 96khz 32bit audio
 
 /**
  * Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Index: libavformat/ape.c
===================================================================
--- libavformat/ape.c	(revision 0)
+++ libavformat/ape.c	(revision 0)
@@ -0,0 +1,487 @@
+/*
+ * Monkey's Audio APE demuxer
+ * Copyright (c) 2007 Benjamin Zores <ben at geexbox.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+
+#include "avformat.h"
+
+/* typedef struct { */
+
+/* } APEContext; */
+
+/* The earliest and latest file formats supported by this library */
+#define APE_MIN_VERSION 3970
+#define APE_MAX_VERSION 3990
+
+#define MAC_FORMAT_FLAG_8_BIT                 1    // is 8-bit [OBSOLETE]
+#define MAC_FORMAT_FLAG_CRC                   2    // uses the new CRC32 error detection [OBSOLETE]
+#define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL        4    // uint32 nPeakLevel after the header [OBSOLETE]
+#define MAC_FORMAT_FLAG_24_BIT                8    // is 24-bit [OBSOLETE]
+#define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS    16    // has the number of seek elements after the peak level
+#define MAC_FORMAT_FLAG_CREATE_WAV_HEADER    32    // create the wave header on decompression (not stored)
+
+#define INPUT_CHUNKSIZE     (32*1024)
+
+/* Special frame codes:
+
+   MONO_SILENCE - All PCM samples in frame are zero (mono streams only)
+   LEFT_SILENCE - All PCM samples for left channel in frame are zero (stereo streams)
+   RIGHT_SILENCE - All PCM samples for left channel in frame are zero (stereo streams)
+   PSEUDO_STEREO - Left and Right channels are identical
+
+*/
+
+#define APE_FRAMECODE_MONO_SILENCE    1
+#define APE_FRAMECODE_STEREO_SILENCE  3
+#define APE_FRAMECODE_PSEUDO_STEREO   4
+
+#define HISTORY_SIZE 512
+#define PREDICTOR_ORDER 8
+
+/* struct predictor_t */
+/* { */
+/*     /\* Adaption co-efficients *\/ */
+/*     int32_t coeffsA[4]; */
+/*     int32_t coeffsB[5]; */
+
+/*     /\* Filter histories *\/ */
+/*     int32_t historybuffer[HISTORY_SIZE + PREDICTOR_ORDER * 4]; */
+/*     int32_t* delayA; */
+/*     int32_t* delayB; */
+/*     int32_t* adaptcoeffsA; */
+/*     int32_t* adaptcoeffsB; */
+
+/*     int32_t lastA; */
+
+/*     int32_t filterA; */
+/*     int32_t filterB; */
+/* }; */
+
+typedef struct {
+  int64_t pos;
+  int nblocks;
+  //int size, skip;
+} APEFrame;
+
+typedef struct
+{
+  /* Derived fields */
+  uint32_t      junklength;
+  uint32_t      firstframe;
+  uint32_t      totalsamples;
+  int           currentframe;
+  APEFrame      *frames;
+  
+  /* Info from Descriptor Block */
+  char          magic[4];
+  int16_t       fileversion;
+  int16_t       padding1;
+  uint32_t      descriptorlength;
+  uint32_t      headerlength;
+  uint32_t      seektablelength;
+  uint32_t      wavheaderlength;
+  uint32_t      audiodatalength;
+  uint32_t      audiodatalength_high;
+  uint32_t      wavtaillength;
+  uint8_t       md5[16];
+
+  /* Info from Header Block */
+  uint16_t      compressiontype;
+  uint16_t      formatflags;
+  uint32_t      blocksperframe;
+  uint32_t      finalframeblocks;
+  uint32_t      totalframes;
+  uint16_t      bps;
+  uint16_t      channels;
+  uint32_t      samplerate;
+
+  /* Seektable */
+  uint32_t*     seektable;
+ 
+  /* Decoder state */
+  uint32_t      CRC;
+  int           frameflags;
+  int           currentframeblocks;
+  int           blocksdecoded;
+  //struct predictor_t predictorY;
+  //struct predictor_t predictorX;
+} APEContext;
+
+static int ape_probe(AVProbeData *p)
+{
+  printf ("%s:%d\n", __FUNCTION__, __LINE__);
+
+  /* check file header */
+  if (p->buf_size <= 32)
+    return 0;
+  
+  if (p->buf[0] == 'M' && p->buf[1] == 'A' &&
+      p->buf[2] == 'C' && p->buf[3] == ' ')
+  {
+    printf ("found an APE file\n");
+    return AVPROBE_SCORE_MAX;
+  }
+
+  return 0;
+}
+
+void ape_dumpinfo (APEContext *ape_ctx)
+{
+  int i;
+
+  printf("Descriptor Block:\n\n");
+  printf("magic                = \"%c%c%c%c\"\n",
+         ape_ctx->magic[0],ape_ctx->magic[1],
+         ape_ctx->magic[2],ape_ctx->magic[3]);
+  printf("fileversion          = %d\n",ape_ctx->fileversion);
+  printf("descriptorlength     = %d\n",ape_ctx->descriptorlength);
+  printf("headerlength         = %d\n",ape_ctx->headerlength);
+  printf("seektablelength      = %d\n",ape_ctx->seektablelength);
+  printf("wavheaderlength      = %d\n",ape_ctx->wavheaderlength);
+  printf("audiodatalength      = %d\n",ape_ctx->audiodatalength);
+  printf("audiodatalength_high = %d\n",ape_ctx->audiodatalength_high);
+  printf("wavtaillength        = %d\n",ape_ctx->wavtaillength);
+  printf("md5                  = ");
+  for (i = 0; i < 16; i++)
+    printf("%02x",ape_ctx->md5[i]);
+  printf("\n");
+
+  printf("\nHeader Block:\n\n");
+
+  printf("compressiontype      = %d\n",ape_ctx->compressiontype);
+  printf("formatflags          = %d\n",ape_ctx->formatflags);
+  printf("blocksperframe       = %d\n",ape_ctx->blocksperframe);
+  printf("finalframeblocks     = %d\n",ape_ctx->finalframeblocks);
+  printf("totalframes          = %d\n",ape_ctx->totalframes);
+  printf("bps                  = %d\n",ape_ctx->bps);
+  printf("channels             = %d\n",ape_ctx->channels);
+  printf("samplerate           = %d\n",ape_ctx->samplerate);
+
+  printf("\nSeektable\n\n");
+  if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes)
+  {
+    printf("No seektable\n");
+  }
+  else
+  {
+    for ( i = 0; i < ape_ctx->seektablelength / sizeof(uint32_t) ; i++)
+    {
+      if (i < ape_ctx->totalframes-1) {
+        printf("%8d   %d (%d bytes)\n",i,ape_ctx->seektable[i],ape_ctx->seektable[i+1]-ape_ctx->seektable[i]);
+      } else {
+        printf("%8d   %d\n",i,ape_ctx->seektable[i]);
+      }
+    }
+  }
+  printf("\nCalculated information:\n\n");
+  printf("junklength           = %d\n",ape_ctx->junklength);
+  printf("firstframe           = %d\n",ape_ctx->firstframe);
+  printf("totalsamples         = %d\n",ape_ctx->totalsamples);
+}
+
+typedef struct {
+  int16_t fileversion;
+  uint16_t compression;
+  uint16_t flags;
+} APECodecInfo;
+
+static int ape_read_header (AVFormatContext *s,
+                            AVFormatParameters *ap)
+{
+  ByteIOContext *pb = &s->pb;
+  APEContext *ape = s->priv_data;
+  APECodecInfo *data;
+  AVStream *st;
+  uint32_t tag;
+  int i;
+  int total_blocks;
+  
+  /* TODO: Skip any leading junk such as id3v2 tags */
+  ape->junklength = 0;
+
+  printf ("%s:%d\n", __FUNCTION__, __LINE__);
+
+  tag = get_le32 (pb);
+  if (tag != MKTAG ('M', 'A', 'C', ' '))
+    return -1;
+  
+  ape->fileversion = get_le16 (pb);
+  printf ("version: %d\n", ape->fileversion);
+
+  if ((ape->fileversion < APE_MIN_VERSION)
+      || (ape->fileversion > APE_MAX_VERSION))
+  {
+    printf ("Unsupported file version - %.2f\n", ape->fileversion / 1000.0);
+    return -1;
+  }
+  
+  if (ape->fileversion >= 3980)
+  {
+    ape->padding1 = get_le16 (pb);
+    ape->descriptorlength = get_le32 (pb);
+    ape->headerlength = get_le32 (pb);
+    ape->seektablelength = get_le32 (pb);
+    ape->wavheaderlength = get_le32 (pb);
+    ape->audiodatalength = get_le32 (pb);
+    ape->audiodatalength_high = get_le32 (pb);
+    ape->wavtaillength = get_le32 (pb);
+    get_buffer (pb, ape->md5, 16);
+
+    /* Skip any unknown bytes at the end of the descriptor.
+       This is for future compatibility */
+    if (ape->descriptorlength > 52)
+      url_fseek (pb, ape->descriptorlength - 52, SEEK_CUR);
+
+    /* Read header data */
+    ape->compressiontype = get_le16 (pb);
+    ape->formatflags = get_le16 (pb);
+    ape->blocksperframe = get_le32 (pb);
+    ape->finalframeblocks = get_le32 (pb);
+    ape->totalframes = get_le32 (pb);
+    ape->bps = get_le16 (pb);
+    ape->channels = get_le16 (pb);
+    ape->samplerate = get_le32 (pb);
+  }
+  else
+  {
+    ape->descriptorlength = 0;
+    ape->headerlength = 32;
+
+    ape->compressiontype = get_le16 (pb);
+    ape->formatflags = get_le16 (pb);
+    ape->channels = get_le16 (pb);
+    ape->samplerate = get_le32 (pb);
+    ape->wavheaderlength = get_le32 (pb);
+    ape->wavtaillength = get_le32 (pb);
+    ape->totalframes = get_le32 (pb);
+    ape->finalframeblocks = get_le32 (pb);
+    
+    if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL)
+    {
+      url_fseek (pb, 4, SEEK_CUR);   /* Skip the peak level */
+      ape->headerlength += 4;
+    }
+
+    if (ape->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS)
+    {
+      ape->seektablelength = get_le32 (pb);
+      ape->headerlength += 4;
+      ape->seektablelength *= sizeof (int32_t);
+    }
+    else
+      ape->seektablelength = ape->totalframes * sizeof (int32_t);
+
+    if (ape->formatflags & MAC_FORMAT_FLAG_8_BIT)
+      ape->bps = 8;
+    else if (ape->formatflags & MAC_FORMAT_FLAG_24_BIT)
+      ape->bps = 24;
+    else
+      ape->bps = 16;
+
+    if (ape->fileversion >= 3950)
+      ape->blocksperframe = 73728 * 4;
+    else if ((ape->fileversion >= 3900) ||
+             (ape->fileversion >= 3800 && ape->compressiontype >= 4000))
+      ape->blocksperframe = 73728;
+    else
+      ape->blocksperframe = 9216;
+
+    /* Skip any stored wav header */
+    if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))
+      url_fseek (pb, ape->wavheaderlength, SEEK_CUR);
+  }
+
+  ape->frames = av_malloc (ape->totalframes * sizeof (APEFrame));
+  ape->firstframe = ape->junklength + ape->descriptorlength +
+    ape->headerlength + ape->seektablelength + ape->wavheaderlength;
+  ape->currentframe = 0;
+
+  ape->frames[0].pos = ape->firstframe;
+  ape->frames[0].nblocks = ape->blocksperframe;
+  for (i = 1; i < ape->totalframes; i++)
+  {
+    ape->frames[i].pos = ape->frames[i-1].pos + ape->blocksperframe;
+    ape->frames[i].nblocks = ape->blocksperframe;
+    printf ("Frame %d (pos = %ld, nblocks = %d)\n",
+            i, ape->frames[i].pos, ape->frames[i].nblocks);
+  }
+  //ape->frames[ape->totalframes].nblocks = ape->finalframeblocks;
+  
+  ape->totalsamples = ape->finalframeblocks;
+  if (ape->totalframes > 1)
+    ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1);
+
+  if (ape->seektablelength > 0)
+  {
+    ape->seektable = av_malloc (ape->seektablelength);
+    for (i = 0; i < ape->seektablelength / sizeof (uint32_t); i++)
+      ape->seektable[i] = get_le32 (pb);
+  }
+ 
+  ape_dumpinfo (ape);
+
+  printf ("Decoding file - v%.2f, compression level %d\n",
+          ape->fileversion / 1000.0, ape->compressiontype);
+
+  /* now we are ready: build format streams */
+  st = av_new_stream (s, 0);
+  if (!st)
+    return -1;
+
+  total_blocks = (ape->totalframes == 0) ? 0 :
+    ((ape->totalframes -1) * ape->blocksperframe) + ape->finalframeblocks;
+  
+  av_set_pts_info (st, 64, 1, ape->samplerate);
+  st->codec->sample_rate = ape->samplerate;
+  s->start_time = 0;
+  st->nb_frames = ape->totalframes;
+  s->duration = (int64_t) total_blocks * AV_TIME_BASE / ape->samplerate;
+  st->need_parsing = 1;
+  
+  // get the wave header
+  /* if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER)) */
+/*   { */
+/*     int size; */
+/*     unsigned int tag; */
+/*     printf ("here\n"); */
+/*     /\* check RIFF header *\/ */
+/*     tag = get_le32(pb); */
+/*     get_le32(pb); /\* file size *\/ */
+/*     tag = get_le32(pb); */
+    
+/*     /\* parse fmt header *\/ */
+/*     tag = get_le32(pb); /\* 'fmt ' *\/ */
+/*     size = get_le32(pb); */
+
+/*     //get_wav_header (pb, st->codec, ape->nWAVHeaderBytes); */
+/*   } */
+/*   else */
+  {
+    int nAPETotalBytes = url_fsize (pb);
+    int nLengthMS = total_blocks * 1000 / ape->samplerate;
+    int nAverageBitrate = (nLengthMS <= 0) ? 0 : (int)(((double)(nAPETotalBytes) * (double)(8)) / (double)(nLengthMS));
+    int block_align = ape->bps / 8 * ape->channels;
+    
+    st->codec->codec_type = CODEC_TYPE_AUDIO;
+    st->codec->codec_id = CODEC_ID_APE;
+    st->codec->channels = ape->channels;
+    st->codec->sample_rate = ape->samplerate;
+    st->codec->bits_per_sample = ape->bps;
+    st->codec->block_align = block_align;
+    st->codec->bit_rate = nAverageBitrate;
+  }
+
+  printf ("Channels: %d\n", st->codec->channels);
+  printf ("Sample rate: %d\n", st->codec->sample_rate);
+  printf ("BPS: %d\n", st->codec->bits_per_sample);
+  printf ("Bitrate: %d\n", st->codec->bit_rate);
+  printf ("Block Align: %d\n", st->codec->block_align);
+
+  data = av_malloc (sizeof (APECodecInfo));
+  data->fileversion = ape->fileversion;
+  data->compression = ape->compressiontype;
+  data->flags = ape->formatflags;
+  st->codec->extradata = (void *) data;
+  st->codec->extradata_size = sizeof (APECodecInfo);
+  
+  /* go to first frame */
+  url_fseek (pb, ape->firstframe, SEEK_SET);
+  
+  return 0;
+}
+
+static int ape_read_packet (AVFormatContext *s, AVPacket *pkt)
+{
+  int ret;
+  int nblocks;
+  APEContext *ape = s->priv_data;
+  uint32_t extra_size = sizeof (uint32_t);
+  
+  //uint8_t *extradata = NULL;
+  //int extradata_size = 0;
+  //int extradata_offset = 0;
+  
+  if (url_feof (&s->pb))
+    return AVERROR (EIO);
+
+  if (ape->currentframe >= ape->totalframes)
+    return -1;
+  
+  //printf ("%s:%d\n", __FUNCTION__, __LINE__);
+
+  /* Initialise the buffer */
+  //bytesinbuffer = read(fd, inbuffer, INPUT_CHUNKSIZE);
+  //firstbyte = 3;  /* Take account of the little-endian 32-bit byte ordering */
+
+  /* Calculate how many blocks there are in this frame */
+  if (ape->currentframe == (ape->totalframes - 1))
+    nblocks = ape->finalframeblocks;
+  else
+    nblocks = ape->blocksperframe;
+  ape->currentframeblocks = nblocks;
+
+  if (av_new_packet (pkt, nblocks + extra_size) < 0)
+    return AVERROR_NOMEM;
+  
+  memcpy (pkt->data, &nblocks, extra_size);
+  ret = get_buffer (&s->pb, pkt->data + extra_size, nblocks);
+  if (ret != nblocks)
+  {
+    av_free_packet (pkt);
+    return AVERROR_IO;
+  }
+  
+  //ret = av_get_packet (&s->pb, pkt, nblocks);
+
+  pkt->pts = ape->currentframe;
+  pkt->stream_index = 0;
+  //if (ret <= 0)
+    //return AVERROR_IO;
+
+  /* note: we need to modify the packet size here to handle the last
+     packet */
+  pkt->size = ret + extra_size;
+
+  //pkt->pts = 0;
+  
+  printf ("Read frame %d : %d (%d)\n", ape->currentframe, pkt->size, ret);
+  ape->currentframe++;
+
+  return 0;
+}
+
+static int ape_read_close(AVFormatContext *s)
+{
+  printf ("%s:%d\n", __FUNCTION__, __LINE__);
+  return 0;
+}
+
+AVInputFormat ape_demuxer = {
+    "ape",
+    "Monkey's Audio",
+    sizeof(APEContext),
+    ape_probe,
+    ape_read_header,
+    ape_read_packet,
+    ape_read_close,
+    //.flags = AVFMT_GENERIC_INDEX,
+    .extensions = "ape,apl,mac", /* XXX: use probe */
+};
Index: libavformat/Makefile
===================================================================
--- libavformat/Makefile	(revision 9370)
+++ libavformat/Makefile	(working copy)
@@ -19,6 +19,7 @@
 OBJS-$(CONFIG_AIFF_MUXER)                += aiff.o riff.o
 OBJS-$(CONFIG_AMR_DEMUXER)               += amr.o
 OBJS-$(CONFIG_AMR_MUXER)                 += amr.o
+OBJS-$(CONFIG_APE_DEMUXER)               += ape.o
 OBJS-$(CONFIG_APC_DEMUXER)               += apc.o
 OBJS-$(CONFIG_ASF_DEMUXER)               += asf.o riff.o
 OBJS-$(CONFIG_ASF_MUXER)                 += asf-enc.o riff.o
Index: libavformat/allformats.c
===================================================================
--- libavformat/allformats.c	(revision 9370)
+++ libavformat/allformats.c	(working copy)
@@ -51,6 +51,7 @@
     REGISTER_MUXER   (ADTS, adts);
     REGISTER_MUXDEMUX(AIFF, aiff);
     REGISTER_MUXDEMUX(AMR, amr);
+    REGISTER_DEMUXER (APE, ape);
     REGISTER_DEMUXER (APC, apc);
     REGISTER_MUXDEMUX(ASF, asf);
     REGISTER_MUXER   (ASF_STREAM, asf_stream);
Index: libavformat/allformats.h
===================================================================
--- libavformat/allformats.h	(revision 9370)
+++ libavformat/allformats.h	(working copy)
@@ -28,6 +28,7 @@
 extern AVInputFormat ac3_demuxer;
 extern AVInputFormat aiff_demuxer;
 extern AVInputFormat amr_demuxer;
+extern AVInputFormat ape_demuxer;
 extern AVInputFormat apc_demuxer;
 extern AVInputFormat asf_demuxer;
 extern AVInputFormat au_demuxer;



More information about the ffmpeg-devel mailing list