libfdk_aac编码AAC

目录

前言

1、AAC介绍

2、AAC 格式

一、libfdk_aac介绍

二、libfdk_aac主要API介绍

1、AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder,const UINT encModules,const UINT maxChannels);

2、AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER  hAacEncoder,const AACENC_PARAM param,const UINT value);

3、AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER  hAacEncoder,AACENC_InfoStruct  *pInfo);

4、AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER  hAacEncoder,const AACENC_BufDesc  *inBufDesc,const AACENC_BufDesc  *outBufDesc,const AACENC_InArgs  *inargs,AACENC_OutArgs *outargs);

5、AACENC_ERROR aacEncClose( HANDLE_AACENCODER *phAacEncoder);

三、libfdk_aac编码示例

四、AAC编码器软件框架


《libfdk-aac实现PCM编码AAC代码实现》链接:

https://edu.csdn.net/learn/38258/606136?spm=1003.2001.3001.4157

前言

1、AAC介绍

      AAC(高级音频编码) 是一种用于有损数字音频压缩的音频编码标准。作为MP3格式的继承者,AAC 在相同比特率下通常可以实现比 MP3 编码器更高的音质;早在1997 年AAC 已被ISO和IEC 标准化为MPEG-2和MPEG-4规范的一部分。AAC 提供 8 kHz 到 96 kHz 之间的采样频率和 1 到 48 之间的任意数量的通道;默认情况下,AAC编码将使用更长的 1024 点/960 点进行压缩编码。AAC属于MPEG-2和MPEG-4规范的一部分,具有复杂的规格,共分为9种规格/档次,如下:
MPEG-2 AAC:
    1、MPEG-2 AAC LC低复杂度规格(Low Complexity);
    2、MPEG-2 AAC Main主规格;
    3、MPEG-2 AAC SSR可变取样率规格(Scaleable Sample Rate);
MPEG-4 AAC:
    4、MPEG-4 AAC LC低复杂度规格(Low Complexity),现在的手机比较常见的MP4格式中的音频部份就包括了该种规格的音频;
    5、MPEG-4 AAC Main主规格;
    6、MPEG-4 AAC SSR可变取样率规格(Scaleable Sample Rate);
    7、MPEG-4 AAC LTP长时期预测规格(Long Term Predicition);
    8、MPEG-4 AAC LD低延迟规格(Low Delay);
    9、MPEG-4 AAC HE高效率规格(High Efficiency)。

2、AAC 格式

       MPEG-2 中定义了AAC的两种格式分别用于文件存储的ADIF(音频数据交换格式),以及用于传输流中传输数据的ADTS(音频数据传输流)格式。

       ADIF格式的AAC音频流由ADIF头数据和AAC音频流组成,通常一个文件中只有一个ADIF头,也就是说ADIF格式的AAC解码必须从文件头部第一帧开始解码。如下图所示在AAC 编码数据流之前有一个ADIF的头信息。
320a06f486e24cb1b5aca30ab2fc588c.png         在AAC标准文档中对ADIF码流格式的介绍如下图1,一个ADIF的音频序列,中首先是ADIF的头,和对齐字节,之后是编码的原始数据流。下图2是ADIF Header的的定义。
28b54bbc9a6340e0949a24d75ddc9549.png                                                                             图1

cd78451790034a4fb42231e89915a0b9.png                                                                图2

       在ADTS格式的音频流中每个音频帧头部有包含一个ADTS的头;和ADIF不同ADTS格式的音频可以从任意一帧AAC音频数据进行解码,无需从音频一帧进行解码。ADTS格式的音频数据流如下图所示。

       在AAC标准文档中对ADTS码流格式的介绍如下图3;ADTS格式的音频数据通过SyncWord来进行判断下一帧音频。

5feae47776054b3994f2948ef6cd6ef1.png

图3

          如下图4,是ADTS格式一帧音频的格式。一帧音频包含了ADTS的固定头adts_fixed_header和可变头adts_variable_header,adts错误检查字段,以及aac编码后的原始数据raw_data_block。

e48007ce54bb4e538f5c18dfc6939ca1.png

图4

     下图5是ADTS的头信息定义,包含了固定头(Fixed Header)和可变头(Variable Header)。可以看出在ADTS的固定头中包含了AAC编码的档次、通道数、采样率索引等。在可变头中包含了帧长度等信息。ADTS的头信息共56Bit(7个字节),在RTP传输ADTS格式的音频时候通常去掉7个字节的ADTS头数据,在解码端重新组装ADTS的头。

43a29d934698460b82ddf630990d752e.png

图5

一、libfdk_aac介绍

       libfdk_aac是一个开源库,用于以AAC 格式对数字音频数据进行编码和解码。它支持多种音频对象类型,包括MPEG-2和MPEG-4 AAC LC、HE-AAC (AAC LC + SBR )、HE-AACv2 (LC + SBR + PS ) 以及AAC-LD (low延迟)和 AAC-ELD(增强低延迟)。编码库支持采样率8~ 96 kHz ,最多可以支持8 个通道(7.1 环绕声)。fdk_aac 支持的音频对象如下表1。

                            表1

AAC Profile名称MPEG-4 Audio object typeFDK_AAC是否支持
低复杂度 (AAC-LC)2YES
高效 (HE-AAC)2、5YES
高效版本 2 (HE-AAC)2、5、29YES
低延迟 (AAC-LD)23YES
增强型低延迟 (AAC-ELD)39YES

         fdk_aac 支持的音频采样率下表2。

表2

采样率80001102512000160002205024000320004410048000640008820096000

         libfdk_aac源码下载路径为github:https://github.com/mstorsjo/fdk-aac.git。

二、libfdk_aac主要API介绍

1、AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder,const UINT encModules,const UINT maxChannels);

       该函数用于打开AAC编码器,成功返回0;函数共有3个参数;phAacEncoder:成功打开编码器后返回AAC编码器的句柄;encModules:通常默认0,表示编码器内部分配内存maxChannels:音频通道数,范围1~8。

2、AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER  hAacEncoder,const AACENC_PARAM param,const UINT value);

      该函数用于设置AAC编码器参数。成功返回0;函数共有3个参数;phAacEncoder:编码句柄;param:编码器参数类型详细见表3;value:参数值。param常见的取值如下表3所示,详细类型定义在AACENC_PARAM中;主要包含音频对象规格、码率、采样率、帧长度、声道模式、编码帧类型等。

表3

AAC 参数类型参数说明参数取值范围
AACENC_AOT音频对象类型2: MPEG-4 AAC Low Complexity等详细见表1
AACENC_BITRATE编码码率如64k,96k等
AACENC_BITRATEMODE码率模式0:CBR固定码率,1-7其他模式
AACENC_SAMPLERATE音频采样率48000,44100等,详细见表2
AACENC_SBR_MODE音普带复制在ELD( Enhanced Low-Delay.)下参数配置
AACENC_GRANULE_LENGTH编码帧长度1024  512  480
AACENC_CHANNELMODE声道模式单声道、双声道、8声道等
AACENC_CHANNELORDER输入音频声道排列方式0:采用MPEG声道排列方式。1:采用wav声道排列方式
AACENC_AFTERBURNER通过消耗内存和CPU来提升音质0:关闭,1:开启
AACENC_BANDWIDTH编码带宽0:编码器内部决定带宽,其他值表示配置等目标带宽
AACENC_TRANSMUX编码帧类型0:原始编码帧,1:带有ADIF头的编码帧,2:带有ADTS头的编码帧,其他:6/7/10

3、AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER  hAacEncoder,AACENC_InfoStruct  *pInfo);

        该函数用于获取编码器信息。函数有2个参数;hAacEncoder编码器句柄;pInfo:编码器信息。AACENC_InfoStruct的定义如下;主要包含声道数、帧长度、编码延长等。

typedef struct {

    UINT     maxOutBufBytes;      /*!< Maximum number of encoder bitstream bytes within one frame.
                                                  Size depends on maximum number of supported channels in encoder instance.
                                                  For superframing (as used for example in DAB+), size has to be a multiple accordingly. */

    UINT      maxAncBytes;         /*!< Maximum number of ancillary data bytes which can be inserted into
                                                  bitstream within one frame. */

    UINT     inBufFillLevel;      /*!< Internal input buffer fill level in samples per channel. This parameter
                                                  will automatically be cleared if samplingrate or channel(Mode/Order) changes. */

    UINT      inputChannels;       /*!< Number of input channels expected in encoding process. */

    UINT       frameLength;         /*!< Amount of input audio samples consumed each frame per channel, depending
                                                  on audio object type configuration. */

    UINT      encoderDelay;        /*!< Codec delay in PCM samples/channel. Depends on framelength and AOT. Does not
                                                  include framing delay for filling up encoder PCM input buffer. */

    UCHAR    confBuf[64];         /*!< Configuration buffer in binary format as an AudioSpecificConfig
                                                  or StreamMuxConfig according to the selected transport type. */

    UINT      confSize;            /*!< Number of valid bytes in confBuf. */

} AACENC_InfoStruct;

4、AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER  hAacEncoder,const AACENC_BufDesc  *inBufDesc,const AACENC_BufDesc  *outBufDesc,const AACENC_InArgs  *inargs,AACENC_OutArgs *outargs);

          该函数用于编码一帧音频数据并输出编码后的音频帧。该函数有5个参数;hAacEncoder:编码器句柄;inBufDesc:输入原始PCM音频数据;outBufDesc:输出编码后的AAC音频数据;inargs:输入原始PCM音频参数,如输入音频所有通道的采样点数;outargs:输出编码后AAC音频参数,如输出AAC帧长度等。

5、AACENC_ERROR aacEncClose( HANDLE_AACENCODER *phAacEncoder);

       该函数用于关闭AAC编码器。

三、libfdk_aac编码示例

1、打开编码器,初始化编码器参数

static HANDLE_AACENCODER init_fdk_aac(int sample_rate,int channels,int bitrate)
{
    HANDLE_AACENCODER handle;
	CHANNEL_MODE mode;
    int aot = 2; //lc 低复杂度,算法速度快
    switch (channels) {
	case 1: mode = MODE_1;       break;
	case 2: mode = MODE_2;       break;
	case 3: mode = MODE_1_2;     break;
	case 4: mode = MODE_1_2_1;   break;
	case 5: mode = MODE_1_2_2;   break;
	case 6: mode = MODE_1_2_2_1; break;
	default:
		fprintf(stderr, "Unsupported WAV channels %d\n", channels);
		return NULL;
	}
    //打开aac 编码器
    if (aacEncOpen(&handle, 0, channels) != AACENC_OK) {
		fprintf(stderr, "Unable to open encoder\n");
		return NULL;
	}
    //设置算法模式 lc等
	if (aacEncoder_SetParam(handle, AACENC_AOT, aot) != AACENC_OK) {
		fprintf(stderr, "Unable to set the AOT\n");
		return NULL;
	}
    //设置编码输入帧长
    if (aacEncoder_SetParam(handle, AACENC_GRANULE_LENGTH, 1024) != AACENC_OK) {
		fprintf(stderr, "Unable to set the audio frame length\n");
		return NULL;
	}
    //设置采样率
	if (aacEncoder_SetParam(handle, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) {
		fprintf(stderr, "Unable to set the AOT\n");
		return NULL;
	}
    //声道模式
	if (aacEncoder_SetParam(handle, AACENC_CHANNELMODE, mode) != AACENC_OK) {
		fprintf(stderr, "Unable to set the channel mode\n");
		return NULL;
	}
    //设置pcm数据格式
	if (aacEncoder_SetParam(handle, AACENC_CHANNELORDER, 1) != AACENC_OK) {
		fprintf(stderr, "Unable to set the wav channel order\n");
		return NULL;
	}
    //设置编码码率
    if (aacEncoder_SetParam(handle, AACENC_BITRATE, bitrate) != AACENC_OK) {
        fprintf(stderr, "Unable to set the bitrate\n");
        return NULL;
    }
	//设置编码帧为ADTS格式
	if (aacEncoder_SetParam(handle, AACENC_TRANSMUX, TT_MP4_ADTS) != AACENC_OK) {
		fprintf(stderr, "Unable to set the ADTS transmux\n");
		return NULL;
	}
    //初始化 handle
	if (aacEncEncode(handle, NULL, NULL, NULL, NULL) != AACENC_OK) {
		fprintf(stderr, "Unable to initialize the encoder\n");
		return NULL;
	}
	//获取音频编码信息
	if (aacEncInfo(handle, &g_aacInfo) != AACENC_OK) {
		fprintf(stderr, "Unable to get the encoder info\n");
		return NULL;
	}

    return handle;
}

2、关闭编码器

static void deInit_fdk_aac(HANDLE_AACENCODER *pHandle)
{
    aacEncClose(pHandle);
}

3、编码PCM音频帧为AAC

static int fdk_aac_enc(HANDLE_AACENCODER *pHandle,uint16_t *pInPcmData,int inputSize,uint8_t *pOutBuff,int outBuffsize)
{
    AACENC_ERROR err;
    AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };
	AACENC_InArgs in_args = { 0 };
	AACENC_OutArgs out_args = { 0 };
    int in_identifier = IN_AUDIO_DATA;
    int out_identifier = OUT_BITSTREAM_DATA;
    int in_size = inputSize, in_elem_size = 2;
    while(1)
    {
        void *in_ptr = pInPcmData;
		//输入参数和输入buff配置
        in_args.numInSamples = inputSize <= 0 ? -1 : inputSize/in_elem_size;//输入数据中所有声道采样点个数
		in_buf.numBufs = 1;   //输入buff个数
		in_buf.bufs = &in_ptr; //输入PCM音频地址
		in_buf.bufferIdentifiers = &in_identifier;//输入
		in_buf.bufSizes = &in_size;  //输入PCM大小
		in_buf.bufElSizes = &in_elem_size;//每个采样点数据类型(大小)short
        //输出参数和输出buff配置
		void * out_ptr = pOutBuff; 
		int out_size = outBuffsize;
		int out_elem_size = 1;   //输出每个
		out_buf.numBufs = 1; //输出buff个数
		out_buf.bufs = &out_ptr;//输出buff的地址
		out_buf.bufferIdentifiers = &out_identifier;
		out_buf.bufSizes = &out_size;//输出buff的大小
		out_buf.bufElSizes = &out_elem_size;//输出数据类型(大小)char
        if ((err = aacEncEncode(*pHandle, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) {
			if (err == AACENC_ENCODE_EOF)
				break;
			fprintf(stderr, "Encoding failed\n");
			return 0;
		}
		if (out_args.numOutBytes == 0)
			continue;
        break;
    }

    return out_args.numOutBytes;
}

四、AAC编码器软件框架

 AAC编码代码实现请参考 <音频数据进行AAC编码课程>

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值