前段时间一直在搞pcm转aac ,一开始打算直接来一个frame就编码,但发现因为pcm音频包每个packet是320个字节,AAC每个Packet是1024个字节。所以要加入个filter来转换。不过你也可以自己弄个buffer,等包够1024再编码,不建议这样做。如果只是想研究就可以,因为pts那些很烦,很容易导致一些奇怪的问题出现。在此可以参考http://www.cnblogs.com/wanggang123/p/5589488.html博客,我也是从那里偷来的。
先奉上编码的信息,这里不采用重采样,重采样等以后再研究,因为要赶项目的原因。
bool InintEnCodecAACMsg(AVFormatContext *&pFormatCtx, AVStream *&fmt, AVStream *& infmt)
{
pFormatCtx->oformat->audio_codec = AV_CODEC_ID_AAC;
AVCodec* AACCodec = NULL;
AVCodecContext* AACCodecCnt, *srcCodectx;
srcCodectx = infmt->codec;
AACCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!AACCodec)
return false;
fmt = avformat_new_stream(pFormatCtx, AACCodec);
fmt->id = pFormatCtx->nb_streams -1;
AACCodecCnt = fmt->codec;
AACCodecCnt->codec_id = AV_CODEC_ID_AAC;
AACCodecCnt->codec_type = AVMEDIA_TYPE_AUDIO ;
AACCodecCnt->profile = FF_PROFILE_AAC_MAIN;
AACCodecCnt->block_align = 0;
AACCodecCnt->bit_rate = 128000;
AACCodecCnt->channels = 1 ;
AACCodecCnt->sample_rate = Input_Audio_Stream->codec->sample_rate;
AACCodecCnt->sample_fmt = AV_SAMPLE_FMT_S16;
AACCodecCnt->channel_layout = AV_CH_LAYOUT_MONO;;
// AACCodecCnt->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
fmt->time_base = {1,AACCodecCnt->sample_rate};
fmt->codec->codec_tag = 0;
//Format wants global header,outputStream.flags : Place global headers in extradata instead of every keyframe.H264输出时候必要
if( pFormatCtx->oformat->flags |= AVFMT_GLOBALHEADER)
fmt->codec->flags |= CODEC_FLAG_GLOBAL_HEADER ;
if (avcodec_open2(AACCodecCnt, AACCodec, NULL) < 0)
{
qDebug() << QString("InintEnCodecAACMsg, can not open the codec ");
return false;
}
return true;
}
github地址:https://github.com/zoring/FFmpegProject
在上次弄完后没有好好测试,导致了这重采样根本是不成功的。原因是在 av_buffersink_set_frame_size(buffersink_ctx, 1024);然后只要你将sample_rate变成一个48k后,你会惊奇发现,那里一直报waring queue input is backward in time还有一个是1000 buffers queue in out。遇到这个错误简直让人痛苦万分,因为在16k的情况下,那一切安然无恙。
这一切的原因就是av_buffersink_set_frame_size导致。这个函数意思是从buffer sink.拿到1024simplate大小的Frame。那么16变48后,那个1frame的大小也会变成3倍,这里是指单声道变双声道。然后你每次只要一个1024大小的,那么铁定会导致buffer不断增加。要解决上述问题,要将av_buffersink_set_frame_size注释到,然后自己弄多个fifo的buffer,那样,只要每次将它编到小于1024时候,那样问题就解决了。