aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2023-10-19 23:36:19 +0200
committerPaul B Mahol <onemda@gmail.com>2023-10-20 17:07:24 +0200
commit3f773d8d02ad75414c8572845cc1a55b0c9e0598 (patch)
treeeb26f5e6ac980a546161e92cbda6efd515805085
parent98857ece48e248d6a2d05ebbaca12c170b121695 (diff)
downloadffmpeg-3f773d8d02ad75414c8572845cc1a55b0c9e0598.tar.gz
avcodec/mlpenc: add support for TrueHD substreams
Add 3.0 channel layout support for truehd encoder.
-rw-r--r--libavcodec/mlpenc.c597
1 files changed, 327 insertions, 270 deletions
diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c
index 031a68449a..09dc9ac0f9 100644
--- a/libavcodec/mlpenc.c
+++ b/libavcodec/mlpenc.c
@@ -71,9 +71,9 @@ typedef struct MatrixParams {
uint8_t outch[MAX_MATRICES]; ///< output channel for each matrix
int32_t forco[MAX_MATRICES][MAX_NCHANNELS]; ///< forward coefficients
int32_t coeff[MAX_MATRICES][MAX_NCHANNELS]; ///< decoding coefficients
- uint8_t fbits[MAX_CHANNELS]; ///< fraction bits
+ 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;
@@ -84,6 +84,7 @@ typedef struct MatrixParams {
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
+ uint8_t output_shift[MAX_CHANNELS]; ///< Left shift to apply to decoded PCM values to get final 24-bit output.
MatrixParams matrix_params;
@@ -109,7 +110,7 @@ typedef struct MLPBlock {
unsigned int seq_size;
ChannelParams channel_params[MAX_CHANNELS];
DecodingParams decoding_params;
- int32_t lossless_check_data; ///< Array with lossless_check_data for each access unit.
+ 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.
@@ -118,6 +119,14 @@ typedef struct MLPBlock {
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;
+} MLPSubstream;
+
typedef struct MLPEncodeContext {
AVClass *class;
AVCodecContext *avctx;
@@ -166,6 +175,7 @@ typedef struct MLPEncodeContext {
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
uint8_t channel_arrangement8; ///< 8 channel arrangement for THD streams
@@ -174,18 +184,11 @@ typedef struct MLPEncodeContext {
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
- RestartHeader restart_header;
- MLPBlock b[MAX_HEADER_INTERVAL + 1];
+ MLPSubstream s[2];
int32_t filter_state[NUM_FILTERS][MAX_HEADER_INTERVAL * MAX_BLOCKSIZE];
int32_t lpc_sample_buffer[MAX_HEADER_INTERVAL * MAX_BLOCKSIZE];
- unsigned int major_cur_subblock_index;
- unsigned int major_filter_state_subblock;
- unsigned int major_number_of_subblocks;
-
- RestartHeader *cur_restart_header;
-
AudioFrameQueue afq;
/* Analysis stage. */
@@ -245,9 +248,10 @@ 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;
@@ -255,18 +259,20 @@ static int compare_matrix_params(MLPEncodeContext *ctx, const MatrixParams *prev
if (!mp->count)
return 0;
- for (unsigned int ch = rh->min_channel; ch <= rh->max_channel; ch++)
- if (prev->fbits[ch] != mp->fbits[ch])
- return 1;
-
for (unsigned int mat = 0; mat < mp->count; mat++) {
if (prev->outch[mat] != mp->outch[mat])
return 1;
+ 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 (unsigned int ch = 0; ch <= rh->max_matrix_channel; ch++)
+ for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
if (prev->coeff[mat][ch] != mp->coeff[mat][ch])
return 1;
}
@@ -278,13 +284,14 @@ static int compare_matrix_params(MLPEncodeContext *ctx, const MatrixParams *prev
* new decoding params header has to be written.
*/
static int compare_decoding_params(MLPEncodeContext *ctx,
+ MLPSubstream *s,
unsigned int index)
{
- const DecodingParams *prev = index ? &ctx->b[index-1].major_decoding_params : restart_decoding_params;
- DecodingParams *dp = &ctx->b[index].major_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)
@@ -293,24 +300,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 = index ? &ctx->b[index-1].major_channel_params[ch] : &restart_channel_params[ch];
- ChannelParams *cp = &ctx->b[index].major_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))
@@ -345,7 +352,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];
}
@@ -353,39 +360,38 @@ 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];
- dst->lsb_bypass[count] = src->lsb_bypass[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->b[index].decoding_params;
+ DecodingParams *dp = &s->b[index].decoding_params;
- copy_matrix_params(&dp->matrix_params, &ctx->b[1].decoding_params.matrix_params);
+ copy_matrix_params(&dp->matrix_params, &s->b[1].decoding_params.matrix_params);
- for (unsigned int channel = 0; channel < ctx->avctx->ch_layout.nb_channels; channel++) {
- ChannelParams *cp = &ctx->b[index].channel_params[channel];
+ for (int ch = 0; ch <= rh->max_channel; ch++) {
+ ChannelParams *cp = &s->b[index].channel_params[ch];
- dp->quant_step_size[channel] = ctx->b[1].decoding_params.quant_step_size[channel];
- dp->matrix_params.shift[channel] = ctx->b[1].decoding_params.matrix_params.shift[channel];
+ dp->quant_step_size[ch] = s->b[1].decoding_params.quant_step_size[ch];
+ dp->output_shift[ch] = s->b[1].decoding_params.output_shift[ch];
if (index)
for (unsigned int filter = 0; filter < NUM_FILTERS; filter++)
- copy_filter_params(cp, &ctx->b[1].channel_params[channel], filter);
+ copy_filter_params(cp, &s->b[1].channel_params[ch], filter);
}
}
}
@@ -401,6 +407,7 @@ static void clear_decoding_params(DecodingParams *decoding_params)
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 ));
}
/** Clears a ChannelParams struct the way it should be after a restart header. */
@@ -469,7 +476,6 @@ 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;
uint64_t channels_present;
int ret;
@@ -523,13 +529,13 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
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;
@@ -548,7 +554,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
ctx->min_restart_interval = ctx->cur_restart_interval = ctx->max_restart_interval;
ctx->restart_intervals = ctx->max_restart_interval / ctx->min_restart_interval;
- 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) {
@@ -574,27 +580,29 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
ctx->summary_info = ff_mlp_ch_info[ctx->channel_arrangement].summary_info ;
} else {
/* TrueHD */
- if (channels_present == AV_CH_LAYOUT_MONO) {
+ 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;
- } else if (channels_present == AV_CH_LAYOUT_STEREO) {
+ 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;
- } else if (channels_present == AV_CH_LAYOUT_5POINT0) {
- ctx->ch2_presentation_mod= 1;
- ctx->ch6_presentation_mod= 1;
- ctx->ch8_presentation_mod= 1;
- ctx->thd_substream_info = 0x104;
- } else if (channels_present == AV_CH_LAYOUT_5POINT1) {
- ctx->ch2_presentation_mod= 2;
- ctx->ch6_presentation_mod= 1;
- ctx->ch8_presentation_mod= 2;
- ctx->thd_substream_info = 0x104;
- } else {
+ break;
+ case AV_CH_LAYOUT_SURROUND:
+ 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;
@@ -604,16 +612,37 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx)
ctx->channel_arrangement8 = layout_truehd(channels_present);
}
- for (unsigned int index = 0; index < ctx->restart_intervals; index++)
- ctx->b[index].seq_size = ((index + 1) * ctx->min_restart_interval) + 1;
+ for (unsigned int index = 0; index < ctx->restart_intervals; index++) {
+ for (int n = 0; n < ctx->num_substreams; n++)
+ ctx->s[n].b[index].seq_size = ((index + 1) * ctx->min_restart_interval) + 1;
+ }
+
/* 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->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;
- 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;
+ if (avctx->ch_layout.nb_channels > 2) {
+ rh = &ctx->s[1].restart_header;
+
+ 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)
@@ -713,9 +742,10 @@ 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;
@@ -736,7 +766,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. */
@@ -750,20 +780,26 @@ 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,
+ MLPSubstream *s,
DecodingParams *dp,
PutBitContext *pb)
{
+ 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, 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);
@@ -782,7 +818,7 @@ static void write_matrix_params(MLPEncodeContext *ctx,
static void write_filter_params(MLPEncodeContext *ctx,
ChannelParams *cp,
PutBitContext *pb,
- unsigned int channel, unsigned int filter)
+ int channel, unsigned int filter)
{
FilterParams *fp = &cp->filter_params[filter];
@@ -807,13 +843,12 @@ static void write_filter_params(MLPEncodeContext *ctx,
/** 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->b[subblock_index].major_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) {
@@ -835,7 +870,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, dp, pb);
+ write_matrix_params(ctx, s, dp, pb);
} else {
put_bits(pb, 1, 0);
}
@@ -844,8 +879,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);
}
@@ -854,15 +889,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->b[subblock_index].major_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);
@@ -908,18 +943,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,
- unsigned int subblock_index)
+static void write_block_data(MLPEncodeContext *ctx, MLPSubstream *s,
+ PutBitContext *pb, unsigned int subblock_index)
{
- RestartHeader *rh = ctx->cur_restart_header;
- DecodingParams *dp = &ctx->b[subblock_index].major_decoding_params;
+ 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->b[subblock_index].major_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];
@@ -945,7 +980,7 @@ static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb,
}
}
- for (unsigned int ch = rh->min_channel; ch <= rh->max_channel; ch++) {
+ 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];
@@ -963,28 +998,29 @@ static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb,
}
/** 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->b[ctx->frame_index].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;
- 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 = cur_subblock_index++;
- params_changed = ctx->b[subblock_index].major_params_changed;
+ params_changed = s->b[subblock_index].major_params_changed;
if (substr_restart_frame || params_changed) {
put_bits(&pb, 1, 1);
@@ -992,19 +1028,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, subblock_index);
+ write_block_data(ctx, s, &pb, subblock_index);
put_bits(&pb, 1, !substr_restart_frame);
@@ -1013,7 +1049,7 @@ 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) {
@@ -1036,13 +1072,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;
}
@@ -1051,9 +1086,10 @@ 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->input_timing;
@@ -1062,11 +1098,13 @@ static void write_frame_headers(MLPEncodeContext *ctx, uint8_t *frame_header,
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);
@@ -1111,7 +1149,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;
@@ -1128,22 +1172,23 @@ 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,
+static void input_data_internal(MLPEncodeContext *ctx, MLPSubstream *s,
+ uint8_t **const samples,
int nb_samples, int is24)
{
- int32_t *lossless_check_data = &ctx->b[ctx->frame_index].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 *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 bits = 0;
for (int i = 0; i < nb_samples; i++) {
- for (unsigned int ch = 0; ch <= rh->max_channel; ch++) {
- int32_t *sample_buffer = ctx->b[ctx->frame_index].inout_buffer[ch];
+ 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;
bits = FFMAX(number_sbits(sample), bits);
@@ -1152,38 +1197,40 @@ static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples,
}
}
- for (int i = nb_samples; i < ctx->avctx->frame_size; i++) {
- for (unsigned int ch = 0; ch <= rh->max_channel; ch++) {
- int32_t *sample_buffer = ctx->b[ctx->frame_index].inout_buffer[ch];
+ 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[i] = 0;
}
}
- ctx->b[ctx->frame_index].max_output_bits = bits;
+ 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, const 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)
{
+ 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->cur_restart_interval;
- DecodingParams *dp = &ctx->b[index+1].decoding_params;
+ DecodingParams *dp = &s->b[index+1].decoding_params;
- for (unsigned int ch = 0; ch < ctx->avctx->ch_layout.nb_channels; ch++) {
- const int32_t *input_buffer = ctx->b[cur_index].inout_buffer[ch];
+ 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 = &ctx->b[index].decoding_params;
+ 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];
@@ -1209,27 +1256,27 @@ static int number_trailing_zeroes(int32_t sample, unsigned int max, unsigned int
/** 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)
{
- RestartHeader *rh = ctx->cur_restart_header;
- DecodingParams *dp1 = &ctx->b[1].decoding_params;
+ 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 (unsigned int j = 0; j <= ctx->cur_restart_interval; j++) {
- DecodingParams *dp = &ctx->b[j].decoding_params;
+ for (int j = 0; j <= ctx->cur_restart_interval; j++) {
+ DecodingParams *dp = &s->b[j].decoding_params;
- for (unsigned int ch = 0; ch <= rh->max_channel; ch++) {
+ for (int ch = 0; ch <= rh->max_channel; ch++) {
int32_t *sample_buffer = dp->sample_buffer[ch];
- for (unsigned int i = 0; i < dp->blocksize; i++)
+ for (int i = 0; i < dp->blocksize; i++)
sample_mask[ch] |= sample_buffer[i];
}
}
- for (unsigned int channel = 0; channel <= rh->max_channel; channel++)
- dp1->quant_step_size[channel] = number_trailing_zeroes(sample_mask[channel], 15, 0);
+ 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
@@ -1258,10 +1305,10 @@ static void code_filter_coeffs(MLPEncodeContext *ctx, FilterParams *fp, const in
/** Determines the best filter parameters for the given data and writes the
* necessary information to the context.
*/
-static void set_filter(MLPEncodeContext *ctx,
+static void set_filter(MLPEncodeContext *ctx, MLPSubstream *s,
int channel, int clear_filter)
{
- ChannelParams *cp = &ctx->b[1].channel_params[channel];
+ ChannelParams *cp = &s->b[1].channel_params[channel];
FilterParams *fp = &cp->filter_params[FIR];
if (clear_filter) {
@@ -1275,7 +1322,7 @@ static void set_filter(MLPEncodeContext *ctx,
int order;
for (unsigned int j = 0; j <= ctx->cur_restart_interval; j++) {
- DecodingParams *dp = &ctx->b[j].decoding_params;
+ DecodingParams *dp = &s->b[j].decoding_params;
int32_t *sample_buffer = dp->sample_buffer[channel];
for (unsigned int i = 0; i < dp->blocksize; i++)
@@ -1292,7 +1339,7 @@ static void set_filter(MLPEncodeContext *ctx,
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];
@@ -1305,17 +1352,17 @@ static void set_filter(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 ch = rh->min_channel; ch <= rh->max_channel; ch++)
- set_filter(ctx, ch, 0);
+ set_filter(ctx, s, ch, 0);
}
-static int estimate_coeff(MLPEncodeContext *ctx,
+static int estimate_coeff(MLPEncodeContext *ctx, MLPSubstream *s,
MatrixParams *mp,
- unsigned int ch0, unsigned int ch1)
+ int ch0, int ch1)
{
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;
@@ -1324,7 +1371,7 @@ static int estimate_coeff(MLPEncodeContext *ctx,
int i, count = 0;
for (int j = 0; j <= ctx->cur_restart_interval; j++) {
- DecodingParams *dp = &ctx->b[j].decoding_params;
+ DecodingParams *dp = &s->b[j].decoding_params;
const int32_t *ch[2];
ch[0] = dp->sample_buffer[ch0];
@@ -1374,7 +1421,7 @@ static int estimate_coeff(MLPEncodeContext *ctx,
count = 1;
i = enl < enr;
- mp->outch[0] = i;
+ mp->outch[0] = ch0 + i;
d[!i] = cf0;
d[ i] = 1 << 14;
@@ -1393,35 +1440,36 @@ static int estimate_coeff(MLPEncodeContext *ctx,
/** 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,
+static void code_matrix_coeffs(MLPEncodeContext *ctx, MLPSubstream *s,
DecodingParams *dp,
unsigned int mat)
{
- RestartHeader *rh = ctx->cur_restart_header;
+ RestartHeader *rh = s->cur_restart_header;
MatrixParams *mp = &dp->matrix_params;
int32_t coeff_mask = 0;
- for (unsigned int channel = 0; channel <= rh->max_matrix_channel; channel++) {
- coeff_mask |= mp->coeff[mat][channel];
- }
+ for (int ch = 0; ch <= rh->max_matrix_channel; ch++)
+ coeff_mask |= mp->coeff[mat][ch];
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->b[1].decoding_params;
+ RestartHeader *rh = s->cur_restart_header;
+ DecodingParams *dp = &s->b[1].decoding_params;
MatrixParams *mp = &dp->matrix_params;
mp->count = 0;
if (ctx->num_channels - 2 != 2)
return;
- mp->count = estimate_coeff(ctx, mp, 0, 1);
+ 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, dp, mat);
+ code_matrix_coeffs(ctx, s, dp, mat);
}
/** Min and max values that can be encoded with each codebook. The values for
@@ -1438,7 +1486,7 @@ static const int8_t codebook_extremes[3][2] = {
*/
static void no_codebook_bits_offset(MLPEncodeContext *ctx,
DecodingParams *dp,
- unsigned int channel, int32_t offset,
+ int channel, int32_t offset,
int32_t min, int32_t max,
BestOffset *bo)
{
@@ -1467,7 +1515,7 @@ static void no_codebook_bits_offset(MLPEncodeContext *ctx,
*/
static void no_codebook_bits(MLPEncodeContext *ctx,
DecodingParams *dp,
- unsigned int channel,
+ int channel,
int32_t min, int32_t max,
BestOffset *bo)
{
@@ -1504,7 +1552,7 @@ static void no_codebook_bits(MLPEncodeContext *ctx,
*/
static inline void codebook_bits_offset(MLPEncodeContext *ctx,
DecodingParams *dp,
- unsigned int channel, int codebook,
+ int channel, int codebook,
int32_t sample_min, int32_t sample_max,
int32_t offset, BestOffset *bo)
{
@@ -1566,7 +1614,7 @@ static inline void codebook_bits_offset(MLPEncodeContext *ctx,
*/
static inline void codebook_bits(MLPEncodeContext *ctx,
DecodingParams *dp,
- unsigned int channel, int codebook,
+ int channel, int codebook,
int offset, int32_t min, int32_t max,
BestOffset *bo, int direction)
{
@@ -1605,15 +1653,15 @@ 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)
{
- RestartHeader *rh = ctx->cur_restart_header;
+ RestartHeader *rh = s->cur_restart_header;
for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
- DecodingParams *dp = &ctx->b[index].decoding_params;
+ DecodingParams *dp = &s->b[index].decoding_params;
- for (unsigned int channel = 0; channel <= rh->max_channel; channel++) {
- ChannelParams *cp = &ctx->b[index].channel_params[channel];
- int32_t *sample_buffer = dp->sample_buffer[channel];
+ 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;
@@ -1621,7 +1669,7 @@ static void determine_bits(MLPEncodeContext *ctx)
/* Determine extremes and average. */
for (int i = 0; i < dp->blocksize; i++) {
- int32_t sample = sample_buffer[i] >> dp->quant_step_size[channel];
+ int32_t sample = sample_buffer[i] >> dp->quant_step_size[ch];
if (sample < min)
min = sample;
if (sample > max)
@@ -1633,30 +1681,30 @@ static void determine_bits(MLPEncodeContext *ctx)
/* 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, channel, min, max, &ctx->b[index].best_offset[channel][0]);
+ 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, channel, offset, min, max, &ctx->b[index].best_offset[channel][0]);
+ 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, UINT32_MAX, 0, 0, 0, };
int32_t offset_max;
- codebook_bits_offset(ctx, dp, channel, i - 1,
+ codebook_bits_offset(ctx, dp, ch, i - 1,
min, max, offset,
&temp_bo);
if (no_filters_used) {
offset_max = temp_bo.max;
- codebook_bits(ctx, dp, channel, i - 1, temp_bo.min - 1,
+ codebook_bits(ctx, dp, ch, i - 1, temp_bo.min - 1,
min, max, &temp_bo, 0);
- codebook_bits(ctx, dp, channel, i - 1, offset_max + 1,
+ codebook_bits(ctx, dp, ch, i - 1, offset_max + 1,
min, max, &temp_bo, 1);
}
- ctx->b[index].best_offset[channel][i] = temp_bo;
+ s->b[index].best_offset[ch][i] = temp_bo;
}
}
}
@@ -1676,15 +1724,15 @@ 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)
{
- DecodingParams *dp = &ctx->b[1].decoding_params;
- ChannelParams *cp = &ctx->b[1].channel_params[channel];
+ 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 = ctx->b[0].decoding_params.sample_buffer[channel];
+ int32_t *sample_buffer = s->b[0].decoding_params.sample_buffer[channel];
unsigned int filter_shift = fp[FIR]->shift;
int32_t *filter_state[NUM_FILTERS] = { ctx->filter_state[FIR],
ctx->filter_state[IIR], };
@@ -1696,8 +1744,8 @@ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
}
while (1) {
- int32_t *sample_buffer = ctx->b[j].decoding_params.sample_buffer[channel];
- unsigned int blocksize = ctx->b[j].decoding_params.blocksize;
+ 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;
@@ -1734,8 +1782,8 @@ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
}
for (int l = 0, j = 0; j <= ctx->cur_restart_interval; j++) {
- int32_t *sample_buffer = ctx->b[j].decoding_params.sample_buffer[channel];
- unsigned int blocksize = ctx->b[j].decoding_params.blocksize;
+ int32_t *sample_buffer = s->b[j].decoding_params.sample_buffer[channel];
+ unsigned int blocksize = s->b[j].decoding_params.blocksize;
for (int i = 0; i < blocksize; i++, l++)
sample_buffer[i] = filter_state[IIR][l];
@@ -1744,28 +1792,28 @@ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
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 ch = rh->min_channel; ch <= rh->max_channel; ch++) {
- if (apply_filter(ctx, ch) < 0) {
+ if (apply_filter(ctx, s, ch) < 0) {
/* Filter is horribly wrong.
* Clear filter parameters and update state. */
- set_filter(ctx, ch, 1);
- apply_filter(ctx, ch);
+ set_filter(ctx, s, ch, 1);
+ apply_filter(ctx, s, ch);
}
}
}
/** 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)
{
- RestartHeader *rh = ctx->cur_restart_header;
+ RestartHeader *rh = s->cur_restart_header;
uint32_t seed = rh->noisegen_seed;
for (unsigned int j = 0; j <= ctx->cur_restart_interval; j++) {
- DecodingParams *dp = &ctx->b[j].decoding_params;
+ 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];
@@ -1782,22 +1830,22 @@ static void generate_2_noise_channels(MLPEncodeContext *ctx)
}
/** Rematrixes all channels using chosen coefficients. */
-static void rematrix_channels(MLPEncodeContext *ctx)
+static void rematrix_channels(MLPEncodeContext *ctx, MLPSubstream *s)
{
- RestartHeader *rh = ctx->cur_restart_header;
- DecodingParams *dp1 = &ctx->b[1].decoding_params;
+ RestartHeader *rh = s->cur_restart_header;
+ DecodingParams *dp1 = &s->b[1].decoding_params;
MatrixParams *mp1 = &dp1->matrix_params;
- unsigned int maxchan = rh->max_matrix_channel;
+ 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 = &ctx->b[j].decoding_params;
+ DecodingParams *dp = &s->b[j].decoding_params;
MatrixParams *mp = &dp->matrix_params;
for (unsigned int i = 0; i < dp->blocksize; i++) {
- for (unsigned int ch = 0; ch <= maxchan; ch++)
+ 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++) {
@@ -1813,7 +1861,7 @@ static void rematrix_channels(MLPEncodeContext *ctx)
rematrix_samples[outch] = accum >> 14;
}
- for (unsigned int ch = 0; ch <= maxchan; ch++)
+ for (int ch = 0; ch <= maxchan; ch++)
dp->sample_buffer[ch][i] = rematrix_samples[ch];
for (unsigned int mat = 0; mat < mp1->count; mat++) {
@@ -1822,7 +1870,7 @@ static void rematrix_channels(MLPEncodeContext *ctx)
int64_t accum = 0;
int8_t bit;
- for (unsigned int ch = 0; ch <= maxchan; ch++) {
+ for (int ch = 0; ch <= maxchan; ch++) {
int32_t sample = rematrix_samples[ch];
accum += (int64_t)sample * mp1->coeff[mat][ch];
@@ -1863,12 +1911,13 @@ static int compare_best_offset(const BestOffset *prev, const BestOffset *cur)
return prev->lsb_bits != cur->lsb_bits;
}
-static uint32_t 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->b[idx].best_offset[channel],
- *prev_bo = idx ? ctx->b[idx - 1].best_offset[channel] :
+ const BestOffset *cur_bo = s->b[idx].best_offset[channel],
+ *prev_bo = idx ? s->b[idx - 1].best_offset[channel] :
restart_best_offset;
uint32_t bitcount = src->bitcount;
int prev_codebook = src->path[idx];
@@ -1882,11 +1931,11 @@ static uint32_t best_codebook_path_cost(MLPEncodeContext *ctx, unsigned int chan
return bitcount;
}
-static void set_best_codebook(MLPEncodeContext *ctx)
+static void set_best_codebook(MLPEncodeContext *ctx, MLPSubstream *s)
{
- 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];
@@ -1898,7 +1947,7 @@ static void set_best_codebook(MLPEncodeContext *ctx)
for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
uint32_t best_bitcount = UINT32_MAX;
- cur_bo = ctx->b[index].best_offset[channel];
+ cur_bo = s->b[index].best_offset[channel];
for (unsigned int codebook = 0; codebook < NUM_CODEBOOKS; codebook++) {
uint32_t prev_best_bitcount = UINT32_MAX;
@@ -1919,7 +1968,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;
@@ -1946,11 +1995,11 @@ static void set_best_codebook(MLPEncodeContext *ctx)
/* Update context. */
for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) {
- ChannelParams *cp = &ctx->b[index].channel_params[channel];
- DecodingParams *dp = &ctx->b[index].decoding_params;
+ ChannelParams *cp = &s->b[index].channel_params[channel];
+ DecodingParams *dp = &s->b[index].decoding_params;
best_codebook = *best_path++;
- cur_bo = &ctx->b[index].best_offset[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];
@@ -1963,85 +2012,83 @@ 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;
- int channels = ctx->avctx->ch_layout.nb_channels;
+ RestartHeader *rh = s->cur_restart_header;
uint8_t max_huff_lsbs = 0, max_output_bits = 0;
- for (unsigned int index = 0; index < ctx->b[ctx->restart_intervals-1].seq_size; index++) {
- memcpy(&ctx->b[index].major_decoding_params,
- &ctx->b[index].decoding_params, sizeof(DecodingParams));
- for (unsigned int channel = 0; channel < channels; channel++) {
- uint8_t huff_lsbs = ctx->b[index].channel_params[channel].huff_lsbs;
+ 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 = rh->min_channel; ch <= rh->max_channel; ch++) {
+ uint8_t huff_lsbs = s->b[index].channel_params[ch].huff_lsbs;
if (max_huff_lsbs < huff_lsbs)
max_huff_lsbs = huff_lsbs;
- memcpy(&ctx->b[index].major_channel_params[channel],
- &ctx->b[index].channel_params[channel],
+ memcpy(&s->b[index].major_channel_params[ch],
+ &s->b[index].channel_params[ch],
sizeof(ChannelParams));
}
}
rh->max_huff_lsbs = max_huff_lsbs;
- for (unsigned int index = 0; index < ctx->number_of_frames; index++)
- if (max_output_bits < ctx->b[index].max_output_bits)
- max_output_bits = ctx->b[index].max_output_bits;
+ 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;
+ s->cur_restart_header = &s->restart_header;
- for (unsigned int index = 0; index <= ctx->cur_restart_interval; index++)
- ctx->b[index].major_params_changed = compare_decoding_params(ctx, index);
+ for (int index = 0; index <= ctx->cur_restart_interval; index++)
+ s->b[index].major_params_changed = compare_decoding_params(ctx, s, index);
- 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)
{
- ctx->cur_restart_header = &ctx->restart_header;
+ 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 = &ctx->b[index+1].decoding_params;
+ 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.
*/
- ctx->b[0].decoding_params.blocksize = 8;
- ctx->b[1].decoding_params.blocksize -= 8;
+ s->b[0].decoding_params.blocksize = 8;
+ s->b[1].decoding_params.blocksize -= 8;
- input_to_sample_buffer (ctx);
- generate_2_noise_channels(ctx);
- lossless_matrix_coeffs (ctx);
- rematrix_channels (ctx);
- determine_quant_step_size(ctx);
- determine_filters (ctx);
- apply_filters (ctx);
+ input_to_sample_buffer (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);
- copy_restart_frame_params(ctx);
+ copy_restart_frame_params(ctx, s);
- determine_bits(ctx);
+ determine_bits(ctx, s);
- set_best_codebook(ctx);
+ set_best_codebook(ctx, s);
}
-static void process_major_frame(MLPEncodeContext *ctx)
+static void process_major_frame(MLPEncodeContext *ctx, MLPSubstream *s)
{
ctx->number_of_frames = ctx->major_number_of_frames;
- ctx->cur_restart_header = &ctx->restart_header;
+ s->cur_restart_header = &s->restart_header;
- generate_2_noise_channels(ctx);
- rematrix_channels (ctx);
+ generate_2_noise_channels(ctx, s);
+ rematrix_channels (ctx, s);
- apply_filters(ctx);
+ apply_filters(ctx, s);
}
/****************************************************************************/
@@ -2083,9 +2130,11 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
if (restart_frame) {
avpkt->flags |= AV_PKT_FLAG_KEY;
- set_major_params(ctx);
+ for (int n = 0; n < ctx->num_substreams; n++)
+ set_major_params(ctx, &ctx->s[n]);
+
if (ctx->min_restart_interval != ctx->cur_restart_interval)
- process_major_frame(ctx);
+ process_major_frame(ctx, &ctx->s[0]);
}
bytes_written = write_access_unit(ctx, avpkt->data, avpkt->size, restart_frame);
@@ -2101,7 +2150,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;
@@ -2114,13 +2164,19 @@ input_and_return:
number_of_samples = avctx->frame_size * ctx->number_of_frames;
- for (unsigned int index = 0; index < ctx->b[seq_index].seq_size; index++) {
- clear_channel_params(ctx->b[index].channel_params, channels);
- default_decoding_params(ctx, &ctx->b[index].decoding_params);
+ for (int n = 0; n < ctx->num_substreams; n++) {
+ MLPSubstream *s = &ctx->s[n];
+
+ 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);
+ }
}
- if (number_of_samples > 0)
- 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->cur_restart_interval - 1)) {
@@ -2197,7 +2253,7 @@ const FFCodec ff_mlp_encoder = {
FF_CODEC_ENCODE_CB(mlp_encode_frame),
.close = mlp_encode_close,
.p.priv_class = &mlp_class,
- .p.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
+ .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},
CODEC_OLD_CHANNEL_LAYOUTS_ARRAY(ff_mlp_channel_layouts)
.p.ch_layouts = ff_mlp_ch_layouts,
@@ -2218,12 +2274,13 @@ const FFCodec ff_truehd_encoder = {
FF_CODEC_ENCODE_CB(mlp_encode_frame),
.close = mlp_encode_close,
.p.priv_class = &mlp_class,
- .p.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
+ .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},
- CODEC_OLD_CHANNEL_LAYOUTS(AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1)
+ CODEC_OLD_CHANNEL_LAYOUTS(AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1)
.p.ch_layouts = (const AVChannelLayout[]) {
AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
AV_CHANNEL_LAYOUT_5POINT0,
AV_CHANNEL_LAYOUT_5POINT1,
{ 0 }