diff options
Diffstat (limited to 'libavcodec/dca.c')
-rw-r--r-- | libavcodec/dca.c | 227 |
1 files changed, 202 insertions, 25 deletions
diff --git a/libavcodec/dca.c b/libavcodec/dca.c index 103f058..f40440c 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -5,20 +5,20 @@ * Copyright (C) 2006 Benjamin Larsson * Copyright (C) 2007 Konstantin Shishkov * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -51,12 +51,14 @@ //#define TRACE #define DCA_PRIM_CHANNELS_MAX (7) -#define DCA_SUBBANDS (32) +#define DCA_SUBBANDS (64) #define DCA_ABITS_MAX (32) /* Should be 28 */ #define DCA_SUBSUBFRAMES_MAX (4) #define DCA_SUBFRAMES_MAX (16) #define DCA_BLOCKS_MAX (16) #define DCA_LFE_MAX (3) +#define DCA_CHSETS_MAX (4) +#define DCA_CHSET_CHANS_MAX (8) enum DCAMode { DCA_MONO = 0, @@ -315,7 +317,6 @@ typedef struct { /* Primary audio coding header */ int subframes; ///< number of subframes - int is_channels_set; ///< check for if the channel number is already set int total_channels; ///< number of channels including extensions int prim_channels; ///< number of primary audio channels int subband_activity[DCA_PRIM_CHANNELS_MAX]; ///< subband activity count @@ -806,7 +807,7 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) "Invalid channel mode %d\n", am); return AVERROR_INVALIDDATA; } - for (j = base_channel; j < s->prim_channels; j++) { + for (j = base_channel; j < FFMIN(s->prim_channels, FF_ARRAY_ELEMS(dca_default_coeffs[am])); j++) { s->downmix_coef[j][0] = dca_default_coeffs[am][j][0]; s->downmix_coef[j][1] = dca_default_coeffs[am][j][1]; } @@ -834,6 +835,7 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) /* Low frequency effect data */ if (!base_channel && s->lfe) { + int quant7; /* LFE samples */ int lfe_samples = 2 * s->lfe * (4 + block_index); int lfe_end_sample = 2 * s->lfe * (4 + block_index + s->subsubframes[s->current_subframe]); @@ -845,8 +847,12 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) } /* Scale factor index */ - skip_bits(&s->gb, 1); - s->lfe_scale_factor = scale_factor_quant7[get_bits(&s->gb, 7)]; + quant7 = get_bits(&s->gb, 8); + if (quant7 > 127) { + av_log_ask_for_sample(s->avctx, "LFEScaleIndex larger than 127\n"); + return AVERROR_INVALIDDATA; + } + s->lfe_scale_factor = scale_factor_quant7[quant7]; /* Quantization step size * scale factor */ lfe_scale = 0.035 * s->lfe_scale_factor; @@ -1416,11 +1422,11 @@ static int dca_exss_parse_asset_header(DCAContext *s) { int header_pos = get_bits_count(&s->gb); int header_size; - int channels; + int channels = 0; int embedded_stereo = 0; int embedded_6ch = 0; int drc_code_present; - int extensions_mask; + int av_uninit(extensions_mask); int i, j; if (get_bits_left(&s->gb) < 16) @@ -1560,6 +1566,166 @@ static int dca_exss_parse_asset_header(DCAContext *s) return 0; } +static int dca_xbr_parse_frame(DCAContext *s) +{ + int scale_table_high[DCA_CHSET_CHANS_MAX][DCA_SUBBANDS][2]; + int active_bands[DCA_CHSETS_MAX][DCA_CHSET_CHANS_MAX]; + int abits_high[DCA_CHSET_CHANS_MAX][DCA_SUBBANDS]; + int anctemp[DCA_CHSET_CHANS_MAX]; + int chset_fsize[DCA_CHSETS_MAX]; + int n_xbr_ch[DCA_CHSETS_MAX]; + int hdr_size, num_chsets, xbr_tmode, hdr_pos; + int i, j, k, l, chset, chan_base; + + av_log(s->avctx, AV_LOG_DEBUG, "DTS-XBR: decoding XBR extension\n"); + + /* get bit position of sync header */ + hdr_pos = get_bits_count(&s->gb) - 32; + + hdr_size = get_bits(&s->gb, 6) + 1; + num_chsets = get_bits(&s->gb, 2) + 1; + + for(i = 0; i < num_chsets; i++) + chset_fsize[i] = get_bits(&s->gb, 14) + 1; + + xbr_tmode = get_bits1(&s->gb); + + for(i = 0; i < num_chsets; i++) { + n_xbr_ch[i] = get_bits(&s->gb, 3) + 1; + k = get_bits(&s->gb, 2) + 5; + for(j = 0; j < n_xbr_ch[i]; j++) + active_bands[i][j] = get_bits(&s->gb, k) + 1; + } + + /* skip to the end of the header */ + i = get_bits_count(&s->gb); + if(hdr_pos + hdr_size * 8 > i) + skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i); + + /* loop over the channel data sets */ + /* only decode as many channels as we've decoded base data for */ + for(chset = 0, chan_base = 0; + chset < num_chsets && chan_base + n_xbr_ch[chset] <= s->prim_channels; + chan_base += n_xbr_ch[chset++]) { + int start_posn = get_bits_count(&s->gb); + int subsubframe = 0; + int subframe = 0; + + /* loop over subframes */ + for (k = 0; k < (s->sample_blocks / 8); k++) { + /* parse header if we're on first subsubframe of a block */ + if(subsubframe == 0) { + /* Parse subframe header */ + for(i = 0; i < n_xbr_ch[chset]; i++) { + anctemp[i] = get_bits(&s->gb, 2) + 2; + } + + for(i = 0; i < n_xbr_ch[chset]; i++) { + get_array(&s->gb, abits_high[i], active_bands[chset][i], anctemp[i]); + } + + for(i = 0; i < n_xbr_ch[chset]; i++) { + anctemp[i] = get_bits(&s->gb, 3); + if(anctemp[i] < 1) { + av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: SYNC ERROR\n"); + return AVERROR_INVALIDDATA; + } + } + + /* generate scale factors */ + for(i = 0; i < n_xbr_ch[chset]; i++) { + const uint32_t *scale_table; + int nbits; + + if (s->scalefactor_huffman[chan_base+i] == 6) { + scale_table = scale_factor_quant7; + } else { + scale_table = scale_factor_quant6; + } + + nbits = anctemp[i]; + + for(j = 0; j < active_bands[chset][i]; j++) { + if(abits_high[i][j] > 0) { + scale_table_high[i][j][0] = + scale_table[get_bits(&s->gb, nbits)]; + + if(xbr_tmode && s->transition_mode[i][j]) { + scale_table_high[i][j][1] = + scale_table[get_bits(&s->gb, nbits)]; + } + } + } + } + } + + /* decode audio array for this block */ + for(i = 0; i < n_xbr_ch[chset]; i++) { + for(j = 0; j < active_bands[chset][i]; j++) { + const int xbr_abits = abits_high[i][j]; + const float quant_step_size = lossless_quant_d[xbr_abits]; + const int sfi = xbr_tmode && s->transition_mode[i][j] && subsubframe >= s->transition_mode[i][j]; + const float rscale = quant_step_size * scale_table_high[i][j][sfi]; + float *subband_samples = s->subband_samples[k][chan_base+i][j]; + int block[8]; + + if(xbr_abits <= 0) + continue; + + if(xbr_abits > 7) { + get_array(&s->gb, block, 8, xbr_abits - 3); + } else { + int block_code1, block_code2, size, levels, err; + + size = abits_sizes[xbr_abits - 1]; + levels = abits_levels[xbr_abits - 1]; + + block_code1 = get_bits(&s->gb, size); + block_code2 = get_bits(&s->gb, size); + err = decode_blockcodes(block_code1, block_code2, + levels, block); + if (err) { + av_log(s->avctx, AV_LOG_ERROR, + "ERROR: DTS-XBR: block code look-up failed\n"); + return AVERROR_INVALIDDATA; + } + } + + /* scale & sum into subband */ + for(l = 0; l < 8; l++) + subband_samples[l] += (float)block[l] * rscale; + } + } + + /* check DSYNC marker */ + if(s->aspf || subsubframe == s->subsubframes[subframe] - 1) { + if(get_bits(&s->gb, 16) != 0xffff) { + av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: Didn't get subframe DSYNC\n"); + return AVERROR_INVALIDDATA; + } + } + + /* advance sub-sub-frame index */ + if(++subsubframe >= s->subsubframes[subframe]) { + subsubframe = 0; + subframe++; + } + } + + /* skip to next channel set */ + i = get_bits_count(&s->gb); + if(start_posn + chset_fsize[chset] * 8 != i) { + j = start_posn + chset_fsize[chset] * 8 - i; + if(j < 0 || j >= 8) + av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: end of channel set," + " skipping further than expected (%d bits)\n", j); + skip_bits_long(&s->gb, j); + } + } + + return 0; +} + /** * Parse extension substream header (HD) */ @@ -1571,15 +1737,20 @@ static void dca_exss_parse_header(DCAContext *s) int num_assets = 1; int active_ss_mask[8]; int i, j; + int start_posn; + int hdrsize; + uint32_t mkr; if (get_bits_left(&s->gb) < 52) return; + start_posn = get_bits_count(&s->gb) - 32; + skip_bits(&s->gb, 8); // user data ss_index = get_bits(&s->gb, 2); blownup = get_bits1(&s->gb); - skip_bits(&s->gb, 8 + 4 * blownup); // header_size + hdrsize = get_bits(&s->gb, 8 + 4 * blownup) + 1; // header_size skip_bits(&s->gb, 16 + 4 * blownup); // hd_size s->static_fields = get_bits1(&s->gb); @@ -1640,6 +1811,18 @@ static void dca_exss_parse_header(DCAContext *s) /* not parsed further, we were only interested in the extensions mask * from the asset header */ + + if(num_assets > 0) { + j = get_bits_count(&s->gb); + if(start_posn + hdrsize * 8 > j) + skip_bits_long(&s->gb, start_posn + hdrsize * 8 - j); + + /* check first asset for XBR -- should also check extension mask! */ + mkr = get_bits_long(&s->gb, 32); + + if(mkr == 0x655e315e) + dca_xbr_parse_frame(s); + } } /** @@ -1825,25 +2008,19 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, s->output = DCA_STEREO; avctx->channel_layout = AV_CH_LAYOUT_STEREO; } + else if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) { + static const int8_t dca_channel_order_native[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + s->channel_order_tab = dca_channel_order_native; + } } else { av_log(avctx, AV_LOG_ERROR, "Non standard configuration %d !\n", s->amode); return AVERROR_INVALIDDATA; } - - /* There is nothing that prevents a dts frame to change channel configuration - but Libav doesn't support that so only set the channels if it is previously - unset. Ideally during the first probe for channels the crc should be checked - and only set avctx->channels when the crc is ok. Right now the decoder could - set the channels based on a broken first frame.*/ - if (s->is_channels_set == 0) { - s->is_channels_set = 1; - avctx->channels = channels; - } if (avctx->channels != channels) { - av_log(avctx, AV_LOG_ERROR, "DCA decoder does not support number of " - "channels changing in stream. Skipping frame.\n"); - return AVERROR_PATCHWELCOME; + if (avctx->channels) + av_log(avctx, AV_LOG_INFO, "Number of channels changed in DCA decoder (%d -> %d)\n", avctx->channels, channels); + avctx->channels = channels; } /* get output buffer */ |