Corrections to channel coupling code to attain conformance for appropriate

streams.

Slightly reworked from a patch by Alex Converse (alex converse gmail com)

Originally committed as revision 15573 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Alex Converse 2008-10-06 16:12:30 +00:00 committed by Robert Swain
parent 69bf69c77e
commit 88de95c2f9
1 changed files with 35 additions and 29 deletions

View File

@ -967,7 +967,7 @@ static int decode_cce(AACContext * ac, GetBitContext * gb, ChannelElement * che)
if (coup->ch_select[c] == 3) if (coup->ch_select[c] == 3)
num_gain++; num_gain++;
} else } else
coup->ch_select[c] = 1; coup->ch_select[c] = 2;
} }
coup->coupling_point += get_bits1(gb); coup->coupling_point += get_bits1(gb);
@ -992,7 +992,7 @@ static int decode_cce(AACContext * ac, GetBitContext * gb, ChannelElement * che)
if (c) { if (c) {
cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb); cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0; gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0;
gain_cache = pow(scale, gain); gain_cache = pow(scale, -gain);
} }
for (g = 0; g < sce->ics.num_window_groups; g++) { for (g = 0; g < sce->ics.num_window_groups; g++) {
for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) { for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) {
@ -1001,12 +1001,12 @@ static int decode_cce(AACContext * ac, GetBitContext * gb, ChannelElement * che)
int t = get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60; int t = get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
if (t) { if (t) {
int s = 1; int s = 1;
t = gain += t;
if (sign) { if (sign) {
s -= 2 * (t & 0x1); s -= 2 * (t & 0x1);
t >>= 1; t >>= 1;
} }
gain += t; gain_cache = pow(scale, -t) * s;
gain_cache = pow(scale, gain) * s;
} }
} }
coup->gain[c][idx] = gain_cache; coup->gain[c][idx] = gain_cache;
@ -1292,25 +1292,30 @@ static void apply_independent_coupling(AACContext * ac, SingleChannelElement * s
* @param apply_coupling_method pointer to (in)dependent coupling function * @param apply_coupling_method pointer to (in)dependent coupling function
*/ */
static void apply_channel_coupling(AACContext * ac, ChannelElement * cc, static void apply_channel_coupling(AACContext * ac, ChannelElement * cc,
enum RawDataBlockType type, int elem_id, enum CouplingPoint coupling_point,
void (*apply_coupling_method)(AACContext * ac, SingleChannelElement * sce, ChannelElement * cc, int index)) void (*apply_coupling_method)(AACContext * ac, SingleChannelElement * sce, ChannelElement * cc, int index))
{ {
int c; int i, c;
int index = 0;
ChannelCoupling * coup = &cc->coup; for (i = 0; i < MAX_ELEM_ID; i++) {
for (c = 0; c <= coup->num_coupled; c++) { ChannelElement *cce = ac->che[TYPE_CCE][i];
if (ac->che[coup->type[c]][coup->id_select[c]]) { int index = 0;
if (coup->ch_select[c] != 2) {
apply_coupling_method(ac, &ac->che[coup->type[c]][coup->id_select[c]]->ch[0], cc, index); if (cce && cce->coup.coupling_point == coupling_point) {
if (coup->ch_select[c] != 0) ChannelCoupling * coup = &cce->coup;
index++;
for (c = 0; c <= coup->num_coupled; c++) {
if (coup->type[c] == type && coup->id_select[c] == elem_id) {
if (coup->ch_select[c] != 1) {
apply_coupling_method(ac, &cc->ch[0], cce, index);
if (coup->ch_select[c] != 0)
index++;
}
if (coup->ch_select[c] != 2)
apply_coupling_method(ac, &cc->ch[1], cce, index++);
} else
index += 1 + (coup->ch_select[c] == 3);
} }
if (coup->ch_select[c] != 1)
apply_coupling_method(ac, &ac->che[coup->type[c]][coup->id_select[c]]->ch[1], cc, index++);
} else {
av_log(ac->avccontext, AV_LOG_ERROR,
"coupling target %sE[%d] not available\n",
coup->type[c] == TYPE_CPE ? "CP" : "SC", coup->id_select[c]);
break;
} }
} }
} }
@ -1320,23 +1325,24 @@ static void apply_channel_coupling(AACContext * ac, ChannelElement * cc,
*/ */
static void spectral_to_sample(AACContext * ac) { static void spectral_to_sample(AACContext * ac) {
int i, type; int i, type;
for (i = 0; i < MAX_ELEM_ID; i++) { for(type = 3; type >= 0; type--) {
for(type = 0; type < 4; type++) { for (i = 0; i < MAX_ELEM_ID; i++) {
ChannelElement *che = ac->che[type][i]; ChannelElement *che = ac->che[type][i];
if(che) { if(che) {
if(che->coup.coupling_point == BEFORE_TNS) if(type <= TYPE_CPE)
apply_channel_coupling(ac, che, apply_dependent_coupling); apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling);
if(che->ch[0].tns.present) if(che->ch[0].tns.present)
apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1); apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
if(che->ch[1].tns.present) if(che->ch[1].tns.present)
apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1); apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
if(che->coup.coupling_point == BETWEEN_TNS_AND_IMDCT) if(type <= TYPE_CPE)
apply_channel_coupling(ac, che, apply_dependent_coupling); apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling);
imdct_and_windowing(ac, &che->ch[0]); if(type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT)
imdct_and_windowing(ac, &che->ch[0]);
if(type == TYPE_CPE) if(type == TYPE_CPE)
imdct_and_windowing(ac, &che->ch[1]); imdct_and_windowing(ac, &che->ch[1]);
if(che->coup.coupling_point == AFTER_IMDCT) if(type <= TYPE_CCE)
apply_channel_coupling(ac, che, apply_independent_coupling); apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, apply_independent_coupling);
} }
} }
} }