Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / libavcodec / mlpenc.c
index 52ddec3..895362f 100644 (file)
 #include "encode.h"
 #include "put_bits.h"
 #include "audio_frame_queue.h"
+#include "libavutil/avassert.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/crc.h"
 #include "libavutil/avstring.h"
 #include "libavutil/intmath.h"
+#include "libavutil/opt.h"
 #include "libavutil/samplefmt.h"
 #include "libavutil/thread.h"
+#include "mlp_parse.h"
 #include "mlp.h"
 #include "lpc.h"
 
-#define MAJOR_HEADER_INTERVAL 16
+#define MAX_NCHANNELS (MAX_CHANNELS + 2)
+
+#define MIN_HEADER_INTERVAL    8
+#define MAX_HEADER_INTERVAL  128
 
 #define MLP_MIN_LPC_ORDER      1
 #define MLP_MAX_LPC_ORDER      8
-#define MLP_MIN_LPC_SHIFT      8
+#define MLP_MIN_LPC_SHIFT      0
 #define MLP_MAX_LPC_SHIFT     15
 
-typedef struct {
+typedef struct RestartHeader {
     uint8_t         min_channel;         ///< The index of the first channel coded in this substream.
     uint8_t         max_channel;         ///< The index of the last channel coded in this substream.
     uint8_t         max_matrix_channel;  ///< The number of channels input into the rematrix stage.
 
+    int8_t          max_shift;
     uint8_t         noise_shift;         ///< The left shift applied to random noise in 0x31ea substreams.
     uint32_t        noisegen_seed;       ///< The current seed value for the pseudorandom noise generator(s).
 
-    int             data_check_present;  ///< Set if the substream contains extra info to check the size of VLC blocks.
+    uint8_t         data_check_present;  ///< Set if the substream contains extra info to check the size of VLC blocks.
 
     int32_t         lossless_check_data; ///< XOR of all output samples
 
@@ -59,43 +66,38 @@ typedef struct {
     uint8_t         max_output_bits;     ///< largest output bit-depth
 } RestartHeader;
 
-typedef struct {
+typedef struct MatrixParams {
     uint8_t         count;                  ///< number of matrices to apply
 
     uint8_t         outch[MAX_MATRICES];    ///< output channel for each matrix
-    int32_t         forco[MAX_MATRICES][MAX_CHANNELS+2];    ///< forward coefficients
-    int32_t         coeff[MAX_MATRICES][MAX_CHANNELS+2];    ///< decoding coefficients
-    uint8_t         fbits[MAX_CHANNELS];    ///< fraction bits
+    int32_t         forco[MAX_MATRICES][MAX_NCHANNELS];    ///< forward coefficients
+    int32_t         coeff[MAX_MATRICES][MAX_NCHANNELS];    ///< decoding coefficients
+    uint8_t         fbits[MAX_MATRICES];    ///< fraction bits
 
-    int8_t          shift[MAX_CHANNELS];    ///< Left shift to apply to decoded PCM values to get final 24-bit output.
+    int8_t          noise_shift[MAX_CHANNELS];
+    uint8_t         lsb_bypass[MAX_MATRICES];
+    int8_t          bypassed_lsbs[MAX_MATRICES][MAX_BLOCKSIZE];
 } MatrixParams;
 
-enum ParamFlags {
-    PARAMS_DEFAULT       = 0xff,
-    PARAM_PRESENCE_FLAGS = 1 << 8,
-    PARAM_BLOCKSIZE      = 1 << 7,
-    PARAM_MATRIX         = 1 << 6,
-    PARAM_OUTSHIFT       = 1 << 5,
-    PARAM_QUANTSTEP      = 1 << 4,
-    PARAM_FIR            = 1 << 3,
-    PARAM_IIR            = 1 << 2,
-    PARAM_HUFFOFFSET     = 1 << 1,
-    PARAM_PRESENT        = 1 << 0,
-};
+#define PARAMS_DEFAULT (0xff)
+#define PARAM_PRESENCE_FLAGS (1 << 8)
 
-typedef struct {
+typedef struct DecodingParams {
     uint16_t        blocksize;                  ///< number of PCM samples in current audio block
     uint8_t         quant_step_size[MAX_CHANNELS];  ///< left shift to apply to Huffman-decoded residuals
+    int8_t          output_shift[MAX_CHANNELS]; ///< Left shift to apply to decoded PCM values to get final 24-bit output.
+    uint8_t         max_order[MAX_CHANNELS];
 
     MatrixParams    matrix_params;
 
     uint8_t         param_presence_flags;       ///< Bitmask of which parameter sets are conveyed in a decoding parameter block.
+    int32_t         sample_buffer[MAX_NCHANNELS][MAX_BLOCKSIZE];
 } DecodingParams;
 
 typedef struct BestOffset {
     int32_t offset;
-    int bitcount;
-    int lsb_bits;
+    uint32_t bitcount;
+    uint8_t lsb_bits;
     int32_t min;
     int32_t max;
 } BestOffset;
@@ -106,9 +108,42 @@ typedef struct BestOffset {
 /** Number of possible codebooks (counting "no codebooks") */
 #define NUM_CODEBOOKS       4
 
+typedef struct MLPBlock {
+    unsigned int    seq_size;
+    ChannelParams   channel_params[MAX_CHANNELS];
+    DecodingParams  decoding_params;
+    int32_t         lossless_check_data;
+    unsigned int    max_output_bits; ///< largest output bit-depth
+    BestOffset      best_offset[MAX_CHANNELS][NUM_CODEBOOKS];
+    ChannelParams   major_channel_params[MAX_CHANNELS]; ///< ChannelParams to be written to bitstream.
+    DecodingParams  major_decoding_params;              ///< DecodingParams to be written to bitstream.
+    int             major_params_changed;               ///< params_changed to be written to bitstream.
+    int32_t         inout_buffer[MAX_NCHANNELS][MAX_BLOCKSIZE];
+} MLPBlock;
+
+typedef struct MLPSubstream {
+    RestartHeader   restart_header;
+    RestartHeader  *cur_restart_header;
+    MLPBlock        b[MAX_HEADER_INTERVAL + 1];
+    unsigned int    major_cur_subblock_index;
+    unsigned int    major_filter_state_subblock;
+    int32_t         coefs[MAX_CHANNELS][MAX_LPC_ORDER][MAX_LPC_ORDER];
+} MLPSubstream;
+
 typedef struct MLPEncodeContext {
+    AVClass        *class;
     AVCodecContext *avctx;
 
+    int             max_restart_interval;   ///< Max interval of access units in between two major frames.
+    int             min_restart_interval;   ///< Min interval of access units in between two major frames.
+    int             cur_restart_interval;
+    int             lpc_coeff_precision;
+    int             rematrix_precision;
+    int             lpc_type;
+    int             lpc_passes;
+    int             prediction_order;
+    int             max_codebook_search;
+
     int             num_substreams;         ///< Number of substreams contained within this stream.
 
     int             num_channels;   /**< Number of channels in major_scratch_buffer.
@@ -122,87 +157,46 @@ typedef struct MLPEncodeContext {
 
     /* channel_meaning */
     int             substream_info;
+    int             thd_substream_info;
     int             fs;
     int             wordlength;
     int             channel_occupancy;
     int             summary_info;
 
-    int32_t        *inout_buffer;           ///< Pointer to data currently being read from lavc or written to bitstream.
-    int32_t        *major_inout_buffer;     ///< Buffer with all in/out data for one entire major frame interval.
-    int32_t        *write_buffer;           ///< Pointer to data currently being written to bitstream.
-    int32_t        *sample_buffer;          ///< Pointer to current access unit samples.
-    int32_t        *major_scratch_buffer;   ///< Scratch buffer big enough to fit all data for one entire major frame interval.
     int32_t         last_frames;            ///< Signal last frames.
 
-    int32_t        *lpc_sample_buffer;
-
     unsigned int    major_number_of_frames;
     unsigned int    next_major_number_of_frames;
 
     unsigned int    major_frame_size;       ///< Number of samples in current major frame being encoded.
     unsigned int    next_major_frame_size;  ///< Counter of number of samples for next major frame.
 
-    int32_t        *lossless_check_data;    ///< Array with lossless_check_data for each access unit.
-
-    unsigned int   *max_output_bits;        ///< largest output bit-depth
     unsigned int    frame_index;            ///< Index of current frame being encoded.
 
-    unsigned int    one_sample_buffer_size; ///< Number of samples*channel for one access unit.
-
-    unsigned int    max_restart_interval;   ///< Max interval of access units in between two major frames.
-    unsigned int    min_restart_interval;   ///< Min interval of access units in between two major frames.
     unsigned int    restart_intervals;      ///< Number of possible major frame sizes.
 
-    uint16_t        timestamp;              ///< Timestamp of current access unit.
-    uint16_t        dts;                    ///< Decoding timestamp of current access unit.
+    uint16_t        output_timing;          ///< Timestamp of current access unit.
+    uint16_t        input_timing;           ///< Decoding timestamp of current access unit.
 
+    uint8_t         noise_type;
     uint8_t         channel_arrangement;    ///< channel arrangement for MLP streams
+    uint16_t        channel_arrangement8;   ///< 8 channel arrangement for THD streams
 
-    uint8_t         ch_modifier_thd0;       ///< channel modifier for TrueHD stream 0
-    uint8_t         ch_modifier_thd1;       ///< channel modifier for TrueHD stream 1
-    uint8_t         ch_modifier_thd2;       ///< channel modifier for TrueHD stream 2
-
-    unsigned int    seq_size  [MAJOR_HEADER_INTERVAL];
-    unsigned int    seq_offset[MAJOR_HEADER_INTERVAL];
-    unsigned int    sequence_size;
-
-    ChannelParams  *channel_params;
+    uint8_t         multichannel_type6ch;   ///< channel modifier for TrueHD stream 0
+    uint8_t         multichannel_type8ch;   ///< channel modifier for TrueHD stream 0
+    uint8_t         ch2_presentation_mod;   ///< channel modifier for TrueHD stream 0
+    uint8_t         ch6_presentation_mod;   ///< channel modifier for TrueHD stream 1
+    uint8_t         ch8_presentation_mod;   ///< channel modifier for TrueHD stream 2
 
-    BestOffset      best_offset[MAJOR_HEADER_INTERVAL+1][MAX_CHANNELS][NUM_CODEBOOKS];
-
-    DecodingParams *decoding_params;
-    RestartHeader   restart_header;
-
-    ChannelParams   major_channel_params[MAJOR_HEADER_INTERVAL+1][MAX_CHANNELS];       ///< ChannelParams to be written to bitstream.
-    DecodingParams  major_decoding_params[MAJOR_HEADER_INTERVAL+1];                    ///< DecodingParams to be written to bitstream.
-    int             major_params_changed[MAJOR_HEADER_INTERVAL+1];                     ///< params_changed to be written to bitstream.
-
-    unsigned int    major_cur_subblock_index;
-    unsigned int    major_filter_state_subblock;
-    unsigned int    major_number_of_subblocks;
-
-    BestOffset    (*cur_best_offset)[NUM_CODEBOOKS];
-    ChannelParams  *cur_channel_params;
-    DecodingParams *cur_decoding_params;
-    RestartHeader  *cur_restart_header;
+    MLPSubstream    s[2];
+    int32_t         filter_state[NUM_FILTERS][MAX_HEADER_INTERVAL * MAX_BLOCKSIZE];
+    int32_t         lpc_sample_buffer[MAX_HEADER_INTERVAL * MAX_BLOCKSIZE];
 
     AudioFrameQueue afq;
 
     /* Analysis stage. */
     unsigned int    number_of_frames;
-    unsigned int    number_of_samples;
     unsigned int    number_of_subblocks;
-    unsigned int    seq_index;              ///< Sequence index for high compression levels.
-
-    const ChannelParams  *prev_channel_params;
-    const DecodingParams *prev_decoding_params;
-
-    ChannelParams  *seq_channel_params;
-    DecodingParams *seq_decoding_params;
-
-    int32_t *filter_state_buffer[NUM_FILTERS];
-
-    unsigned int    max_codebook_search;
 
     int             shorten_by;
 
@@ -241,7 +235,7 @@ static int compare_filter_params(const ChannelParams *prev_cp, const ChannelPara
     if (prev->order != fp->order)
         return 1;
 
-    if (!prev->order)
+    if (!fp->order)
         return 0;
 
     if (prev->shift != fp->shift)
@@ -257,26 +251,32 @@ static int compare_filter_params(const ChannelParams *prev_cp, const ChannelPara
 /** 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, const MatrixParams *prev, const MatrixParams *mp)
+static int compare_matrix_params(MLPEncodeContext *ctx, MLPSubstream *s,
+                                 const MatrixParams *prev, const MatrixParams *mp)
 {
-    RestartHeader *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
 
     if (prev->count != mp->count)
         return 1;
 
-    if (!prev->count)
+    if (!mp->count)
         return 0;
 
-    for (unsigned int channel = rh->min_channel; channel <= rh->max_channel; channel++)
-        if (prev->fbits[channel] != mp->fbits[channel])
-            return 1;
-
     for (unsigned int mat = 0; mat < mp->count; mat++) {
         if (prev->outch[mat] != mp->outch[mat])
             return 1;
 
-        for (unsigned int channel = 0; channel < ctx->num_channels; channel++)
-            if (prev->coeff[mat][channel] != mp->coeff[mat][channel])
+        if (prev->fbits[mat] != mp->fbits[mat])
+            return 1;
+
+        if (prev->noise_shift[mat] != mp->noise_shift[mat])
+            return 1;
+
+        if (prev->lsb_bypass[mat] != mp->lsb_bypass[mat])
+            return 1;
+
+        for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+            if (prev->coeff[mat][ch] != mp->coeff[mat][ch])
                 return 1;
     }
 
@@ -286,13 +286,15 @@ static int compare_matrix_params(MLPEncodeContext *ctx, const MatrixParams *prev
 /** 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)
+static int compare_decoding_params(MLPEncodeContext *ctx,
+                                   MLPSubstream *s,
+                                   unsigned int index)
 {
-    const DecodingParams *prev = ctx->prev_decoding_params;
-    DecodingParams *dp = ctx->cur_decoding_params;
+    const DecodingParams *prev = index ? &s->b[index-1].major_decoding_params : restart_decoding_params;
+    DecodingParams *dp = &s->b[index].major_decoding_params;
     const MatrixParams *prev_mp = &prev->matrix_params;
     MatrixParams *mp = &dp->matrix_params;
-    RestartHeader  *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
     int retval = 0;
 
     if (prev->param_presence_flags != dp->param_presence_flags)
@@ -301,24 +303,24 @@ static int compare_decoding_params(MLPEncodeContext *ctx)
     if (prev->blocksize != dp->blocksize)
         retval |= PARAM_BLOCKSIZE;
 
-    if (compare_matrix_params(ctx, prev_mp, mp))
+    if (compare_matrix_params(ctx, s, prev_mp, mp))
         retval |= PARAM_MATRIX;
 
-    for (unsigned int ch = 0; ch <= rh->max_matrix_channel; ch++)
-        if (prev_mp->shift[ch] != mp->shift[ch]) {
+    for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+        if (prev->output_shift[ch] != dp->output_shift[ch]) {
             retval |= PARAM_OUTSHIFT;
             break;
         }
 
-    for (unsigned int ch = 0; ch <= rh->max_channel; ch++)
+    for (int ch = 0; ch <= rh->max_channel; ch++)
         if (prev->quant_step_size[ch] != dp->quant_step_size[ch]) {
             retval |= PARAM_QUANTSTEP;
             break;
         }
 
-    for (unsigned int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-        const ChannelParams *prev_cp = &ctx->prev_channel_params[ch];
-        ChannelParams *cp = &ctx->cur_channel_params[ch];
+    for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+        const ChannelParams *prev_cp = index ? &s->b[index-1].major_channel_params[ch] : &restart_channel_params[ch];
+        ChannelParams *cp = &s->b[index].major_channel_params[ch];
 
         if (!(retval & PARAM_FIR) &&
             compare_filter_params(prev_cp, cp, FIR))
@@ -333,7 +335,7 @@ static int compare_decoding_params(MLPEncodeContext *ctx)
 
         if (prev_cp->codebook    != cp->codebook  ||
             prev_cp->huff_lsbs   != cp->huff_lsbs  )
-            retval |= PARAM_PRESENT;
+            retval |= PARAM_PRESENCE;
     }
 
     return retval;
@@ -353,7 +355,7 @@ static void copy_filter_params(ChannelParams *dst_cp, ChannelParams *src_cp, int
         dst->coeff_bits = src->coeff_bits;
     }
 
-    for (unsigned int order = 0; order < dst->order; order++)
+    for (int order = 0; order < dst->order; order++)
         dst_cp->coeff[filter][order] = src_cp->coeff[filter][order];
 }
 
@@ -361,37 +363,40 @@ static void copy_matrix_params(MatrixParams *dst, MatrixParams *src)
 {
     dst->count = src->count;
 
-    if (dst->count) {
-        for (unsigned int channel = 0; channel < MAX_CHANNELS; channel++) {
-
-            dst->fbits[channel] = src->fbits[channel];
-            dst->shift[channel] = src->shift[channel];
+    if (!dst->count)
+        return;
 
-            for (unsigned int count = 0; count < MAX_MATRICES; count++)
-                dst->coeff[count][channel] = src->coeff[count][channel];
-        }
+    for (int count = 0; count < MAX_MATRICES; count++) {
+        dst->outch[count] = src->outch[count];
+        dst->fbits[count] = src->fbits[count];
+        dst->noise_shift[count] = src->noise_shift[count];
+        dst->lsb_bypass[count] = src->lsb_bypass[count];
 
-        for (unsigned int count = 0; count < MAX_MATRICES; count++)
-            dst->outch[count] = src->outch[count];
+        for (int channel = 0; channel < MAX_NCHANNELS; channel++)
+            dst->coeff[count][channel] = src->coeff[count][channel];
     }
 }
 
-static void copy_restart_frame_params(MLPEncodeContext *ctx)
+static void copy_restart_frame_params(MLPEncodeContext *ctx, MLPSubstream *s)
 {
+    RestartHeader *rh = s->cur_restart_header;
+
     for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
-        DecodingParams *dp = ctx->seq_decoding_params + index;
+        DecodingParams *dp = &s->b[index].decoding_params;
+
+        copy_matrix_params(&dp->matrix_params, &s->b[1].decoding_params.matrix_params);
 
-        copy_matrix_params(&dp->matrix_params, &ctx->cur_decoding_params->matrix_params);
+        for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+            dp->output_shift[ch] = s->b[1].decoding_params.output_shift[ch];
 
-        for (unsigned int channel = 0; channel < ctx->avctx->ch_layout.nb_channels; channel++) {
-            ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->ch_layout.nb_channels) + channel;
+        for (int ch = 0; ch <= rh->max_channel; ch++) {
+            ChannelParams *cp = &s->b[index].channel_params[ch];
 
-            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];
+            dp->quant_step_size[ch] = s->b[1].decoding_params.quant_step_size[ch];
 
             if (index)
                 for (unsigned int filter = 0; filter < NUM_FILTERS; filter++)
-                    copy_filter_params(cp, &ctx->cur_channel_params[channel], filter);
+                    copy_filter_params(cp, &s->b[1].channel_params[ch], filter);
         }
     }
 }
@@ -402,14 +407,17 @@ static void clear_decoding_params(DecodingParams *decoding_params)
     DecodingParams *dp = decoding_params;
 
     dp->param_presence_flags   = 0xff;
-    dp->blocksize              = 8;
+    dp->blocksize              = 0;
 
-    memset(&dp->matrix_params , 0, sizeof(MatrixParams       ));
+    memset(&dp->matrix_params,  0, sizeof(dp->matrix_params  ));
     memset(dp->quant_step_size, 0, sizeof(dp->quant_step_size));
+    memset(dp->sample_buffer,   0, sizeof(dp->sample_buffer  ));
+    memset(dp->output_shift,    0, sizeof(dp->output_shift   ));
+    memset(dp->max_order, MAX_FIR_ORDER, sizeof(dp->max_order));
 }
 
 /** Clears a ChannelParams struct the way it should be after a restart header. */
-static void clear_channel_params(ChannelParams channel_params[MAX_CHANNELS], int nb_channels)
+static void clear_channel_params(ChannelParams *channel_params, int nb_channels)
 {
     for (unsigned channel = 0; channel < nb_channels; channel++) {
         ChannelParams *cp = &channel_params[channel];
@@ -424,21 +432,20 @@ static void clear_channel_params(ChannelParams channel_params[MAX_CHANNELS], int
 }
 
 /** Sets default vales in our encoder for a DecodingParams struct. */
-static void default_decoding_params(MLPEncodeContext *ctx, DecodingParams *decoding_params)
+static void default_decoding_params(MLPEncodeContext *ctx, DecodingParams *dp)
 {
-    DecodingParams *dp = decoding_params;
     uint8_t param_presence_flags = 0;
 
-    clear_decoding_params(decoding_params);
+    clear_decoding_params(dp);
 
     param_presence_flags |= PARAM_BLOCKSIZE;
     param_presence_flags |= PARAM_MATRIX;
     param_presence_flags |= PARAM_OUTSHIFT;
     param_presence_flags |= PARAM_QUANTSTEP;
     param_presence_flags |= PARAM_FIR;
-  /*param_presence_flags |= PARAM_IIR; */
+    param_presence_flags |= PARAM_IIR;
     param_presence_flags |= PARAM_HUFFOFFSET;
-    param_presence_flags |= PARAM_PRESENT;
+    param_presence_flags |= PARAM_PRESENCE;
 
     dp->param_presence_flags = param_presence_flags;
 }
@@ -448,12 +455,9 @@ static void default_decoding_params(MLPEncodeContext *ctx, DecodingParams *decod
 /** 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)
+static int inline number_sbits(int32_t n)
 {
-    if (number < -1)
-        number++;
-
-    return av_log2(FFABS(number)) + 1 + !!number;
+    return 33 - ff_clz(FFABS(n)|1) - !n;
 }
 
 enum InputBitDepth {
@@ -478,9 +482,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
 {
     static AVOnce init_static_once = AV_ONCE_INIT;
     MLPEncodeContext *ctx = avctx->priv_data;
-    RestartHeader *const rh = &ctx->restart_header;
-    unsigned int sum = 0;
-    size_t size;
+    uint64_t channels_present;
     int ret;
 
     ctx->avctx = avctx;
@@ -526,28 +528,20 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
     }
     ctx->coded_sample_rate[1] = -1 & 0xf;
 
-    /* TODO Keep count of bitrate and calculate real value. */
     ctx->coded_peak_bitrate = mlp_peak_bitrate(9600000, avctx->sample_rate);
 
-    /* TODO support more channels. */
-    if (avctx->ch_layout.nb_channels > 2) {
-        av_log(avctx, AV_LOG_WARNING,
-               "Only mono and stereo are supported at the moment.\n");
-    }
-
     ctx->substream_info |= SUBSTREAM_INFO_ALWAYS_SET;
-    if (avctx->ch_layout.nb_channels <= 2) {
+    if (avctx->ch_layout.nb_channels <= 2)
         ctx->substream_info |= SUBSTREAM_INFO_MAX_2_CHAN;
-    }
 
     switch (avctx->sample_fmt) {
-    case AV_SAMPLE_FMT_S16:
+    case AV_SAMPLE_FMT_S16P:
         ctx->coded_sample_fmt[0] = BITS_16;
         ctx->wordlength = 16;
         avctx->bits_per_raw_sample = 16;
         break;
     /* TODO 20 bits: */
-    case AV_SAMPLE_FMT_S32:
+    case AV_SAMPLE_FMT_S32P:
         ctx->coded_sample_fmt[0] = BITS_24;
         ctx->wordlength = 24;
         avctx->bits_per_raw_sample = 24;
@@ -559,53 +553,32 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
     }
     ctx->coded_sample_fmt[1] = -1 & 0xf;
 
-    ctx->dts = -avctx->frame_size;
+    ctx->input_timing = -avctx->frame_size;
 
     ctx->num_channels = avctx->ch_layout.nb_channels + 2; /* +2 noise channels */
-    ctx->one_sample_buffer_size = avctx->frame_size
-                                * ctx->num_channels;
-    /* TODO Let user pass major header interval as parameter. */
-    ctx->max_restart_interval = MAJOR_HEADER_INTERVAL;
 
-    ctx->max_codebook_search = 3;
-    ctx->min_restart_interval = MAJOR_HEADER_INTERVAL;
+    ctx->min_restart_interval = ctx->cur_restart_interval = ctx->max_restart_interval;
     ctx->restart_intervals = ctx->max_restart_interval / ctx->min_restart_interval;
 
-    /* TODO Let user pass parameters for LPC filter. */
-
-    size = avctx->frame_size * ctx->max_restart_interval;
-    ctx->lpc_sample_buffer = av_calloc(size, sizeof(*ctx->lpc_sample_buffer));
-    if (!ctx->lpc_sample_buffer)
-        return AVERROR(ENOMEM);
-
-    size = ctx->one_sample_buffer_size * ctx->max_restart_interval;
-    ctx->major_scratch_buffer = av_calloc(size, sizeof(*ctx->major_scratch_buffer));
-    if (!ctx->major_scratch_buffer)
-        return AVERROR(ENOMEM);
-
-    ctx->major_inout_buffer = av_calloc(size, sizeof(*ctx->major_inout_buffer));
-    if (!ctx->major_inout_buffer)
-        return AVERROR(ENOMEM);
-
-    ctx->num_substreams = 1; // TODO: change this after adding multi-channel support for TrueHD
+    ctx->num_substreams = 1;
 
+    channels_present = av_channel_layout_subset(&avctx->ch_layout, ~(uint64_t)0);
     if (ctx->avctx->codec_id == AV_CODEC_ID_MLP) {
-        static const AVChannelLayout layout_arrangement[] = {
-            AV_CHANNEL_LAYOUT_MONO,         AV_CHANNEL_LAYOUT_STEREO,
-            AV_CHANNEL_LAYOUT_2_1,          AV_CHANNEL_LAYOUT_QUAD,
-            AV_CHANNEL_LAYOUT_2POINT1,      { 0 }, { 0 },
-            AV_CHANNEL_LAYOUT_SURROUND,     AV_CHANNEL_LAYOUT_4POINT0,
-            AV_CHANNEL_LAYOUT_5POINT0_BACK, AV_CHANNEL_LAYOUT_3POINT1,
-            AV_CHANNEL_LAYOUT_4POINT1,      AV_CHANNEL_LAYOUT_5POINT1_BACK,
+        static const uint64_t layout_arrangement[] = {
+            AV_CH_LAYOUT_MONO,         AV_CH_LAYOUT_STEREO,
+            AV_CH_LAYOUT_2_1,          AV_CH_LAYOUT_QUAD,
+            AV_CH_LAYOUT_2POINT1,      0, 0,
+            AV_CH_LAYOUT_SURROUND,     AV_CH_LAYOUT_4POINT0,
+            AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_3POINT1,
+            AV_CH_LAYOUT_4POINT1,      AV_CH_LAYOUT_5POINT1_BACK,
         };
         int i;
 
-        for (i = 0; i < FF_ARRAY_ELEMS(layout_arrangement); i++)
-            if (!av_channel_layout_compare(&avctx->ch_layout, &layout_arrangement[i]))
+        for (i = 0;; i++) {
+            av_assert1(i < FF_ARRAY_ELEMS(layout_arrangement) ||
+                       !"Impossible channel layout");
+            if (channels_present == layout_arrangement[i])
                 break;
-        if (i == FF_ARRAY_ELEMS(layout_arrangement)) {
-            av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n");
-            return AVERROR(EINVAL);
         }
         ctx->channel_arrangement = i;
         ctx->flags = FLAGS_DVDA;
@@ -613,78 +586,78 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
         ctx->summary_info      = ff_mlp_ch_info[ctx->channel_arrangement].summary_info     ;
     } else {
         /* TrueHD */
-        if (!av_channel_layout_compare(&avctx->ch_layout,
-                                       &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) {
-            ctx->ch_modifier_thd0    = 0;
-            ctx->ch_modifier_thd1    = 0;
-            ctx->ch_modifier_thd2    = 0;
-            ctx->channel_arrangement = 1;
-        } else if (!av_channel_layout_compare(&avctx->ch_layout,
-                                              &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK)) {
-            ctx->ch_modifier_thd0    = 1;
-            ctx->ch_modifier_thd1    = 1;
-            ctx->ch_modifier_thd2    = 1;
-            ctx->channel_arrangement = 11;
-        } else if (!av_channel_layout_compare(&avctx->ch_layout,
-                                              &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK)) {
-            ctx->ch_modifier_thd0    = 2;
-            ctx->ch_modifier_thd1    = 1;
-            ctx->ch_modifier_thd2    = 2;
-            ctx->channel_arrangement = 15;
-        } else {
-            av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n");
-            return AVERROR(EINVAL);
+        ctx->num_substreams = 1 + (avctx->ch_layout.nb_channels > 2);
+        switch (channels_present) {
+        case AV_CH_LAYOUT_MONO:
+            ctx->ch2_presentation_mod= 3;
+            ctx->ch6_presentation_mod= 3;
+            ctx->ch8_presentation_mod= 3;
+            ctx->thd_substream_info  = 0x14;
+            break;
+        case AV_CH_LAYOUT_STEREO:
+            ctx->ch2_presentation_mod= 1;
+            ctx->ch6_presentation_mod= 1;
+            ctx->ch8_presentation_mod= 1;
+            ctx->thd_substream_info  = 0x14;
+            break;
+        case AV_CH_LAYOUT_2POINT1:
+        case AV_CH_LAYOUT_SURROUND:
+        case AV_CH_LAYOUT_3POINT1:
+        case AV_CH_LAYOUT_4POINT0:
+        case AV_CH_LAYOUT_4POINT1:
+        case AV_CH_LAYOUT_5POINT0:
+        case AV_CH_LAYOUT_5POINT1:
+            ctx->ch2_presentation_mod= 0;
+            ctx->ch6_presentation_mod= 0;
+            ctx->ch8_presentation_mod= 0;
+            ctx->thd_substream_info  = 0x3C;
+            break;
+        default:
+            av_assert1(!"AVCodec.ch_layouts needs to be updated");
         }
         ctx->flags = 0;
         ctx->channel_occupancy = 0;
         ctx->summary_info = 0;
+        ctx->channel_arrangement =
+        ctx->channel_arrangement8 = layout_truehd(channels_present);
     }
 
-    size = ctx->max_restart_interval;
-    ctx->max_output_bits = av_calloc(size, sizeof(*ctx->max_output_bits));
-    if (!ctx->max_output_bits)
-        return AVERROR(ENOMEM);
-
-    size = ctx->max_restart_interval;
-    ctx->lossless_check_data = av_calloc(size, sizeof(*ctx->lossless_check_data));
-    if (!ctx->lossless_check_data)
-        return AVERROR(ENOMEM);
-
     for (unsigned int index = 0; index < ctx->restart_intervals; index++) {
-        ctx->seq_offset[index] = sum;
-        ctx->seq_size  [index] = ((index + 1) * ctx->min_restart_interval) + 1;
-        sum += ctx->seq_size[index];
+        for (int n = 0; n < ctx->num_substreams; n++)
+            ctx->s[n].b[index].seq_size = ((index + 1) * ctx->min_restart_interval) + 1;
     }
-    ctx->sequence_size = sum;
-    size = ctx->restart_intervals * ctx->sequence_size * ctx->avctx->ch_layout.nb_channels;
-    ctx->channel_params = av_calloc(size, sizeof(*ctx->channel_params));
-    if (!ctx->channel_params)
-        return AVERROR(ENOMEM);
 
-    size = ctx->restart_intervals * ctx->sequence_size;
-    ctx->decoding_params = av_calloc(size, sizeof(*ctx->decoding_params));
-    if (!ctx->decoding_params)
-        return AVERROR(ENOMEM);
 
     /* TODO see if noisegen_seed is really worth it. */
-    rh->noisegen_seed      = 0;
+    if (ctx->avctx->codec_id == AV_CODEC_ID_MLP) {
+        RestartHeader *const rh = &ctx->s[0].restart_header;
+
+        rh->noisegen_seed      = 0;
+        rh->min_channel        = 0;
+        rh->max_channel        = avctx->ch_layout.nb_channels - 1;
+        rh->max_matrix_channel = rh->max_channel;
+    } else {
+        RestartHeader *rh = &ctx->s[0].restart_header;
 
-    rh->min_channel        = 0;
-    rh->max_channel        = avctx->ch_layout.nb_channels - 1;
-    /* FIXME: this works for 1 and 2 channels, but check for more */
-    rh->max_matrix_channel = rh->max_channel;
+        rh->noisegen_seed      = 0;
+        rh->min_channel        = 0;
+        rh->max_channel        = FFMIN(avctx->ch_layout.nb_channels, 2) - 1;
+        rh->max_matrix_channel = rh->max_channel;
 
-    if ((ret = ff_lpc_init(&ctx->lpc_ctx, ctx->number_of_samples,
-                    MLP_MAX_LPC_ORDER, FF_LPC_TYPE_LEVINSON)) < 0)
-        return ret;
+        if (avctx->ch_layout.nb_channels > 2) {
+            rh = &ctx->s[1].restart_header;
 
-    for (int i = 0; i < NUM_FILTERS; i++) {
-        ctx->filter_state_buffer[i] = av_calloc(avctx->frame_size * ctx->max_restart_interval,
-                                                sizeof(*ctx->filter_state_buffer[0]));
-        if (!ctx->filter_state_buffer[i])
-            return AVERROR(ENOMEM);
+            rh->noisegen_seed      = 0;
+            rh->min_channel        = 2;
+            rh->max_channel        = avctx->ch_layout.nb_channels - 1;
+            rh->max_matrix_channel = rh->max_channel;
+        }
     }
 
+    if ((ret = ff_lpc_init(&ctx->lpc_ctx, ctx->avctx->frame_size,
+                           MLP_MAX_LPC_ORDER, ctx->lpc_type)) < 0)
+        return ret;
+
     ff_af_queue_init(avctx, &ctx->afq);
 
     ff_thread_once(&init_static_once, mlp_encode_init_static);
@@ -718,12 +691,14 @@ static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
     } else if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
         put_bits(&pb,  8, SYNC_TRUEHD              );
         put_bits(&pb,  4, ctx->coded_sample_rate[0]);
-        put_bits(&pb,  4, 0                        ); /* ignored */
-        put_bits(&pb,  2, ctx->ch_modifier_thd0    );
-        put_bits(&pb,  2, ctx->ch_modifier_thd1    );
+        put_bits(&pb,  1, ctx->multichannel_type6ch);
+        put_bits(&pb,  1, ctx->multichannel_type8ch);
+        put_bits(&pb,  2, 0                        ); /* ignored */
+        put_bits(&pb,  2, ctx->ch2_presentation_mod);
+        put_bits(&pb,  2, ctx->ch6_presentation_mod);
         put_bits(&pb,  5, ctx->channel_arrangement );
-        put_bits(&pb,  2, ctx->ch_modifier_thd2    );
-        put_bits(&pb, 13, ctx->channel_arrangement );
+        put_bits(&pb,  2, ctx->ch8_presentation_mod);
+        put_bits(&pb, 13, ctx->channel_arrangement8);
     }
 
     put_bits(&pb, 16, MAJOR_SYNC_INFO_SIGNATURE);
@@ -731,21 +706,42 @@ static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
     put_bits(&pb, 16, 0                        ); /* ignored */
     put_bits(&pb,  1, 1                        ); /* is_vbr */
     put_bits(&pb, 15, ctx->coded_peak_bitrate  );
-    put_bits(&pb,  4, 1                        ); /* num_substreams */
-    put_bits(&pb,  4, 0x1                      ); /* ignored */
+    put_bits(&pb,  4, ctx->num_substreams      );
+    put_bits(&pb,  2, 0                        ); /* ignored */
+    put_bits(&pb,  2, 0                        ); /* extended substream info */
 
     /* channel_meaning */
-    put_bits(&pb,  8, ctx->substream_info      );
-    put_bits(&pb,  5, ctx->fs                  );
-    put_bits(&pb,  5, ctx->wordlength          );
-    put_bits(&pb,  6, ctx->channel_occupancy   );
-    put_bits(&pb,  3, 0                        ); /* ignored */
-    put_bits(&pb, 10, 0                        ); /* speaker_layout */
-    put_bits(&pb,  3, 0                        ); /* copy_protection */
-    put_bits(&pb, 16, 0x8080                   ); /* ignored */
-    put_bits(&pb,  7, 0                        ); /* ignored */
-    put_bits(&pb,  4, 0                        ); /* source_format */
-    put_bits(&pb,  5, ctx->summary_info        );
+    if (ctx->avctx->codec_id == AV_CODEC_ID_MLP) {
+        put_bits(&pb,  8, ctx->substream_info      );
+        put_bits(&pb,  5, ctx->fs                  );
+        put_bits(&pb,  5, ctx->wordlength          );
+        put_bits(&pb,  6, ctx->channel_occupancy   );
+        put_bits(&pb,  3, 0                        ); /* ignored */
+        put_bits(&pb, 10, 0                        ); /* speaker_layout */
+        put_bits(&pb,  3, 0                        ); /* copy_protection */
+        put_bits(&pb, 16, 0x8080                   ); /* ignored */
+        put_bits(&pb,  7, 0                        ); /* ignored */
+        put_bits(&pb,  4, 0                        ); /* source_format */
+        put_bits(&pb,  5, ctx->summary_info        );
+    } else if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
+        put_bits(&pb,  8, ctx->thd_substream_info  );
+        put_bits(&pb,  6, 0                        ); /* reserved */
+        put_bits(&pb,  1, 0                        ); /* 2ch control enabled */
+        put_bits(&pb,  1, 0                        ); /* 6ch control enabled */
+        put_bits(&pb,  1, 0                        ); /* 8ch control enabled */
+        put_bits(&pb,  1, 0                        ); /* reserved */
+        put_bits(&pb,  7, 0                        ); /* drc start up gain */
+        put_bits(&pb,  6, 0                        ); /* 2ch dialogue norm */
+        put_bits(&pb,  6, 0                        ); /* 2ch mix level */
+        put_bits(&pb,  5, 0                        ); /* 6ch dialogue norm */
+        put_bits(&pb,  6, 0                        ); /* 6ch mix level */
+        put_bits(&pb,  5, 0                        ); /* 6ch source format */
+        put_bits(&pb,  5, 0                        ); /* 8ch dialogue norm */
+        put_bits(&pb,  6, 0                        ); /* 8ch mix level */
+        put_bits(&pb,  6, 0                        ); /* 8ch source format */
+        put_bits(&pb,  1, 0                        ); /* reserved */
+        put_bits(&pb,  1, 0                        ); /* extra channel meaning present */
+    }
 
     flush_put_bits(&pb);
 
@@ -756,22 +752,23 @@ static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size)
  *  decoded losslessly again after such a header and the subsequent decoding
  *  params header.
  */
-static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb)
+static void write_restart_header(MLPEncodeContext *ctx, MLPSubstream *s,
+                                 PutBitContext *pb)
 {
-    RestartHeader *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
     uint8_t lossless_check = xor_32_to_8(rh->lossless_check_data);
     unsigned int start_count = put_bits_count(pb);
     PutBitContext tmpb;
     uint8_t checksum;
 
     put_bits(pb, 14, 0x31ea                ); /* TODO 0x31eb */
-    put_bits(pb, 16, ctx->timestamp        );
+    put_bits(pb, 16, ctx->output_timing    );
     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,  4, 0                     ); /* TODO max_shift */
+    put_bits(pb,  4, rh->max_shift         );
     put_bits(pb,  5, rh->max_huff_lsbs     );
     put_bits(pb,  5, rh->max_output_bits   );
     put_bits(pb,  5, rh->max_output_bits   );
@@ -779,7 +776,7 @@ static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb)
     put_bits(pb,  8, lossless_check        );
     put_bits(pb, 16, 0                     ); /* ignored */
 
-    for (unsigned int ch = 0; ch <= rh->max_matrix_channel; ch++)
+    for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
         put_bits(pb, 6, ch);
 
     /* Data must be flushed for the checksum to be correct. */
@@ -792,20 +789,27 @@ static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb)
 }
 
 /** Writes matrix params for all primitive matrices to the bitstream. */
-static void write_matrix_params(MLPEncodeContext *ctx, PutBitContext *pb)
+static void write_matrix_params(MLPEncodeContext *ctx,
+                                MLPSubstream *s,
+                                DecodingParams *dp,
+                                PutBitContext *pb)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
+    RestartHeader *rh = s->cur_restart_header;
     MatrixParams *mp = &dp->matrix_params;
+    int max_channel = rh->max_matrix_channel;
 
     put_bits(pb, 4, mp->count);
 
+    if (!ctx->noise_type)
+        max_channel += 2;
+
     for (unsigned int mat = 0; mat < mp->count; mat++) {
         put_bits(pb, 4, mp->outch[mat]); /* matrix_out_ch */
         put_bits(pb, 4, mp->fbits[mat]);
-        put_bits(pb, 1, 0             ); /* lsb_bypass */
+        put_bits(pb, 1, mp->lsb_bypass[mat]);
 
-        for (unsigned int channel = 0; channel < ctx->num_channels; channel++) {
-            int32_t coeff = mp->coeff[mat][channel];
+        for (int ch = 0; ch <= max_channel; ch++) {
+            int32_t coeff = mp->coeff[mat][ch];
 
             if (coeff) {
                 put_bits(pb, 1, 1);
@@ -821,15 +825,17 @@ static void write_matrix_params(MLPEncodeContext *ctx, PutBitContext *pb)
 }
 
 /** Writes filter parameters for one filter to the bitstream. */
-static void write_filter_params(MLPEncodeContext *ctx, PutBitContext *pb,
-                                unsigned int channel, unsigned int filter)
+static void write_filter_params(MLPEncodeContext *ctx,
+                                ChannelParams *cp,
+                                PutBitContext *pb,
+                                int channel, unsigned int filter)
 {
-    FilterParams *fp = &ctx->cur_channel_params[channel].filter_params[filter];
+    FilterParams *fp = &cp->filter_params[filter];
 
     put_bits(pb, 4, fp->order);
 
     if (fp->order > 0) {
-        int32_t *fcoeff = ctx->cur_channel_params[channel].coeff[filter];
+        int32_t *fcoeff = cp->coeff[filter];
 
         put_bits(pb, 4, fp->shift      );
         put_bits(pb, 5, fp->coeff_bits );
@@ -847,12 +853,12 @@ static void write_filter_params(MLPEncodeContext *ctx, PutBitContext *pb,
 /** Writes decoding parameters to the bitstream. These change very often,
  *  usually at almost every frame.
  */
-static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
-                                  int params_changed)
+static void write_decoding_params(MLPEncodeContext *ctx, MLPSubstream *s,
+                                  PutBitContext *pb, int params_changed,
+                                  unsigned int subblock_index)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    RestartHeader  *rh = ctx->cur_restart_header;
-    MatrixParams *mp = &dp->matrix_params;
+    DecodingParams *dp = &s->b[subblock_index].major_decoding_params;
+    RestartHeader *rh = s->cur_restart_header;
 
     if (dp->param_presence_flags != PARAMS_DEFAULT &&
         params_changed & PARAM_PRESENCE_FLAGS) {
@@ -874,7 +880,7 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
     if (dp->param_presence_flags & PARAM_MATRIX) {
         if (params_changed       & PARAM_MATRIX) {
             put_bits(pb, 1, 1);
-            write_matrix_params(ctx, pb);
+            write_matrix_params(ctx, s, dp, pb);
         } else {
             put_bits(pb, 1, 0);
         }
@@ -883,8 +889,8 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
     if (dp->param_presence_flags & PARAM_OUTSHIFT) {
         if (params_changed       & PARAM_OUTSHIFT) {
             put_bits(pb, 1, 1);
-            for (unsigned int ch = 0; ch <= rh->max_matrix_channel; ch++)
-                put_sbits(pb, 4, mp->shift[ch]);
+            for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+                put_sbits(pb, 4, dp->output_shift[ch]);
         } else {
             put_bits(pb, 1, 0);
         }
@@ -893,15 +899,15 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
     if (dp->param_presence_flags & PARAM_QUANTSTEP) {
         if (params_changed       & PARAM_QUANTSTEP) {
             put_bits(pb, 1, 1);
-            for (unsigned int ch = 0; ch <= rh->max_channel; ch++)
+            for (int ch = 0; ch <= rh->max_channel; ch++)
                 put_bits(pb, 4, dp->quant_step_size[ch]);
         } else {
             put_bits(pb, 1, 0);
         }
     }
 
-    for (unsigned int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-        ChannelParams *cp = &ctx->cur_channel_params[ch];
+    for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+        ChannelParams *cp = &s->b[subblock_index].major_channel_params[ch];
 
         if (dp->param_presence_flags & 0xF) {
             put_bits(pb, 1, 1);
@@ -909,7 +915,7 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
             if (dp->param_presence_flags & PARAM_FIR) {
                 if (params_changed       & PARAM_FIR) {
                     put_bits(pb, 1, 1);
-                    write_filter_params(ctx, pb, ch, FIR);
+                    write_filter_params(ctx, cp, pb, ch, FIR);
                 } else {
                     put_bits(pb, 1, 0);
                 }
@@ -918,7 +924,7 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
             if (dp->param_presence_flags & PARAM_IIR) {
                 if (params_changed       & PARAM_IIR) {
                     put_bits(pb, 1, 1);
-                    write_filter_params(ctx, pb, ch, IIR);
+                    write_filter_params(ctx, cp, pb, ch, IIR);
                 } else {
                     put_bits(pb, 1, 0);
                 }
@@ -933,7 +939,7 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
                 }
             }
             if (cp->codebook > 0 && cp->huff_lsbs > 24) {
-                av_log(ctx->avctx, AV_LOG_ERROR, "Invalid Huff LSBs\n");
+                av_log(ctx->avctx, AV_LOG_ERROR, "Invalid Huff LSBs %d\n", cp->huff_lsbs);
             }
 
             put_bits(pb, 2, cp->codebook );
@@ -947,17 +953,18 @@ static void write_decoding_params(MLPEncodeContext *ctx, PutBitContext *pb,
 /** 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)
+static void write_block_data(MLPEncodeContext *ctx, MLPSubstream *s,
+                             PutBitContext *pb, unsigned int subblock_index)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    RestartHeader  *rh = ctx->cur_restart_header;
-    int32_t *sample_buffer = ctx->write_buffer;
+    RestartHeader *rh = s->cur_restart_header;
+    DecodingParams *dp = &s->b[subblock_index].major_decoding_params;
+    MatrixParams *mp = &dp->matrix_params;
     int32_t sign_huff_offset[MAX_CHANNELS];
     int codebook_index      [MAX_CHANNELS];
     int lsb_bits            [MAX_CHANNELS];
 
-    for (unsigned int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-        ChannelParams *cp = &ctx->cur_channel_params[ch];
+    for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+        ChannelParams *cp = &s->b[subblock_index].major_channel_params[ch];
         int sign_shift;
 
         lsb_bits        [ch] = cp->huff_lsbs - dp->quant_step_size[ch];
@@ -975,53 +982,55 @@ static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb)
     }
 
     for (unsigned int i = 0; i < dp->blocksize; i++) {
-        for (unsigned int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
-            int32_t sample = *sample_buffer++ >> dp->quant_step_size[ch];
+        for (unsigned int mat = 0; mat < mp->count; mat++) {
+            if (mp->lsb_bypass[mat]) {
+                const int8_t *bypassed_lsbs = mp->bypassed_lsbs[mat];
+
+                put_bits(pb, 1, bypassed_lsbs[i]);
+            }
+        }
+
+        for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+            int32_t *sample_buffer = dp->sample_buffer[ch];
+            int32_t sample = sample_buffer[i] >> 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]);
+                sample &= ((1 << lsb_bits[ch]) - 1);
             }
 
-            put_sbits(pb, lsb_bits[ch], sample);
+            put_bits(pb, lsb_bits[ch], sample);
         }
-        sample_buffer += 2; /* noise channels */
     }
-
-    ctx->write_buffer = sample_buffer;
 }
 
 /** Writes the substream data to the bitstream. */
-static uint8_t *write_substr(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
+static uint8_t *write_substr(MLPEncodeContext *ctx,
+                             MLPSubstream *s,
+                             uint8_t *buf, int buf_size,
                              int restart_frame,
-                             uint16_t substream_data_len[MAX_SUBSTREAMS])
+                             uint16_t *substream_data_len)
 {
-    int32_t *lossless_check_data = ctx->lossless_check_data;
-    unsigned int cur_subblock_index = ctx->major_cur_subblock_index;
-    unsigned int num_subblocks = ctx->major_filter_state_subblock;
-    RestartHeader  *rh = &ctx->restart_header;
+    int32_t *lossless_check_data = &s->b[ctx->frame_index].lossless_check_data;
+    unsigned int cur_subblock_index = s->major_cur_subblock_index;
+    unsigned int num_subblocks = s->major_filter_state_subblock;
+    RestartHeader *rh = &s->restart_header;
     int substr_restart_frame = restart_frame;
     uint8_t parity, checksum;
     PutBitContext pb;
     int params_changed;
-    int end = 0;
 
-    lossless_check_data += ctx->frame_index;
-    ctx->cur_restart_header = rh;
+    s->cur_restart_header = rh;
 
     init_put_bits(&pb, buf, buf_size);
 
     for (unsigned int subblock = 0; subblock <= num_subblocks; subblock++) {
-        unsigned int subblock_index;
-
-        subblock_index = cur_subblock_index++;
-
-        ctx->cur_decoding_params = &ctx->major_decoding_params[subblock_index];
-        ctx->cur_channel_params = ctx->major_channel_params[subblock_index];
+        unsigned int subblock_index = cur_subblock_index++;
 
-        params_changed = ctx->major_params_changed[subblock_index];
+        params_changed = s->b[subblock_index].major_params_changed;
 
         if (substr_restart_frame || params_changed) {
             put_bits(&pb, 1, 1);
@@ -1029,18 +1038,19 @@ static uint8_t *write_substr(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
             if (substr_restart_frame) {
                 put_bits(&pb, 1, 1);
 
-                write_restart_header(ctx, &pb);
+                write_restart_header(ctx, s, &pb);
                 rh->lossless_check_data = 0;
             } else {
                 put_bits(&pb, 1, 0);
             }
 
-            write_decoding_params(ctx, &pb, params_changed);
+            write_decoding_params(ctx, s, &pb, params_changed,
+                                  subblock_index);
         } else {
             put_bits(&pb, 1, 0);
         }
 
-        write_block_data(ctx, &pb);
+        write_block_data(ctx, s, &pb, subblock_index);
 
         put_bits(&pb, 1, !substr_restart_frame);
 
@@ -1049,14 +1059,14 @@ static uint8_t *write_substr(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
 
     put_bits(&pb, (-put_bits_count(&pb)) & 15, 0);
 
-    rh->lossless_check_data ^= *lossless_check_data++;
+    rh->lossless_check_data ^= lossless_check_data[0];
 
     if (ctx->last_frames == 0 && ctx->shorten_by) {
         if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
             put_bits(&pb, 16, END_OF_STREAM & 0xFFFF);
-            put_bits(&pb, 16, (ctx->shorten_by & 0x1FFF) | 0x2000);
+            put_bits(&pb, 16, (ctx->shorten_by & 0x1FFF) | 0xE000);
         } else {
-            put_bits(&pb, 32, END_OF_STREAM);
+            put_bits32(&pb, END_OF_STREAM);
         }
     }
 
@@ -1072,13 +1082,12 @@ static uint8_t *write_substr(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
 
     flush_put_bits(&pb);
 
-    end += put_bytes_output(&pb);
-    substream_data_len[0] = end;
+    substream_data_len[0] = put_bytes_output(&pb);
 
-    buf += put_bytes_output(&pb);
+    buf += substream_data_len[0];
 
-    ctx->major_cur_subblock_index += ctx->major_filter_state_subblock + 1;
-    ctx->major_filter_state_subblock = 0;
+    s->major_cur_subblock_index += s->major_filter_state_subblock + 1;
+    s->major_filter_state_subblock = 0;
 
     return buf;
 }
@@ -1087,22 +1096,25 @@ static uint8_t *write_substr(MLPEncodeContext *ctx, uint8_t *buf, int buf_size,
 static void write_frame_headers(MLPEncodeContext *ctx, uint8_t *frame_header,
                                 uint8_t *substream_headers, unsigned int length,
                                 int restart_frame,
-                                uint16_t substream_data_len[1])
+                                uint16_t substream_data_len[MAX_SUBSTREAMS])
 {
     uint16_t access_unit_header = 0;
+    uint16_t substream_data_end = 0;
     uint16_t parity_nibble = 0;
 
-    parity_nibble  = ctx->dts;
+    parity_nibble  = ctx->input_timing;
     parity_nibble ^= length;
 
     for (unsigned int substr = 0; substr < ctx->num_substreams; substr++) {
         uint16_t substr_hdr = 0;
 
+        substream_data_end += substream_data_len[substr];
+
         substr_hdr |= (0 << 15); /* extraword */
         substr_hdr |= (!restart_frame << 14); /* !restart_frame */
         substr_hdr |= (1 << 13); /* checkdata */
         substr_hdr |= (0 << 12); /* ??? */
-        substr_hdr |= (substream_data_len[substr] / 2) & 0x0FFF;
+        substr_hdr |= (substream_data_end / 2) & 0x0FFF;
 
         AV_WB16(substream_headers, substr_hdr);
 
@@ -1118,7 +1130,7 @@ static void write_frame_headers(MLPEncodeContext *ctx, uint8_t *frame_header,
     access_unit_header |= length & 0xFFF;
 
     AV_WB16(frame_header  , access_unit_header);
-    AV_WB16(frame_header+2, ctx->dts          );
+    AV_WB16(frame_header+2, ctx->input_timing );
 }
 
 /** Writes an entire access unit to the bitstream. */
@@ -1147,7 +1159,13 @@ static int write_access_unit(MLPEncodeContext *ctx, uint8_t *buf,
         buf_size -= 2;
     }
 
-    buf = write_substr(ctx, buf, buf_size, restart_frame, &substream_data_len[0]);
+    for (int substr = 0; substr < ctx->num_substreams; substr++) {
+        MLPSubstream *s = &ctx->s[substr];
+        uint8_t *buf0 = buf;
+
+        buf = write_substr(ctx, s, buf, buf_size, restart_frame, &substream_data_len[substr]);
+        buf_size -= buf - buf0;
+    }
 
     total_length = buf - buf0;
 
@@ -1164,62 +1182,73 @@ static int write_access_unit(MLPEncodeContext *ctx, uint8_t *buf,
  *  appropriately depending on the bit-depth, and calculates the
  *  lossless_check_data that will be written to the restart header.
  */
-static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples,
-                                int nb_samples,
-                                int is24)
+static void input_data_internal(MLPEncodeContext *ctx, MLPSubstream *s,
+                                uint8_t **const samples,
+                                int nb_samples, int is24)
 {
-    int32_t *lossless_check_data = ctx->lossless_check_data;
-    const int32_t *samples_32 = (const int32_t *) samples;
-    const int16_t *samples_16 = (const int16_t *) samples;
-    RestartHeader *rh = &ctx->restart_header;
-    int32_t *sample_buffer = ctx->inout_buffer;
+    int32_t *lossless_check_data = &s->b[ctx->frame_index].lossless_check_data;
+    RestartHeader *rh = &s->restart_header;
     int32_t temp_lossless_check_data = 0;
-    uint32_t greatest = 0;
-
-    lossless_check_data += ctx->frame_index;
+    uint32_t bits = 0;
 
     for (int i = 0; i < nb_samples; i++) {
-        for (unsigned int channel = 0; channel <= rh->max_channel; channel++) {
-            uint32_t abs_sample;
+        for (int ch = 0; ch <= rh->max_channel; ch++) {
+            const int32_t *samples_32 = (const int32_t *)samples[ch];
+            const int16_t *samples_16 = (const int16_t *)samples[ch];
+            int32_t *sample_buffer = s->b[ctx->frame_index].inout_buffer[ch];
             int32_t sample;
 
-            sample = is24 ? *samples_32++ >> 8 : *samples_16++ * 256;
+            sample = is24 ? samples_32[i] >> 8 : samples_16[i] * 256;
 
-            /* TODO Find out if number_sbits can be used for negative values. */
-            abs_sample = FFABS(sample);
-            greatest = FFMAX(greatest, abs_sample);
+            bits = FFMAX(number_sbits(sample), bits);
 
-            temp_lossless_check_data ^= (sample & 0x00ffffff) << channel;
-            *sample_buffer++ = sample;
+            temp_lossless_check_data ^= (sample & 0x00ffffff) << ch;
+            sample_buffer[i] = sample;
         }
+    }
+
+    for (int ch = 0; ch <= rh->max_channel; ch++) {
+        for (int i = nb_samples; i < ctx->avctx->frame_size; i++) {
+            int32_t *sample_buffer = s->b[ctx->frame_index].inout_buffer[ch];
 
-        sample_buffer += 2; /* noise channels */
+            sample_buffer[i] = 0;
+        }
     }
 
-    ctx->max_output_bits[ctx->frame_index] = number_sbits(greatest);
+    s->b[ctx->frame_index].max_output_bits = bits;
 
-    *lossless_check_data++ = temp_lossless_check_data;
+    lossless_check_data[0] = temp_lossless_check_data;
 }
 
 /** Wrapper function for inputting data in two different bit-depths. */
-static void input_data(MLPEncodeContext *ctx, void *samples, int nb_samples)
+static void input_data(MLPEncodeContext *ctx, MLPSubstream *s, uint8_t **const samples, int nb_samples)
 {
-    input_data_internal(ctx, samples, nb_samples, ctx->avctx->sample_fmt == AV_SAMPLE_FMT_S32);
+    input_data_internal(ctx, s, samples, nb_samples, ctx->avctx->sample_fmt == AV_SAMPLE_FMT_S32P);
 }
 
-static void input_to_sample_buffer(MLPEncodeContext *ctx)
+static void input_to_sample_buffer(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    int32_t *sample_buffer = ctx->sample_buffer;
+    RestartHeader *rh = &s->restart_header;
 
     for (unsigned int index = 0; index < ctx->number_of_frames; index++) {
-        unsigned int cur_index = (ctx->frame_index + index + 1) % ctx->max_restart_interval;
-        int32_t *input_buffer = ctx->inout_buffer + cur_index * ctx->one_sample_buffer_size;
-
-        for (unsigned int i = 0; i < ctx->avctx->frame_size; i++) {
-            for (unsigned int channel = 0; channel < ctx->avctx->ch_layout.nb_channels; channel++)
-                *sample_buffer++ = *input_buffer++;
-            sample_buffer += 2; /* noise_channels */
-            input_buffer += 2; /* noise_channels */
+        unsigned int cur_index = (ctx->frame_index + index + 1) % ctx->cur_restart_interval;
+        DecodingParams *dp = &s->b[index+1].decoding_params;
+
+        for (int ch = 0; ch <= rh->max_channel; ch++) {
+            const int32_t *input_buffer = s->b[cur_index].inout_buffer[ch];
+            int32_t *sample_buffer = dp->sample_buffer[ch];
+            int off = 0;
+
+            if (dp->blocksize < ctx->avctx->frame_size) {
+                DecodingParams *dp = &s->b[index].decoding_params;
+                int32_t *sample_buffer = dp->sample_buffer[ch];
+                for (unsigned int i = 0; i < dp->blocksize; i++)
+                    sample_buffer[i] = input_buffer[i];
+                off = dp->blocksize;
+            }
+
+            for (unsigned int i = 0; i < dp->blocksize; i++)
+                sample_buffer[i] = input_buffer[i + off];
         }
     }
 }
@@ -1229,113 +1258,138 @@ static void input_to_sample_buffer(MLPEncodeContext *ctx)
  ****************************************************************************/
 
 /** Counts the number of trailing zeroes in a value */
-static int number_trailing_zeroes(int32_t sample)
+static int number_trailing_zeroes(int32_t sample, unsigned int max, unsigned int def)
 {
-    int bits = ff_ctz(sample);
+    return sample ? FFMIN(max, ff_ctz(sample)) : def;
+}
 
-    /* All samples are 0. TODO Return previous quant_step_size to avoid
-     * writing a new header. */
-    if (bits >= 24)
-        return 0;
+static void determine_output_shift(MLPEncodeContext *ctx, MLPSubstream *s)
+{
+    RestartHeader *rh = s->cur_restart_header;
+    DecodingParams *dp1 = &s->b[1].decoding_params;
+    int32_t sample_mask[MAX_CHANNELS];
+
+    memset(sample_mask, 0, sizeof(sample_mask));
+
+    for (int j = 0; j <= ctx->cur_restart_interval; j++) {
+        DecodingParams *dp = &s->b[j].decoding_params;
+
+        for (int ch = 0; ch <= rh->max_matrix_channel; ch++) {
+            int32_t *sample_buffer = dp->sample_buffer[ch];
+
+            for (int i = 0; i < dp->blocksize; i++)
+                sample_mask[ch] |= sample_buffer[i];
+        }
+    }
+
+    for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+        dp1->output_shift[ch] = number_trailing_zeroes(sample_mask[ch], 7, 0);
+
+    for (int j = 0; j <= ctx->cur_restart_interval; j++) {
+        DecodingParams *dp = &s->b[j].decoding_params;
 
-    return bits;
+        for (int ch = 0; ch <= rh->max_matrix_channel; ch++) {
+            int32_t *sample_buffer = dp->sample_buffer[ch];
+            const int shift = dp1->output_shift[ch];
+
+            for (int i = 0; i < dp->blocksize; i++)
+                sample_buffer[i] >>= shift;
+        }
+    }
 }
 
 /** Determines how many bits are zero at the end of all samples so they can be
  *  shifted out.
  */
-static void determine_quant_step_size(MLPEncodeContext *ctx)
+static void determine_quant_step_size(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    RestartHeader  *rh = ctx->cur_restart_header;
-    MatrixParams *mp = &dp->matrix_params;
-    int32_t *sample_buffer = ctx->sample_buffer;
+    RestartHeader *rh = s->cur_restart_header;
+    DecodingParams *dp1 = &s->b[1].decoding_params;
     int32_t sample_mask[MAX_CHANNELS];
 
-    memset(sample_mask, 0x00, sizeof(sample_mask));
+    memset(sample_mask, 0, sizeof(sample_mask));
 
-    for (unsigned int i = 0; i < ctx->number_of_samples; i++) {
-        for (unsigned int channel = 0; channel <= rh->max_channel; channel++)
-            sample_mask[channel] |= *sample_buffer++;
+    for (int j = 0; j <= ctx->cur_restart_interval; j++) {
+        DecodingParams *dp = &s->b[j].decoding_params;
 
-        sample_buffer += 2; /* noise channels */
+        for (int ch = 0; ch <= rh->max_channel; ch++) {
+            int32_t *sample_buffer = dp->sample_buffer[ch];
+
+            for (int i = 0; i < dp->blocksize; i++)
+                sample_mask[ch] |= sample_buffer[i];
+        }
     }
 
-    for (unsigned int channel = 0; channel <= rh->max_channel; channel++)
-        dp->quant_step_size[channel] = number_trailing_zeroes(sample_mask[channel]) - mp->shift[channel];
+    for (int ch = 0; ch <= rh->max_channel; ch++)
+        dp1->quant_step_size[ch] = number_trailing_zeroes(sample_mask[ch], 15, 0);
 }
 
 /** 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, int32_t *fcoeff)
+static void code_filter_coeffs(MLPEncodeContext *ctx, FilterParams *fp, const int32_t *fcoeff)
 {
-    int min = INT_MAX, max = INT_MIN;
-    int bits, shift;
-    int coeff_mask = 0;
+    uint32_t coeff_mask = 0;
+    int bits = 0, shift;
 
     for (int order = 0; order < fp->order; order++) {
-        int coeff = fcoeff[order];
+        int32_t coeff = fcoeff[order];
 
-        if (coeff < min)
-            min = coeff;
-        if (coeff > max)
-            max = coeff;
+        bits = FFMAX(number_sbits(coeff), bits);
 
         coeff_mask |= coeff;
     }
 
-    bits = FFMAX(number_sbits(min), number_sbits(max));
-
-    for (shift = 0; shift < 7 && bits + shift < 16 && !(coeff_mask & (1<<shift)); shift++);
+    shift = FFMIN(7, coeff_mask ? ff_ctz(coeff_mask) : 0);
 
-    fp->coeff_bits  = bits;
-    fp->coeff_shift = shift;
+    fp->coeff_bits  = FFMAX(1, bits - shift);
+    fp->coeff_shift = FFMIN(shift, 16 - fp->coeff_bits);
 }
 
 /** Determines the best filter parameters for the given data and writes the
  *  necessary information to the context.
- *  TODO Add IIR filter predictor!
  */
-static void set_filter_params(MLPEncodeContext *ctx,
-                              unsigned int channel, unsigned int filter,
-                              int clear_filter)
+static void set_filter(MLPEncodeContext *ctx, MLPSubstream *s,
+                       int channel, int retry_filter)
 {
-    ChannelParams *cp = &ctx->cur_channel_params[channel];
-    FilterParams *fp = &cp->filter_params[filter];
+    ChannelParams *cp = &s->b[1].channel_params[channel];
+    DecodingParams *dp1 = &s->b[1].decoding_params;
+    FilterParams *fp = &cp->filter_params[FIR];
 
-    if ((filter == IIR && ctx->substream_info & SUBSTREAM_INFO_HIGH_RATE) ||
-        clear_filter) {
-        fp->order = 0;
-    } else if (filter == IIR) {
+    if (retry_filter)
+        dp1->max_order[channel]--;
+
+    if (dp1->max_order[channel] == 0) {
         fp->order = 0;
-    } else if (filter == FIR) {
-        const int max_order = (ctx->substream_info & SUBSTREAM_INFO_HIGH_RATE)
-                              ? 4 : MLP_MAX_LPC_ORDER;
-        int32_t *sample_buffer = ctx->sample_buffer + channel;
-        int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER];
+    } else {
         int32_t *lpc_samples = ctx->lpc_sample_buffer;
-        int32_t *fcoeff = ctx->cur_channel_params[channel].coeff[filter];
-        int shift[MLP_MAX_LPC_ORDER];
+        int32_t *fcoeff = cp->coeff[FIR];
+        int shift[MAX_LPC_ORDER];
         int order;
 
-        for (unsigned int i = 0; i < ctx->number_of_samples; i++) {
-            *lpc_samples++ = *sample_buffer;
-            sample_buffer += ctx->num_channels;
+        for (unsigned int j = 0; j <= ctx->cur_restart_interval; j++) {
+            DecodingParams *dp = &s->b[j].decoding_params;
+            int32_t *sample_buffer = dp->sample_buffer[channel];
+
+            for (unsigned int i = 0; i < dp->blocksize; i++)
+                lpc_samples[i] = sample_buffer[i];
+            lpc_samples += dp->blocksize;
         }
 
         order = ff_lpc_calc_coefs(&ctx->lpc_ctx, ctx->lpc_sample_buffer,
-                                  ctx->number_of_samples, MLP_MIN_LPC_ORDER,
-                                  max_order, 11, coefs, shift, FF_LPC_TYPE_LEVINSON, 0,
-                                  ORDER_METHOD_EST, MLP_MIN_LPC_SHIFT,
-                                  MLP_MAX_LPC_SHIFT, MLP_MIN_LPC_SHIFT);
+                                  lpc_samples - ctx->lpc_sample_buffer,
+                                  MLP_MIN_LPC_ORDER, dp1->max_order[channel],
+                                  ctx->lpc_coeff_precision,
+                                  s->coefs[channel], shift, ctx->lpc_type, ctx->lpc_passes,
+                                  ctx->prediction_order, MLP_MIN_LPC_SHIFT,
+                                  MLP_MAX_LPC_SHIFT, 0);
 
         fp->order = order;
-        fp->shift = shift[order-1];
+        fp->shift = order ? shift[order-1] : 0;
 
         for (unsigned int i = 0; i < order; i++)
-            fcoeff[i] = coefs[order-1][i];
+            fcoeff[i] = s->coefs[channel][order-1][i];
 
         code_filter_coeffs(ctx, fp, fcoeff);
     }
@@ -1345,118 +1399,124 @@ static void set_filter_params(MLPEncodeContext *ctx,
  *  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)
+static void determine_filters(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    RestartHeader *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
 
-    for (int channel = rh->min_channel; channel <= rh->max_channel; channel++) {
-        for (int filter = 0; filter < NUM_FILTERS; filter++)
-            set_filter_params(ctx, channel, filter, 0);
-    }
+    for (int ch = rh->min_channel; ch <= rh->max_channel; ch++)
+        set_filter(ctx, s, ch, 0);
 }
 
-enum MLPChMode {
-    MLP_CHMODE_LEFT_RIGHT,
-    MLP_CHMODE_LEFT_SIDE,
-    MLP_CHMODE_RIGHT_SIDE,
-    MLP_CHMODE_MID_SIDE,
-};
-
-static enum MLPChMode estimate_stereo_mode(MLPEncodeContext *ctx)
+static int estimate_coeff(MLPEncodeContext *ctx, MLPSubstream *s,
+                          MatrixParams *mp,
+                          int ch0, int ch1)
 {
-    uint64_t score[4], sum[4] = { 0, 0, 0, 0, };
-    int32_t *right_ch = ctx->sample_buffer + 1;
-    int32_t *left_ch  = ctx->sample_buffer;
-    int i;
-    enum MLPChMode best = 0;
-
-    for(i = 2; i < ctx->number_of_samples; i++) {
-        int32_t left  = left_ch [i * ctx->num_channels] - 2 * left_ch [(i - 1) * ctx->num_channels] + left_ch [(i - 2) * ctx->num_channels];
-        int32_t right = right_ch[i * ctx->num_channels] - 2 * right_ch[(i - 1) * ctx->num_channels] + right_ch[(i - 2) * ctx->num_channels];
-
-        sum[0] += FFABS( left        );
-        sum[1] += FFABS(        right);
-        sum[2] += FFABS((left + right) >> 1);
-        sum[3] += FFABS( left - right);
+    int32_t maxl = INT32_MIN, maxr = INT32_MIN, minl = INT32_MAX, minr = INT32_MAX;
+    int64_t summ = 0, sums = 0, suml = 0, sumr = 0, enl = 0, enr = 0;
+    const int shift = 14 - ctx->rematrix_precision;
+    int32_t cf0, cf1, e[4], d[4], ml, mr;
+    int i, count = 0;
+
+    for (int j = 0; j <= ctx->cur_restart_interval; j++) {
+        DecodingParams *dp = &s->b[j].decoding_params;
+        const int32_t *ch[2];
+
+        ch[0] = dp->sample_buffer[ch0];
+        ch[1] = dp->sample_buffer[ch1];
+
+        for (int i = 0; i < dp->blocksize; i++) {
+            int32_t lm = ch[0][i], rm = ch[1][i];
+
+            enl  += FFABS(lm);
+            enr  += FFABS(rm);
+
+            summ += FFABS(lm + rm);
+            sums += FFABS(lm - rm);
+
+            suml += lm;
+            sumr += rm;
+
+            maxl = FFMAX(maxl, lm);
+            maxr = FFMAX(maxr, rm);
+
+            minl = FFMIN(minl, lm);
+            minr = FFMIN(minr, rm);
+        }
     }
 
-    score[MLP_CHMODE_LEFT_RIGHT] = sum[0] + sum[1];
-    score[MLP_CHMODE_LEFT_SIDE]  = sum[0] + sum[3];
-    score[MLP_CHMODE_RIGHT_SIDE] = sum[1] + sum[3];
-    score[MLP_CHMODE_MID_SIDE]   = sum[2] + sum[3];
+    summ -= FFABS(suml + sumr);
+    sums -= FFABS(suml - sumr);
+
+    ml = maxl - minl;
+    mr = maxr - minr;
+
+    if (!summ && !sums)
+        return 0;
+
+    if (!ml || !mr)
+        return 0;
+
+    if ((FFABS(ml) + FFABS(mr)) >= (1 << 24))
+        return 0;
+
+    cf0 = (FFMIN(FFABS(mr), FFABS(ml)) * (1LL << 14)) / FFMAX(FFABS(ml), FFABS(mr));
+    cf0 = (cf0 >> shift) << shift;
+    cf1 = -cf0;
+
+    if (sums > summ)
+        FFSWAP(int32_t, cf0, cf1);
 
-    for(i = 1; i < 3; i++)
-        if(score[i] < score[best])
-            best = i;
+    count = 1;
+    i = enl < enr;
+    mp->outch[0] = ch0 + i;
 
-    return best;
+    d[!i] = cf0;
+    d[ i] = 1 << 14;
+    e[!i] = cf1;
+    e[ i] = 1 << 14;
+
+    mp->coeff[0][ch0] = av_clip_intp2(d[0], 15);
+    mp->coeff[0][ch1] = av_clip_intp2(d[1], 15);
+
+    mp->forco[0][ch0] = av_clip_intp2(e[0], 15);
+    mp->forco[0][ch1] = av_clip_intp2(e[1], 15);
+
+    return count;
 }
 
 /** Determines how many fractional bits are needed to encode matrix
  *  coefficients. Also shifts the coefficients to fit within 2.14 bits.
  */
-static void code_matrix_coeffs(MLPEncodeContext *ctx, unsigned int mat)
+static void code_matrix_coeffs(MLPEncodeContext *ctx, MLPSubstream *s,
+                               DecodingParams *dp,
+                               unsigned int mat)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
+    RestartHeader *rh = s->cur_restart_header;
     MatrixParams *mp = &dp->matrix_params;
     int32_t coeff_mask = 0;
-    unsigned int bits;
 
-    for (unsigned int channel = 0; channel < ctx->num_channels; channel++) {
-        int32_t coeff = mp->coeff[mat][channel];
-        coeff_mask |= coeff;
-    }
-
-    for (bits = 0; bits < 14 && !(coeff_mask & (1<<bits)); bits++);
+    for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+        coeff_mask |= mp->coeff[mat][ch];
 
-    mp->fbits   [mat] = 14 - bits;
+    mp->fbits[mat] = 14 - number_trailing_zeroes(coeff_mask, 14, 14);
 }
 
 /** Determines best coefficients to use for the lossless matrix. */
-static void lossless_matrix_coeffs(MLPEncodeContext *ctx)
+static void lossless_matrix_coeffs(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
+    RestartHeader *rh = s->cur_restart_header;
+    DecodingParams *dp = &s->b[1].decoding_params;
     MatrixParams *mp = &dp->matrix_params;
-    unsigned int shift = 0;
-    enum MLPChMode mode;
 
-    /* No decorrelation for non-stereo. */
-    if (ctx->num_channels - 2 != 2) {
-        mp->count = 0;
+    mp->count = 0;
+    if (ctx->num_channels - 2 != 2)
         return;
-    }
 
-    mode = estimate_stereo_mode(ctx);
-
-    switch (mode) {
-    /* TODO: add matrix for MID_SIDE */
-    case MLP_CHMODE_MID_SIDE:
-    case MLP_CHMODE_LEFT_RIGHT:
-        mp->count    = 0;
-        break;
-    case MLP_CHMODE_LEFT_SIDE:
-        mp->count    = 1;
-        mp->outch[0] = 1;
-        mp->coeff[0][0] =  1 << 14; mp->coeff[0][1] = -(1 << 14);
-        mp->coeff[0][2] =  0 << 14; mp->coeff[0][2] =   0 << 14;
-        mp->forco[0][0] =  1 << 14; mp->forco[0][1] = -(1 << 14);
-        mp->forco[0][2] =  0 << 14; mp->forco[0][2] =   0 << 14;
-        break;
-    case MLP_CHMODE_RIGHT_SIDE:
-        mp->count    = 1;
-        mp->outch[0] = 0;
-        mp->coeff[0][0] =  1 << 14; mp->coeff[0][1] =   1 << 14;
-        mp->coeff[0][2] =  0 << 14; mp->coeff[0][2] =   0 << 14;
-        mp->forco[0][0] =  1 << 14; mp->forco[0][1] = -(1 << 14);
-        mp->forco[0][2] =  0 << 14; mp->forco[0][2] =   0 << 14;
-        break;
-    }
+    mp->count = estimate_coeff(ctx, s, mp,
+                               rh->min_channel, rh->max_channel);
 
     for (int mat = 0; mat < mp->count; mat++)
-        code_matrix_coeffs(ctx, mat);
-
-    for (unsigned int channel = 0; channel < ctx->num_channels; channel++)
-        mp->shift[channel] = shift;
+        code_matrix_coeffs(ctx, s, dp, mat);
 }
 
 /** Min and max values that can be encoded with each codebook. The values for
@@ -1464,7 +1524,7 @@ static void lossless_matrix_coeffs(MLPEncodeContext *ctx)
  *  codebook is outside the coded value, so it has one more bit of precision.
  *  It should actually be -7 -> 7, shifted down by 0.5.
  */
-static const int codebook_extremes[3][2] = {
+static const int8_t codebook_extremes[3][2] = {
     {-9, 8}, {-8, 7}, {-15, 14},
 };
 
@@ -1472,11 +1532,11 @@ static const int codebook_extremes[3][2] = {
  *  codebooks and a specified offset.
  */
 static void no_codebook_bits_offset(MLPEncodeContext *ctx,
-                                    unsigned int channel, int16_t offset,
+                                    DecodingParams *dp,
+                                    int channel, int32_t offset,
                                     int32_t min, int32_t max,
                                     BestOffset *bo)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
     int32_t unsign = 0;
     int lsb_bits;
 
@@ -1488,7 +1548,7 @@ static void no_codebook_bits_offset(MLPEncodeContext *ctx,
     lsb_bits += !!lsb_bits;
 
     if (lsb_bits > 0)
-        unsign = 1 << (lsb_bits - 1);
+        unsign = 1U << (lsb_bits - 1);
 
     bo->offset   = offset;
     bo->lsb_bits = lsb_bits;
@@ -1501,15 +1561,13 @@ static void no_codebook_bits_offset(MLPEncodeContext *ctx,
  *  codebooks.
  */
 static void no_codebook_bits(MLPEncodeContext *ctx,
-                             unsigned int channel,
+                             DecodingParams *dp,
+                             int channel,
                              int32_t min, int32_t max,
                              BestOffset *bo)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    int16_t offset;
-    int32_t unsign = 0;
-    uint32_t diff;
-    int lsb_bits;
+    int32_t offset, unsign = 0;
+    uint8_t lsb_bits;
 
     /* Set offset inside huffoffset's boundaries by adjusting extremes
      * so that more bits are used, thus shifting the offset. */
@@ -1518,40 +1576,40 @@ static void no_codebook_bits(MLPEncodeContext *ctx,
     if (max > HUFF_OFFSET_MAX)
         min = FFMIN(min, 2 * HUFF_OFFSET_MAX - max - 1);
 
-    /* Determine offset and minimum number of bits. */
-    diff = max - min;
-
-    lsb_bits = number_sbits(diff) - 1;
+    lsb_bits = FFMAX(number_sbits(min), number_sbits(max));
 
     if (lsb_bits > 0)
         unsign = 1 << (lsb_bits - 1);
 
     /* If all samples are the same (lsb_bits == 0), offset must be
      * adjusted because of sign_shift. */
-    offset = min + diff / 2 + !!lsb_bits;
+    offset = min + (max - min) / 2 + !!lsb_bits;
 
     bo->offset   = offset;
     bo->lsb_bits = lsb_bits;
     bo->bitcount = lsb_bits * dp->blocksize;
     bo->min      = max - unsign + 1;
     bo->max      = min + unsign;
+    bo->min      = FFMAX(bo->min, HUFF_OFFSET_MIN);
+    bo->max      = FFMIN(bo->max, HUFF_OFFSET_MAX);
 }
 
 /** Determines the least amount of bits needed to encode the samples using a
  *  given codebook and a given offset.
  */
 static inline void codebook_bits_offset(MLPEncodeContext *ctx,
-                                        unsigned int channel, int codebook,
+                                        DecodingParams *dp,
+                                        int channel, int codebook,
                                         int32_t sample_min, int32_t sample_max,
-                                        int16_t offset, BestOffset *bo)
+                                        int32_t offset, BestOffset *bo)
 {
     int32_t codebook_min = codebook_extremes[codebook][0];
     int32_t codebook_max = codebook_extremes[codebook][1];
-    int32_t *sample_buffer = ctx->sample_buffer + channel;
-    DecodingParams *dp = ctx->cur_decoding_params;
+    int32_t *sample_buffer = dp->sample_buffer[channel];
     int codebook_offset  = 7 + (2 - codebook);
     int32_t unsign_offset = offset;
-    int lsb_bits = 0, bitcount = 0;
+    uint32_t bitcount = 0;
+    int lsb_bits = 0;
     int offset_min = INT_MAX, offset_max = INT_MAX;
     int unsign, mask;
 
@@ -1573,7 +1631,7 @@ static inline void codebook_bits_offset(MLPEncodeContext *ctx,
     }
 
     for (int i = 0; i < dp->blocksize; i++) {
-        int32_t sample = *sample_buffer >> dp->quant_step_size[channel];
+        int32_t sample = sample_buffer[i] >> dp->quant_step_size[channel];
         int temp_min, temp_max;
 
         sample -= unsign_offset;
@@ -1589,8 +1647,6 @@ static inline void codebook_bits_offset(MLPEncodeContext *ctx,
         sample >>= lsb_bits;
 
         bitcount += ff_mlp_huffman_tables[codebook][sample + codebook_offset][1];
-
-        sample_buffer += ctx->num_channels;
     }
 
     bo->offset   = offset;
@@ -1604,11 +1660,12 @@ static inline void codebook_bits_offset(MLPEncodeContext *ctx,
  *  given codebook. Searches for the best offset to minimize the bits.
  */
 static inline void codebook_bits(MLPEncodeContext *ctx,
-                                 unsigned int channel, int codebook,
+                                 DecodingParams *dp,
+                                 int channel, int codebook,
                                  int offset, int32_t min, int32_t max,
                                  BestOffset *bo, int direction)
 {
-    int previous_count = INT_MAX;
+    uint32_t previous_count = UINT32_MAX;
     int offset_min, offset_max;
     int is_greater = 0;
 
@@ -1618,7 +1675,7 @@ static inline void codebook_bits(MLPEncodeContext *ctx,
     while (offset <= offset_max && offset >= offset_min) {
         BestOffset temp_bo;
 
-        codebook_bits_offset(ctx, channel, codebook,
+        codebook_bits_offset(ctx, dp, channel, codebook,
                              min, max, offset,
                              &temp_bo);
 
@@ -1643,58 +1700,59 @@ static inline void codebook_bits(MLPEncodeContext *ctx,
 /** Determines the least amount of bits needed to encode the samples using
  *  any or no codebook.
  */
-static void determine_bits(MLPEncodeContext *ctx)
+static void determine_bits(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    RestartHeader  *rh = ctx->cur_restart_header;
-
-    for (unsigned int channel = 0; channel <= rh->max_channel; channel++) {
-        ChannelParams *cp = &ctx->cur_channel_params[channel];
-        int32_t *sample_buffer = ctx->sample_buffer + channel;
-        int32_t min = INT32_MAX, max = INT32_MIN;
-        int no_filters_used = !cp->filter_params[FIR].order;
-        int average = 0;
-        int offset = 0;
-
-        /* Determine extremes and average. */
-        for (int i = 0; i < dp->blocksize; i++) {
-            int32_t sample = *sample_buffer >> dp->quant_step_size[channel];
-            if (sample < min)
-                min = sample;
-            if (sample > max)
-                max = sample;
-            average += sample;
-            sample_buffer += ctx->num_channels;
-        }
-        average /= dp->blocksize;
+    RestartHeader *rh = s->cur_restart_header;
+    for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
+        DecodingParams *dp = &s->b[index].decoding_params;
+
+        for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+            ChannelParams *cp = &s->b[index].channel_params[ch];
+            int32_t *sample_buffer = dp->sample_buffer[ch];
+            int32_t min = INT32_MAX, max = INT32_MIN;
+            int no_filters_used = !cp->filter_params[FIR].order;
+            int average = 0;
+            int offset = 0;
+
+            /* Determine extremes and average. */
+            for (int i = 0; i < dp->blocksize; i++) {
+                int32_t sample = sample_buffer[i] >> dp->quant_step_size[ch];
+                if (sample < min)
+                    min = sample;
+                if (sample > max)
+                    max = sample;
+                average += sample;
+            }
+            average /= dp->blocksize;
 
-        /* If filtering is used, we always set the offset to zero, otherwise
-         * we search for the offset that minimizes the bitcount. */
-        if (no_filters_used) {
-            no_codebook_bits(ctx, channel, min, max, &ctx->cur_best_offset[channel][0]);
-            offset = av_clip(average, HUFF_OFFSET_MIN, HUFF_OFFSET_MAX);
-        } else {
-            no_codebook_bits_offset(ctx, channel, offset, min, max, &ctx->cur_best_offset[channel][0]);
-        }
+            /* If filtering is used, we always set the offset to zero, otherwise
+             * we search for the offset that minimizes the bitcount. */
+            if (no_filters_used) {
+                no_codebook_bits(ctx, dp, ch, min, max, &s->b[index].best_offset[ch][0]);
+                offset = av_clip(average, HUFF_OFFSET_MIN, HUFF_OFFSET_MAX);
+            } else {
+                no_codebook_bits_offset(ctx, dp, ch, offset, min, max, &s->b[index].best_offset[ch][0]);
+            }
 
-        for (int i = 1; i < NUM_CODEBOOKS; i++) {
-            BestOffset temp_bo = { 0, INT_MAX, 0, 0, 0, };
-            int16_t offset_max;
+            for (int i = 1; i < NUM_CODEBOOKS; i++) {
+                BestOffset temp_bo = { 0, UINT32_MAX, 0, 0, 0, };
+                int32_t offset_max;
 
-            codebook_bits_offset(ctx, channel, i - 1,
-                                 min, max, offset,
-                                 &temp_bo);
+                codebook_bits_offset(ctx, dp, ch, i - 1,
+                                     min, max, offset,
+                                     &temp_bo);
 
-            if (no_filters_used) {
-                offset_max = temp_bo.max;
+                if (no_filters_used) {
+                    offset_max = temp_bo.max;
 
-                codebook_bits(ctx, channel, i - 1, temp_bo.min - 1,
-                            min, max, &temp_bo, 0);
-                codebook_bits(ctx, channel, i - 1, offset_max + 1,
-                            min, max, &temp_bo, 1);
-            }
+                    codebook_bits(ctx, dp, ch, i - 1, temp_bo.min - 1,
+                                  min, max, &temp_bo, 0);
+                    codebook_bits(ctx, dp, ch, i - 1, offset_max + 1,
+                                  min, max, &temp_bo, 1);
+                }
 
-            ctx->cur_best_offset[channel][i] = temp_bo;
+                s->b[index].best_offset[ch][i] = temp_bo;
+            }
         }
     }
 }
@@ -1713,130 +1771,177 @@ static void determine_bits(MLPEncodeContext *ctx)
  *  maximum amount of bits allowed (24), the samples buffer is left as is and
  *  the function returns -1.
  */
-static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
+static int apply_filter(MLPEncodeContext *ctx, MLPSubstream *s, int channel)
 {
-    FilterParams *fp[NUM_FILTERS] = { &ctx->cur_channel_params[channel].filter_params[FIR],
-                                      &ctx->cur_channel_params[channel].filter_params[IIR], };
-    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;
+    DecodingParams *dp = &s->b[1].decoding_params;
+    ChannelParams *cp = &s->b[1].channel_params[channel];
+    FilterParams *fp[NUM_FILTERS] = { &cp->filter_params[FIR],
+                                      &cp->filter_params[IIR], };
+    const uint8_t codebook = cp->codebook;
+    int32_t mask = MSB_MASK(dp->quant_step_size[channel]);
+    int32_t *sample_buffer = s->b[0].decoding_params.sample_buffer[channel];
     unsigned int filter_shift = fp[FIR]->shift;
-    int ret = 0;
-
-    for (int i = 0; i < 8; i++) {
-        ctx->filter_state_buffer[FIR][i] = *sample_buffer;
-        ctx->filter_state_buffer[IIR][i] = *sample_buffer;
+    int32_t *filter_state[NUM_FILTERS] = { ctx->filter_state[FIR],
+                                           ctx->filter_state[IIR], };
+    int i, j = 1, k = 0;
 
-        sample_buffer += ctx->num_channels;
+    for (i = 0; i < 8; i++) {
+        filter_state[FIR][i] = sample_buffer[i];
+        filter_state[IIR][i] = sample_buffer[i];
     }
 
-    for (int i = 8; i < number_of_samples; i++) {
-        int32_t sample = *sample_buffer;
+    while (1) {
+        int32_t *sample_buffer = s->b[j].decoding_params.sample_buffer[channel];
+        unsigned int blocksize = s->b[j].decoding_params.blocksize;
+        int32_t sample, residual;
         int64_t accum = 0;
-        int64_t residual;
+
+        if (!blocksize)
+            break;
 
         for (int filter = 0; filter < NUM_FILTERS; filter++) {
-            int32_t *fcoeff = ctx->cur_channel_params[channel].coeff[filter];
+            int32_t *fcoeff = cp->coeff[filter];
             for (unsigned int order = 0; order < fp[filter]->order; order++)
-                accum += (int64_t)ctx->filter_state_buffer[filter][i - 1 - order] *
-                         fcoeff[order];
+                accum += (int64_t)filter_state[filter][i - 1 - order] *
+                    fcoeff[order];
         }
 
+        sample = sample_buffer[k];
         accum  >>= filter_shift;
         residual = sample - (accum & mask);
 
-        if (residual < SAMPLE_MIN(24) || residual > SAMPLE_MAX(24)) {
-            ret = AVERROR_INVALIDDATA;
-            return ret;
-        }
+        if ((codebook > 0) &&
+            (residual < SAMPLE_MIN(24) ||
+             residual > SAMPLE_MAX(24)))
+            return -1;
 
-        ctx->filter_state_buffer[FIR][i] = sample;
-        ctx->filter_state_buffer[IIR][i] = (int32_t) residual;
+        filter_state[FIR][i] = sample;
+        filter_state[IIR][i] = residual;
 
-        sample_buffer += ctx->num_channels;
+        i++;
+        k++;
+        if (k >= blocksize) {
+            k = 0;
+            j++;
+            if (j > ctx->cur_restart_interval)
+                break;
+        }
     }
 
-    sample_buffer = ctx->sample_buffer + channel;
-    for (int i = 0; i < number_of_samples; i++) {
-        *sample_buffer = ctx->filter_state_buffer[IIR][i];
+    for (int l = 0, j = 0; j <= ctx->cur_restart_interval; j++) {
+        int32_t *sample_buffer = s->b[j].decoding_params.sample_buffer[channel];
+        unsigned int blocksize = s->b[j].decoding_params.blocksize;
 
-        sample_buffer += ctx->num_channels;
+        for (int i = 0; i < blocksize; i++, l++)
+            sample_buffer[i] = filter_state[IIR][l];
     }
 
-    return ret;
+    return 0;
 }
 
-static void apply_filters(MLPEncodeContext *ctx)
+static void apply_filters(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    RestartHeader *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
 
-    for (int channel = rh->min_channel; channel <= rh->max_channel; channel++) {
-        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);
+    for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+        while (apply_filter(ctx, s, ch) < 0) {
+            /* Filter is horribly wrong. Retry. */
+            set_filter(ctx, s, ch, 1);
         }
     }
 }
 
 /** Generates two noise channels worth of data. */
-static void generate_2_noise_channels(MLPEncodeContext *ctx)
+static void generate_2_noise_channels(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    int32_t *sample_buffer = ctx->sample_buffer + ctx->num_channels - 2;
-    RestartHeader *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
     uint32_t seed = rh->noisegen_seed;
 
-    for (unsigned int i = 0; i < ctx->number_of_samples; i++) {
-        uint16_t seed_shr7 = seed >> 7;
-        *sample_buffer++ = ((int8_t)(seed >> 15)) * (1 << rh->noise_shift);
-        *sample_buffer++ = ((int8_t) seed_shr7)   * (1 << rh->noise_shift);
+    for (unsigned int j = 0; j <= ctx->cur_restart_interval; j++) {
+        DecodingParams *dp = &s->b[j].decoding_params;
+        int32_t *sample_buffer2 = dp->sample_buffer[ctx->num_channels-2];
+        int32_t *sample_buffer1 = dp->sample_buffer[ctx->num_channels-1];
 
-        seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5);
+        for (unsigned int i = 0; i < dp->blocksize; i++) {
+            uint16_t seed_shr7 = seed >> 7;
+            sample_buffer2[i] = ((int8_t)(seed >> 15)) * (1 << rh->noise_shift);
+            sample_buffer1[i] = ((int8_t) seed_shr7)   * (1 << rh->noise_shift);
 
-        sample_buffer += ctx->num_channels - 2;
+            seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5);
+        }
     }
 
     rh->noisegen_seed = seed & ((1 << 24)-1);
 }
 
 /** Rematrixes all channels using chosen coefficients. */
-static void rematrix_channels(MLPEncodeContext *ctx)
+static void rematrix_channels(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    MatrixParams *mp = &dp->matrix_params;
-    int32_t *sample_buffer = ctx->sample_buffer;
-    unsigned int maxchan = ctx->num_channels;
+    RestartHeader *rh = s->cur_restart_header;
+    DecodingParams *dp1 = &s->b[1].decoding_params;
+    MatrixParams *mp1 = &dp1->matrix_params;
+    const int maxchan = rh->max_matrix_channel;
+    int32_t orig_samples[MAX_NCHANNELS];
+    int32_t rematrix_samples[MAX_NCHANNELS];
+    uint8_t lsb_bypass[MAX_MATRICES] = { 0 };
+
+    for (unsigned int j = 0; j <= ctx->cur_restart_interval; j++) {
+        DecodingParams *dp = &s->b[j].decoding_params;
+        MatrixParams *mp = &dp->matrix_params;
+
+        for (unsigned int i = 0; i < dp->blocksize; i++) {
+            for (int ch = 0; ch <= maxchan; ch++)
+                orig_samples[ch] = rematrix_samples[ch] = dp->sample_buffer[ch][i];
+
+            for (int mat = 0; mat < mp1->count; mat++) {
+                unsigned int outch = mp1->outch[mat];
+                int64_t accum = 0;
+
+                for (int ch = 0; ch <= maxchan; ch++) {
+                    int32_t sample = rematrix_samples[ch];
+
+                    accum += (int64_t)sample * mp1->forco[mat][ch];
+                }
 
-    for (unsigned int mat = 0; mat < mp->count; mat++) {
-        unsigned int msb_mask_bits = (ctx->avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 8 : 0) - mp->shift[mat];
-        int32_t mask = MSB_MASK(msb_mask_bits);
-        unsigned int outch = mp->outch[mat];
+                rematrix_samples[outch] = accum >> 14;
+            }
 
-        sample_buffer = ctx->sample_buffer;
-        for (unsigned int i = 0; i < ctx->number_of_samples; i++) {
-            int64_t accum = 0;
+            for (int ch = 0; ch <= maxchan; ch++)
+                dp->sample_buffer[ch][i] = rematrix_samples[ch];
 
-            for (unsigned int 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;
+            for (unsigned int mat = 0; mat < mp1->count; mat++) {
+                int8_t *bypassed_lsbs = mp->bypassed_lsbs[mat];
+                unsigned int outch = mp1->outch[mat];
+                int64_t accum = 0;
+                int8_t bit;
+
+                for (int ch = 0; ch <= maxchan; ch++) {
+                    int32_t sample = rematrix_samples[ch];
+
+                    accum += (int64_t)sample * mp1->coeff[mat][ch];
+                }
 
-            sample_buffer += ctx->num_channels;
+                rematrix_samples[outch] = accum >> 14;
+                bit = rematrix_samples[outch] != orig_samples[outch];
+
+                bypassed_lsbs[i] = bit;
+                lsb_bypass[mat] |= bit;
+            }
         }
     }
+
+    for (unsigned int mat = 0; mat < mp1->count; mat++)
+        mp1->lsb_bypass[mat] = lsb_bypass[mat];
 }
 
 /****************************************************************************
  **** Functions that deal with determining the best parameters and output ***
  ****************************************************************************/
 
-typedef struct {
-    char    path[MAJOR_HEADER_INTERVAL + 2];
+typedef struct PathCounter {
+    char    path[MAX_HEADER_INTERVAL + 2];
     int     cur_idx;
-    int     bitcount;
+    uint32_t bitcount;
 } PathCounter;
 
 #define CODEBOOK_CHANGE_BITS    21
@@ -1851,14 +1956,15 @@ static int compare_best_offset(const BestOffset *prev, const BestOffset *cur)
     return prev->lsb_bits != cur->lsb_bits;
 }
 
-static int best_codebook_path_cost(MLPEncodeContext *ctx, unsigned int channel,
-                                   PathCounter *src, int cur_codebook)
+static uint32_t best_codebook_path_cost(MLPEncodeContext *ctx, MLPSubstream *s,
+                                        int channel,
+                                        PathCounter *src, int cur_codebook)
 {
     int idx = src->cur_idx;
-    const BestOffset *cur_bo = ctx->best_offset[idx][channel],
-                    *prev_bo = idx ? ctx->best_offset[idx - 1][channel] :
+    const BestOffset *cur_bo = s->b[idx].best_offset[channel],
+                    *prev_bo = idx ? s->b[idx - 1].best_offset[channel] :
                                      restart_best_offset;
-    int bitcount = src->bitcount;
+    uint32_t bitcount = src->bitcount;
     int prev_codebook = src->path[idx];
 
     bitcount += cur_bo[cur_codebook].bitcount;
@@ -1870,12 +1976,11 @@ static int best_codebook_path_cost(MLPEncodeContext *ctx, unsigned int channel,
     return bitcount;
 }
 
-static void set_best_codebook(MLPEncodeContext *ctx)
+static void set_best_codebook(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    DecodingParams *dp = ctx->cur_decoding_params;
-    RestartHeader *rh = ctx->cur_restart_header;
+    RestartHeader *rh = s->cur_restart_header;
 
-    for (unsigned int channel = rh->min_channel; channel <= rh->max_channel; channel++) {
+    for (int channel = rh->min_channel; channel <= rh->max_channel; channel++) {
         const BestOffset *prev_bo = restart_best_offset;
         BestOffset *cur_bo;
         PathCounter path_counter[NUM_CODEBOOKS + 1];
@@ -1885,17 +1990,17 @@ static void set_best_codebook(MLPEncodeContext *ctx)
         clear_path_counter(path_counter);
 
         for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
-            unsigned int best_bitcount = INT_MAX;
+            uint32_t best_bitcount = UINT32_MAX;
 
-            cur_bo = ctx->best_offset[index][channel];
+            cur_bo = s->b[index].best_offset[channel];
 
             for (unsigned int codebook = 0; codebook < NUM_CODEBOOKS; codebook++) {
-                int prev_best_bitcount = INT_MAX;
+                uint32_t prev_best_bitcount = UINT32_MAX;
 
                 for (unsigned int last_best = 0; last_best < 2; last_best++) {
                     PathCounter *dst_path = &path_counter[codebook];
                     PathCounter *src_path;
-                    int  temp_bitcount;
+                    uint32_t temp_bitcount;
 
                     /* First test last path with same headers,
                      * then with last best. */
@@ -1908,7 +2013,7 @@ static void set_best_codebook(MLPEncodeContext *ctx)
                             src_path = &path_counter[codebook];
                     }
 
-                    temp_bitcount = best_codebook_path_cost(ctx, channel, src_path, codebook);
+                    temp_bitcount = best_codebook_path_cost(ctx, s, channel, src_path, codebook);
 
                     if (temp_bitcount < best_bitcount) {
                         best_bitcount = temp_bitcount;
@@ -1935,10 +2040,11 @@ static void set_best_codebook(MLPEncodeContext *ctx)
 
         /* Update context. */
         for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
-            ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->ch_layout.nb_channels) + channel;
+            ChannelParams *cp = &s->b[index].channel_params[channel];
+            DecodingParams *dp = &s->b[index].decoding_params;
 
             best_codebook = *best_path++;
-            cur_bo = &ctx->best_offset[index][channel][best_codebook];
+            cur_bo = &s->b[index].best_offset[channel][best_codebook];
 
             cp->huff_offset      = cur_bo->offset;
             cp->huff_lsbs        = cur_bo->lsb_bits + dp->quant_step_size[channel];
@@ -1951,113 +2057,92 @@ static void set_best_codebook(MLPEncodeContext *ctx)
  *  individual access unit.
  *  TODO This is just a stub!
  */
-static void set_major_params(MLPEncodeContext *ctx)
+static void set_major_params(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    RestartHeader *rh = ctx->cur_restart_header;
-    uint8_t max_huff_lsbs = 0;
-    uint8_t max_output_bits = 0;
-    int channels = ctx->avctx->ch_layout.nb_channels;
-    DecodingParams *seq_dp = ctx->decoding_params + ctx->seq_offset[0] * channels;
-    ChannelParams *seq_cp = ctx->channel_params + ctx->seq_offset[0] * channels;
-
-    for (unsigned int index = 0; index < ctx->seq_size[ctx->restart_intervals-1]; index++) {
-        memcpy(&ctx->major_decoding_params[index], seq_dp + index, sizeof(DecodingParams));
-        for (unsigned int channel = 0; channel < channels; channel++) {
-            uint8_t huff_lsbs = (seq_cp + index*(channels) + channel)->huff_lsbs;
-            if (max_huff_lsbs < huff_lsbs)
-                max_huff_lsbs = huff_lsbs;
-            memcpy(&ctx->major_channel_params[index][channel],
-                   (seq_cp + index*(channels) + channel),
+    RestartHeader *rh = s->cur_restart_header;
+    uint8_t max_huff_lsbs = 0, max_output_bits = 0;
+    int8_t max_shift = 0;
+
+    for (int index = 0; index < s->b[ctx->restart_intervals-1].seq_size; index++) {
+        memcpy(&s->b[index].major_decoding_params,
+               &s->b[index].decoding_params, sizeof(DecodingParams));
+        for (int ch = 0; ch <= rh->max_matrix_channel; ch++) {
+            int8_t shift = s->b[index].decoding_params.output_shift[ch];
+
+            max_shift = FFMAX(max_shift, shift);
+        }
+        for (int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+            uint8_t huff_lsbs = s->b[index].channel_params[ch].huff_lsbs;
+
+            max_huff_lsbs = FFMAX(max_huff_lsbs, huff_lsbs);
+
+            memcpy(&s->b[index].major_channel_params[ch],
+                   &s->b[index].channel_params[ch],
                    sizeof(ChannelParams));
         }
     }
 
     rh->max_huff_lsbs = max_huff_lsbs;
+    rh->max_shift     = max_shift;
 
-    for (unsigned int index = 0; index < ctx->number_of_frames; index++)
-        if (max_output_bits < ctx->max_output_bits[index])
-            max_output_bits = ctx->max_output_bits[index];
+    for (int index = 0; index < ctx->number_of_frames; index++)
+        if (max_output_bits < s->b[index].max_output_bits)
+            max_output_bits = s->b[index].max_output_bits;
     rh->max_output_bits = max_output_bits;
 
-    ctx->cur_restart_header = &ctx->restart_header;
-
-    ctx->prev_decoding_params = restart_decoding_params;
-    ctx->prev_channel_params = restart_channel_params;
-
-    for (unsigned int index = 0; index < MAJOR_HEADER_INTERVAL + 1; index++) {
-        ctx->cur_decoding_params = &ctx->major_decoding_params[index];
-        ctx->cur_channel_params = ctx->major_channel_params[index];
+    s->cur_restart_header = &s->restart_header;
 
-        ctx->major_params_changed[index] = compare_decoding_params(ctx);
+    for (int index = 0; index <= ctx->cur_restart_interval; index++)
+        s->b[index].major_params_changed = compare_decoding_params(ctx, s, index);
 
-        ctx->prev_decoding_params = ctx->cur_decoding_params;
-        ctx->prev_channel_params = ctx->cur_channel_params;
-    }
-
-    ctx->major_number_of_subblocks = ctx->number_of_subblocks;
-    ctx->major_filter_state_subblock = 1;
-    ctx->major_cur_subblock_index = 0;
+    s->major_filter_state_subblock = 1;
+    s->major_cur_subblock_index = 0;
 }
 
-static void analyze_sample_buffer(MLPEncodeContext *ctx)
+static void analyze_sample_buffer(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    ChannelParams *seq_cp = ctx->seq_channel_params;
-    DecodingParams *seq_dp = ctx->seq_decoding_params;
-
-    ctx->cur_restart_header = &ctx->restart_header;
-    ctx->cur_decoding_params = seq_dp + 1;
-    ctx->cur_channel_params = seq_cp + ctx->avctx->ch_layout.nb_channels;
-
-    determine_quant_step_size(ctx);
-    generate_2_noise_channels(ctx);
-    lossless_matrix_coeffs   (ctx);
-    rematrix_channels        (ctx);
-    determine_filters        (ctx);
-    apply_filters            (ctx);
-
-    copy_restart_frame_params(ctx);
+    s->cur_restart_header = &s->restart_header;
 
     /* Copy frame_size from frames 0...max to decoding_params 1...max + 1
      * decoding_params[0] is for the filter state subblock.
      */
     for (unsigned int index = 0; index < ctx->number_of_frames; index++) {
-        DecodingParams *dp = seq_dp + (index + 1);
+        DecodingParams *dp = &s->b[index+1].decoding_params;
         dp->blocksize = ctx->avctx->frame_size;
     }
     /* The official encoder seems to always encode a filter state subblock
      * even if there are no filters. TODO check if it is possible to skip
      * the filter state subblock for no filters.
      */
-    (seq_dp + 0)->blocksize  = 8;
-    (seq_dp + 1)->blocksize -= 8;
+    s->b[0].decoding_params.blocksize  = 8;
+    s->b[1].decoding_params.blocksize -= 8;
 
-    for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
-        ctx->cur_decoding_params = seq_dp + index;
-        ctx->cur_channel_params = seq_cp + index*(ctx->avctx->ch_layout.nb_channels);
-        ctx->cur_best_offset = ctx->best_offset[index];
-        determine_bits(ctx);
-        ctx->sample_buffer += ctx->cur_decoding_params->blocksize * ctx->num_channels;
-    }
+    input_to_sample_buffer   (ctx, s);
+    determine_output_shift   (ctx, s);
+    generate_2_noise_channels(ctx, s);
+    lossless_matrix_coeffs   (ctx, s);
+    rematrix_channels        (ctx, s);
+    determine_quant_step_size(ctx, s);
+    determine_filters        (ctx, s);
+    apply_filters            (ctx, s);
 
-    set_best_codebook(ctx);
+    copy_restart_frame_params(ctx, s);
+
+    determine_bits(ctx, s);
+
+    set_best_codebook(ctx, s);
 }
 
-static void process_major_frame(MLPEncodeContext *ctx)
+static void process_major_frame(MLPEncodeContext *ctx, MLPSubstream *s)
 {
-    ctx->sample_buffer = ctx->major_inout_buffer;
-
     ctx->number_of_frames = ctx->major_number_of_frames;
-    ctx->number_of_samples = ctx->major_frame_size;
 
-    ctx->cur_restart_header = &ctx->restart_header;
+    s->cur_restart_header = &s->restart_header;
 
-    ctx->cur_decoding_params = &ctx->major_decoding_params[1];
-    ctx->cur_channel_params = ctx->major_channel_params[1];
+    generate_2_noise_channels(ctx, s);
+    rematrix_channels        (ctx, s);
 
-    generate_2_noise_channels(ctx);
-    rematrix_channels        (ctx);
-
-    apply_filters(ctx);
+    apply_filters(ctx, s);
 }
 
 /****************************************************************************/
@@ -2069,7 +2154,7 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     int bytes_written = 0;
     int channels = avctx->ch_layout.nb_channels;
     int restart_frame, ret;
-    uint8_t *data;
+    const uint8_t *data;
 
     if (!frame && !ctx->last_frames)
         ctx->last_frames = (ctx->afq.remaining_samples + avctx->frame_size - 1) / avctx->frame_size;
@@ -2088,17 +2173,9 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 
     data = frame ? frame->data[0] : NULL;
 
-    ctx->frame_index = avctx->frame_number % ctx->max_restart_interval;
-
-    ctx->inout_buffer = ctx->major_inout_buffer
-                      + ctx->frame_index * ctx->one_sample_buffer_size;
-
-    ctx->sample_buffer = ctx->major_scratch_buffer
-                       + ctx->frame_index * ctx->one_sample_buffer_size;
-
-    ctx->write_buffer = ctx->inout_buffer;
+    ctx->frame_index = avctx->frame_num % ctx->cur_restart_interval;
 
-    if (avctx->frame_number < ctx->max_restart_interval) {
+    if (avctx->frame_num < ctx->cur_restart_interval) {
         if (data)
             goto input_and_return;
     }
@@ -2107,18 +2184,17 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 
     if (restart_frame) {
         avpkt->flags |= AV_PKT_FLAG_KEY;
-        set_major_params(ctx);
-        if (ctx->min_restart_interval != ctx->max_restart_interval)
-            process_major_frame(ctx);
-    }
+        for (int n = 0; n < ctx->num_substreams; n++)
+            set_major_params(ctx, &ctx->s[n]);
 
-    if (ctx->min_restart_interval == ctx->max_restart_interval)
-        ctx->write_buffer = ctx->sample_buffer;
+        if (ctx->min_restart_interval != ctx->cur_restart_interval)
+            process_major_frame(ctx, &ctx->s[0]);
+    }
 
     bytes_written = write_access_unit(ctx, avpkt->data, avpkt->size, restart_frame);
 
-    ctx->timestamp += avctx->frame_size;
-    ctx->dts       += avctx->frame_size;
+    ctx->output_timing += avctx->frame_size;
+    ctx->input_timing  += avctx->frame_size;
 
 input_and_return:
 
@@ -2128,7 +2204,8 @@ input_and_return:
         ctx->next_major_number_of_frames++;
     }
     if (data)
-        input_data(ctx, data, frame->nb_samples);
+        for (int n = 0; n < ctx->num_substreams; n++)
+            input_data(ctx, &ctx->s[n], frame->extended_data, frame->nb_samples);
 
     restart_frame = (ctx->frame_index + 1) % ctx->min_restart_interval;
 
@@ -2136,30 +2213,27 @@ input_and_return:
         for (unsigned int seq_index = 0; seq_index < ctx->restart_intervals; seq_index++) {
             unsigned int number_of_samples;
 
-            ctx->sample_buffer = ctx->major_scratch_buffer;
-            ctx->inout_buffer = ctx->major_inout_buffer;
-
             ctx->number_of_frames = ctx->next_major_number_of_frames;
             ctx->number_of_subblocks = ctx->next_major_number_of_frames + 1;
 
-            ctx->seq_channel_params = ctx->channel_params + ctx->seq_offset[seq_index] * channels;
-
-            ctx->seq_decoding_params = ctx->decoding_params + ctx->seq_offset[seq_index];
-
             number_of_samples = avctx->frame_size * ctx->number_of_frames;
-            ctx->number_of_samples = number_of_samples;
 
-            for (unsigned int index = 0; index < ctx->seq_size[seq_index]; index++) {
-                clear_channel_params(ctx->seq_channel_params + index * channels, channels);
-                default_decoding_params(ctx, ctx->seq_decoding_params + index);
-            }
+            for (int n = 0; n < ctx->num_substreams; n++) {
+                MLPSubstream *s = &ctx->s[n];
 
-            input_to_sample_buffer(ctx);
+                for (int i = 0; i < s->b[seq_index].seq_size; i++) {
+                    clear_channel_params(s->b[i].channel_params, channels);
+                    default_decoding_params(ctx, &s->b[i].decoding_params);
+                }
+            }
 
-            analyze_sample_buffer(ctx);
+            if (number_of_samples > 0) {
+                for (int n = 0; n < ctx->num_substreams; n++)
+                    analyze_sample_buffer(ctx, &ctx->s[n]);
+            }
         }
 
-        if (ctx->frame_index == (ctx->max_restart_interval - 1)) {
+        if (ctx->frame_index == (ctx->cur_restart_interval - 1)) {
             ctx->major_frame_size = ctx->next_major_frame_size;
             ctx->next_major_frame_size = 0;
             ctx->major_number_of_frames = ctx->next_major_number_of_frames;
@@ -2167,8 +2241,8 @@ input_and_return:
         }
     }
 
-    if (!frame && ctx->last_frames < ctx->max_restart_interval - 1)
-        avctx->frame_number++;
+    if (!frame && ctx->last_frames < ctx->cur_restart_interval - 1)
+        avctx->frame_num++;
 
     if (bytes_written > 0) {
         ff_af_queue_remove(&ctx->afq,
@@ -2191,64 +2265,84 @@ static av_cold int mlp_encode_close(AVCodecContext *avctx)
     MLPEncodeContext *ctx = avctx->priv_data;
 
     ff_lpc_end(&ctx->lpc_ctx);
-
-    av_freep(&ctx->lossless_check_data);
-    av_freep(&ctx->major_scratch_buffer);
-    av_freep(&ctx->major_inout_buffer);
-    av_freep(&ctx->lpc_sample_buffer);
-    av_freep(&ctx->decoding_params);
-    av_freep(&ctx->channel_params);
-    av_freep(&ctx->max_output_bits);
     ff_af_queue_close(&ctx->afq);
 
-    for (int i = 0; i < NUM_FILTERS; i++)
-        av_freep(&ctx->filter_state_buffer[i]);
-
     return 0;
 }
 
+#define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
+#define OFFSET(x) offsetof(MLPEncodeContext, x)
+static const AVOption mlp_options[] = {
+{ "max_interval", "Max number of frames between each new header", OFFSET(max_restart_interval),  AV_OPT_TYPE_INT, {.i64 = 16 }, MIN_HEADER_INTERVAL, MAX_HEADER_INTERVAL, FLAGS },
+{ "lpc_coeff_precision", "LPC coefficient precision", OFFSET(lpc_coeff_precision), AV_OPT_TYPE_INT, {.i64 = 15 }, 0, 15, FLAGS },
+{ "lpc_type", "LPC algorithm", OFFSET(lpc_type), AV_OPT_TYPE_INT, {.i64 = FF_LPC_TYPE_LEVINSON }, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_CHOLESKY, FLAGS, "lpc_type" },
+{ "levinson", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_LEVINSON }, 0, 0, FLAGS, "lpc_type" },
+{ "cholesky", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_CHOLESKY }, 0, 0, FLAGS, "lpc_type" },
+{ "lpc_passes", "Number of passes to use for Cholesky factorization during LPC analysis", OFFSET(lpc_passes),  AV_OPT_TYPE_INT, {.i64 = 2 }, 1, INT_MAX, FLAGS },
+{ "codebook_search", "Max number of codebook searches", OFFSET(max_codebook_search),  AV_OPT_TYPE_INT, {.i64 = 3 }, 1, 100, FLAGS },
+{ "prediction_order", "Search method for selecting prediction order", OFFSET(prediction_order), AV_OPT_TYPE_INT, {.i64 = ORDER_METHOD_EST }, ORDER_METHOD_EST, ORDER_METHOD_SEARCH, FLAGS, "predm" },
+{ "estimation", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_EST },    0, 0, FLAGS, "predm" },
+{ "search",     NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_SEARCH }, 0, 0, FLAGS, "predm" },
+{ "rematrix_precision", "Rematrix coefficient precision", OFFSET(rematrix_precision), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 14, FLAGS },
+{ NULL },
+};
+
+static const AVClass mlp_class = {
+    .class_name = "mlpenc",
+    .item_name  = av_default_item_name,
+    .option     = mlp_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 #if CONFIG_MLP_ENCODER
 const FFCodec ff_mlp_encoder = {
     .p.name                 ="mlp",
-    .p.long_name            = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"),
+    CODEC_LONG_NAME("MLP (Meridian Lossless Packing)"),
     .p.type                 = AVMEDIA_TYPE_AUDIO,
     .p.id                   = AV_CODEC_ID_MLP,
+    .p.capabilities         = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                              AV_CODEC_CAP_EXPERIMENTAL,
     .priv_data_size         = sizeof(MLPEncodeContext),
     .init                   = mlp_encode_init,
     FF_CODEC_ENCODE_CB(mlp_encode_frame),
     .close                  = mlp_encode_close,
-    .p.capabilities         = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
-    .p.sample_fmts          = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
+    .p.priv_class           = &mlp_class,
+    .p.sample_fmts          = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE},
     .p.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
-#if FF_API_OLD_CHANNEL_LAYOUT
-    .p.channel_layouts      = ff_mlp_channel_layouts,
-#endif
+    CODEC_OLD_CHANNEL_LAYOUTS_ARRAY(ff_mlp_channel_layouts)
     .p.ch_layouts           = ff_mlp_ch_layouts,
-    .caps_internal          = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
+    .caps_internal          = FF_CODEC_CAP_INIT_CLEANUP,
 };
 #endif
 #if CONFIG_TRUEHD_ENCODER
 const FFCodec ff_truehd_encoder = {
     .p.name                 ="truehd",
-    .p.long_name            = NULL_IF_CONFIG_SMALL("TrueHD"),
+    CODEC_LONG_NAME("TrueHD"),
     .p.type                 = AVMEDIA_TYPE_AUDIO,
     .p.id                   = AV_CODEC_ID_TRUEHD,
+    .p.capabilities         = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                              AV_CODEC_CAP_SMALL_LAST_FRAME |
+                              AV_CODEC_CAP_EXPERIMENTAL,
     .priv_data_size         = sizeof(MLPEncodeContext),
     .init                   = mlp_encode_init,
     FF_CODEC_ENCODE_CB(mlp_encode_frame),
     .close                  = mlp_encode_close,
-    .p.capabilities         = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
-    .p.sample_fmts          = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
+    .p.priv_class           = &mlp_class,
+    .p.sample_fmts          = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE},
     .p.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
-#if FF_API_OLD_CHANNEL_LAYOUT
-    .p.channel_layouts      = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0},
-#endif
+    CODEC_OLD_CHANNEL_LAYOUTS(AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_2POINT1, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_3POINT1, AV_CH_LAYOUT_4POINT0, AV_CH_LAYOUT_4POINT1, AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1)
     .p.ch_layouts           = (const AVChannelLayout[]) {
+                                  AV_CHANNEL_LAYOUT_MONO,
                                   AV_CHANNEL_LAYOUT_STEREO,
-                                  AV_CHANNEL_LAYOUT_5POINT0_BACK,
-                                  AV_CHANNEL_LAYOUT_5POINT1_BACK,
+                                  AV_CHANNEL_LAYOUT_2POINT1,
+                                  AV_CHANNEL_LAYOUT_SURROUND,
+                                  AV_CHANNEL_LAYOUT_3POINT1,
+                                  AV_CHANNEL_LAYOUT_4POINT0,
+                                  AV_CHANNEL_LAYOUT_4POINT1,
+                                  AV_CHANNEL_LAYOUT_5POINT0,
+                                  AV_CHANNEL_LAYOUT_5POINT1,
                                   { 0 }
                               },
-    .caps_internal          = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
+    .caps_internal          = FF_CODEC_CAP_INIT_CLEANUP,
 };
 #endif