faad库实现aac编解码流程:
自定义一个结构体:
typedef struct
{
long bytes_in_buffer;//当前缓存的待处理的总数据量
long bytes_consumed;//当前缓存中已经消耗数据量
long file_offset;//当前处理到的位置(相对于文件的偏移)
unsigned char *buffer; //缓存 准备足够大 malloc(FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
int at_eof;//文件结束标志
FILE *infile;//输入文件操作句柄
FILE *pOutputFile;//输出文件句柄
} aac_buffer;
#define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */
#define MAX_CHANNELS (8)
1、创建解码器
NeAACDecHandle NEAACDECAPI NeAACDecOpen(void);
2、配置解码器 //对于原始AAC数据是必须的 否则解码器不知道音频封装信息
//对于ADTS封装的AAC 不需要设置 解码器可以从视频数据中获取
NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder);
//输入的参数为第一步创建的解码器的句柄,返回为解码器配置参数的结构体的指针。获取失败则会返回为空。
设置参数如下:
conf->defObjectType = LC;//类型
conf->defSampleRate = sampleRate;//采样率
conf->outputFormat = FAAD_FMT_16BIT;//保存音频的位数
conf->dontUpSampleImplicitSBR = 1;//SBR标志
unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hDecoder,
NeAACDecConfigurationPtr config);
//函数中,第一个参数为解码器句柄,第二个为我们的的配置结构体的指针对象。返回值为0时代表配置失败。
//数据初始化
long NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, //解码器句柄
unsigned char *buffer, //输入数据的指针
unsigned long buffer_size, // 输入数据的长度
unsigned long *samplerate, //保存从aac数据中获取的编码的采样率
unsigned char *channels); //保存从aac数据中获取的编码的通道数
//返回非0则代表成功。此方法只需要在解码数据前调用一次,无需重复调用。其中输入的数据最好多余一个aac数据包,以便正确解析数据。
解码AAC数据//每次输入一帧ADTS 解码为PCM 利用同步数据为0xfff来分割aac数据帧
void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder, //解码器句柄
NeAACDecFrameInfo *hInfo, //解码frame的信息
unsigned char *buffer, //需要解码的数据指针
unsigned long buffer_size); //需要解码的数据的长度
//NeAACDecFrameInfo *hInfo.error>0表示解码失败
//我们可以根据第二个参数返回的 unsigned long samples;unsigned char channels;两个属性进行手动计算PCM数据的大小,然后从返回指针的起始地址读取相应的字节数,这时候此段内存中保存的数据即为解码的PCM数据。
关闭解码器:
void NEAACDECAPI NeAACDecClose(NeAACDecHandle hDecoder);
音频编解码基础(wav/aac/pcma/pcmu)
此人的函数:
do{
//抛弃已经使用过的数据 将buf中用掉的长度移除
advance_buffer(&g_AacBuffer, lOffset);
//空的缓存填充新的数据---为buf补充用掉的长度使之回到最初的长度
fill_buffer(&g_AacBuffer);
lOffset=0;
while(1)
{
int iConsumNum=0;
int iRet = getADTSframe(g_AacBuffer.buffer+lOffset, g_AacBuffer.bytes_into_buffer-lOffset,&iConsumNum, pTempBuffer ,&(iFrameSize));
if(iRet == 0)//找到一个frame
{
lOffset+=iConsumNum;
AdtsHeadInfo stHeadInfo;
if(ParserAdtsHead(pTempBuffer ,iFrameSize,&stHeadInfo))//解析一帧提取一帧的头的几个数据
printf("Profile:%02d\tChans:%02d\tSampleRate:%05d\tHeadSize:%01d\tFrameSize:%06d\t\n",stHeadInfo.iProfile,stHeadInfo.iChans,stHeadInfo.iSampleRate,stHeadInfo.iHeadLen,stHeadInfo.iFrameSize);
}
else if(iRet == 1){//buf长度不够一个frame
lOffset+=iConsumNum;
break;
}
}
}while(没有读到文件结尾);