X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmlpdec.c;h=8cfeea617564115eb03e2f98f07a136ed81b3586;hb=5f74bd31a9bd1ac7655103b11743c12d38e0419f;hp=c0174b49b67f6f36eabbd0ea4d85a68103670b31;hpb=ed1b01131e662c9086b27aaaea69684d8575fbea;p=ffmpeg diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index c0174b49b67..8cfeea61756 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -27,6 +27,7 @@ #include #include "avcodec.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/channel_layout.h" #include "get_bits.h" @@ -36,9 +37,16 @@ #include "mlp_parser.h" #include "mlpdsp.h" #include "mlp.h" +#include "config.h" /** number of bits used for VLC lookup - longest Huffman code is 9 */ +#if ARCH_ARM +#define VLC_BITS 5 +#define VLC_STATIC_SIZE 64 +#else #define VLC_BITS 9 +#define VLC_STATIC_SIZE 512 +#endif typedef struct SubStream { /// Set if a valid restart header has been read. Otherwise the substream cannot be decoded. @@ -59,6 +67,8 @@ typedef struct SubStream { uint8_t ch_assign[MAX_CHANNELS]; /// The channel layout for this substream uint64_t ch_layout; + /// The matrix encoding mode for this substream + enum AVMatrixEncoding matrix_encoding; /// Channel coding parameters for channels in the substream ChannelParams channel_params[MAX_CHANNELS]; @@ -118,11 +128,13 @@ typedef struct SubStream { typedef struct MLPDecodeContext { AVCodecContext *avctx; - AVFrame frame; /// Current access unit being read has a major sync. int is_major_sync_unit; + /// Size of the major sync unit, in bytes + int major_sync_header_size; + /// Set if a valid major sync block has been read. Otherwise no decoding is possible. uint8_t params_valid; @@ -188,13 +200,13 @@ static av_cold void init_static(void) if (!huff_vlc[0].bits) { INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18, &ff_mlp_huffman_tables[0][0][1], 2, 1, - &ff_mlp_huffman_tables[0][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[0][0][0], 2, 1, VLC_STATIC_SIZE); INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16, &ff_mlp_huffman_tables[1][0][1], 2, 1, - &ff_mlp_huffman_tables[1][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[1][0][0], 2, 1, VLC_STATIC_SIZE); INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15, &ff_mlp_huffman_tables[2][0][1], 2, 1, - &ff_mlp_huffman_tables[2][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[2][0][0], 2, 1, VLC_STATIC_SIZE); } ff_mlp_init_crc(); @@ -268,9 +280,6 @@ static av_cold int mlp_decode_init(AVCodecContext *avctx) m->substream[substr].lossless_check_data = 0xffffffff; ff_mlpdsp_init(&m->dsp); - avcodec_get_frame_defaults(&m->frame); - avctx->coded_frame = &m->frame; - return 0; } @@ -333,17 +342,22 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) return AVERROR_INVALIDDATA; } if (mh.num_substreams > MAX_SUBSTREAMS) { - av_log_ask_for_sample(m->avctx, - "Number of substreams %d is larger than the maximum supported " - "by the decoder.\n", mh.num_substreams); + avpriv_request_sample(m->avctx, + "%d substreams (more than the " + "maximum supported by the decoder)", + mh.num_substreams); return AVERROR_PATCHWELCOME; } + m->major_sync_header_size = mh.header_size; + m->access_unit_size = mh.access_unit_size; m->access_unit_size_pow2 = mh.access_unit_size_pow2; m->num_substreams = mh.num_substreams; - m->max_decoded_substream = m->num_substreams - 1; + + /* limit to decoding 3 substreams, as the 4th is used by Dolby Atmos for non-audio data */ + m->max_decoded_substream = FFMIN(m->num_substreams - 1, 2); m->avctx->sample_rate = mh.group1_samplerate; m->avctx->frame_size = mh.access_unit_size; @@ -353,6 +367,10 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->avctx->sample_fmt = AV_SAMPLE_FMT_S32; else m->avctx->sample_fmt = AV_SAMPLE_FMT_S16; + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(m->substream[m->max_decoded_substream].ch_assign, + m->substream[m->max_decoded_substream].output_shift, + m->substream[m->max_decoded_substream].max_matrix_channel, + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); m->params_valid = 1; for (substr = 0; substr < MAX_SUBSTREAMS; substr++) @@ -376,6 +394,46 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->substream[substr].ch_layout = mh.channel_layout_thd_stream1; } + /* Parse the TrueHD decoder channel modifiers and set each substream's + * AVMatrixEncoding accordingly. + * + * The meaning of the modifiers depends on the channel layout: + * + * - THD_CH_MODIFIER_LTRT, THD_CH_MODIFIER_LBINRBIN only apply to 2-channel + * + * - THD_CH_MODIFIER_MONO applies to 1-channel or 2-channel (dual mono) + * + * - THD_CH_MODIFIER_SURROUNDEX, THD_CH_MODIFIER_NOTSURROUNDEX only apply to + * layouts with an Ls/Rs channel pair + */ + for (substr = 0; substr < MAX_SUBSTREAMS; substr++) + m->substream[substr].matrix_encoding = AV_MATRIX_ENCODING_NONE; + if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD) { + if (mh.num_substreams > 2 && + mh.channel_layout_thd_stream2 & AV_CH_SIDE_LEFT && + mh.channel_layout_thd_stream2 & AV_CH_SIDE_RIGHT && + mh.channel_modifier_thd_stream2 == THD_CH_MODIFIER_SURROUNDEX) + m->substream[2].matrix_encoding = AV_MATRIX_ENCODING_DOLBYEX; + + if (mh.num_substreams > 1 && + mh.channel_layout_thd_stream1 & AV_CH_SIDE_LEFT && + mh.channel_layout_thd_stream1 & AV_CH_SIDE_RIGHT && + mh.channel_modifier_thd_stream1 == THD_CH_MODIFIER_SURROUNDEX) + m->substream[1].matrix_encoding = AV_MATRIX_ENCODING_DOLBYEX; + + if (mh.num_substreams > 0) + switch (mh.channel_modifier_thd_stream0) { + case THD_CH_MODIFIER_LTRT: + m->substream[0].matrix_encoding = AV_MATRIX_ENCODING_DOLBY; + break; + case THD_CH_MODIFIER_LBINRBIN: + m->substream[0].matrix_encoding = AV_MATRIX_ENCODING_DOLBYHEADPHONE; + break; + default: + break; + } + } + return 0; } @@ -392,9 +450,10 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, uint8_t checksum; uint8_t lossless_check; int start_count = get_bits_count(gbp); - const int max_matrix_channel = m->avctx->codec_id == AV_CODEC_ID_MLP - ? MAX_MATRIX_CHANNEL_MLP - : MAX_MATRIX_CHANNEL_TRUEHD; + int min_channel, max_channel, max_matrix_channel; + const int std_max_matrix_channel = m->avctx->codec_id == AV_CODEC_ID_MLP + ? MAX_MATRIX_CHANNEL_MLP + : MAX_MATRIX_CHANNEL_TRUEHD; sync_word = get_bits(gbp, 13); @@ -413,18 +472,18 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, skip_bits(gbp, 16); /* Output timestamp */ - s->min_channel = get_bits(gbp, 4); - s->max_channel = get_bits(gbp, 4); - s->max_matrix_channel = get_bits(gbp, 4); + min_channel = get_bits(gbp, 4); + max_channel = get_bits(gbp, 4); + max_matrix_channel = get_bits(gbp, 4); - if (s->max_matrix_channel > max_matrix_channel) { + if (max_matrix_channel > std_max_matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max matrix channel cannot be greater than %d.\n", max_matrix_channel); return AVERROR_INVALIDDATA; } - if (s->max_channel != s->max_matrix_channel) { + if (max_channel != max_matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max channel must be equal max matrix channel.\n"); return AVERROR_INVALIDDATA; @@ -433,31 +492,25 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, /* This should happen for TrueHD streams with >6 channels and MLP's noise * type. It is not yet known if this is allowed. */ if (s->max_channel > MAX_MATRIX_CHANNEL_MLP && !s->noise_type) { - av_log_ask_for_sample(m->avctx, - "Number of channels %d is larger than the maximum supported " - "by the decoder.\n", s->max_channel + 2); + avpriv_request_sample(m->avctx, + "%d channels (more than the " + "maximum supported by the decoder)", + s->max_channel + 2); return AVERROR_PATCHWELCOME; } - if (s->min_channel > s->max_channel) { + if (min_channel > max_channel) { av_log(m->avctx, AV_LOG_ERROR, "Substream min channel cannot be greater than max channel.\n"); return AVERROR_INVALIDDATA; } -#if FF_API_REQUEST_CHANNELS - if (m->avctx->request_channels > 0 && - m->avctx->request_channels <= s->max_channel + 1 && - m->max_decoded_substream > substr) { - av_log(m->avctx, AV_LOG_DEBUG, - "Extracting %d-channel downmix from substream %d. " - "Further substreams will be skipped.\n", - s->max_channel + 1, substr); - m->max_decoded_substream = substr; - } else -#endif - if (m->avctx->request_channel_layout == s->ch_layout && - m->max_decoded_substream > substr) { + s->min_channel = min_channel; + s->max_channel = max_channel; + s->max_matrix_channel = max_matrix_channel; + + if (m->avctx->request_channel_layout && (s->ch_layout & m->avctx->request_channel_layout) == + m->avctx->request_channel_layout && m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, "Extracting %d-channel downmix (0x%"PRIx64") from substream %d. " "Further substreams will be skipped.\n", @@ -493,10 +546,10 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, ch_assign = av_get_channel_layout_channel_index(s->ch_layout, channel); } - if (ch_assign > s->max_matrix_channel) { - av_log_ask_for_sample(m->avctx, - "Assignment of matrix channel %d to invalid output channel %d.\n", - ch, ch_assign); + if (ch_assign < 0 || ch_assign > s->max_matrix_channel) { + avpriv_request_sample(m->avctx, + "Assignment of matrix channel %d to invalid output channel %d", + ch, ch_assign); return AVERROR_PATCHWELCOME; } s->ch_assign[ch_assign] = ch; @@ -525,7 +578,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, /* Default audio coding is 24-bit raw PCM. */ cp->huff_offset = 0; - cp->sign_huff_offset = (-1) << 23; + cp->sign_huff_offset = -(1 << 23); cp->codebook = 0; cp->huff_lsbs = 24; } @@ -533,6 +586,10 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, if (substr == m->max_decoded_substream) { m->avctx->channels = s->max_matrix_channel + 1; m->avctx->channel_layout = s->ch_layout; + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, + s->output_shift, + s->max_matrix_channel, + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); } return 0; @@ -763,9 +820,15 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, return ret; if (s->param_presence_flags & PARAM_OUTSHIFT) - if (get_bits1(gbp)) + if (get_bits1(gbp)) { for (ch = 0; ch <= s->max_matrix_channel; ch++) s->output_shift[ch] = get_sbits(gbp, 4); + if (substr == m->max_decoded_substream) + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, + s->output_shift, + s->max_matrix_channel, + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); + } if (s->param_presence_flags & PARAM_QUANTSTEP) if (get_bits1(gbp)) @@ -827,8 +890,8 @@ static int read_block_data(MLPDecodeContext *m, GetBitContext *gbp, if (s->data_check_present) { expected_stream_pos = get_bits_count(gbp); expected_stream_pos += get_bits(gbp, 16); - av_log_ask_for_sample(m->avctx, "This file contains some features " - "we have not tested yet.\n"); + avpriv_request_sample(m->avctx, + "Substreams with VLC block size check info"); } if (s->blockpos + s->blocksize > m->access_unit_size) { @@ -930,7 +993,7 @@ static void fill_noise_buffer(MLPDecodeContext *m, unsigned int substr) static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) { SubStream *s = &m->substream[substr]; - unsigned int mat, src_ch, i; + unsigned int mat; unsigned int maxchan; maxchan = s->max_matrix_channel; @@ -942,44 +1005,28 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) } for (mat = 0; mat < s->num_primitive_matrices; mat++) { - int matrix_noise_shift = s->matrix_noise_shift[mat]; unsigned int dest_ch = s->matrix_out_ch[mat]; - int32_t mask = MSB_MASK(s->quant_step_size[dest_ch]); - int32_t *coeffs = s->matrix_coeff[mat]; - int index = s->num_primitive_matrices - mat; - int index2 = 2 * index + 1; - - /* TODO: DSPContext? */ - - for (i = 0; i < s->blockpos; i++) { - int32_t bypassed_lsb = m->bypassed_lsbs[i][mat]; - int32_t *samples = m->sample_buffer[i]; - int64_t accum = 0; - - for (src_ch = 0; src_ch <= maxchan; src_ch++) - accum += (int64_t) samples[src_ch] * coeffs[src_ch]; - - if (matrix_noise_shift) { - index &= m->access_unit_size_pow2 - 1; - accum += m->noise_buffer[index] << (matrix_noise_shift + 7); - index += index2; - } - - samples[dest_ch] = ((accum >> 14) & mask) + bypassed_lsb; - } + m->dsp.mlp_rematrix_channel(&m->sample_buffer[0][0], + s->matrix_coeff[mat], + &m->bypassed_lsbs[0][mat], + m->noise_buffer, + s->num_primitive_matrices - mat, + dest_ch, + s->blockpos, + maxchan, + s->matrix_noise_shift[mat], + m->access_unit_size_pow2, + MSB_MASK(s->quant_step_size[dest_ch])); } } /** Write the audio data into the output buffer. */ static int output_data(MLPDecodeContext *m, unsigned int substr, - void *data, int *got_frame_ptr) + AVFrame *frame, int *got_frame_ptr) { AVCodecContext *avctx = m->avctx; SubStream *s = &m->substream[substr]; - unsigned int i, out_ch = 0; - int32_t *data_32; - int16_t *data_16; int ret; int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); @@ -988,28 +1035,31 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, return AVERROR_INVALIDDATA; } + if (!s->blockpos) { + av_log(avctx, AV_LOG_ERROR, "No samples to output.\n"); + return AVERROR_INVALIDDATA; + } + /* get output buffer */ - m->frame.nb_samples = s->blockpos; - if ((ret = ff_get_buffer(avctx, &m->frame)) < 0) { + frame->nb_samples = s->blockpos; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } - data_32 = (int32_t *)m->frame.data[0]; - data_16 = (int16_t *)m->frame.data[0]; - - for (i = 0; i < s->blockpos; i++) { - for (out_ch = 0; out_ch <= s->max_matrix_channel; out_ch++) { - int mat_ch = s->ch_assign[out_ch]; - int32_t sample = m->sample_buffer[i][mat_ch] - << s->output_shift[mat_ch]; - s->lossless_check_data ^= (sample & 0xffffff) << mat_ch; - if (is32) *data_32++ = sample << 8; - else *data_16++ = sample >> 8; - } - } + s->lossless_check_data = m->dsp.mlp_pack_output(s->lossless_check_data, + s->blockpos, + m->sample_buffer, + frame->data[0], + s->ch_assign, + s->output_shift, + s->max_matrix_channel, + is32); + + /* Update matrix encoding side data */ + if ((ret = ff_side_data_update_matrix_encoding(frame, s->matrix_encoding)) < 0) + return ret; - *got_frame_ptr = 1; - *(AVFrame *)data = m->frame; + *got_frame_ptr = 1; return 0; } @@ -1049,7 +1099,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data, if (read_major_sync(m, &gb) < 0) goto error; m->is_major_sync_unit = 1; - header_size += 28; + header_size += m->major_sync_header_size; } if (!m->params_valid) { @@ -1216,24 +1266,24 @@ error: AVCodec ff_mlp_decoder = { .name = "mlp", + .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_MLP, .priv_data_size = sizeof(MLPDecodeContext), .init = mlp_decode_init, .decode = read_access_unit, - .capabilities = CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), + .capabilities = AV_CODEC_CAP_DR1, }; #if CONFIG_TRUEHD_DECODER AVCodec ff_truehd_decoder = { .name = "truehd", + .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_TRUEHD, .priv_data_size = sizeof(MLPDecodeContext), .init = mlp_decode_init, .decode = read_access_unit, - .capabilities = CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), + .capabilities = AV_CODEC_CAP_DR1, }; #endif /* CONFIG_TRUEHD_DECODER */