[FFmpeg-soc] [soc]: r3601 - mlp/mlpenc.c

ramiro subversion at mplayerhq.hu
Mon Aug 25 01:14:20 CEST 2008


Author: ramiro
Date: Mon Aug 25 01:14:20 2008
New Revision: 3601

Log:
Reorder functions into logical blocks.

Modified:
   mlp/mlpenc.c

Modified: mlp/mlpenc.c
==============================================================================
--- mlp/mlpenc.c	(original)
+++ mlp/mlpenc.c	Mon Aug 25 01:14:20 2008
@@ -156,120 +156,182 @@ typedef struct {
 #define SYNC_MLP        0xbb
 #define SYNC_TRUEHD     0xba
 
-enum InputBitDepth {
-    BITS_16,
-    BITS_20,
-    BITS_24,
-};
+/****************************************************************************
+ ************ Functions that copy, clear, or compare parameters *************
+ ****************************************************************************/
 
-/** Returns the coded sample_rate for MLP. */
-static int mlp_sample_rate(int sample_rate)
+/** Compares two FilterParams structures and returns 1 if anything has
+ *  changed. Returns 0 if they are both equal.
+ */
+static int compare_filter_params(FilterParams *prev, FilterParams *fp)
 {
-    switch (sample_rate) {
-    case 44100 << 0: return 0x8 + 0;
-    case 44100 << 1: return 0x8 + 1;
-    case 44100 << 2: return 0x8 + 2;
-    case 48000 << 0: return 0x0 + 0;
-    case 48000 << 1: return 0x0 + 1;
-    case 48000 << 2: return 0x0 + 2;
-    default:
-        return -1;
-    }
+    int i;
+
+    if (prev->order != fp->order)
+        return 1;
+
+    if (!prev->order)
+        return 0;
+
+    if (prev->shift != fp->shift)
+        return 1;
+
+    for (i = 0; i < fp->order; i++)
+        if (prev->coeff[i] != fp->coeff[i])
+            return 1;
+
+    return 0;
 }
 
-/** Writes a major sync header to the bitstream. */
-static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
+/** Compare two primitive matrices and returns 1 if anything has changed.
+ *  Returns 0 if they are both equal.
+ */
+static int compare_matrix_params(MLPEncodeContext *ctx, MatrixParams *prev, MatrixParams *mp)
 {
-    PutBitContext pb;
-
-    init_put_bits(&pb, buf, buf_size);
+    RestartHeader *rh = ctx->cur_restart_header;
+    unsigned int channel, mat;
 
-    put_bits(&pb, 24, SYNC_MAJOR           );
-    put_bits(&pb,  8, SYNC_MLP             );
-    put_bits(&pb,  4, ctx->sample_fmt      );
-    put_bits(&pb,  4, ctx->sample_fmt      );
-    put_bits(&pb,  4, ctx->mlp_sample_rate );
-    put_bits(&pb,  4, ctx->mlp_sample_rate );
-    put_bits(&pb, 11, 0                    ); /* This value is 0 in all tested
-                                               * MLP samples. */
-    put_bits(&pb,  5, ctx->mlp_channels);
+    if (prev->count != mp->count)
+        return 1;
 
-    /* These values seem to be constant for all tested MLP samples. */
-    put_bits(&pb, 16, 0xb752);
-    put_bits(&pb, 16, 0x4000);
-    put_bits(&pb, 16, 0x0000);
+    if (!prev->count)
+        return 0;
 
-    put_bits(&pb,  1, 1); /* is_vbr: This value is 1 in all tested MLP samples.
-                           * I suppose it would be 0 only when no filters
-                           * or codebooks are used. */
-    put_bits(&pb, 15, 0); /* TODO peak_bitrate: Most MLP samples tested encode
-                           * a value that evaluates peak_bitrate to 9600000 or
-                           * a little bit less. */
-    put_bits(&pb,  4, 1); /* TODO Support more num_substreams. */
+    for (channel = rh->min_channel; channel <= rh->max_channel; channel++)
+        if (prev->fbits[channel] != mp->fbits[channel])
+            return 1;
 
-    put_bits(&pb, 20, 0x1054c); /* TODO These values have something to do with
-                                 * the sample rate. The ones used here come
-                                 * from samples that are stereo and have
-                                 * 44100Hz. */
-    put_bits(&pb,  8, ctx->mlp_channels2);
-    put_bits(&pb, 32, 0x00008080        ); /* These values seem */
-    put_bits(&pb,  8, 0x00              ); /* to be constants.  */
-    put_bits(&pb,  8, ctx->mlp_channels3); /* TODO Finish understanding this field. */
+    for (mat = 0; mat < mp->count; mat++) {
+        if (prev->outch[mat] != mp->outch[mat])
+            return 1;
 
-    flush_put_bits(&pb);
+        for (channel = 0; channel < ctx->num_channels; channel++)
+            if (prev->coeff[mat][channel] != mp->coeff[mat][channel])
+                return 1;
+    }
 
-    AV_WL16(buf+26, ff_mlp_checksum16(buf, 26));
+    return 0;
 }
 
-/** Writes a restart header to the bitstream. Damaged streams can start being
- *  decoded losslessly again after such a header and the subsequent decoding
- *  params header.
+/** Compares two DecodingParams and ChannelParams structures to decide if a
+ *  new decoding params header has to be written.
  */
-static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb)
+static int compare_decoding_params(MLPEncodeContext *ctx)
 {
-    RestartHeader *rh = ctx->cur_restart_header;
-    int32_t lossless_check = xor_32_to_8(rh->lossless_check_data);
-    unsigned int start_count = put_bits_count(pb);
-    PutBitContext tmpb;
-    uint8_t checksum;
+    DecodingParams *prev = ctx->prev_decoding_params;
+    DecodingParams *dp = ctx->cur_decoding_params;
+    MatrixParams *prev_mp = &prev->matrix_params;
+    MatrixParams *mp = &dp->matrix_params;
+    RestartHeader  *rh = ctx->restart_header;
     unsigned int ch;
+    int retval = 0;
 
-    put_bits(pb, 14, 0x31ea                ); /* TODO 0x31eb */
-    put_bits(pb, 16, 0                     ); /* TODO I don't know what this is. Ask Ian. */
-    put_bits(pb,  4, rh->min_channel       );
-    put_bits(pb,  4, rh->max_channel       );
-    put_bits(pb,  4, rh->max_matrix_channel);
-    put_bits(pb,  4, rh->noise_shift       );
-    put_bits(pb, 23, rh->noisegen_seed     );
-    put_bits(pb, 19, 0                     ); /* TODO What the hell is this? */
-    put_bits(pb,  1, rh->data_check_present);
-    put_bits(pb,  8, lossless_check        );
-    put_bits(pb, 16, 0                     ); /* This is zero =) */
+    if (prev->param_presence_flags != dp->param_presence_flags)
+        retval |= PARAM_PRESENCE_FLAGS;
+
+    if (prev->blocksize != dp->blocksize)
+        retval |= PARAM_BLOCKSIZE;
+
+    if (compare_matrix_params(ctx, prev_mp, mp))
+        retval |= PARAM_MATRIX;
 
     for (ch = 0; ch <= rh->max_matrix_channel; ch++)
-        put_bits(pb, 6, ch);
+        if (prev_mp->shift[ch] != mp->shift[ch]) {
+            retval |= PARAM_OUTSHIFT;
+            break;
+        }
 
-    /* Data must be flushed for the checksum to be correct. */
-    tmpb = *pb;
-    flush_put_bits(&tmpb);
+    for (ch = 0; ch <= rh->max_channel; ch++)
+        if (prev->quant_step_size[ch] != dp->quant_step_size[ch]) {
+            retval |= PARAM_QUANTSTEP;
+            break;
+        }
 
-    checksum = ff_mlp_restart_checksum(pb->buf, put_bits_count(pb) - start_count);
+    for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+        ChannelParams *prev_cp = &ctx->prev_channel_params[ch];
+        ChannelParams *cp = &ctx->cur_channel_params[ch];
 
-    put_bits(pb,  8, checksum);
+        if (!(retval & PARAM_FIR) &&
+            compare_filter_params(&prev_cp->filter_params[FIR],
+                                  &     cp->filter_params[FIR]))
+            retval |= PARAM_FIR;
+
+        if (!(retval & PARAM_IIR) &&
+            compare_filter_params(&prev_cp->filter_params[IIR],
+                                  &     cp->filter_params[IIR]))
+            retval |= PARAM_IIR;
+
+        if (prev_cp->huff_offset != cp->huff_offset)
+            retval |= PARAM_HUFFOFFSET;
+
+        if (prev_cp->codebook    != cp->codebook  ||
+            prev_cp->huff_lsbs   != cp->huff_lsbs  )
+            retval |= 0x1;
+    }
+
+    return retval;
 }
 
-/** Encodes the third type of channel information for the sync headers.
- *  TODO This field is not yet fully understood. These values are just copied
- *       from some samples out in the wild.
- */
-static uint8_t get_channels3_code(int channels)
+static void copy_filter_params(FilterParams *dst, FilterParams *src)
 {
-    switch (channels) {
-    case 1: return 0x1f;
-    case 2: return 0x1b;
-    case 6: return 0x00;
-    default:
-        return 0x1b;
+    dst->order = src->order;
+
+    if (dst->order) {
+        unsigned int order;
+
+        dst->shift = src->shift;
+
+        dst->coeff_shift = src->coeff_shift;
+        dst->coeff_bits = src->coeff_bits;
+
+        for (order = 0; order < dst->order; order++)
+            dst->coeff[order] = src->coeff[order];
+    }
+}
+
+static void copy_matrix_params(MatrixParams *dst, MatrixParams *src)
+{
+    dst->count = src->count;
+
+    if (dst->count) {
+        unsigned int channel, count;
+
+        for (channel = 0; channel < MAX_CHANNELS; channel++) {
+
+            dst->fbits[channel] = src->fbits[channel];
+            dst->shift[channel] = src->shift[channel];
+
+            for (count = 0; count < MAX_MATRICES; count++)
+                dst->coeff[count][channel] = src->coeff[count][channel];
+        }
+
+        for (count = 0; count < MAX_MATRICES; count++)
+            dst->outch[count] = src->outch[count];
+    }
+}
+
+static void copy_restart_frame_params(MLPEncodeContext *ctx,
+                                      unsigned int substr)
+{
+    unsigned int index;
+
+    for (index = 0; index < ctx->number_of_frames; index++) {
+        DecodingParams *dp = &ctx->decoding_params[ctx->frame_index][index][0][substr];
+        unsigned int channel;
+
+        copy_matrix_params(&dp->matrix_params, &ctx->cur_decoding_params->matrix_params);
+
+        for (channel = 0; channel < MAX_CHANNELS; channel++) {
+            ChannelParams *cp = &ctx->channel_params[ctx->frame_index][index][0][channel];
+            unsigned int filter;
+
+            dp->quant_step_size[channel] = ctx->cur_decoding_params->quant_step_size[channel];
+            dp->matrix_params.shift[channel] = ctx->cur_decoding_params->matrix_params.shift[channel];
+
+            if (index)
+                for (filter = 0; filter < NUM_FILTERS; filter++)
+                    copy_filter_params(&cp->filter_params[filter], &ctx->cur_channel_params[channel].filter_params[filter]);
+        }
     }
 }
 
@@ -330,6 +392,44 @@ static void default_decoding_params(MLPE
     }
 }
 
+/****************************************************************************/
+
+/** Encodes the third type of channel information for the sync headers.
+ *  TODO This field is not yet fully understood. These values are just copied
+ *       from some samples out in the wild.
+ */
+static uint8_t get_channels3_code(int channels)
+{
+    switch (channels) {
+    case 1: return 0x1f;
+    case 2: return 0x1b;
+    case 6: return 0x00;
+    default:
+        return 0x1b;
+    }
+}
+
+enum InputBitDepth {
+    BITS_16,
+    BITS_20,
+    BITS_24,
+};
+
+/** Returns the coded sample_rate for MLP. */
+static int mlp_sample_rate(int sample_rate)
+{
+    switch (sample_rate) {
+    case 44100 << 0: return 0x8 + 0;
+    case 44100 << 1: return 0x8 + 1;
+    case 44100 << 2: return 0x8 + 2;
+    case 48000 << 0: return 0x0 + 0;
+    case 48000 << 1: return 0x0 + 1;
+    case 48000 << 2: return 0x0 + 2;
+    default:
+        return -1;
+    }
+}
+
 static av_cold int mlp_encode_init(AVCodecContext *avctx)
 {
     MLPEncodeContext *ctx = avctx->priv_data;
@@ -456,69 +556,89 @@ static av_cold int mlp_encode_init(AVCod
     return 0;
 }
 
-/** Calculates the smallest number of bits it takes to encode a given signed
- *  value in two's complement.
- */
-static int inline number_sbits(int number)
-{
-    if (number < 0)
-        number++;
-
-    return av_log2(FFABS(number)) + 1 + !!number;
-}
+/****************************************************************************
+ ****************** Functions that write to the bitstream *******************
+ ****************************************************************************/
 
-/** Determines the smallest number of bits needed to encode the filter
- *  coefficients, and if it's possible to right-shift their values without
- *  losing any precision.
- */
-static void code_filter_coeffs(MLPEncodeContext *ctx, FilterParams *fp)
+/** Writes a major sync header to the bitstream. */
+static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
 {
-    int min = INT_MAX, max = INT_MIN;
-    int bits, shift;
-    int coeff_mask = 0;
-    int order;
+    PutBitContext pb;
 
-    for (order = 0; order < fp->order; order++) {
-        int coeff = fp->coeff[order];
+    init_put_bits(&pb, buf, buf_size);
 
-        if (coeff < min)
-            min = coeff;
-        if (coeff > max)
-            max = coeff;
+    put_bits(&pb, 24, SYNC_MAJOR           );
+    put_bits(&pb,  8, SYNC_MLP             );
+    put_bits(&pb,  4, ctx->sample_fmt      );
+    put_bits(&pb,  4, ctx->sample_fmt      );
+    put_bits(&pb,  4, ctx->mlp_sample_rate );
+    put_bits(&pb,  4, ctx->mlp_sample_rate );
+    put_bits(&pb, 11, 0                    ); /* This value is 0 in all tested
+                                               * MLP samples. */
+    put_bits(&pb,  5, ctx->mlp_channels);
 
-        coeff_mask |= coeff;
-    }
+    /* These values seem to be constant for all tested MLP samples. */
+    put_bits(&pb, 16, 0xb752);
+    put_bits(&pb, 16, 0x4000);
+    put_bits(&pb, 16, 0x0000);
 
-    bits = FFMAX(number_sbits(min), number_sbits(max));
+    put_bits(&pb,  1, 1); /* is_vbr: This value is 1 in all tested MLP samples.
+                           * I suppose it would be 0 only when no filters
+                           * or codebooks are used. */
+    put_bits(&pb, 15, 0); /* TODO peak_bitrate: Most MLP samples tested encode
+                           * a value that evaluates peak_bitrate to 9600000 or
+                           * a little bit less. */
+    put_bits(&pb,  4, 1); /* TODO Support more num_substreams. */
 
-    for (shift = 0; shift < 7 && !(coeff_mask & (1<<shift)); shift++);
+    put_bits(&pb, 20, 0x1054c); /* TODO These values have something to do with
+                                 * the sample rate. The ones used here come
+                                 * from samples that are stereo and have
+                                 * 44100Hz. */
+    put_bits(&pb,  8, ctx->mlp_channels2);
+    put_bits(&pb, 32, 0x00008080        ); /* These values seem */
+    put_bits(&pb,  8, 0x00              ); /* to be constants.  */
+    put_bits(&pb,  8, ctx->mlp_channels3); /* TODO Finish understanding this field. */
 
-    fp->coeff_bits  = bits;
-    fp->coeff_shift = shift;
+    flush_put_bits(&pb);
+
+    AV_WL16(buf+26, ff_mlp_checksum16(buf, 26));
 }
 
-/** Writes filter parameters for one filter to the bitstream. */
-static void write_filter_params(MLPEncodeContext *ctx, PutBitContext *pb,
-                                unsigned int channel, unsigned int filter)
+/** Writes a restart header to the bitstream. Damaged streams can start being
+ *  decoded losslessly again after such a header and the subsequent decoding
+ *  params header.
+ */
+static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb)
 {
-    FilterParams *fp = &ctx->cur_channel_params[channel].filter_params[filter];
+    RestartHeader *rh = ctx->cur_restart_header;
+    int32_t lossless_check = xor_32_to_8(rh->lossless_check_data);
+    unsigned int start_count = put_bits_count(pb);
+    PutBitContext tmpb;
+    uint8_t checksum;
+    unsigned int ch;
 
-    put_bits(pb, 4, fp->order);
+    put_bits(pb, 14, 0x31ea                ); /* TODO 0x31eb */
+    put_bits(pb, 16, 0                     ); /* TODO I don't know what this is. Ask Ian. */
+    put_bits(pb,  4, rh->min_channel       );
+    put_bits(pb,  4, rh->max_channel       );
+    put_bits(pb,  4, rh->max_matrix_channel);
+    put_bits(pb,  4, rh->noise_shift       );
+    put_bits(pb, 23, rh->noisegen_seed     );
+    put_bits(pb, 19, 0                     ); /* TODO What the hell is this? */
+    put_bits(pb,  1, rh->data_check_present);
+    put_bits(pb,  8, lossless_check        );
+    put_bits(pb, 16, 0                     ); /* This is zero =) */
 
-    if (fp->order > 0) {
-        int i;
+    for (ch = 0; ch <= rh->max_matrix_channel; ch++)
+        put_bits(pb, 6, ch);
 
-        put_bits(pb, 4, fp->shift  );
-        put_bits(pb, 5, fp->coeff_bits );
-        put_bits(pb, 3, fp->coeff_shift);
+    /* Data must be flushed for the checksum to be correct. */
+    tmpb = *pb;
+    flush_put_bits(&tmpb);
 
-        for (i = 0; i < fp->order; i++) {
-            put_sbits(pb, fp->coeff_bits, fp->coeff[i] >> fp->coeff_shift);
-        }
+    checksum = ff_mlp_restart_checksum(pb->buf, put_bits_count(pb) - start_count);
 
-        /* TODO state data for IIR filter. */
-        put_bits(pb, 1, 0);
-    }
+    put_bits(pb,  8, checksum);
 }
 
 /** Writes matrix params for all primitive matrices to the bitstream. */
@@ -553,6 +673,30 @@ static void write_matrix_params(MLPEncod
     }
 }
 
+/** Writes filter parameters for one filter to the bitstream. */
+static void write_filter_params(MLPEncodeContext *ctx, PutBitContext *pb,
+                                unsigned int channel, unsigned int filter)
+{
+    FilterParams *fp = &ctx->cur_channel_params[channel].filter_params[filter];
+
+    put_bits(pb, 4, fp->order);
+
+    if (fp->order > 0) {
+        int i;
+
+        put_bits(pb, 4, fp->shift  );
+        put_bits(pb, 5, fp->coeff_bits );
+        put_bits(pb, 3, fp->coeff_shift);
+
+        for (i = 0; i < fp->order; i++) {
+            put_sbits(pb, fp->coeff_bits, fp->coeff[i] >> fp->coeff_shift);
+        }
+
+        /* TODO state data for IIR filter. */
+        put_bits(pb, 1, 0);
+    }
+}
+
 /** Writes decoding parameters to the bitstream. These change very often,
  *  usually at almost every frame.
  */
@@ -651,6 +795,229 @@ static void write_decoding_params(MLPEnc
     }
 }
 
+/** Writes the residuals to the bitstream. That is, the VLC codes from the
+ *  codebooks (if any is used), and then the residual.
+ */
+static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb)
+{
+    DecodingParams *dp = ctx->cur_decoding_params;
+    RestartHeader  *rh = ctx->restart_header;
+    int32_t *sample_buffer = ctx->write_buffer;
+    int32_t sign_huff_offset[MAX_CHANNELS];
+    int codebook_index      [MAX_CHANNELS];
+    int lsb_bits            [MAX_CHANNELS];
+    unsigned int i, ch;
+
+    for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+        ChannelParams *cp = &ctx->cur_channel_params[ch];
+        int sign_shift;
+
+        lsb_bits        [ch] = cp->huff_lsbs - dp->quant_step_size[ch];
+        codebook_index  [ch] = cp->codebook  - 1;
+        sign_huff_offset[ch] = cp->huff_offset;
+
+        sign_shift = lsb_bits[ch] - 1;
+
+        if (cp->codebook > 0) {
+            sign_huff_offset[ch] -= 7 << lsb_bits[ch];
+            sign_shift += 3 - cp->codebook;
+        }
+
+        /* Unsign if needed. */
+        if (sign_shift >= 0)
+            sign_huff_offset[ch] -= 1 << sign_shift;
+    }
+
+    for (i = 0; i < dp->blocksize; i++) {
+        for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+            int32_t sample = *sample_buffer++ >> dp->quant_step_size[ch];
+
+            sample -= sign_huff_offset[ch];
+
+            if (codebook_index[ch] >= 0) {
+                int vlc = sample >> lsb_bits[ch];
+                put_bits(pb, ff_mlp_huffman_tables[codebook_index[ch]][vlc][1],
+                             ff_mlp_huffman_tables[codebook_index[ch]][vlc][0]);
+            }
+
+            put_sbits(pb, lsb_bits[ch], sample);
+        }
+        sample_buffer += 2; /* noise channels */
+    }
+
+    ctx->write_buffer = sample_buffer;
+}
+
+/** Writes the substreams data to the bitstream. */
+static uint8_t *write_substrs(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
+                             int restart_frame,
+                             uint16_t substream_data_len[MAX_SUBSTREAMS])
+{
+    int32_t *lossless_check_data = ctx->lossless_check_data;
+    unsigned int substr;
+    int end = 0;
+
+    lossless_check_data += ctx->frame_index * ctx->num_substreams;
+
+    for (substr = 0; substr < ctx->num_substreams; substr++) {
+        unsigned int subblock, num_subblocks = restart_frame;
+        RestartHeader  *rh = &ctx->restart_header [substr];
+        uint8_t parity, checksum;
+        PutBitContext pb, tmpb;
+        int params_changed;
+
+        ctx->cur_restart_header = rh;
+
+        init_put_bits(&pb, buf, buf_size);
+
+        for (subblock = 0; subblock <= num_subblocks; subblock++) {
+
+            ctx->cur_decoding_params = &ctx->major_decoding_params[ctx->frame_index][subblock][substr];
+            ctx->cur_channel_params = ctx->major_channel_params[ctx->frame_index][subblock];
+
+            params_changed = ctx->major_params_changed[ctx->frame_index][subblock][substr];
+
+            if (restart_frame || params_changed) {
+                put_bits(&pb, 1, 1);
+
+                if (restart_frame) {
+                    put_bits(&pb, 1, 1);
+
+                    write_restart_header(ctx, &pb);
+                    rh->lossless_check_data = 0;
+                } else {
+                    put_bits(&pb, 1, 0);
+                }
+
+                write_decoding_params(ctx, &pb, params_changed);
+            } else {
+                put_bits(&pb, 1, 0);
+            }
+
+            if (!restart_frame)
+                rh->lossless_check_data ^= *lossless_check_data++;
+
+            write_block_data(ctx, &pb);
+
+            put_bits(&pb, 1, !restart_frame);
+
+            if (restart_frame)
+                restart_frame = 0;
+        }
+
+        put_bits(&pb, (-put_bits_count(&pb)) & 15, 0);
+
+        if (ctx->last_frame == ctx->inout_buffer) {
+            /* TODO find a sample and implement shorten_by. */
+            put_bits(&pb, 32, END_OF_STREAM);
+        }
+
+        /* Data must be flushed for the checksum and parity to be correct. */
+        tmpb = pb;
+        flush_put_bits(&tmpb);
+
+        parity   = ff_mlp_calculate_parity(buf, put_bits_count(&pb) >> 3) ^ 0xa9;
+        checksum = ff_mlp_checksum8       (buf, put_bits_count(&pb) >> 3);
+
+        put_bits(&pb, 8, parity  );
+        put_bits(&pb, 8, checksum);
+
+        flush_put_bits(&pb);
+
+        end += put_bits_count(&pb) >> 3;
+        substream_data_len[substr] = end;
+
+        buf += put_bits_count(&pb) >> 3;
+    }
+
+    return buf;
+}
+
+/** Writes the access unit and substream headers to the bitstream. */
+static void write_frame_headers(MLPEncodeContext *ctx, uint8_t *frame_header,
+                                uint8_t *substream_headers, unsigned int length,
+                                uint16_t substream_data_len[MAX_SUBSTREAMS])
+{
+    uint16_t access_unit_header = 0;
+    uint16_t parity_nibble = 0;
+    unsigned int substr;
+
+    parity_nibble  = ctx->timestamp;
+    parity_nibble ^= length;
+
+    for (substr = 0; substr < ctx->num_substreams; substr++) {
+        uint16_t substr_hdr = 0;
+
+        substr_hdr |= (0 << 15); /* extraword */
+        substr_hdr |= (0 << 14); /* ??? */
+        substr_hdr |= (1 << 13); /* checkdata */
+        substr_hdr |= (0 << 12); /* ??? */
+        substr_hdr |= (substream_data_len[substr] / 2) & 0x0FFF;
+
+        AV_WB16(substream_headers, substr_hdr);
+
+        parity_nibble ^= *substream_headers++;
+        parity_nibble ^= *substream_headers++;
+    }
+
+    parity_nibble ^= parity_nibble >> 8;
+    parity_nibble ^= parity_nibble >> 4;
+    parity_nibble &= 0xF;
+
+    access_unit_header |= (parity_nibble ^ 0xF) << 12;
+    access_unit_header |= length & 0xFFF;
+
+    AV_WB16(frame_header  , access_unit_header);
+    AV_WB16(frame_header+2, ctx->timestamp    );
+}
+
+/** Writes an entire access unit to the bitstream. */
+static unsigned int write_access_unit(MLPEncodeContext *ctx, uint8_t *buf,
+                                      int buf_size, int restart_frame)
+{
+    uint16_t substream_data_len[MAX_SUBSTREAMS];
+    uint8_t *buf2, *buf1, *buf0 = buf;
+    unsigned int substr;
+    int total_length;
+
+    if (buf_size < 4)
+        return -1;
+
+    /* Frame header will be written at the end. */
+    buf      += 4;
+    buf_size -= 4;
+
+    if (restart_frame) {
+        if (buf_size < 28)
+            return -1;
+        write_major_sync(ctx, buf, buf_size);
+        buf      += 28;
+        buf_size -= 28;
+    }
+
+    buf1 = buf;
+
+    /* Substream headers will be written at the end. */
+    for (substr = 0; substr < ctx->num_substreams; substr++) {
+        buf      += 2;
+        buf_size -= 2;
+    }
+
+    buf2 = buf;
+
+    buf = write_substrs(ctx, buf, buf_size, restart_frame, substream_data_len);
+
+    total_length = buf - buf0;
+
+    write_frame_headers(ctx, buf0, buf1, total_length / 2, substream_data_len);
+
+    return total_length;
+}
+
+/****************************************************************************
+ ****************** Functions that input data to context ********************
+ ****************************************************************************/
+
 /** Inputs data from the samples passed by lavc into the context, shifts them
  *  appropriately depending on the bit-depth, and calculates the
  *  lossless_check_data that will be written to the restart header.
@@ -699,6 +1066,24 @@ static void input_data(MLPEncodeContext 
         input_data_internal(ctx, samples, 0);
 }
 
+static void input_to_sample_buffer(MLPEncodeContext *ctx)
+{
+    int32_t *sample_buffer = ctx->sample_buffer;
+    int32_t *input_buffer = ctx->inout_buffer + ctx->starting_frame_index * ctx->one_sample_buffer_size;
+    unsigned int i, channel;
+
+    for (i = 0; i < ctx->number_of_samples; i++) {
+        for (channel = 0; channel < ctx->avctx->channels; channel++)
+            *sample_buffer++ = *input_buffer++;
+        sample_buffer += 2; /* noise_channels */
+        input_buffer += 2; /* noise_channels */
+    }
+}
+
+/****************************************************************************
+ ********* Functions that analyze the data and set the parameters ***********
+ ****************************************************************************/
+
 /** Counts the number of trailing zeroes in a value */
 static int number_trailing_zeroes(int32_t sample)
 {
@@ -740,42 +1125,45 @@ static void determine_quant_step_size(ML
         dp->quant_step_size[channel] = number_trailing_zeroes(sample_mask[channel]) - mp->shift[channel];
 }
 
-static void copy_filter_params(FilterParams *dst, FilterParams *src)
+/** Calculates the smallest number of bits it takes to encode a given signed
+ *  value in two's complement.
+ */
+static int inline number_sbits(int number)
 {
-    dst->order = src->order;
-
-    if (dst->order) {
-        unsigned int order;
-
-        dst->shift = src->shift;
-
-        dst->coeff_shift = src->coeff_shift;
-        dst->coeff_bits = src->coeff_bits;
+    if (number < 0)
+        number++;
 
-        for (order = 0; order < dst->order; order++)
-            dst->coeff[order] = src->coeff[order];
-    }
+    return av_log2(FFABS(number)) + 1 + !!number;
 }
 
-static void copy_matrix_params(MatrixParams *dst, MatrixParams *src)
+/** Determines the smallest number of bits needed to encode the filter
+ *  coefficients, and if it's possible to right-shift their values without
+ *  losing any precision.
+ */
+static void code_filter_coeffs(MLPEncodeContext *ctx, FilterParams *fp)
 {
-    dst->count = src->count;
+    int min = INT_MAX, max = INT_MIN;
+    int bits, shift;
+    int coeff_mask = 0;
+    int order;
 
-    if (dst->count) {
-        unsigned int channel, count;
+    for (order = 0; order < fp->order; order++) {
+        int coeff = fp->coeff[order];
 
-        for (channel = 0; channel < MAX_CHANNELS; channel++) {
+        if (coeff < min)
+            min = coeff;
+        if (coeff > max)
+            max = coeff;
 
-            dst->fbits[channel] = src->fbits[channel];
-            dst->shift[channel] = src->shift[channel];
+        coeff_mask |= coeff;
+    }
 
-            for (count = 0; count < MAX_MATRICES; count++)
-                dst->coeff[count][channel] = src->coeff[count][channel];
-        }
+    bits = FFMAX(number_sbits(min), number_sbits(max));
 
-        for (count = 0; count < MAX_MATRICES; count++)
-            dst->outch[count] = src->outch[count];
-    }
+    for (shift = 0; shift < 7 && !(coeff_mask & (1<<shift)); shift++);
+
+    fp->coeff_bits  = bits;
+    fp->coeff_shift = shift;
 }
 
 /** Determines the best filter parameters for the given data and writes the
@@ -820,87 +1208,28 @@ static void set_filter_params(MLPEncodeC
     }
 }
 
-#define INT24_MAX ((1 << 23) - 1)
-#define INT24_MIN (~INT24_MAX)
-
-#define MSB_MASK(bits)  (-1u << bits)
+static int apply_filter(MLPEncodeContext *ctx, unsigned int channel);
 
-/** Applies the filter to the current samples, and saves the residual back
- *  into the samples buffer. If the filter is too bad and overflows the
- *  maximum amount of bits allowed (24), the samples buffer is left as is and
- *  the function returns -1.
+/** Tries to determine a good prediction filter, and applies it to the samples
+ *  buffer if the filter is good enough. Sets the filter data to be cleared if
+ *  no good filter was found.
  */
-static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
-{
-    FilterParams *fp[NUM_FILTERS] = { &ctx->cur_channel_params[channel].filter_params[FIR],
-                                      &ctx->cur_channel_params[channel].filter_params[IIR], };
-    int32_t filter_state_buffer[NUM_FILTERS][ctx->number_of_samples];
-    int32_t mask = MSB_MASK(ctx->cur_decoding_params->quant_step_size[channel]);
-    int32_t *sample_buffer = ctx->sample_buffer + channel;
-    unsigned int number_of_samples = ctx->number_of_samples;
-    unsigned int filter_shift = fp[FIR]->shift;
-    int filter;
-    int i;
-
-    for (i = 0; i < 8; i++) {
-        filter_state_buffer[FIR][i] = *sample_buffer;
-        filter_state_buffer[IIR][i] = *sample_buffer;
-
-        sample_buffer += ctx->num_channels;
-    }
-
-    for (i = 8; i < number_of_samples; i++) {
-        int32_t sample = *sample_buffer;
-        unsigned int order;
-        int64_t accum = 0;
-        int32_t residual;
-
-        for (filter = 0; filter < NUM_FILTERS; filter++)
-            for (order = 0; order < fp[filter]->order; order++)
-                accum += (int64_t)filter_state_buffer[filter][i - 1 - order] *
-                         fp[filter]->coeff[order];
-
-        accum  >>= filter_shift;
-        residual = sample - (accum & mask);
-
-        if (residual < INT24_MIN || residual > INT24_MAX)
-            return -1;
-
-        filter_state_buffer[FIR][i] = sample;
-        filter_state_buffer[IIR][i] = residual;
-
-        sample_buffer += ctx->num_channels;
-    }
-
-    sample_buffer = ctx->sample_buffer + channel;
-    for (i = 0; i < number_of_samples; i++) {
-        *sample_buffer = filter_state_buffer[IIR][i];
-
-        sample_buffer += ctx->num_channels;
-    }
-
-    return 0;
-}
-
-/** Generates two noise channels worth of data. */
-static void generate_2_noise_channels(MLPEncodeContext *ctx)
+static void determine_filters(MLPEncodeContext *ctx)
 {
-    int32_t *sample_buffer = ctx->sample_buffer + ctx->num_channels - 2;
     RestartHeader *rh = ctx->restart_header;
-    unsigned int i;
-    uint32_t seed = rh->noisegen_seed;
-
-    for (i = 0; i < ctx->number_of_samples; i++) {
-        uint16_t seed_shr7 = seed >> 7;
-        *sample_buffer++ = ((int8_t)(seed >> 15)) << rh->noise_shift;
-        *sample_buffer++ = ((int8_t) seed_shr7)   << rh->noise_shift;
-
-        seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5);
+    int channel, filter;
 
-        sample_buffer += ctx->num_channels - 2;
+    for (channel = rh->min_channel; channel <= rh->max_channel; channel++) {
+        for (filter = 0; filter < NUM_FILTERS; filter++)
+            set_filter_params(ctx, channel, filter, 0);
+        if (apply_filter(ctx, channel) < 0) {
+            /* Filter is horribly wrong.
+             * Clear filter params and update state. */
+            set_filter_params(ctx, channel, FIR, 1);
+            set_filter_params(ctx, channel, IIR, 1);
+            apply_filter(ctx, channel);
+        }
     }
-
-    rh->noisegen_seed = seed & ((1 << 24)-1);
 }
 
 #define MLP_CHMODE_LEFT_RIGHT   0
@@ -1021,37 +1350,6 @@ static void lossless_matrix_coeffs(MLPEn
         mp->shift[channel] = shift;
 }
 
-/** Rematrixes all channels using chosen coefficients. */
-static void rematrix_channels(MLPEncodeContext *ctx)
-{
-    DecodingParams *dp = ctx->cur_decoding_params;
-    MatrixParams *mp = &dp->matrix_params;
-    int32_t *sample_buffer = ctx->sample_buffer;
-    unsigned int mat, i, maxchan;
-
-    maxchan = ctx->num_channels;
-
-    for (mat = 0; mat < mp->count; mat++) {
-        unsigned int msb_mask_bits = (ctx->avctx->sample_fmt == SAMPLE_FMT_S16 ? 8 : 0) - mp->shift[mat];
-        int32_t mask = MSB_MASK(msb_mask_bits);
-        unsigned int outch = mp->outch[mat];
-
-        sample_buffer = ctx->sample_buffer;
-        for (i = 0; i < ctx->number_of_samples; i++) {
-            unsigned int src_ch;
-            int64_t accum = 0;
-
-            for (src_ch = 0; src_ch < maxchan; src_ch++) {
-                int32_t sample = *(sample_buffer + src_ch);
-                accum += (int64_t) sample * mp->forco[mat][src_ch];
-            }
-            sample_buffer[outch] = (accum >> 14) & mask;
-
-            sample_buffer += ctx->num_channels;
-        }
-    }
-}
-
 /** Min and max values that can be encoded with each codebook. The values for
  *  the third codebook take into account the fact that the sign shift for this
  *  codebook is outside the coded value, so it has one more bit of precision.
@@ -1279,397 +1577,127 @@ static void determine_bits(MLPEncodeCont
     }
 }
 
-/** Writes the residuals to the bitstream. That is, the VLC codes from the
- *  codebooks (if any is used), and then the residual.
- */
-static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb)
-{
-    DecodingParams *dp = ctx->cur_decoding_params;
-    RestartHeader  *rh = ctx->restart_header;
-    int32_t *sample_buffer = ctx->write_buffer;
-    int32_t sign_huff_offset[MAX_CHANNELS];
-    int codebook_index      [MAX_CHANNELS];
-    int lsb_bits            [MAX_CHANNELS];
-    unsigned int i, ch;
-
-    for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-        ChannelParams *cp = &ctx->cur_channel_params[ch];
-        int sign_shift;
-
-        lsb_bits        [ch] = cp->huff_lsbs - dp->quant_step_size[ch];
-        codebook_index  [ch] = cp->codebook  - 1;
-        sign_huff_offset[ch] = cp->huff_offset;
-
-        sign_shift = lsb_bits[ch] - 1;
-
-        if (cp->codebook > 0) {
-            sign_huff_offset[ch] -= 7 << lsb_bits[ch];
-            sign_shift += 3 - cp->codebook;
-        }
-
-        /* Unsign if needed. */
-        if (sign_shift >= 0)
-            sign_huff_offset[ch] -= 1 << sign_shift;
-    }
-
-    for (i = 0; i < dp->blocksize; i++) {
-        for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-            int32_t sample = *sample_buffer++ >> dp->quant_step_size[ch];
-
-            sample -= sign_huff_offset[ch];
-
-            if (codebook_index[ch] >= 0) {
-                int vlc = sample >> lsb_bits[ch];
-                put_bits(pb, ff_mlp_huffman_tables[codebook_index[ch]][vlc][1],
-                             ff_mlp_huffman_tables[codebook_index[ch]][vlc][0]);
-            }
+/****************************************************************************
+ *************** Functions that process the data in some way ****************
+ ****************************************************************************/
 
-            put_sbits(pb, lsb_bits[ch], sample);
-        }
-        sample_buffer += 2; /* noise channels */
-    }
+#define INT24_MAX ((1 << 23) - 1)
+#define INT24_MIN (~INT24_MAX)
 
-    ctx->write_buffer = sample_buffer;
-}
+#define MSB_MASK(bits)  (-1u << bits)
 
-/** Compares two FilterParams structures and returns 1 if anything has
- *  changed. Returns 0 if they are both equal.
+/** Applies the filter to the current samples, and saves the residual back
+ *  into the samples buffer. If the filter is too bad and overflows the
+ *  maximum amount of bits allowed (24), the samples buffer is left as is and
+ *  the function returns -1.
  */
-static int compare_filter_params(FilterParams *prev, FilterParams *fp)
+static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
 {
+    FilterParams *fp[NUM_FILTERS] = { &ctx->cur_channel_params[channel].filter_params[FIR],
+                                      &ctx->cur_channel_params[channel].filter_params[IIR], };
+    int32_t filter_state_buffer[NUM_FILTERS][ctx->number_of_samples];
+    int32_t mask = MSB_MASK(ctx->cur_decoding_params->quant_step_size[channel]);
+    int32_t *sample_buffer = ctx->sample_buffer + channel;
+    unsigned int number_of_samples = ctx->number_of_samples;
+    unsigned int filter_shift = fp[FIR]->shift;
+    int filter;
     int i;
 
-    if (prev->order != fp->order)
-        return 1;
-
-    if (!prev->order)
-        return 0;
-
-    if (prev->shift != fp->shift)
-        return 1;
-
-    for (i = 0; i < fp->order; i++)
-        if (prev->coeff[i] != fp->coeff[i])
-            return 1;
-
-    return 0;
-}
-
-/** Compare two primitive matrices and returns 1 if anything has changed.
- *  Returns 0 if they are both equal.
- */
-static int compare_matrix_params(MLPEncodeContext *ctx, MatrixParams *prev, MatrixParams *mp)
-{
-    RestartHeader *rh = ctx->cur_restart_header;
-    unsigned int channel, mat;
-
-    if (prev->count != mp->count)
-        return 1;
-
-    if (!prev->count)
-        return 0;
-
-    for (channel = rh->min_channel; channel <= rh->max_channel; channel++)
-        if (prev->fbits[channel] != mp->fbits[channel])
-            return 1;
-
-    for (mat = 0; mat < mp->count; mat++) {
-        if (prev->outch[mat] != mp->outch[mat])
-            return 1;
+    for (i = 0; i < 8; i++) {
+        filter_state_buffer[FIR][i] = *sample_buffer;
+        filter_state_buffer[IIR][i] = *sample_buffer;
 
-        for (channel = 0; channel < ctx->num_channels; channel++)
-            if (prev->coeff[mat][channel] != mp->coeff[mat][channel])
-                return 1;
+        sample_buffer += ctx->num_channels;
     }
 
-    return 0;
-}
-
-/** Compares two DecodingParams and ChannelParams structures to decide if a
- *  new decoding params header has to be written.
- */
-static int compare_decoding_params(MLPEncodeContext *ctx)
-{
-    DecodingParams *prev = ctx->prev_decoding_params;
-    DecodingParams *dp = ctx->cur_decoding_params;
-    MatrixParams *prev_mp = &prev->matrix_params;
-    MatrixParams *mp = &dp->matrix_params;
-    RestartHeader  *rh = ctx->restart_header;
-    unsigned int ch;
-    int retval = 0;
-
-    if (prev->param_presence_flags != dp->param_presence_flags)
-        retval |= PARAM_PRESENCE_FLAGS;
-
-    if (prev->blocksize != dp->blocksize)
-        retval |= PARAM_BLOCKSIZE;
-
-    if (compare_matrix_params(ctx, prev_mp, mp))
-        retval |= PARAM_MATRIX;
-
-    for (ch = 0; ch <= rh->max_matrix_channel; ch++)
-        if (prev_mp->shift[ch] != mp->shift[ch]) {
-            retval |= PARAM_OUTSHIFT;
-            break;
-        }
-
-    for (ch = 0; ch <= rh->max_channel; ch++)
-        if (prev->quant_step_size[ch] != dp->quant_step_size[ch]) {
-            retval |= PARAM_QUANTSTEP;
-            break;
-        }
+    for (i = 8; i < number_of_samples; i++) {
+        int32_t sample = *sample_buffer;
+        unsigned int order;
+        int64_t accum = 0;
+        int32_t residual;
 
-    for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-        ChannelParams *prev_cp = &ctx->prev_channel_params[ch];
-        ChannelParams *cp = &ctx->cur_channel_params[ch];
+        for (filter = 0; filter < NUM_FILTERS; filter++)
+            for (order = 0; order < fp[filter]->order; order++)
+                accum += (int64_t)filter_state_buffer[filter][i - 1 - order] *
+                         fp[filter]->coeff[order];
 
-        if (!(retval & PARAM_FIR) &&
-            compare_filter_params(&prev_cp->filter_params[FIR],
-                                  &     cp->filter_params[FIR]))
-            retval |= PARAM_FIR;
+        accum  >>= filter_shift;
+        residual = sample - (accum & mask);
 
-        if (!(retval & PARAM_IIR) &&
-            compare_filter_params(&prev_cp->filter_params[IIR],
-                                  &     cp->filter_params[IIR]))
-            retval |= PARAM_IIR;
+        if (residual < INT24_MIN || residual > INT24_MAX)
+            return -1;
 
-        if (prev_cp->huff_offset != cp->huff_offset)
-            retval |= PARAM_HUFFOFFSET;
+        filter_state_buffer[FIR][i] = sample;
+        filter_state_buffer[IIR][i] = residual;
 
-        if (prev_cp->codebook    != cp->codebook  ||
-            prev_cp->huff_lsbs   != cp->huff_lsbs  )
-            retval |= 0x1;
+        sample_buffer += ctx->num_channels;
     }
 
-    return retval;
-}
-
-/** Writes the access unit and substream headers to the bitstream. */
-static void write_frame_headers(MLPEncodeContext *ctx, uint8_t *frame_header,
-                                uint8_t *substream_headers, unsigned int length,
-                                uint16_t substream_data_len[MAX_SUBSTREAMS])
-{
-    uint16_t access_unit_header = 0;
-    uint16_t parity_nibble = 0;
-    unsigned int substr;
-
-    parity_nibble  = ctx->timestamp;
-    parity_nibble ^= length;
-
-    for (substr = 0; substr < ctx->num_substreams; substr++) {
-        uint16_t substr_hdr = 0;
-
-        substr_hdr |= (0 << 15); /* extraword */
-        substr_hdr |= (0 << 14); /* ??? */
-        substr_hdr |= (1 << 13); /* checkdata */
-        substr_hdr |= (0 << 12); /* ??? */
-        substr_hdr |= (substream_data_len[substr] / 2) & 0x0FFF;
-
-        AV_WB16(substream_headers, substr_hdr);
+    sample_buffer = ctx->sample_buffer + channel;
+    for (i = 0; i < number_of_samples; i++) {
+        *sample_buffer = filter_state_buffer[IIR][i];
 
-        parity_nibble ^= *substream_headers++;
-        parity_nibble ^= *substream_headers++;
+        sample_buffer += ctx->num_channels;
     }
 
-    parity_nibble ^= parity_nibble >> 8;
-    parity_nibble ^= parity_nibble >> 4;
-    parity_nibble &= 0xF;
-
-    access_unit_header |= (parity_nibble ^ 0xF) << 12;
-    access_unit_header |= length & 0xFFF;
-
-    AV_WB16(frame_header  , access_unit_header);
-    AV_WB16(frame_header+2, ctx->timestamp    );
+    return 0;
 }
 
-/** Tries to determine a good prediction filter, and applies it to the samples
- *  buffer if the filter is good enough. Sets the filter data to be cleared if
- *  no good filter was found.
- */
-static void determine_filters(MLPEncodeContext *ctx)
+/** Generates two noise channels worth of data. */
+static void generate_2_noise_channels(MLPEncodeContext *ctx)
 {
+    int32_t *sample_buffer = ctx->sample_buffer + ctx->num_channels - 2;
     RestartHeader *rh = ctx->restart_header;
-    int channel, filter;
-
-    for (channel = rh->min_channel; channel <= rh->max_channel; channel++) {
-        for (filter = 0; filter < NUM_FILTERS; filter++)
-            set_filter_params(ctx, channel, filter, 0);
-        if (apply_filter(ctx, channel) < 0) {
-            /* Filter is horribly wrong.
-             * Clear filter params and update state. */
-            set_filter_params(ctx, channel, FIR, 1);
-            set_filter_params(ctx, channel, IIR, 1);
-            apply_filter(ctx, channel);
-        }
-    }
-}
-
-/** Writes the substreams data to the bitstream. */
-static uint8_t *write_substrs(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
-                             int restart_frame,
-                             uint16_t substream_data_len[MAX_SUBSTREAMS])
-{
-    int32_t *lossless_check_data = ctx->lossless_check_data;
-    unsigned int substr;
-    int end = 0;
-
-    lossless_check_data += ctx->frame_index * ctx->num_substreams;
-
-    for (substr = 0; substr < ctx->num_substreams; substr++) {
-        unsigned int subblock, num_subblocks = restart_frame;
-        RestartHeader  *rh = &ctx->restart_header [substr];
-        uint8_t parity, checksum;
-        PutBitContext pb, tmpb;
-        int params_changed;
-
-        ctx->cur_restart_header = rh;
-
-        init_put_bits(&pb, buf, buf_size);
-
-        for (subblock = 0; subblock <= num_subblocks; subblock++) {
-
-            ctx->cur_decoding_params = &ctx->major_decoding_params[ctx->frame_index][subblock][substr];
-            ctx->cur_channel_params = ctx->major_channel_params[ctx->frame_index][subblock];
-
-            params_changed = ctx->major_params_changed[ctx->frame_index][subblock][substr];
-
-            if (restart_frame || params_changed) {
-                put_bits(&pb, 1, 1);
-
-                if (restart_frame) {
-                    put_bits(&pb, 1, 1);
-
-                    write_restart_header(ctx, &pb);
-                    rh->lossless_check_data = 0;
-                } else {
-                    put_bits(&pb, 1, 0);
-                }
-
-                write_decoding_params(ctx, &pb, params_changed);
-            } else {
-                put_bits(&pb, 1, 0);
-            }
-
-            if (!restart_frame)
-                rh->lossless_check_data ^= *lossless_check_data++;
-
-            write_block_data(ctx, &pb);
-
-            put_bits(&pb, 1, !restart_frame);
-
-            if (restart_frame)
-                restart_frame = 0;
-        }
-
-        put_bits(&pb, (-put_bits_count(&pb)) & 15, 0);
-
-        if (ctx->last_frame == ctx->inout_buffer) {
-            /* TODO find a sample and implement shorten_by. */
-            put_bits(&pb, 32, END_OF_STREAM);
-        }
-
-        /* Data must be flushed for the checksum and parity to be correct. */
-        tmpb = pb;
-        flush_put_bits(&tmpb);
-
-        parity   = ff_mlp_calculate_parity(buf, put_bits_count(&pb) >> 3) ^ 0xa9;
-        checksum = ff_mlp_checksum8       (buf, put_bits_count(&pb) >> 3);
-
-        put_bits(&pb, 8, parity  );
-        put_bits(&pb, 8, checksum);
-
-        flush_put_bits(&pb);
-
-        end += put_bits_count(&pb) >> 3;
-        substream_data_len[substr] = end;
-
-        buf += put_bits_count(&pb) >> 3;
-    }
-
-    return buf;
-}
-
-/** Writes an entire access unit to the bitstream. */
-static unsigned int write_access_unit(MLPEncodeContext *ctx, uint8_t *buf,
-                                      int buf_size, int restart_frame)
-{
-    uint16_t substream_data_len[MAX_SUBSTREAMS];
-    uint8_t *buf2, *buf1, *buf0 = buf;
-    unsigned int substr;
-    int total_length;
-
-    if (buf_size < 4)
-        return -1;
-
-    /* Frame header will be written at the end. */
-    buf      += 4;
-    buf_size -= 4;
+    unsigned int i;
+    uint32_t seed = rh->noisegen_seed;
 
-    if (restart_frame) {
-        if (buf_size < 28)
-            return -1;
-        write_major_sync(ctx, buf, buf_size);
-        buf      += 28;
-        buf_size -= 28;
-    }
+    for (i = 0; i < ctx->number_of_samples; i++) {
+        uint16_t seed_shr7 = seed >> 7;
+        *sample_buffer++ = ((int8_t)(seed >> 15)) << rh->noise_shift;
+        *sample_buffer++ = ((int8_t) seed_shr7)   << rh->noise_shift;
 
-    buf1 = buf;
+        seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5);
 
-    /* Substream headers will be written at the end. */
-    for (substr = 0; substr < ctx->num_substreams; substr++) {
-        buf      += 2;
-        buf_size -= 2;
+        sample_buffer += ctx->num_channels - 2;
     }
 
-    buf2 = buf;
-
-    buf = write_substrs(ctx, buf, buf_size, restart_frame, substream_data_len);
-
-    total_length = buf - buf0;
-
-    write_frame_headers(ctx, buf0, buf1, total_length / 2, substream_data_len);
-
-    return total_length;
+    rh->noisegen_seed = seed & ((1 << 24)-1);
 }
 
-static void copy_restart_frame_params(MLPEncodeContext *ctx,
-                                      unsigned int substr)
+/** Rematrixes all channels using chosen coefficients. */
+static void rematrix_channels(MLPEncodeContext *ctx)
 {
-    unsigned int index;
+    DecodingParams *dp = ctx->cur_decoding_params;
+    MatrixParams *mp = &dp->matrix_params;
+    int32_t *sample_buffer = ctx->sample_buffer;
+    unsigned int mat, i, maxchan;
 
-    for (index = 0; index < ctx->number_of_frames; index++) {
-        DecodingParams *dp = &ctx->decoding_params[ctx->frame_index][index][0][substr];
-        unsigned int channel;
+    maxchan = ctx->num_channels;
 
-        copy_matrix_params(&dp->matrix_params, &ctx->cur_decoding_params->matrix_params);
+    for (mat = 0; mat < mp->count; mat++) {
+        unsigned int msb_mask_bits = (ctx->avctx->sample_fmt == SAMPLE_FMT_S16 ? 8 : 0) - mp->shift[mat];
+        int32_t mask = MSB_MASK(msb_mask_bits);
+        unsigned int outch = mp->outch[mat];
 
-        for (channel = 0; channel < MAX_CHANNELS; channel++) {
-            ChannelParams *cp = &ctx->channel_params[ctx->frame_index][index][0][channel];
-            unsigned int filter;
+        sample_buffer = ctx->sample_buffer;
+        for (i = 0; i < ctx->number_of_samples; i++) {
+            unsigned int src_ch;
+            int64_t accum = 0;
 
-            dp->quant_step_size[channel] = ctx->cur_decoding_params->quant_step_size[channel];
-            dp->matrix_params.shift[channel] = ctx->cur_decoding_params->matrix_params.shift[channel];
+            for (src_ch = 0; src_ch < maxchan; src_ch++) {
+                int32_t sample = *(sample_buffer + src_ch);
+                accum += (int64_t) sample * mp->forco[mat][src_ch];
+            }
+            sample_buffer[outch] = (accum >> 14) & mask;
 
-            if (index)
-                for (filter = 0; filter < NUM_FILTERS; filter++)
-                    copy_filter_params(&cp->filter_params[filter], &ctx->cur_channel_params[channel].filter_params[filter]);
+            sample_buffer += ctx->num_channels;
         }
     }
 }
 
-static void input_to_sample_buffer(MLPEncodeContext *ctx)
-{
-    int32_t *sample_buffer = ctx->sample_buffer;
-    int32_t *input_buffer = ctx->inout_buffer + ctx->starting_frame_index * ctx->one_sample_buffer_size;
-    unsigned int i, channel;
-
-    for (i = 0; i < ctx->number_of_samples; i++) {
-        for (channel = 0; channel < ctx->avctx->channels; channel++)
-            *sample_buffer++ = *input_buffer++;
-        sample_buffer += 2; /* noise_channels */
-        input_buffer += 2; /* noise_channels */
-    }
-}
+/****************************************************************************
+ **** Functions that deal with determining the best parameters and output ***
+ ****************************************************************************/
 
 /** Analyzes all collected bitcounts and selects the best parameters for each
  *  individual access unit.
@@ -1757,6 +1785,8 @@ static void process_major_frame(MLPEncod
     }
 }
 
+/****************************************************************************/
+
 static int mlp_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size,
                             void *data)
 {



More information about the FFmpeg-soc mailing list