You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	aacdec: Try to sniff a reasonable channel layout for PCE based configurations.
This changes the output order of multichannel PCE based streams.
This commit is contained in:
		| @@ -263,9 +263,8 @@ typedef struct { | ||||
|      * @name Channel element related data | ||||
|      * @{ | ||||
|      */ | ||||
|     enum ChannelPosition che_pos[4][MAX_ELEM_ID]; /**< channel element channel mapping with the | ||||
|                                                    *   first index as the first 4 raw data block types | ||||
|                                                    */ | ||||
|     uint8_t layout_map[MAX_ELEM_ID*4][3]; | ||||
|     int layout_map_tags; | ||||
|     ChannelElement          *che[4][MAX_ELEM_ID]; | ||||
|     ChannelElement  *tag_che_map[4][MAX_ELEM_ID]; | ||||
|     int tags_mapped; | ||||
|   | ||||
| @@ -163,15 +163,14 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int count_channels(enum ChannelPosition che_pos[4][MAX_ELEM_ID]) | ||||
| static int count_channels(uint8_t (*layout)[3], int tags) | ||||
| { | ||||
|     int i, type, sum = 0; | ||||
|     for (i = 0; i < MAX_ELEM_ID; i++) { | ||||
|         for (type = 0; type < 4; type++) { | ||||
|             sum += (1 + (type == TYPE_CPE)) * | ||||
|                 (che_pos[type][i] != AAC_CHANNEL_OFF && | ||||
|                  che_pos[type][i] != AAC_CHANNEL_CC); | ||||
|         } | ||||
|     int i, sum = 0; | ||||
|     for (i = 0; i < tags; i++) { | ||||
|         int syn_ele = layout[i][0]; | ||||
|         int pos     = layout[i][2]; | ||||
|         sum += (1 + (syn_ele == TYPE_CPE)) * | ||||
|                (pos != AAC_CHANNEL_OFF && pos != AAC_CHANNEL_CC); | ||||
|     } | ||||
|     return sum; | ||||
| } | ||||
| @@ -213,30 +212,217 @@ static av_cold int che_configure(AACContext *ac, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| struct elem_to_channel { | ||||
|     uint64_t av_position; | ||||
|     uint8_t syn_ele; | ||||
|     uint8_t elem_id; | ||||
|     uint8_t aac_position; | ||||
| }; | ||||
|  | ||||
| static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID], | ||||
|     uint8_t (*layout_map)[3], int offset, int tags, uint64_t left, | ||||
|     uint64_t right, int pos) | ||||
| { | ||||
|     if (layout_map[offset][0] == TYPE_CPE) { | ||||
|         e2c_vec[offset] = (struct elem_to_channel) { | ||||
|             .av_position = left | right, .syn_ele = TYPE_CPE, | ||||
|             .elem_id = layout_map[offset    ][1], .aac_position = pos }; | ||||
|         return 1; | ||||
|     } else { | ||||
|         e2c_vec[offset]   = (struct elem_to_channel) { | ||||
|             .av_position = left, .syn_ele = TYPE_SCE, | ||||
|             .elem_id = layout_map[offset    ][1], .aac_position = pos }; | ||||
|         e2c_vec[offset + 1] = (struct elem_to_channel) { | ||||
|             .av_position = right, .syn_ele = TYPE_SCE, | ||||
|             .elem_id = layout_map[offset + 1][1], .aac_position = pos }; | ||||
|         return 2; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos, int *current) { | ||||
|     int num_pos_channels = 0; | ||||
|     int first_cpe = 0; | ||||
|     int sce_parity = 0; | ||||
|     int i; | ||||
|     for (i = *current; i < tags; i++) { | ||||
|         if (layout_map[i][2] != pos) | ||||
|             break; | ||||
|         if (layout_map[i][0] == TYPE_CPE) { | ||||
|             if (sce_parity) { | ||||
|                 if (pos == AAC_CHANNEL_FRONT || !first_cpe) { | ||||
|                     sce_parity = 0; | ||||
|                 } else { | ||||
|                     return -1; | ||||
|                 } | ||||
|             } | ||||
|             num_pos_channels += 2; | ||||
|             first_cpe = 1; | ||||
|         } else { | ||||
|             num_pos_channels++; | ||||
|             sce_parity ^= 1; | ||||
|         } | ||||
|     } | ||||
|     if (sce_parity && | ||||
|         ((pos == AAC_CHANNEL_FRONT && first_cpe) || pos == AAC_CHANNEL_SIDE)) | ||||
|             return -1; | ||||
|     *current = i; | ||||
|     return num_pos_channels; | ||||
| } | ||||
|  | ||||
| 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[MAX_ELEM_ID] = {{ 0 }}; | ||||
|     int num_front_channels, num_side_channels, num_back_channels; | ||||
|     uint64_t layout; | ||||
|  | ||||
|     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; | ||||
|  | ||||
|     i = 0; | ||||
|     if (num_front_channels & 1) { | ||||
|         e2c_vec[i] = (struct elem_to_channel) { | ||||
|             .av_position = AV_CH_FRONT_CENTER, .syn_ele = TYPE_SCE, | ||||
|             .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_FRONT }; | ||||
|         i++; | ||||
|         num_front_channels--; | ||||
|     } | ||||
|     if (num_front_channels >= 4) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          AV_CH_FRONT_LEFT_OF_CENTER, | ||||
|                          AV_CH_FRONT_RIGHT_OF_CENTER, | ||||
|                          AAC_CHANNEL_FRONT); | ||||
|         num_front_channels -= 2; | ||||
|     } | ||||
|     if (num_front_channels >= 2) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          AV_CH_FRONT_LEFT, | ||||
|                          AV_CH_FRONT_RIGHT, | ||||
|                          AAC_CHANNEL_FRONT); | ||||
|         num_front_channels -= 2; | ||||
|     } | ||||
|     while (num_front_channels >= 2) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          UINT64_MAX, | ||||
|                          UINT64_MAX, | ||||
|                          AAC_CHANNEL_FRONT); | ||||
|         num_front_channels -= 2; | ||||
|     } | ||||
|  | ||||
|     if (num_side_channels >= 2) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          AV_CH_SIDE_LEFT, | ||||
|                          AV_CH_SIDE_RIGHT, | ||||
|                          AAC_CHANNEL_FRONT); | ||||
|         num_side_channels -= 2; | ||||
|     } | ||||
|     while (num_side_channels >= 2) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          UINT64_MAX, | ||||
|                          UINT64_MAX, | ||||
|                          AAC_CHANNEL_SIDE); | ||||
|         num_side_channels -= 2; | ||||
|     } | ||||
|  | ||||
|     while (num_back_channels >= 4) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          UINT64_MAX, | ||||
|                          UINT64_MAX, | ||||
|                          AAC_CHANNEL_BACK); | ||||
|         num_back_channels -= 2; | ||||
|     } | ||||
|     if (num_back_channels >= 2) { | ||||
|         i += assign_pair(e2c_vec, layout_map, i, tags, | ||||
|                          AV_CH_BACK_LEFT, | ||||
|                          AV_CH_BACK_RIGHT, | ||||
|                          AAC_CHANNEL_BACK); | ||||
|         num_back_channels -= 2; | ||||
|     } | ||||
|     if (num_back_channels) { | ||||
|         e2c_vec[i] = (struct elem_to_channel) { | ||||
|           .av_position = AV_CH_BACK_CENTER, .syn_ele = TYPE_SCE, | ||||
|           .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_BACK }; | ||||
|         i++; | ||||
|         num_back_channels--; | ||||
|     } | ||||
|  | ||||
|     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 }; | ||||
|         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++; | ||||
|     } | ||||
|  | ||||
|     // Must choose a stable sort | ||||
|     total_non_cc_elements = n = i; | ||||
|     do { | ||||
|         int next_n = 0; | ||||
|         for (i = 1; i < n; i++) { | ||||
|             if (e2c_vec[i-1].av_position > e2c_vec[i].av_position) { | ||||
|                 FFSWAP(struct elem_to_channel, e2c_vec[i-1], e2c_vec[i]); | ||||
|                 next_n = i; | ||||
|             } | ||||
|         } | ||||
|         n = next_n; | ||||
|     } while (n > 0); | ||||
|  | ||||
|     layout = 0; | ||||
|     for (i = 0; i < total_non_cc_elements; i++) { | ||||
|         layout_map[i][0] = e2c_vec[i].syn_ele; | ||||
|         layout_map[i][1] = e2c_vec[i].elem_id; | ||||
|         layout_map[i][2] = e2c_vec[i].aac_position; | ||||
|         if (e2c_vec[i].av_position != UINT64_MAX) { | ||||
|             layout |= e2c_vec[i].av_position; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return layout; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Configure output channel order based on the current program configuration element. | ||||
|  * | ||||
|  * @param   che_pos current channel position configuration | ||||
|  * @param   new_che_pos New channel position configuration - we only do something if it differs from the current one. | ||||
|  * | ||||
|  * @return  Returns error status. 0 - OK, !0 - error | ||||
|  */ | ||||
| static av_cold int output_configure(AACContext *ac, | ||||
|                                     enum ChannelPosition new_che_pos[4][MAX_ELEM_ID], | ||||
|                                     uint8_t layout_map[MAX_ELEM_ID*4][3], int tags, | ||||
|                                     int channel_config, enum OCStatus oc_type) | ||||
| { | ||||
|     AVCodecContext *avctx = ac->avctx; | ||||
|     int i, type, channels = 0, ret; | ||||
|     int i, channels = 0, ret; | ||||
|  | ||||
|     if (new_che_pos) | ||||
|         memcpy(ac->che_pos, new_che_pos, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); | ||||
|     if (ac->layout_map != layout_map) { | ||||
|         memcpy(ac->layout_map, layout_map, tags * sizeof(layout_map[0])); | ||||
|         ac->layout_map_tags = tags; | ||||
|     } | ||||
|  | ||||
|     if (channel_config) { | ||||
|         for (i = 0; i < tags_per_config[channel_config]; i++) { | ||||
|             int id = aac_channel_layout_map[channel_config - 1][i][1]; | ||||
|             type = aac_channel_layout_map[channel_config - 1][i][0]; | ||||
|             if ((ret = che_configure(ac, ac->che_pos[type][id], | ||||
|                                      type, id, &channels))) | ||||
|             int type    = aac_channel_layout_map[channel_config - 1][i][0]; | ||||
|             int id      = aac_channel_layout_map[channel_config - 1][i][1]; | ||||
|             int positon = aac_channel_layout_map[channel_config - 1][i][2]; | ||||
|             if ((ret = che_configure(ac, positon, | ||||
|                                      type, id, | ||||
|                                      &channels))) | ||||
|                 return ret; | ||||
|         } | ||||
|  | ||||
| @@ -247,20 +433,24 @@ static av_cold int output_configure(AACContext *ac, | ||||
|         /* Allocate or free elements depending on if they are in the | ||||
|          * current program configuration. | ||||
|          * | ||||
|          * Set up default 1:1 output mapping. | ||||
|          * Try to sniff a reasonable channel order, otherwise output the | ||||
|          * channels in the order the PCE declared them. | ||||
|          */ | ||||
|  | ||||
|         for (i = 0; i < MAX_ELEM_ID; i++) { | ||||
|             for (type = 0; type < 4; type++) { | ||||
|                 if ((ret = che_configure(ac, ac->che_pos[type][i], | ||||
|                                          type, i, &channels))) | ||||
|                     return ret; | ||||
|             } | ||||
|         uint64_t layout = sniff_channel_order(layout_map, tags); | ||||
|         for (i = 0; i < tags; i++) { | ||||
|             int type =     layout_map[i][0]; | ||||
|             int id =       layout_map[i][1]; | ||||
|             int position = layout_map[i][2]; | ||||
|             if ((ret = che_configure(ac, position, | ||||
|                                      type, id, | ||||
|                                      &channels))) | ||||
|                 return ret; | ||||
|         } | ||||
|  | ||||
|         memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); | ||||
|  | ||||
|         avctx->channel_layout = 0; | ||||
|         avctx->channel_layout = layout; | ||||
|     } | ||||
|  | ||||
|     avctx->channels = channels; | ||||
| @@ -277,30 +467,45 @@ static av_cold int output_configure(AACContext *ac, | ||||
|  * @param sce_map mono (Single Channel Element) map | ||||
|  * @param type speaker type/position for these channels | ||||
|  */ | ||||
| static void decode_channel_map(enum ChannelPosition *cpe_map, | ||||
|                                enum ChannelPosition *sce_map, | ||||
| static void decode_channel_map(uint8_t layout_map[][3], | ||||
|                                enum ChannelPosition type, | ||||
|                                GetBitContext *gb, int n) | ||||
| { | ||||
|     while (n--) { | ||||
|         enum ChannelPosition *map = cpe_map && get_bits1(gb) ? cpe_map : sce_map; // stereo or mono map | ||||
|         map[get_bits(gb, 4)] = type; | ||||
|         enum RawDataBlockType syn_ele; | ||||
|         switch (type) { | ||||
|         case AAC_CHANNEL_FRONT: | ||||
|         case AAC_CHANNEL_BACK: | ||||
|         case AAC_CHANNEL_SIDE: | ||||
|             syn_ele = get_bits1(gb); | ||||
|             break; | ||||
|         case AAC_CHANNEL_CC: | ||||
|             skip_bits1(gb); | ||||
|             syn_ele = TYPE_CCE; | ||||
|             break; | ||||
|         case AAC_CHANNEL_LFE: | ||||
|             syn_ele = TYPE_LFE; | ||||
|             break; | ||||
|         } | ||||
|         layout_map[0][0] = syn_ele; | ||||
|         layout_map[0][1] = get_bits(gb, 4); | ||||
|         layout_map[0][2] = type; | ||||
|         layout_map++; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Decode program configuration element; reference: table 4.2. | ||||
|  * | ||||
|  * @param   new_che_pos New channel position configuration - we only do something if it differs from the current one. | ||||
|  * | ||||
|  * @return  Returns error status. 0 - OK, !0 - error | ||||
|  */ | ||||
| static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac, | ||||
|                       enum ChannelPosition new_che_pos[4][MAX_ELEM_ID], | ||||
|                       uint8_t (*layout_map)[3], | ||||
|                       GetBitContext *gb) | ||||
| { | ||||
|     int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc, sampling_index; | ||||
|     int comment_len; | ||||
|     int tags; | ||||
|  | ||||
|     skip_bits(gb, 2);  // object_type | ||||
|  | ||||
| @@ -323,14 +528,19 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac, | ||||
|     if (get_bits1(gb)) | ||||
|         skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround | ||||
|  | ||||
|     decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_FRONT, gb, num_front); | ||||
|     decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_SIDE,  gb, num_side ); | ||||
|     decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_BACK,  gb, num_back ); | ||||
|     decode_channel_map(NULL,                  new_che_pos[TYPE_LFE], AAC_CHANNEL_LFE,   gb, num_lfe  ); | ||||
|     decode_channel_map(layout_map       , AAC_CHANNEL_FRONT, gb, num_front); | ||||
|     tags = num_front; | ||||
|     decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE,  gb, num_side); | ||||
|     tags += num_side; | ||||
|     decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK,  gb, num_back); | ||||
|     tags += num_back; | ||||
|     decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE,   gb, num_lfe); | ||||
|     tags += num_lfe; | ||||
|  | ||||
|     skip_bits_long(gb, 4 * num_assoc_data); | ||||
|  | ||||
|     decode_channel_map(new_che_pos[TYPE_CCE], new_che_pos[TYPE_CCE], AAC_CHANNEL_CC,    gb, num_cc   ); | ||||
|     decode_channel_map(layout_map + tags, AAC_CHANNEL_CC,    gb, num_cc); | ||||
|     tags += num_cc; | ||||
|  | ||||
|     align_get_bits(gb); | ||||
|  | ||||
| @@ -341,19 +551,18 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac, | ||||
|         return -1; | ||||
|     } | ||||
|     skip_bits_long(gb, comment_len); | ||||
|     return 0; | ||||
|     return tags; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set up channel positions based on a default channel configuration | ||||
|  * as specified in table 1.17. | ||||
|  * | ||||
|  * @param   new_che_pos New channel position configuration - we only do something if it differs from the current one. | ||||
|  * | ||||
|  * @return  Returns error status. 0 - OK, !0 - error | ||||
|  */ | ||||
| static av_cold int set_default_channel_config(AVCodecContext *avctx, | ||||
|                                               enum ChannelPosition new_che_pos[4][MAX_ELEM_ID], | ||||
|                                               uint8_t (*layout_map)[3], | ||||
|                                               int *tags, | ||||
|                                               int channel_config) | ||||
| { | ||||
|     if (channel_config < 1 || channel_config > 7) { | ||||
| @@ -361,32 +570,8 @@ static av_cold int set_default_channel_config(AVCodecContext *avctx, | ||||
|                channel_config); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     /* default channel configurations: | ||||
|      * | ||||
|      * 1ch : front center (mono) | ||||
|      * 2ch : L + R (stereo) | ||||
|      * 3ch : front center + L + R | ||||
|      * 4ch : front center + L + R + back center | ||||
|      * 5ch : front center + L + R + back stereo | ||||
|      * 6ch : front center + L + R + back stereo + LFE | ||||
|      * 7ch : front center + L + R + outer front left + outer front right + back stereo + LFE | ||||
|      */ | ||||
|  | ||||
|     if (channel_config != 2) | ||||
|         new_che_pos[TYPE_SCE][0] = AAC_CHANNEL_FRONT; // front center (or mono) | ||||
|     if (channel_config > 1) | ||||
|         new_che_pos[TYPE_CPE][0] = AAC_CHANNEL_FRONT; // L + R (or stereo) | ||||
|     if (channel_config == 4) | ||||
|         new_che_pos[TYPE_SCE][1] = AAC_CHANNEL_BACK;  // back center | ||||
|     if (channel_config > 4) | ||||
|         new_che_pos[TYPE_CPE][(channel_config == 7) + 1] | ||||
|         = AAC_CHANNEL_BACK;  // back stereo | ||||
|     if (channel_config > 5) | ||||
|         new_che_pos[TYPE_LFE][0] = AAC_CHANNEL_LFE;   // LFE | ||||
|     if (channel_config == 7) | ||||
|         new_che_pos[TYPE_CPE][1] = AAC_CHANNEL_FRONT; // outer front left + outer front right | ||||
|  | ||||
|     *tags = tags_per_config[channel_config]; | ||||
|     memcpy(layout_map, aac_channel_layout_map[channel_config-1], *tags * sizeof(*layout_map)); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -403,8 +588,9 @@ static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx, | ||||
|                                      MPEG4AudioConfig *m4ac, | ||||
|                                      int channel_config) | ||||
| { | ||||
|     enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]; | ||||
|     int extension_flag, ret; | ||||
|     uint8_t layout_map[MAX_ELEM_ID*4][3]; | ||||
|     int tags = 0; | ||||
|  | ||||
|     if (get_bits1(gb)) { // frameLengthFlag | ||||
|         av_log_missing_feature(avctx, "960/120 MDCT window is", 1); | ||||
| @@ -419,22 +605,23 @@ static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx, | ||||
|         m4ac->object_type == AOT_ER_AAC_SCALABLE) | ||||
|         skip_bits(gb, 3);     // layerNr | ||||
|  | ||||
|     memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); | ||||
|     if (channel_config == 0) { | ||||
|         skip_bits(gb, 4);  // element_instance_tag | ||||
|         if ((ret = decode_pce(avctx, m4ac, new_che_pos, gb))) | ||||
|             return ret; | ||||
|         tags = decode_pce(avctx, m4ac, layout_map, gb); | ||||
|         if (tags < 0) | ||||
|             return tags; | ||||
|     } else { | ||||
|         if ((ret = set_default_channel_config(avctx, new_che_pos, channel_config))) | ||||
|         if ((ret = set_default_channel_config(avctx, layout_map, &tags, channel_config))) | ||||
|             return ret; | ||||
|     } | ||||
|  | ||||
|     if (count_channels(new_che_pos) > 1) { | ||||
|     if (count_channels(layout_map, tags) > 1) { | ||||
|         m4ac->ps = 0; | ||||
|     } else if (m4ac->sbr == 1 && m4ac->ps == -1) | ||||
|         m4ac->ps = 1; | ||||
|  | ||||
|     if (ac && (ret = output_configure(ac, new_che_pos, channel_config, OC_GLOBAL_HDR))) | ||||
|     if (ac && (ret = output_configure(ac, layout_map, tags, | ||||
|                                       channel_config, OC_GLOBAL_HDR))) | ||||
|         return ret; | ||||
|  | ||||
|     if (extension_flag) { | ||||
| @@ -588,7 +775,8 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) | ||||
|             return -1; | ||||
|     } else { | ||||
|         int sr, i; | ||||
|         enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]; | ||||
|         uint8_t layout_map[MAX_ELEM_ID*4][3]; | ||||
|         int layout_map_tags; | ||||
|  | ||||
|         sr = sample_rate_idx(avctx->sample_rate); | ||||
|         ac->m4ac.sampling_index = sr; | ||||
| @@ -605,9 +793,11 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) | ||||
|         ac->m4ac.chan_config = i; | ||||
|  | ||||
|         if (ac->m4ac.chan_config) { | ||||
|             int ret = set_default_channel_config(avctx, new_che_pos, ac->m4ac.chan_config); | ||||
|             int ret = set_default_channel_config(avctx, layout_map, | ||||
|                 &layout_map_tags, ac->m4ac.chan_config); | ||||
|             if (!ret) | ||||
|                 output_configure(ac, new_che_pos, ac->m4ac.chan_config, OC_GLOBAL_HDR); | ||||
|                 output_configure(ac, layout_map, layout_map_tags, | ||||
|                                  ac->m4ac.chan_config, OC_GLOBAL_HDR); | ||||
|             else if (avctx->err_recognition & AV_EF_EXPLODE) | ||||
|                 return AVERROR_INVALIDDATA; | ||||
|         } | ||||
| @@ -1711,7 +1901,8 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt, | ||||
|         } else if (ac->m4ac.ps == -1 && ac->output_configured < OC_LOCKED && ac->avctx->channels == 1) { | ||||
|             ac->m4ac.sbr = 1; | ||||
|             ac->m4ac.ps = 1; | ||||
|             output_configure(ac, NULL, ac->m4ac.chan_config, ac->output_configured); | ||||
|             output_configure(ac, ac->layout_map, ac->layout_map_tags, | ||||
|                              ac->m4ac.chan_config, ac->output_configured); | ||||
|         } else { | ||||
|             ac->m4ac.sbr = 1; | ||||
|         } | ||||
| @@ -2085,16 +2276,18 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) | ||||
| { | ||||
|     int size; | ||||
|     AACADTSHeaderInfo hdr_info; | ||||
|     uint8_t layout_map[MAX_ELEM_ID*4][3]; | ||||
|     int layout_map_tags; | ||||
|  | ||||
|     size = avpriv_aac_parse_header(gb, &hdr_info); | ||||
|     if (size > 0) { | ||||
|         if (hdr_info.chan_config) { | ||||
|             enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]; | ||||
|             memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); | ||||
|             ac->m4ac.chan_config = hdr_info.chan_config; | ||||
|             if (set_default_channel_config(ac->avctx, new_che_pos, hdr_info.chan_config)) | ||||
|             if (set_default_channel_config(ac->avctx, layout_map, | ||||
|                     &layout_map_tags, hdr_info.chan_config)) | ||||
|                 return -7; | ||||
|             if (output_configure(ac, new_che_pos, hdr_info.chan_config, | ||||
|             if (output_configure(ac, layout_map, layout_map_tags, | ||||
|                                  hdr_info.chan_config, | ||||
|                                  FFMAX(ac->output_configured, OC_TRIAL_FRAME))) | ||||
|                 return -7; | ||||
|         } else if (ac->output_configured != OC_LOCKED) { | ||||
| @@ -2181,15 +2374,18 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, | ||||
|             break; | ||||
|  | ||||
|         case TYPE_PCE: { | ||||
|             enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]; | ||||
|             memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); | ||||
|             if ((err = decode_pce(avctx, &ac->m4ac, new_che_pos, gb))) | ||||
|             uint8_t layout_map[MAX_ELEM_ID*4][3]; | ||||
|             int tags; | ||||
|             tags = decode_pce(avctx, &ac->m4ac, layout_map, gb); | ||||
|             if (tags < 0) { | ||||
|                 err = tags; | ||||
|                 break; | ||||
|             } | ||||
|             if (ac->output_configured > OC_TRIAL_PCE) | ||||
|                 av_log(avctx, AV_LOG_ERROR, | ||||
|                        "Not evaluating a further program_config_element as this construct is dubious at best.\n"); | ||||
|             else | ||||
|                 err = output_configure(ac, new_che_pos, 0, OC_TRIAL_PCE); | ||||
|                 err = output_configure(ac, layout_map, tags, 0, OC_TRIAL_PCE); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -80,14 +80,14 @@ static const float * const tns_tmp2_map[4] = { | ||||
|  | ||||
| static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||||
|  | ||||
| static const uint8_t aac_channel_layout_map[7][5][2] = { | ||||
|     { { TYPE_SCE, 0 }, }, | ||||
|     { { TYPE_CPE, 0 }, }, | ||||
|     { { TYPE_CPE, 0 }, { TYPE_SCE, 0 }, }, | ||||
|     { { TYPE_CPE, 0 }, { TYPE_SCE, 0 }, { TYPE_SCE, 1 }, }, | ||||
|     { { TYPE_CPE, 0 }, { TYPE_SCE, 0 }, { TYPE_CPE, 1 }, }, | ||||
|     { { TYPE_CPE, 0 }, { TYPE_SCE, 0 }, { TYPE_LFE, 0 }, { TYPE_CPE, 1 }, }, | ||||
|     { { TYPE_CPE, 1 }, { TYPE_SCE, 0 }, { TYPE_LFE, 0 }, { TYPE_CPE, 2 }, { TYPE_CPE, 0 }, }, | ||||
| static const uint8_t aac_channel_layout_map[7][5][3] = { | ||||
|     { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, | ||||
|     { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, | ||||
|     { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, | ||||
|     { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, }, | ||||
|     { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, }, | ||||
|     { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_LFE, 0, AAC_CHANNEL_LFE  }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, }, | ||||
|     { { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_LFE, 0, AAC_CHANNEL_LFE  }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, | ||||
| }; | ||||
|  | ||||
| static const uint64_t aac_channel_layout[8] = { | ||||
|   | ||||
| @@ -8,15 +8,15 @@ fate-aac-al05_44: REF = $(SAMPLES)/aac/al05_44.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al06_44 | ||||
| fate-aac-al06_44: CMD = pcm -i $(SAMPLES)/aac/al06_44.mp4 | ||||
| fate-aac-al06_44: REF = $(SAMPLES)/aac/al06_44.s16 | ||||
| fate-aac-al06_44: REF = $(SAMPLES)/aac/al06_44_reorder.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al07_96 | ||||
| fate-aac-al07_96: CMD = pcm -i $(SAMPLES)/aac/al07_96.mp4 | ||||
| fate-aac-al07_96: REF = $(SAMPLES)/aac/al07_96.s16 | ||||
| fate-aac-al07_96: REF = $(SAMPLES)/aac/al07_96_reorder.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al15_44 | ||||
| fate-aac-al15_44: CMD = pcm -i $(SAMPLES)/aac/al15_44.mp4 | ||||
| fate-aac-al15_44: REF = $(SAMPLES)/aac/al15_44.s16 | ||||
| fate-aac-al15_44: REF = $(SAMPLES)/aac/al15_44_reorder.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al17_44 | ||||
| fate-aac-al17_44: CMD = pcm -i $(SAMPLES)/aac/al17_44.mp4 | ||||
| @@ -32,7 +32,7 @@ fate-aac-am00_88: REF = $(SAMPLES)/aac/am00_88.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-am05_44 | ||||
| fate-aac-am05_44: CMD = pcm -i $(SAMPLES)/aac/am05_44.mp4 | ||||
| fate-aac-am05_44: REF = $(SAMPLES)/aac/am05_44.s16 | ||||
| fate-aac-am05_44: REF = $(SAMPLES)/aac/am05_44_reorder.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al_sbr_hq_cm_48_2 | ||||
| fate-aac-al_sbr_hq_cm_48_2: CMD = pcm -i $(SAMPLES)/aac/al_sbr_cm_48_2.mp4 | ||||
| @@ -40,7 +40,7 @@ fate-aac-al_sbr_hq_cm_48_2: REF = $(SAMPLES)/aac/al_sbr_hq_cm_48_2.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al_sbr_hq_cm_48_5.1 | ||||
| fate-aac-al_sbr_hq_cm_48_5.1: CMD = pcm -i $(SAMPLES)/aac/al_sbr_cm_48_5.1.mp4 | ||||
| fate-aac-al_sbr_hq_cm_48_5.1: REF = $(SAMPLES)/aac/al_sbr_hq_cm_48_5.1.s16 | ||||
| fate-aac-al_sbr_hq_cm_48_5.1: REF = $(SAMPLES)/aac/al_sbr_hq_cm_48_5.1_reorder.s16 | ||||
|  | ||||
| FATE_AAC += fate-aac-al_sbr_ps_06_ur | ||||
| fate-aac-al_sbr_ps_06_ur: CMD = pcm -i $(SAMPLES)/aac/al_sbr_ps_06_new.mp4 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user