summaryrefslogtreecommitdiff
path: root/libavcodec/dcadec.c
diff options
context:
space:
mode:
authorTim Walker <tdskywalker@gmail.com>2013-11-22 23:42:37 +0100
committerAnton Khirnov <anton@khirnov.net>2013-11-28 22:02:53 +0100
commit44b17d794aa508ae21f438ae80bfe8aaf4b426e1 (patch)
tree35b80b9ad5de2f64ca40de51c7677cb07edfecb2 /libavcodec/dcadec.c
parent27245b4e1bbb7a863341db321b5bdc5792e427d9 (diff)
dca: extract core substream's embedded downmix coeffcient codes, if present.
As per ETSI TS 102 114 V1.4.1 specification. Signed-off-by: Anton Khirnov <anton@khirnov.net>
Diffstat (limited to 'libavcodec/dcadec.c')
-rw-r--r--libavcodec/dcadec.c152
1 files changed, 119 insertions, 33 deletions
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index eb229ce98e..cf1da8c09b 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -339,6 +339,13 @@ typedef struct {
float downmix_coef[DCA_PRIM_CHANNELS_MAX][2]; ///< stereo downmix coefficients
int dynrange_coef; ///< dynamic range coefficient
+ /* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1)
+ * Input: primary audio channels (incl. LFE if present)
+ * Output: downmix audio channels (up to 4, no LFE) */
+ uint8_t core_downmix; ///< embedded downmix coefficients available
+ uint8_t core_downmix_amode; ///< audio channel arrangement of embedded downmix
+ uint16_t core_downmix_codes[DCA_PRIM_CHANNELS_MAX + 1][4]; ///< embedded downmix coefficients (9-bit codes)
+
int high_freq_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< VQ encoded high frequency subbands
float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data
@@ -796,25 +803,6 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
}
}
- /* Stereo downmix coefficients */
- if (!base_channel && s->prim_channels > 2) {
- int am = s->amode & DCA_CHANNEL_MASK;
- if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
- av_log(s->avctx, AV_LOG_ERROR,
- "Invalid channel mode %d\n", am);
- return AVERROR_INVALIDDATA;
- }
- if (s->prim_channels > FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
- avpriv_request_sample(s->avctx, "Downmixing %d channels",
- s->prim_channels);
- return AVERROR_PATCHWELCOME;
- }
- for (j = base_channel; j < s->prim_channels; j++) {
- s->downmix_coef[j][0] = dca_default_coeffs[am][j][0];
- s->downmix_coef[j][1] = dca_default_coeffs[am][j][1];
- }
- }
-
/* Dynamic range coefficient */
if (!base_channel && s->dynrange)
s->dynrange_coef = get_bits(&s->gb, 8);
@@ -909,16 +897,6 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
av_log(s->avctx, AV_LOG_DEBUG, "\n");
}
}
- if (!base_channel && s->prim_channels > 2) {
- av_log(s->avctx, AV_LOG_DEBUG, "Downmix coeffs:\n");
- for (j = 0; j < s->prim_channels; j++) {
- av_log(s->avctx, AV_LOG_DEBUG, "Channel 0, %d = %f\n", j,
- s->downmix_coef[j][0]);
- av_log(s->avctx, AV_LOG_DEBUG, "Channel 1, %d = %f\n", j,
- s->downmix_coef[j][1]);
- }
- av_log(s->avctx, AV_LOG_DEBUG, "\n");
- }
for (j = base_channel; j < s->prim_channels; j++)
for (k = s->vq_start_subband[j]; k < s->subband_activity[j]; k++)
av_log(s->avctx, AV_LOG_DEBUG, "VQ index: %i\n", s->high_freq_vq[j][k]);
@@ -1292,7 +1270,7 @@ static int dca_filter_channels(DCAContext *s, int block_index)
static int dca_subframe_footer(DCAContext *s, int base_channel)
{
- int aux_data_count = 0, i;
+ int in, out, aux_data_count, aux_data_end, reserved;
/*
* Unpack optional information
@@ -1303,11 +1281,74 @@ static int dca_subframe_footer(DCAContext *s, int base_channel)
if (s->timestamp)
skip_bits_long(&s->gb, 32);
- if (s->aux_data)
+ if (s->aux_data) {
aux_data_count = get_bits(&s->gb, 6);
- for (i = 0; i < aux_data_count; i++)
- get_bits(&s->gb, 8);
+ // align (32-bit)
+ skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+
+ aux_data_end = 8 * aux_data_count + get_bits_count(&s->gb);
+
+ if (get_bits_long(&s->gb, 32) != 0x9A1105A0) // nSYNCAUX
+ return AVERROR_INVALIDDATA;
+
+ if (get_bits1(&s->gb)) { // bAUXTimeStampFlag
+ avpriv_request_sample(s->avctx,
+ "Auxiliary Decode Time Stamp Flag");
+ // align (4-bit)
+ skip_bits(&s->gb, (-get_bits_count(&s->gb)) & 4);
+ // 44 bits: nMSByte (8), nMarker (4), nLSByte (28), nMarker (4)
+ skip_bits_long(&s->gb, 44);
+ }
+
+ if ((s->core_downmix = get_bits1(&s->gb))) {
+ switch (get_bits(&s->gb, 3)) {
+ case 0:
+ s->core_downmix_amode = DCA_MONO;
+ break;
+ case 1:
+ s->core_downmix_amode = DCA_STEREO;
+ break;
+ case 2:
+ s->core_downmix_amode = DCA_STEREO_TOTAL;
+ break;
+ case 3:
+ s->core_downmix_amode = DCA_3F;
+ break;
+ case 4:
+ s->core_downmix_amode = DCA_2F1R;
+ break;
+ case 5:
+ s->core_downmix_amode = DCA_2F2R;
+ break;
+ case 6:
+ s->core_downmix_amode = DCA_3F1R;
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+ for (out = 0; out < dca_channels[s->core_downmix_amode]; out++) {
+ for (in = 0; in < s->prim_channels + !!s->lfe; in++) {
+ uint16_t tmp = get_bits(&s->gb, 9);
+ if ((tmp & 0xFF) > 241)
+ return AVERROR_INVALIDDATA;
+ s->core_downmix_codes[in][out] = tmp;
+ }
+ }
+ }
+
+ align_get_bits(&s->gb); // byte align
+ skip_bits(&s->gb, 16); // nAUXCRC16
+
+ // additional data (reserved, cf. ETSI TS 102 114 V1.4.1)
+ if ((reserved = (aux_data_end - get_bits_count(&s->gb))) < 0)
+ return AVERROR_INVALIDDATA;
+ else if (reserved) {
+ avpriv_request_sample(s->avctx,
+ "Core auxiliary data reserved content");
+ skip_bits_long(&s->gb, reserved);
+ }
+ }
if (s->crc_present && s->dynrange)
get_bits(&s->gb, 16);
@@ -1822,6 +1863,51 @@ FF_ENABLE_DEPRECATION_WARNINGS
channels = 2;
s->output = DCA_STEREO;
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+
+ /* Stereo downmix coefficients
+ *
+ * The decoder can only downmix to 2-channel, so we need to ensure
+ * embedded downmix coefficients are actually targeting 2-channel.
+ *
+ * Coefficients for the LFE channel are ignored (not supported) */
+ if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
+ s->core_downmix_amode == DCA_STEREO_TOTAL)) {
+ int sign, code;
+ for (i = 0; i < s->prim_channels; i++) {
+ sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
+ code = s->core_downmix_codes[i][0] & 0x0FF;
+ s->downmix_coef[i][0] = (!code ? 0.0f :
+ sign * dca_dmixtable[code - 1]);
+ sign = s->core_downmix_codes[i][1] & 0x100 ? 1 : -1;
+ code = s->core_downmix_codes[i][1] & 0x0FF;
+ s->downmix_coef[i][1] = (!code ? 0.0f :
+ sign * dca_dmixtable[code - 1]);
+ }
+ } else {
+ int am = s->amode & DCA_CHANNEL_MASK;
+ if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "Invalid channel mode %d\n", am);
+ return AVERROR_INVALIDDATA;
+ }
+ if (s->prim_channels > FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
+ avpriv_request_sample(s->avctx, "Downmixing %d channels",
+ s->prim_channels);
+ return AVERROR_PATCHWELCOME;
+ }
+ for (i = 0; i < s->prim_channels; i++) {
+ s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
+ s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
+ }
+ }
+ av_dlog(s->avctx, "Stereo downmix coeffs:\n");
+ for (i = 0; i < s->prim_channels; i++) {
+ av_dlog(s->avctx, "L, input channel %d = %f\n", i,
+ s->downmix_coef[i][0]);
+ av_dlog(s->avctx, "R, input channel %d = %f\n", i,
+ s->downmix_coef[i][1]);
+ }
+ av_dlog(s->avctx, "\n");
}
} else {
av_log(avctx, AV_LOG_ERROR, "Non standard configuration %d !\n", s->amode);