Corrections to channel coupling code to attain conformance for appropriate
authorAlex Converse <alex.converse@gmail.com>
Mon, 6 Oct 2008 16:12:30 +0000 (16:12 +0000)
committerRobert Swain <robert.swain@gmail.com>
Mon, 6 Oct 2008 16:12:30 +0000 (16:12 +0000)
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

libavcodec/aac.c

index eca6a9a..dbf39b4 100644 (file)
@@ -967,7 +967,7 @@ static int decode_cce(AACContext * ac, GetBitContext * gb, ChannelElement * che)
             if (coup->ch_select[c] == 3)
                 num_gain++;
         } else
-            coup->ch_select[c] = 1;
+            coup->ch_select[c] = 2;
     }
     coup->coupling_point += get_bits1(gb);
 
@@ -992,7 +992,7 @@ static int decode_cce(AACContext * ac, GetBitContext * gb, ChannelElement * che)
         if (c) {
             cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
             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 (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;
                         if (t) {
                             int s = 1;
+                            t = gain += t;
                             if (sign) {
                                 s  -= 2 * (t & 0x1);
                                 t >>= 1;
                             }
-                            gain += t;
-                            gain_cache = pow(scale, gain) * s;
+                            gain_cache = pow(scale, -t) * s;
                         }
                     }
                     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
  */
 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))
 {
-    int c;
-    int index = 0;
-    ChannelCoupling * coup = &cc->coup;
-    for (c = 0; c <= coup->num_coupled; c++) {
-        if (ac->che[coup->type[c]][coup->id_select[c]]) {
-            if (coup->ch_select[c] != 2) {
-                apply_coupling_method(ac, &ac->che[coup->type[c]][coup->id_select[c]]->ch[0], cc, index);
-                if (coup->ch_select[c] != 0)
-                    index++;
+    int i, c;
+
+    for (i = 0; i < MAX_ELEM_ID; i++) {
+        ChannelElement *cce = ac->che[TYPE_CCE][i];
+        int index = 0;
+
+        if (cce && cce->coup.coupling_point == coupling_point) {
+            ChannelCoupling * coup = &cce->coup;
+
+            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) {
     int i, type;
-    for (i = 0; i < MAX_ELEM_ID; i++) {
-        for(type = 0; type < 4; type++) {
+    for(type = 3; type >= 0; type--) {
+        for (i = 0; i < MAX_ELEM_ID; i++) {
             ChannelElement *che = ac->che[type][i];
             if(che) {
-                if(che->coup.coupling_point == BEFORE_TNS)
-                    apply_channel_coupling(ac, che, apply_dependent_coupling);
+                if(type <= TYPE_CPE)
+                    apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling);
                 if(che->ch[0].tns.present)
                     apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
                 if(che->ch[1].tns.present)
                     apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
-                if(che->coup.coupling_point == BETWEEN_TNS_AND_IMDCT)
-                    apply_channel_coupling(ac, che, apply_dependent_coupling);
-                imdct_and_windowing(ac, &che->ch[0]);
+                if(type <= TYPE_CPE)
+                    apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling);
+                if(type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT)
+                    imdct_and_windowing(ac, &che->ch[0]);
                 if(type == TYPE_CPE)
                     imdct_and_windowing(ac, &che->ch[1]);
-                if(che->coup.coupling_point == AFTER_IMDCT)
-                    apply_channel_coupling(ac, che, apply_independent_coupling);
+                if(type <= TYPE_CCE)
+                    apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, apply_independent_coupling);
             }
         }
     }