AAC ADTS封装实现

一、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;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值