aac: Correctly map multichannel ADTS AAC with non-zero channel_config + PCE
[ffmpeg.git] / libavcodec / aacdec.c
index ebeda9b..0c7e2c4 100644 (file)
@@ -443,12 +443,18 @@ static int output_configure(AACContext *ac,
     AVCodecContext *avctx = ac->avctx;
     int i, channels = 0, ret;
     uint64_t layout = 0;
+    uint8_t id_map[TYPE_END][MAX_ELEM_ID] = {{ 0 }};
+    uint8_t type_counts[TYPE_END] = { 0 };
 
     if (ac->oc[1].layout_map != layout_map) {
         memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0]));
         ac->oc[1].layout_map_tags = tags;
     }
-
+    for (i = 0; i < tags; i++) {
+        int type =         layout_map[i][0];
+        int id =           layout_map[i][1];
+        id_map[type][id] = type_counts[type]++;
+    }
     // Try to sniff a reasonable channel order, otherwise output the
     // channels in the order the PCE declared them.
     if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE)
@@ -456,12 +462,14 @@ static int output_configure(AACContext *ac,
     for (i = 0; i < tags; i++) {
         int type =     layout_map[i][0];
         int id =       layout_map[i][1];
+        int iid =      id_map[type][id];
         int position = layout_map[i][2];
         // Allocate or free elements depending on if they are in the
         // current program configuration.
-        ret = che_configure(ac, position, type, id, &channels);
+        ret = che_configure(ac, position, type, iid, &channels);
         if (ret < 0)
             return ret;
+        ac->tag_che_map[type][id] = ac->che[type][iid];
     }
     if (ac->oc[1].m4ac.ps == 1 && channels == 2) {
         if (layout == AV_CH_FRONT_CENTER) {
@@ -471,7 +479,6 @@ static int output_configure(AACContext *ac,
         }
     }
 
-    memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
     avctx->channel_layout = ac->oc[1].channel_layout = layout;
     avctx->channels       = ac->oc[1].channels       = channels;
     ac->oc[1].status = oc_type;
@@ -819,7 +826,7 @@ static int decode_eld_specific_config(AACContext *ac, AVCodecContext *avctx,
         if (len == 15 + 255)
             len += get_bits(gb, 16);
         if (get_bits_left(gb) < len * 8 + 4) {
-            av_log(ac->avctx, AV_LOG_ERROR, overread_err);
+            av_log(avctx, AV_LOG_ERROR, overread_err);
             return AVERROR_INVALIDDATA;
         }
         skip_bits_long(gb, 8 * len);