diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 4a88aeae1d..245fd9f6fe 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -238,13 +238,13 @@ static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID],
 }
 
 static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
-                                 int *current)
+                                 int current)
 {
     int num_pos_channels = 0;
     int first_cpe        = 0;
     int sce_parity       = 0;
     int i;
-    for (i = *current; i < tags; i++) {
+    for (i = current; i < tags; i++) {
         if (layout_map[i][2] != pos)
             break;
         if (layout_map[i][0] == TYPE_CPE) {
@@ -259,207 +259,117 @@ static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
             first_cpe         = 1;
         } else {
             num_pos_channels++;
-            sce_parity ^= 1;
+            sce_parity ^= (pos != AAC_CHANNEL_LFE);
         }
     }
     if (sce_parity &&
-        ((pos == AAC_CHANNEL_FRONT && first_cpe) || pos == AAC_CHANNEL_SIDE))
+        (pos == AAC_CHANNEL_FRONT && first_cpe))
         return -1;
-    *current = i;
+
     return num_pos_channels;
 }
 
-#define PREFIX_FOR_22POINT2 (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_LOW_FREQUENCY_2)
-static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
+static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t (*layout_map)[3],
+                           uint64_t *layout, int tags, int layer, int pos, int *current)
 {
-    int i, n, total_non_cc_elements;
-    struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
-    int num_front_channels, num_side_channels, num_back_channels;
-    uint64_t layout = 0;
+    int i = *current, j = 0;
+    int nb_channels = count_paired_channels(layout_map, tags, pos, i);
 
-    if (FF_ARRAY_ELEMS(e2c_vec) < tags)
+    if (nb_channels < 0 || nb_channels > 5)
         return 0;
 
-    i = 0;
-    num_front_channels =
-        count_paired_channels(layout_map, tags, AAC_CHANNEL_FRONT, &i);
-    if (num_front_channels < 0)
-        return 0;
-    num_side_channels =
-        count_paired_channels(layout_map, tags, AAC_CHANNEL_SIDE, &i);
-    if (num_side_channels < 0)
-        return 0;
-    num_back_channels =
-        count_paired_channels(layout_map, tags, AAC_CHANNEL_BACK, &i);
-    if (num_back_channels < 0)
-        return 0;
+    if (pos == AAC_CHANNEL_LFE) {
+        while (nb_channels) {
+            if (aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE)
+                return -1;
+            e2c_vec[i] = (struct elem_to_channel) {
+                .av_position  = 1ULL << aac_channel_map[layer][pos - 1][j],
+                .syn_ele      = layout_map[i][0],
+                .elem_id      = layout_map[i][1],
+                .aac_position = pos
+            };
+            *layout |= e2c_vec[i].av_position;
+            i++;
+            j++;
+            nb_channels--;
+        }
+        *current = i;
 
-    if (num_side_channels == 0 && num_back_channels >= 4) {
-        num_side_channels = 2;
-        num_back_channels -= 2;
+        return 0;
     }
 
-    i = 0;
-    if (num_front_channels & 1) {
+    while (nb_channels & 1) {
+        if (aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE)
+            return -1;
+        if (aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED)
+            break;
         e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_FRONT_CENTER,
-            .syn_ele      = TYPE_SCE,
+            .av_position  = 1ULL << aac_channel_map[layer][pos - 1][0],
+            .syn_ele      = layout_map[i][0],
             .elem_id      = layout_map[i][1],
-            .aac_position = AAC_CHANNEL_FRONT
+            .aac_position = pos
         };
-        layout |= e2c_vec[i].av_position;
+        *layout |= e2c_vec[i].av_position;
         i++;
-        num_front_channels--;
+        nb_channels--;
     }
-    if (num_front_channels >= 4) {
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_FRONT_LEFT_OF_CENTER,
-                         AV_CH_FRONT_RIGHT_OF_CENTER,
-                         AAC_CHANNEL_FRONT, &layout);
-        num_front_channels -= 2;
-    }
-    if (num_front_channels >= 2) {
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_FRONT_LEFT,
-                         AV_CH_FRONT_RIGHT,
-                         AAC_CHANNEL_FRONT, &layout);
-        num_front_channels -= 2;
-    }
-    if (num_front_channels)
-        return 0; // Non standard PCE defined layout
 
-    if (num_side_channels >= 2) {
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_SIDE_LEFT,
-                         AV_CH_SIDE_RIGHT,
-                         AAC_CHANNEL_SIDE, &layout);
-        num_side_channels -= 2;
-    }
-    if (num_side_channels)
-        return 0; // Non standard PCE defined layout
-
-    if (num_back_channels >= 2) {
+    j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1;
+    while (nb_channels >= 2) {
+        if (aac_channel_map[layer][pos - 1][j]   == AV_CHAN_NONE ||
+            aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE)
+            return -1;
         i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_BACK_LEFT,
-                         AV_CH_BACK_RIGHT,
-                         AAC_CHANNEL_BACK, &layout);
-        num_back_channels -= 2;
-    }
-    if (num_back_channels) {
+                         1ULL << aac_channel_map[layer][pos - 1][j],
+                         1ULL << aac_channel_map[layer][pos - 1][j+1],
+                         pos, layout);
+        j += 2;
+        nb_channels -= 2;
+    }
+    while (nb_channels & 1) {
+        if (aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE)
+            return -1;
         e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_BACK_CENTER,
-            .syn_ele      = TYPE_SCE,
+            .av_position  = 1ULL << aac_channel_map[layer][pos - 1][5],
+            .syn_ele      = layout_map[i][0],
             .elem_id      = layout_map[i][1],
-            .aac_position = AAC_CHANNEL_BACK
+            .aac_position = pos
         };
-        layout |= e2c_vec[i].av_position;
+        *layout |= e2c_vec[i].av_position;
         i++;
-        num_back_channels--;
+        nb_channels--;
     }
-    if (num_back_channels)
-        return 0; // Non standard PCE defined layout
+    if (nb_channels)
+        return -1;
 
-    if (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) {
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_LOW_FREQUENCY,
-            .syn_ele      = TYPE_LFE,
-            .elem_id      = layout_map[i][1],
-            .aac_position = AAC_CHANNEL_LFE
-        };
-        layout |= e2c_vec[i].av_position;
-        i++;
-    }
-    if (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) {
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_LOW_FREQUENCY_2,
-            .syn_ele      = TYPE_LFE,
-            .elem_id      = layout_map[i][1],
-            .aac_position = AAC_CHANNEL_LFE
-        };
-        layout |= e2c_vec[i].av_position;
-        i++;
-    }
-    while (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) {
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = UINT64_MAX,
-            .syn_ele      = TYPE_LFE,
-            .elem_id      = layout_map[i][1],
-            .aac_position = AAC_CHANNEL_LFE
-        };
-        i++;
-    }
+    *current = i;
 
-    // The previous checks would end up at 4 at this point for chan_config 14
-    if (layout == AV_CH_LAYOUT_5POINT1_BACK && tags == 5 && i == 4) {
-        const uint8_t (*reference_layout_map)[3] = aac_channel_layout_map[13];
-        for (int j = 0; j < tags; j++) {
-            if (layout_map[j][0] != reference_layout_map[j][0] ||
-                layout_map[j][2] != reference_layout_map[j][2])
-                goto end_of_layout_definition;
-        }
+    return 0;
+}
 
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_TOP_FRONT_LEFT,
-                         AV_CH_TOP_FRONT_RIGHT,
-                         AAC_CHANNEL_FRONT,
-                         &layout);
-    }
-    // The previous checks would end up at 8 at this point for 22.2
-    if (layout == PREFIX_FOR_22POINT2 && tags == 16 && i == 8) {
-        const uint8_t (*reference_layout_map)[3] = aac_channel_layout_map[12];
-        for (int j = 0; j < tags; j++) {
-            if (layout_map[j][0] != reference_layout_map[j][0] ||
-                layout_map[j][2] != reference_layout_map[j][2])
-                goto end_of_layout_definition;
-        }
+static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
+{
+    int i, n, total_non_cc_elements;
+    struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
+    uint64_t layout = 0;
 
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_TOP_FRONT_CENTER,
-            .syn_ele      = layout_map[i][0],
-            .elem_id      = layout_map[i][1],
-            .aac_position = layout_map[i][2]
-        }; layout |= e2c_vec[i].av_position; i++;
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_TOP_FRONT_LEFT,
-                         AV_CH_TOP_FRONT_RIGHT,
-                         AAC_CHANNEL_FRONT,
-                         &layout);
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_TOP_SIDE_LEFT,
-                         AV_CH_TOP_SIDE_RIGHT,
-                         AAC_CHANNEL_SIDE,
-                         &layout);
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_TOP_CENTER,
-            .syn_ele      = layout_map[i][0],
-            .elem_id      = layout_map[i][1],
-            .aac_position = layout_map[i][2]
-        }; layout |= e2c_vec[i].av_position; i++;
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_TOP_BACK_LEFT,
-                         AV_CH_TOP_BACK_RIGHT,
-                         AAC_CHANNEL_BACK,
-                         &layout);
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_TOP_BACK_CENTER,
-            .syn_ele      = layout_map[i][0],
-            .elem_id      = layout_map[i][1],
-            .aac_position = layout_map[i][2]
-        }; layout |= e2c_vec[i].av_position; i++;
-        e2c_vec[i] = (struct elem_to_channel) {
-            .av_position  = AV_CH_BOTTOM_FRONT_CENTER,
-            .syn_ele      = layout_map[i][0],
-            .elem_id      = layout_map[i][1],
-            .aac_position = layout_map[i][2]
-        }; layout |= e2c_vec[i].av_position; i++;
-        i += assign_pair(e2c_vec, layout_map, i,
-                         AV_CH_BOTTOM_FRONT_LEFT,
-                         AV_CH_BOTTOM_FRONT_RIGHT,
-                         AAC_CHANNEL_FRONT,
-                         &layout);
-    }
+    if (FF_ARRAY_ELEMS(e2c_vec) < tags)
+        return 0;
 
-end_of_layout_definition:
+    for (n = 0, i = 0; n < 3 && i < tags; n++) {
+        int ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_FRONT, &i);
+        if (ret < 0)
+            return 0;
+        ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_SIDE, &i);
+        if (ret < 0)
+		    return 0;
+        ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_BACK, &i);
+        if (ret < 0)
+		    return 0;
+        ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_LFE, &i);
+        if (ret < 0)
+		    return 0;
+    }
 
     total_non_cc_elements = n = i;
 
@@ -655,7 +565,7 @@ static int set_default_channel_config(AACContext *ac, AVCodecContext *avctx,
      * 7.1 layout was intended.
      */
     if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) {
-        layout_map[2][2] = AAC_CHANNEL_SIDE;
+        layout_map[2][2] = AAC_CHANNEL_BACK;
 
         if (!ac || !ac->warned_71_wide++) {
             av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout"
diff --git a/libavcodec/aacdectab.h b/libavcodec/aacdectab.h
index 0e5e47da64..41f1db781d 100644
--- a/libavcodec/aacdectab.h
+++ b/libavcodec/aacdectab.h
@@ -49,12 +49,12 @@ static const uint8_t aac_channel_layout_map[16][16][3] = {
     { { 0, } },
     { { 0, } },
     { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE  }, },
-    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE  }, },
+    { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE  }, },
     {
       { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, // SCE1 = FC,
       { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, // CPE1 = FLc and FRc,
       { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, // CPE2 = FL and FR,
-      { TYPE_CPE, 2, AAC_CHANNEL_SIDE  }, // CPE3 = SiL and SiR,
+      { TYPE_CPE, 2, AAC_CHANNEL_BACK  }, // CPE3 = SiL and SiR,
       { TYPE_CPE, 3, AAC_CHANNEL_BACK  }, // CPE4 = BL and BR,
       { TYPE_SCE, 1, AAC_CHANNEL_BACK  }, // SCE2 = BC,
       { TYPE_LFE, 0, AAC_CHANNEL_LFE   }, // LFE1 = LFE1,
@@ -62,7 +62,7 @@ static const uint8_t aac_channel_layout_map[16][16][3] = {
       { TYPE_SCE, 2, AAC_CHANNEL_FRONT }, // SCE3 = TpFC,
       { TYPE_CPE, 4, AAC_CHANNEL_FRONT }, // CPE5 = TpFL and TpFR,
       { TYPE_CPE, 5, AAC_CHANNEL_SIDE  }, // CPE6 = TpSiL and TpSiR,
-      { TYPE_SCE, 3, AAC_CHANNEL_FRONT }, // SCE4 = TpC,
+      { TYPE_SCE, 3, AAC_CHANNEL_SIDE  }, // SCE4 = TpC,
       { TYPE_CPE, 6, AAC_CHANNEL_BACK  }, // CPE7 = TpBL and TpBR,
       { TYPE_SCE, 4, AAC_CHANNEL_BACK  }, // SCE5 = TpBC,
       { TYPE_SCE, 5, AAC_CHANNEL_FRONT }, // SCE6 = BtFC,
@@ -72,6 +72,27 @@ static const uint8_t aac_channel_layout_map[16][16][3] = {
     { { 0, } },
 };
 
+static const int16_t aac_channel_map[3][4][6] = {
+    {
+      { AV_CHAN_FRONT_CENTER,        AV_CHAN_FRONT_LEFT_OF_CENTER, AV_CHAN_FRONT_RIGHT_OF_CENTER, AV_CHAN_FRONT_LEFT,        AV_CHAN_FRONT_RIGHT,        AV_CHAN_NONE },
+      { AV_CHAN_UNUSED,              AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_NONE },
+      { AV_CHAN_UNUSED,              AV_CHAN_SIDE_LEFT,            AV_CHAN_SIDE_RIGHT,            AV_CHAN_BACK_LEFT,         AV_CHAN_BACK_RIGHT,         AV_CHAN_BACK_CENTER },
+      { AV_CHAN_LOW_FREQUENCY,       AV_CHAN_LOW_FREQUENCY_2,      AV_CHAN_NONE,                  AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_NONE },
+    },
+    {
+      { AV_CHAN_TOP_FRONT_CENTER,    AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_TOP_FRONT_LEFT,    AV_CHAN_TOP_FRONT_RIGHT,    AV_CHAN_NONE },
+      { AV_CHAN_UNUSED,              AV_CHAN_TOP_SIDE_LEFT,        AV_CHAN_TOP_SIDE_RIGHT,        AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_TOP_CENTER},
+      { AV_CHAN_UNUSED,              AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_TOP_BACK_LEFT,     AV_CHAN_TOP_BACK_RIGHT,     AV_CHAN_TOP_BACK_CENTER},
+      { AV_CHAN_NONE,                AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_NONE},
+    },
+    {
+      { AV_CHAN_BOTTOM_FRONT_CENTER, AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_BOTTOM_FRONT_LEFT, AV_CHAN_BOTTOM_FRONT_RIGHT, AV_CHAN_NONE },
+      { AV_CHAN_NONE,                AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_NONE },
+      { AV_CHAN_NONE,                AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_NONE },
+      { AV_CHAN_NONE,                AV_CHAN_NONE,                 AV_CHAN_NONE,                  AV_CHAN_NONE,              AV_CHAN_NONE,               AV_CHAN_NONE },
+    },
+};
+
 #if FF_API_OLD_CHANNEL_LAYOUT
 static const uint64_t aac_channel_layout[] = {
     AV_CH_LAYOUT_MONO,
