You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	Support ADTS AAC files in the ffaac decoder (limited to streams containing one
raw_data_block() per ADTS frame) Patch by Alex Converse ( alex converse gmail com) based on a patch by Robert Swain ( robert swain gmail com ) Originally committed as revision 16485 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		| @@ -86,6 +86,7 @@ | ||||
| #include "aactab.h" | ||||
| #include "aacdectab.h" | ||||
| #include "mpeg4audio.h" | ||||
| #include "aac_parser.h" | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <errno.h> | ||||
| @@ -384,12 +385,24 @@ static av_cold int aac_decode_init(AVCodecContext * avccontext) { | ||||
|  | ||||
|     ac->avccontext = avccontext; | ||||
|  | ||||
|     if (avccontext->extradata_size <= 0 || | ||||
|         decode_audio_specific_config(ac, avccontext->extradata, avccontext->extradata_size)) | ||||
|     if (avccontext->extradata_size > 0) { | ||||
|         if(decode_audio_specific_config(ac, avccontext->extradata, avccontext->extradata_size)) | ||||
|             return -1; | ||||
|         avccontext->sample_rate = ac->m4ac.sample_rate; | ||||
|     } else if (avccontext->channels > 0) { | ||||
|         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(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)) | ||||
|             return -1; | ||||
|         ac->m4ac.sample_rate = avccontext->sample_rate; | ||||
|     } else { | ||||
|         ff_log_missing_feature(ac->avccontext, "Implicit channel configuration is", 0); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     avccontext->sample_fmt  = SAMPLE_FMT_S16; | ||||
|     avccontext->sample_rate = ac->m4ac.sample_rate; | ||||
|     avccontext->frame_size  = 1024; | ||||
|  | ||||
|     AAC_INIT_VLC_STATIC( 0, 144); | ||||
| @@ -1506,6 +1519,29 @@ static void spectral_to_sample(AACContext * ac) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int parse_adts_frame_header(AACContext * ac, GetBitContext * gb) { | ||||
|  | ||||
|     int size; | ||||
|     AACADTSHeaderInfo hdr_info; | ||||
|  | ||||
|     size = ff_aac_parse_header(gb, &hdr_info); | ||||
|     if (size > 0) { | ||||
|         if (hdr_info.chan_config) | ||||
|             ac->m4ac.chan_config = hdr_info.chan_config; | ||||
|         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; | ||||
|     } | ||||
|     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; | ||||
|     GetBitContext gb; | ||||
| @@ -1514,6 +1550,13 @@ static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data | ||||
|  | ||||
|     init_get_bits(&gb, buf, buf_size*8); | ||||
|  | ||||
|     if (show_bits(&gb, 12) == 0xfff) { | ||||
|         if ((err = parse_adts_frame_header(ac, &gb)) < 0) { | ||||
|             av_log(avccontext, AV_LOG_ERROR, "Error decoding AAC frame header.\n"); | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // parse | ||||
|     while ((elem_type = get_bits(&gb, 3)) != TYPE_END) { | ||||
|         elem_id = get_bits(&gb, 4); | ||||
|   | ||||
| @@ -22,16 +22,64 @@ | ||||
|  | ||||
| #include "parser.h" | ||||
| #include "aac_ac3_parser.h" | ||||
| #include "aac_parser.h" | ||||
| #include "bitstream.h" | ||||
| #include "mpeg4audio.h" | ||||
|  | ||||
| #define AAC_HEADER_SIZE 7 | ||||
|  | ||||
| int ff_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) | ||||
| { | ||||
|     int size, rdb, ch, sr; | ||||
|     int aot, crc_abs; | ||||
|  | ||||
|     if(get_bits(gbc, 12) != 0xfff) | ||||
|         return AAC_AC3_PARSE_ERROR_SYNC; | ||||
|  | ||||
|     skip_bits1(gbc);             /* id */ | ||||
|     skip_bits(gbc, 2);           /* layer */ | ||||
|     crc_abs = get_bits1(gbc);    /* protection_absent */ | ||||
|     aot     = get_bits(gbc, 2);  /* profile_objecttype */ | ||||
|     sr      = get_bits(gbc, 4);  /* sample_frequency_index */ | ||||
|     if(!ff_mpeg4audio_sample_rates[sr]) | ||||
|         return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; | ||||
|     skip_bits1(gbc);             /* private_bit */ | ||||
|     ch      = get_bits(gbc, 3);  /* channel_configuration */ | ||||
|  | ||||
|     if(!ff_mpeg4audio_channels[ch]) | ||||
|         return AAC_AC3_PARSE_ERROR_CHANNEL_CFG; | ||||
|  | ||||
|     skip_bits1(gbc);             /* original/copy */ | ||||
|     skip_bits1(gbc);             /* home */ | ||||
|  | ||||
|     /* adts_variable_header */ | ||||
|     skip_bits1(gbc);             /* copyright_identification_bit */ | ||||
|     skip_bits1(gbc);             /* copyright_identification_start */ | ||||
|     size    = get_bits(gbc, 13); /* aac_frame_length */ | ||||
|     if(size < AAC_HEADER_SIZE) | ||||
|         return AAC_AC3_PARSE_ERROR_FRAME_SIZE; | ||||
|  | ||||
|     skip_bits(gbc, 11);          /* adts_buffer_fullness */ | ||||
|     rdb = get_bits(gbc, 2);      /* number_of_raw_data_blocks_in_frame */ | ||||
|  | ||||
|     hdr->object_type    = aot; | ||||
|     hdr->chan_config    = ch; | ||||
|     hdr->crc_absent     = crc_abs; | ||||
|     hdr->num_aac_frames = rdb + 1; | ||||
|     hdr->sampling_index = sr; | ||||
|     hdr->sample_rate    = ff_mpeg4audio_sample_rates[sr]; | ||||
|     hdr->samples        = (rdb + 1) * 1024; | ||||
|     hdr->bit_rate       = size * 8 * hdr->sample_rate / hdr->samples; | ||||
|  | ||||
|     return size; | ||||
| } | ||||
|  | ||||
| static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info, | ||||
|         int *need_next_header, int *new_frame_start) | ||||
| { | ||||
|     GetBitContext bits; | ||||
|     int size, rdb, ch, sr; | ||||
|     AACADTSHeaderInfo hdr; | ||||
|     int size; | ||||
|     union { | ||||
|         uint64_t u64; | ||||
|         uint8_t  u8[8]; | ||||
| @@ -40,40 +88,14 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info, | ||||
|     tmp.u64 = be2me_64(state); | ||||
|     init_get_bits(&bits, tmp.u8+8-AAC_HEADER_SIZE, AAC_HEADER_SIZE * 8); | ||||
|  | ||||
|     if(get_bits(&bits, 12) != 0xfff) | ||||
|     if ((size = ff_aac_parse_header(&bits, &hdr)) < 0) | ||||
|         return 0; | ||||
|  | ||||
|     skip_bits1(&bits);          /* id */ | ||||
|     skip_bits(&bits, 2);        /* layer */ | ||||
|     skip_bits1(&bits);          /* protection_absent */ | ||||
|     skip_bits(&bits, 2);        /* profile_objecttype */ | ||||
|     sr = get_bits(&bits, 4);    /* sample_frequency_index */ | ||||
|     if(!ff_mpeg4audio_sample_rates[sr]) | ||||
|         return 0; | ||||
|     skip_bits1(&bits);          /* private_bit */ | ||||
|     ch = get_bits(&bits, 3);    /* channel_configuration */ | ||||
|     if(!ff_mpeg4audio_channels[ch]) | ||||
|         return 0; | ||||
|     skip_bits1(&bits);          /* original/copy */ | ||||
|     skip_bits1(&bits);          /* home */ | ||||
|  | ||||
|     /* adts_variable_header */ | ||||
|     skip_bits1(&bits);          /* copyright_identification_bit */ | ||||
|     skip_bits1(&bits);          /* copyright_identification_start */ | ||||
|     size = get_bits(&bits, 13); /* aac_frame_length */ | ||||
|     if(size < AAC_HEADER_SIZE) | ||||
|         return 0; | ||||
|  | ||||
|     skip_bits(&bits, 11);       /* adts_buffer_fullness */ | ||||
|     rdb = get_bits(&bits, 2);   /* number_of_raw_data_blocks_in_frame */ | ||||
|  | ||||
|     hdr_info->channels = ff_mpeg4audio_channels[ch]; | ||||
|     hdr_info->sample_rate = ff_mpeg4audio_sample_rates[sr]; | ||||
|     hdr_info->samples = (rdb + 1) * 1024; | ||||
|     hdr_info->bit_rate = size * 8 * hdr_info->sample_rate / hdr_info->samples; | ||||
|  | ||||
|     *need_next_header = 0; | ||||
|     *new_frame_start  = 1; | ||||
|     hdr_info->sample_rate = hdr.sample_rate; | ||||
|     hdr_info->channels    = ff_mpeg4audio_channels[hdr.chan_config]; | ||||
|     hdr_info->samples     = hdr.samples; | ||||
|     hdr_info->bit_rate    = hdr.bit_rate; | ||||
|     return size; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										53
									
								
								libavcodec/aac_parser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								libavcodec/aac_parser.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  * AAC parser prototypes | ||||
|  * Copyright (c) 2003 Fabrice Bellard | ||||
|  * Copyright (c) 2003 Michael Niedermayer | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with FFmpeg; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
|  | ||||
| #ifndef AVCODEC_AAC_PARSER_H | ||||
| #define AVCODEC_AAC_PARSER_H | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include "aac_ac3_parser.h" | ||||
| #include "bitstream.h" | ||||
|  | ||||
| typedef struct { | ||||
|     uint32_t sample_rate; | ||||
|     uint32_t samples; | ||||
|     uint32_t bit_rate; | ||||
|     uint8_t  crc_absent; | ||||
|     uint8_t  object_type; | ||||
|     uint8_t  sampling_index; | ||||
|     uint8_t  chan_config; | ||||
|     uint8_t  num_aac_frames; | ||||
| } AACADTSHeaderInfo; | ||||
|  | ||||
| /** | ||||
|  * Parses AAC frame header. | ||||
|  * Parses the ADTS frame header to the end of the variable header, which is | ||||
|  * the first 54 bits. | ||||
|  * @param gbc[in] BitContext containing the first 54 bits of the frame. | ||||
|  * @param hdr[out] Pointer to struct where header info is written. | ||||
|  * @return Returns 0 on success, -1 if there is a sync word mismatch, | ||||
|  * -2 if the version element is invalid, -3 if the sample rate | ||||
|  * element is invalid, or -4 if the bit rate element is invalid. | ||||
|  */ | ||||
| int ff_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr); | ||||
|  | ||||
| #endif /* AVCODEC_AAC_PARSER_H */ | ||||
		Reference in New Issue
	
	Block a user