一、AAC音频格式种类有哪些
AAC音频格式是一种由MPEG-4标准定义的有损音频压缩格式。AAC包含两种封装格式 ADIF(Audio Data Interchange Format音频数据交换格式)和ADTS(Audio Data transport Stream音频数据传输流)。
ADIF
特点:可以确定的找到音视频数据的开始,不需要进行在音视频数据流中间开始的解码,它的解码必须在明确的定义开始。
应用场景:常用在磁盘文件中。
ADTS
特点:具有同步字的比特流,解码可以在这个流中任何位置开始。类似于mp3数据流格式。
应用场景:应用比较广泛,可用于网络直播等。
二、ADIF和ADTS的区别
1、解码
ADTS:每一帧都有头信息,因此可以在任意帧解码;
ADIF:只有一个头信息,需要得到所有的数据后才能解码。
2、头格式
(1)AAC ADIF格式
(2)AAC ADTS格式
空白处表示前后帧
有时候我们在编码AAC裸流的时候,会遇到写出来的AAC文件不能在PC和手机上播放,很大的可能就是AAC文件的每一帧缺少了ADTS头信息文件的包装拼接。如果是这种情况,我们只需要加入头文件ADTS即可。
三、ADTS详解
ADTS是帧序列,本身具备流特征,在音频流的传输与处理方面更加合适。
ADTS帧生成方法:一个AAC原始数据块长度是可变的,对原始帧加上ADTS头进行ADTS的封装,就形成了ADTS帧。
AAC音频文件的每一帧由ADTS header和AAC Audio Data组成。每一帧的ADTS头文件都包含了音频的采样率、声道、帧长等信息。
ADTS头由固定头信息(adts_fixed_header)和可变头信息(adts_variable_header)组成,一般情况下共7个字节,如果添加校验则为9个字节。
1、固定头信息(adts_fixed_header)
数据结构定义:
No.of bits Mnemonic
adts_fixed_header()
{
syncword; 12bit bslbf
ID; 1bit bslbf
layer; 2bit uimsbf
protection_absent; 1bit bslbf
profile; 2bit uimsbf
sampling_frequency_Index; 4bit uimsbf
private_bit; 1bit bslbf
channel_configuration; 3bit uimsbf
original_copy; 1bit bslbf
home; 1bit bslbf
}
参数说明:
(1)syncword:同步头,总是0xFF,所有的bit都必须设置为1,表示一个ADTS帧的开始。
(2)ID:MPEG表示符,0:标识MPEG-4,1:标识MPEG-2。
(3)layer:一般设置为‘00’。
(4)protection_absent:表示是否要做校验,0:校验,1:不校验。
(5)profile:表示使用哪个级别的AAC,如01 Low Complexity(LC)AAC LC。
(6)sampling_frequency_Index:表示使用的采样率下标,通过这个下标可在Sampling Frequencies[]数组查找得知采样率的值。
(7)channel_configuration:表示声道数,取值如下,比如2表示立体声双声道。
0: Defined in AOT Specifc Config
1: 1 channel: front-center
2: 2 channels: front-left, front-right
3: 3 channels: front-center, front-left, front-right
4: 4 channels: front-center, front-left, front-right, back-center
5: 5 channels: front-center, front-left, front-right, back-left, backright
6: 6 channels: front-center, front-left, front-right, back-left, backright,
LFE-channel
7: 8 channels: front-center, front-left, front-right, side-left, side-right,
back-left, back-right, LFE-channel
8-15: Reserved
2、可变头信息(adts_variable_header)
No.of bits Mnemonic
adts_variable_header()
{
copyright_identification_bit; 1bit bslbf
copyright_identification_start; 1bit bslbf
aac_frame_length; 13bit bslbf
adts_buffer_fullness; 11bit bslbf
number_of_raw_data_blocks_in_frame; 2bit uimsbf
}
(1)frame_length : 1个ADTS帧的长度,包括ADTS头和AAC原始流,
frame length, this value must include 7 or 9 bytes of header length:
aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame)
protection_absent=0时, header length=9bytes
protection_absent=1时, header length=7bytes
(2)adts_buffer_fullness:0x7FF 说明是码率可变的码流。
(3)number_of_raw_data_blocks_in_frame:表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。所以说number_of_raw_data_blocks_in_frame = 0 表示说ADTS帧中有1个AAC数据块。
3、实例数据分析ADTS的ACC文件部分
高字节开始算
第一帧的帧头7个字节为:0xFF 0xF1 0x4C 0x40 0x20 0xFF 0xFC
根据固定头信息和可变头信息数据格式,分析各个关键数值:
111111111111
0
00
1
01
0011
0
001
0
0
0
0
0000100000111(帧长度,转换为十进制为263)
11111111111
00
帧长度计算方法(帧长度为13位,使用unsigned int来存储帧长数值):
unsigned int getFrameLength(unsigned char* str)
{
if ( !str )
{
return 0;
}
unsigned int len = 0;
int f_bit = str[3];
int m_bit = str[4];
int b_bit = str[5];
len += (b_bit>>5);
len += (m_bit<<3);
len += ((f_bit&3)<<11);
return len;
}
4、提取音频数据合成音频文件实现
把一个音视频文件的音频提取出来,合成音频文件并保存到本地。
实现流程
源码实现
(1)循环读取文件处理audio模块
while(av_read_frame(ifmt_ctx, &pkt) >=0 )
{
if(pkt.stream_index == audio_index)
{
char adts_header_buf[7] = {0};
adts_header(adts_header_buf, pkt.size,
ifmt_ctx->streams[audio_index]->codecpar->profile,
ifmt_ctx->streams[audio_index]->codecpar->sample_rate,
ifmt_ctx->streams[audio_index]->codecpar->channels);
//对于FFmpeg来说,MP4和flv是不带ADTS header,所以这里需要对ADTS header进行封装
fwrite(adts_header_buf, 1, 7, aac_fd); // 写adts header , ts流不适用,ts流分离出来的packet带了adts header
len = fwrite( pkt.data, 1, pkt.size, aac_fd); // 写adts data
}
av_packet_unref(&pkt);
}
(2)ADTS header封装源码
const int sampling_frequencies[] = {
96000, // 0x0
88200, // 0x1
64000, // 0x2
48000, // 0x3
44100, // 0x4
32000, // 0x5
24000, // 0x6
22050, // 0x7
16000, // 0x8
12000, // 0x9
11025, // 0xa
8000 // 0xb
// 0xc d e f是保留的
};
int adts_header(char * const p_adts_header, const int data_length,
const int profile, const int samplerate,
const int channels)
{
int sampling_frequency_index = 3; // 默认使用48000hz
int adtsLen = data_length + 7; //这里不做校验,直接+7个字节用于存放ADTS header
int frequencies_size = sizeof(sampling_frequencies) / sizeof(sampling_frequencies[0]);
int i = 0;
for(i = 0; i < frequencies_size; i++)
{
if(sampling_frequencies[i] == samplerate)
{
sampling_frequency_index = i;
break;
}
}
if(i >= frequencies_size)
{
printf("unsupport samplerate:%d\n", samplerate);
return -1;
}
p_adts_header[0] = 0xff; //syncword:0xfff 高8bits
p_adts_header[1] = 0xf0; //syncword:0xfff 低4bits
p_adts_header[1] |= (0 << 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2 1bit
p_adts_header[1] |= (0 << 1); //Layer:0 2bits
p_adts_header[1] |= 1; //protection absent:1 1bit
p_adts_header[2] = (profile)<<6; //profile:profile 2bits
p_adts_header[2] |= (sampling_frequency_index & 0x0f)<<2; //sampling frequency index:sampling_frequency_index 4bits
p_adts_header[2] |= (0 << 1); //private bit:0 1bit
p_adts_header[2] |= (channels & 0x04)>>2; //channel configuration:channels 高1bit
p_adts_header[3] = (channels & 0x03)<<6; //channel configuration:channels 低2bits
p_adts_header[3] |= (0 << 5); //original:0 1bit
p_adts_header[3] |= (0 << 4); //home:0 1bit
p_adts_header[3] |= (0 << 3); //copyright id bit:0 1bit
p_adts_header[3] |= (0 << 2); //copyright id start:0 1bit
p_adts_header[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bits
p_adts_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3); //frame length:value 中间8bits
p_adts_header[5] = (uint8_t)((adtsLen & 0x7) << 5); //frame length:value 低3bits
p_adts_header[5] |= 0x1f; //buffer fullness:0x7ff 高5bits
p_adts_header[6] = 0xfc; //11111100 //buffer fullness:0x7ff 低6bits
// number_of_raw_data_blocks_in_frame:
// 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。
return 0;
}