diff options
author | Paul B Mahol <onemda@gmail.com> | 2023-10-20 16:28:08 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2023-10-20 17:07:25 +0200 |
commit | 79c568dd4e0066bc62c1ae6fbbc70fdb1a088dea (patch) | |
tree | d7493ea1a153bc99d5134fec9bd8a11f924987bc /libavcodec | |
parent | 3f773d8d02ad75414c8572845cc1a55b0c9e0598 (diff) | |
download | ffmpeg-79c568dd4e0066bc62c1ae6fbbc70fdb1a088dea.tar.gz |
avcodec/mlpenc: add proper support for output bit shift
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/mlpenc.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c index 09dc9ac0f9..dcc61bd8c9 100644 --- a/libavcodec/mlpenc.c +++ b/libavcodec/mlpenc.c @@ -54,6 +54,7 @@ typedef struct RestartHeader { 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). @@ -84,7 +85,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. + int8_t output_shift[MAX_CHANNELS]; ///< Left shift to apply to decoded PCM values to get final 24-bit output. MatrixParams matrix_params; @@ -383,11 +384,13 @@ static void copy_restart_frame_params(MLPEncodeContext *ctx, MLPSubstream *s) copy_matrix_params(&dp->matrix_params, &s->b[1].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 (int ch = 0; ch <= rh->max_channel; ch++) { ChannelParams *cp = &s->b[index].channel_params[ch]; 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++) @@ -758,7 +761,7 @@ static void write_restart_header(MLPEncodeContext *ctx, MLPSubstream *s, 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 ); @@ -1253,6 +1256,41 @@ static int number_trailing_zeroes(int32_t sample, unsigned int max, unsigned int return sample ? FFMIN(max, ff_ctz(sample)) : def; } +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; + + 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. */ @@ -2016,14 +2054,21 @@ static void set_major_params(MLPEncodeContext *ctx, MLPSubstream *s) { 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; - if (max_huff_lsbs < huff_lsbs) - max_huff_lsbs = 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)); @@ -2031,6 +2076,7 @@ static void set_major_params(MLPEncodeContext *ctx, MLPSubstream *s) } rh->max_huff_lsbs = max_huff_lsbs; + rh->max_shift = max_shift; for (int index = 0; index < ctx->number_of_frames; index++) if (max_output_bits < s->b[index].max_output_bits) @@ -2065,6 +2111,7 @@ static void analyze_sample_buffer(MLPEncodeContext *ctx, MLPSubstream *s) s->b[1].decoding_params.blocksize -= 8; 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); |