summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2010-02-09 17:36:18 +0000
committerReinhard Tartler <siretart@tauware.de>2010-02-09 17:36:18 +0000
commit7d061cfe175ceef84b9201490163e76b3a6f0e06 (patch)
tree8fd72fe6cf820b5ca2f04aa088c7b428289fbc18
parente21e76a914c6194438ee649b06c9be2bed7bfca5 (diff)
fix aac playback regression
Discussed at http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/103768 related reports: - http://bugs.debian.org/540729 - https://roundup.ffmpeg.org/roundup/ffmpeg/issue800 Originally committed as revision 21706 to svn://svn.ffmpeg.org/ffmpeg/branches/0.5
-rw-r--r--libavcodec/aac.c100
-rw-r--r--libavcodec/aac.h2
2 files changed, 78 insertions, 24 deletions
diff --git a/libavcodec/aac.c b/libavcodec/aac.c
index 80195c0641..b6759dd763 100644
--- a/libavcodec/aac.c
+++ b/libavcodec/aac.c
@@ -97,6 +97,56 @@ static VLC vlc_scalefactors;
static VLC vlc_spectral[11];
+static ChannelElement* get_che(AACContext *ac, int type, int elem_id) {
+ static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0 };
+ if (ac->tag_che_map[type][elem_id]) {
+ return ac->tag_che_map[type][elem_id];
+ }
+ if (ac->tags_mapped >= tags_per_config[ac->m4ac.chan_config]) {
+ return NULL;
+ }
+ switch (ac->m4ac.chan_config) {
+ case 7:
+ if (ac->tags_mapped == 3 && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
+ }
+ case 6:
+ /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1]
+ instead of SCE[0] CPE[0] CPE[0] LFE[0]. If we seem to have
+ encountered such a stream, transfer the LFE[0] element to SCE[1] */
+ if (ac->tags_mapped == tags_per_config[ac->m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
+ }
+ case 5:
+ if (ac->tags_mapped == 2 && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
+ }
+ case 4:
+ if (ac->tags_mapped == 2 && ac->m4ac.chan_config == 4 && type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 3:
+ case 2:
+ if (ac->tags_mapped == (ac->m4ac.chan_config != 2) && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0];
+ } else if (ac->m4ac.chan_config == 2) {
+ return NULL;
+ }
+ case 1:
+ if (!ac->tags_mapped && type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
+ }
+ default:
+ return NULL;
+ }
+}
+
/**
* Configure output channel order based on the current program configuration element.
*
@@ -106,7 +156,7 @@ static VLC vlc_spectral[11];
* @return Returns error status. 0 - OK, !0 - error
*/
static int output_configure(AACContext *ac, enum ChannelPosition che_pos[4][MAX_ELEM_ID],
- enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]) {
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID], int channel_config) {
AVCodecContext *avctx = ac->avccontext;
int i, type, channels = 0;
@@ -140,7 +190,16 @@ static int output_configure(AACContext *ac, enum ChannelPosition che_pos[4][MAX_
}
}
+ if (channel_config) {
+ memset(ac->tag_che_map, 0, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
+ ac->tags_mapped = 0;
+ } else {
+ memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
+ ac->tags_mapped = 4*MAX_ELEM_ID;
+ }
+
avctx->channels = channels;
+
return 0;
}
@@ -286,7 +345,7 @@ static int decode_ga_specific_config(AACContext * ac, GetBitContext * gb, int ch
if((ret = set_default_channel_config(ac, new_che_pos, channel_config)))
return ret;
}
- if((ret = output_configure(ac, ac->che_pos, new_che_pos)))
+ if((ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config)))
return ret;
if (extension_flag) {
@@ -394,7 +453,7 @@ static av_cold int aac_decode_init(AVCodecContext * avccontext) {
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
if(set_default_channel_config(ac, new_che_pos, avccontext->channels - (avccontext->channels == 8)))
return -1;
- if(output_configure(ac, ac->che_pos, new_che_pos))
+ if(output_configure(ac, ac->che_pos, new_che_pos, 1))
return -1;
ac->m4ac.sample_rate = avccontext->sample_rate;
} else {
@@ -1538,19 +1597,20 @@ static int parse_adts_frame_header(AACContext * ac, GetBitContext * gb) {
ac->m4ac.sample_rate = hdr_info.sample_rate;
ac->m4ac.sampling_index = hdr_info.sampling_index;
ac->m4ac.object_type = hdr_info.object_type;
- }
- if (hdr_info.num_aac_frames == 1) {
- if (!hdr_info.crc_absent)
- skip_bits(gb, 16);
- } else {
- ff_log_missing_feature(ac->avccontext, "More than one AAC RDB per ADTS frame is", 0);
- return -1;
+ if (hdr_info.num_aac_frames == 1) {
+ if (!hdr_info.crc_absent)
+ skip_bits(gb, 16);
+ } else {
+ ff_log_missing_feature(ac->avccontext, "More than one AAC RDB per ADTS frame is", 0);
+ return -1;
+ }
}
return size;
}
static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data_size, const uint8_t * buf, int buf_size) {
AACContext * ac = avccontext->priv_data;
+ ChannelElement * che = NULL;
GetBitContext gb;
enum RawDataBlockType elem_type;
int err, elem_id, data_size_tmp;
@@ -1573,15 +1633,7 @@ static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data
elem_id = get_bits(&gb, 4);
err = -1;
- if(elem_type == TYPE_SCE && elem_id == 1 &&
- !ac->che[TYPE_SCE][elem_id] && ac->che[TYPE_LFE][0]) {
- /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1]
- instead of SCE[0] CPE[0] CPE[0] LFE[0]. If we seem to have
- encountered such a stream, transfer the LFE[0] element to SCE[1] */
- ac->che[TYPE_SCE][elem_id] = ac->che[TYPE_LFE][0];
- ac->che[TYPE_LFE][0] = NULL;
- }
- if(elem_type < TYPE_DSE && !ac->che[elem_type][elem_id]) {
+ if(elem_type < TYPE_DSE && !(che=get_che(ac, elem_type, elem_id))) {
av_log(ac->avccontext, AV_LOG_ERROR, "channel element %d.%d is not allocated\n", elem_type, elem_id);
return -1;
}
@@ -1589,19 +1641,19 @@ static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data
switch (elem_type) {
case TYPE_SCE:
- err = decode_ics(ac, &ac->che[TYPE_SCE][elem_id]->ch[0], &gb, 0, 0);
+ err = decode_ics(ac, &che->ch[0], &gb, 0, 0);
break;
case TYPE_CPE:
- err = decode_cpe(ac, &gb, ac->che[TYPE_CPE][elem_id]);
+ err = decode_cpe(ac, &gb, che);
break;
case TYPE_CCE:
- err = decode_cce(ac, &gb, ac->che[TYPE_CCE][elem_id]);
+ err = decode_cce(ac, &gb, che);
break;
case TYPE_LFE:
- err = decode_ics(ac, &ac->che[TYPE_LFE][elem_id]->ch[0], &gb, 0, 0);
+ err = decode_ics(ac, &che->ch[0], &gb, 0, 0);
break;
case TYPE_DSE:
@@ -1615,7 +1667,7 @@ static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
if((err = decode_pce(ac, new_che_pos, &gb)))
break;
- err = output_configure(ac, ac->che_pos, new_che_pos);
+ err = output_configure(ac, ac->che_pos, new_che_pos, 0);
break;
}
diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 66b2e22d0e..32e7224c47 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -260,6 +260,8 @@ typedef struct {
* first index as the first 4 raw data block types
*/
ChannelElement * che[4][MAX_ELEM_ID];
+ ChannelElement * tag_che_map[4][MAX_ELEM_ID];
+ int tags_mapped;
/** @} */
/**