使用FAAD解码AAC音频为PCM数据流程可以参考下面的文章
http://blog.csdn.net/gavinr/article/details/6959198#reply
-
-
-
-
-
#include <stdio.h>
-
#include <memory.h>
-
#include "faad.h"
-
-
#define FRAME_MAX_LEN 1024*5
-
#define BUFFER_MAX_LEN 1024*1024
-
-
void show_usage()
-
{
-
printf("usagenfaaddec src_file dst_file");
-
}
-
-
-
-
-
int get_one_ADTS_frame(unsigned char* buffer, size_t buf_size, unsigned char* data ,size_t* data_size)
-
{
-
size_t size = 0;
-
-
if(!buffer || !data || !data_size )
-
{
-
return -1;
-
}
-
-
while(1)
-
{
-
if(buf_size < 7 )
-
{
-
return -1;
-
}
-
-
if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) )
-
{
-
size |= ((buffer[3] & 0x03) <<11);
-
size |= buffer[4]<<3;
-
size |= ((buffer[5] & 0xe0)>>5);
-
break;
-
}
-
--buf_size;
-
++buffer;
-
}
-
-
if(buf_size < size)
-
{
-
return -1;
-
}
-
-
memcpy(data, buffer, size);
-
*data_size = size;
-
-
return 0;
-
}
-
-
int main(int argc, char* argv[])
-
{
-
static unsigned char frame[FRAME_MAX_LEN];
-
static unsigned char buffer[BUFFER_MAX_LEN] = {0};
-
-
char src_file[128] = {0};
-
char dst_file[128] = {0};
-
FILE* ifile = NULL;
-
FILE* ofile = NULL;
-
-
unsigned long samplerate;
-
unsigned char channels;
-
NeAACDecHandle decoder = 0;
-
-
size_t data_size = 0;
-
size_t size = 0;
-
-
NeAACDecFrameInfo frame_info;
-
unsigned char* input_data = buffer;
-
unsigned char* pcm_data = NULL;
-
-
-
if(argc < 3)
-
{
-
show_usage();
-
return -1;
-
}
-
sscanf(argv[1], "%s", src_file);
-
sscanf(argv[2], "%s", dst_file);
-
-
-
ifile = fopen(src_file, "rb");
-
ofile = fopen(dst_file, "wb");
-
if(!ifile || !ofile)
-
{
-
printf("source or destination file");
-
return -1;
-
}
-
-
data_size = fread(buffer, 1, BUFFER_MAX_LEN, ifile);
-
-
-
decoder = NeAACDecOpen();
-
if(get_one_ADTS_frame(buffer, data_size, frame, &size) < 0)
-
{
-
return -1;
-
}
-
-
-
NeAACDecInit(decoder, frame, size, &samplerate, &channels);
-
printf("samplerate %d, channels %dn", samplerate, channels);
-
-
while(get_one_ADTS_frame(input_data, data_size, frame, &size) == 0)
-
{
-
-
-
-
pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, frame, size);
-
-
if(frame_info.error > 0)
-
{
-
printf("%sn",NeAACDecGetErrorMessage(frame_info.error));
-
-
}
-
else if(pcm_data && frame_info.samples > 0)
-
{
-
printf("frame info: bytesconsumed %d, channels %d, header_type %d
-
object_type %d, samples %d, samplerate %dn",
-
frame_info.bytesconsumed,
-
frame_info.channels, frame_info.header_type,
-
frame_info.object_type, frame_info.samples,
-
frame_info.samplerate);
-
-
fwrite(pcm_data, 1, frame_info.samples * frame_info.channels, ofile);
-
fflush(ofile);
-
}
-
data_size -= size;
-
input_data += size;
-
}
-
-
NeAACDecClose(decoder);
-
-
fclose(ifile);
-
fclose(ofile);
-
-
return 0;
-
}
之前用FAAC编码了一段PCM数据(源数据是16000采样率,单通道,16位取样),编码时设置的参数也是16000采样率,单通道,16位取样。。。然后用FAAD解码时,在NeAACDecInit的时候,是先在之前编码好的aac数据(ADTS头封装的)上往buffer中写入一帧的含ADTS头的数据,然后传入到NeAACDecInit()中初始化解码器,但不知道为什么,返回的采样率总是32000,通道数总是2,我已经查看过编码后的数据,其中与采样率、通道数相应的位,表示的就是16000采样率和1通道。。
后来跟踪源码才发现 FAAD的NeAACDecInit() 源代码,问题出现在这里
-
long NEAACDECAPI NeAACDecInit(NeAACDecHandle hpDecoder,
-
unsignedchar *buffer,
-
unsignedlong buffer_size,
-
unsignedlong *samplerate,
-
unsignedchar *channels)
-
{
-
-
#if (defined(PS_DEC) || defined(DRM_PS))
-
-
if (*channels == 1)
-
{
-
-
*channels = 2;
-
}
-
#endif
-
-
hDecoder->channelConfiguration = *channels;
-
-
#ifdef SBR_DEC
-
-
if (*samplerate <= 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0))
-
{
-
*samplerate *= 2;
-
hDecoder->forceUpSampling = 1;
-
}
-
else if (*samplerate > 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0)) {
-
hDecoder->downSampledSBR = 1;
-
}
-
#endif
-
}
上面那些宏,在源代码中貌似已经定死了,不是通过条件编译生成的,
也就是 PS_DEC 和 SBR_DEC是define过的...也不是通过./configure 的时候生成的...
再仔细看上面代码的if语句
if (*samplerate <= 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0))
只要让 hDecoder->config.dontUpSampleImplicitSBR 不为0 不就OK吗?
我们看看在neaacdec.h 文件中该结构体NeAACDecConfiguration 的定义
现在解决这个问题就简单了,初始化前把参数dontUpSampleImplicitSBR设置为1即可。
NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
conf->defObjectType = LC;
conf->defSampleRate = 8000; //real samplerate/2
conf->outputFormat = FAAD_FMT_16BIT ; //
conf->dontUpSampleImplicitSBR = 1;
NeAACDecSetConfiguration(decoder, conf);
最后吐槽一下。在从官网下载的faad 说明文档 对NeAACDecConfiguration 这个结构体说明,
居然没有dontUpSampleImplicitSBR这个成员,太坑爹了
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/coloriy/article/details/52053144
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。