[FFmpeg-devel] [PATCH] ALAC Encoder

Jai Menon realityman
Mon Aug 18 18:25:10 CEST 2008


Hi,

On Monday 18 Aug 2008 3:46:23 am Michael Niedermayer wrote:
> On Mon, Aug 18, 2008 at 02:38:24AM +0530, Jai Menon wrote:
> > Hi,
> >
> > On Sunday 17 Aug 2008 5:17:52 pm Michael Niedermayer wrote:
> > > On Sun, Aug 17, 2008 at 11:17:10AM +0530, Jai Menon wrote:
>
> [...]
>
> [...]
>
> > Index: libavcodec/alacenc.c
> > ===================================================================
> > --- libavcodec/alacenc.c	(revision 14818)
> > +++ libavcodec/alacenc.c	(working copy)
> > @@ -33,15 +33,58 @@
> >
> >  #define ALAC_ESCAPE_CODE          0x1FF
> >  #define ALAC_MAX_LPC_ORDER        30
> > +#define DEFAULT_MAX_PRED_ORDER    6
> > +#define DEFAULT_MIN_PRED_ORDER    4
> > +#define ALAC_MAX_LPC_PRECISION    9
> > +#define ALAC_MAX_LPC_SHIFT        9
>
> ok
>
> > +#define ALAC_CHMODE_LEFT_RIGHT    1
> > +#define ALAC_CHMODE_LEFT_SIDE     8
> > +#define ALAC_CHMODE_RIGHT_SIDE    9
> > +#define ALAC_CHMODE_MID_SIDE     10
> > +
> >
> > +typedef struct RiceContext {
> > +    int history_mult;
> > +    int initial_history;
> > +    int k_modifier;
> > +    int rice_modifier;
> > +} RiceContext;
> > +
> > +typedef struct LPCContext {
> > +    int lpc_order;
> > +    int lpc_coeff[ALAC_MAX_LPC_ORDER+1];
> > +    int lpc_quant;
> > +} LPCContext;
> > +
> > +typedef struct AlacEncodeContext {
> > +    int compression_level;
> > +    int max_coded_frame_size;
> > +    int write_sample_size;
> > +    int32_t sample_buf[MAX_CHANNELS][DEFAULT_FRAME_SIZE];
>
> ok
>
> > +    int32_t predictor_buf[DEFAULT_FRAME_SIZE];
> >      int interlacing_shift;
> >      int interlacing_leftweight;
> >      PutBitContext pbctx;
> >
> > +    RiceContext rc;
> > +    LPCContext lpc[MAX_CHANNELS];
>
> ok
>
> >      DSPContext dspctx;
> >      AVCodecContext *avctx;
> >  } AlacEncodeContext;
> >
> >
> >
> > +static void init_sample_buffers(AlacEncodeContext *s, int16_t
> > *input_samples) +{
> > +    int ch, i;
> > +
> > +    for(ch=0;ch<s->avctx->channels;ch++) {
> > +        int16_t *sptr = input_samples + ch;
> > +        for(i=0;i<s->avctx->frame_size;i++) {
> > +            s->sample_buf[ch][i] = *sptr;
> > +            sptr += s->avctx->channels;
> > +        }
> > +    }
> > +}
> > +
> >  static void encode_scalar(AlacEncodeContext *s, int x, int k, int
> > write_sample_size) {
> >      int divisor, q, r;
>
> ok
>
> > @@ -71,7 +114,7 @@
> >
> >  static void write_frame_header(AlacEncodeContext *s, int is_verbatim)
> >  {
> > -    put_bits(&s->pbctx, 3,  s->channels-1);                 // No. of
> > channels -1 +    put_bits(&s->pbctx, 3,  s->avctx->channels-1);         
> > // No. of channels -1 put_bits(&s->pbctx, 16, 0);                        
> >     // Seems to be zero put_bits(&s->pbctx, 1,  1);                      
> >       // Sample count is in the header put_bits(&s->pbctx, 2,  0);       
> >                      // FIXME: Wasted bytes field
>
> ok
>
> > @@ -79,6 +122,205 @@
> >      put_bits(&s->pbctx, 32, s->avctx->frame_size);          // No. of
> > samples in the frame }
> >
> > +static void calc_predictor_params(AlacEncodeContext *s, int ch)
> > +{
> > +    int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER];
> > +    int shift[MAX_LPC_ORDER];
> > +    int opt_order;
> > +
> > +    opt_order = ff_lpc_calc_coefs(&s->dspctx, s->sample_buf[ch],
> > s->avctx->frame_size, DEFAULT_MIN_PRED_ORDER, DEFAULT_MAX_PRED_ORDER, +  
> >                                 ALAC_MAX_LPC_PRECISION, coefs, shift, 1,
> > ORDER_METHOD_EST, ALAC_MAX_LPC_SHIFT, 1); +
> > +    s->lpc[ch].lpc_order = opt_order;
> > +    s->lpc[ch].lpc_quant = shift[opt_order-1];
> > +    memcpy(s->lpc[ch].lpc_coeff, coefs[opt_order-1],
> > opt_order*sizeof(int)); +}
> > +
>
> I think this should be using AVCodecContext.min/max_prediction_order
>
> > +static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int
> > n) +{
> > +    int i, best;
> > +    int32_t lt, rt;
> > +    uint64_t sum[4];
> > +    uint64_t score[4];
> > +
> > +    /* calculate sum of 2nd order residual for each channel */
> > +    sum[0] = sum[1] = sum[2] = sum[3] = 0;
> > +    for(i=2; i<n; i++) {
> > +        lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2];
> > +        rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2];
> > +        sum[2] += FFABS((lt + rt) >> 1);
> > +        sum[3] += FFABS(lt - rt);
> > +        sum[0] += FFABS(lt);
> > +        sum[1] += FFABS(rt);
> > +    }
> > +
> > +    /* calculate score for each mode */
> > +    score[0] = sum[0] + sum[1];
> > +    score[1] = sum[0] + sum[3];
> > +    score[2] = sum[1] + sum[3];
> > +    score[3] = sum[2] + sum[3];
> > +
> > +    /* return mode with lowest score */
> > +    best = 0;
> > +    for(i=1; i<4; i++) {
> > +        if(score[i] < score[best]) {
> > +            best = i;
> > +        }
> > +    }
>
> ok
>
> > +    if(best == 0) {
> > +        return ALAC_CHMODE_LEFT_RIGHT;
> > +    } else if(best == 1) {
> > +        return ALAC_CHMODE_LEFT_SIDE;
> > +    } else if(best == 2) {
> > +        return ALAC_CHMODE_RIGHT_SIDE;
> > +    } else {
> > +        return ALAC_CHMODE_MID_SIDE;
> > +    }
> > +}
>
> i think best could simply be returned
>
> > +
> > +static void alac_stereo_decorrelation(AlacEncodeContext *s)
> > +{
> > +    int32_t *left = s->sample_buf[0], *right = s->sample_buf[1];
> > +    int i, mode, n = s->avctx->frame_size;
> > +
> > +    mode = estimate_stereo_mode(left, right, n);
> > +
> > +    if(mode == ALAC_CHMODE_LEFT_RIGHT) {
> > +        s->interlacing_leftweight = 0;
> > +        s->interlacing_shift = 0;
> > +        return;
> > +    }
> > +
> > +    if(mode == ALAC_CHMODE_LEFT_SIDE) {
> > +        for(i=0; i<n; i++) {
> > +            right[i] = left[i] - right[i];
> > +        }
> > +        s->interlacing_leftweight = 1;
> > +        s->interlacing_shift = 0;
> > +
> > +    } else {
> > +        int32_t tmp;
> > +        for(i=0; i<n; i++) {
> > +            tmp = left[i];
> > +            left[i] = (tmp + right[i]) >> 1;
> > +            right[i] = tmp - right[i];
> > +        }
> > +        s->interlacing_leftweight = 1;
> > +        s->interlacing_shift = 1;
> > +    }
>
> i think 1 mode is missing

I left out the right-side mode because I really don't see how the decoder 
could support it without accidentally swapping channels. Or am I missing 
something?

Regards,

Jai Menon




More information about the ffmpeg-devel mailing list