AAC是一种常见的音频格式,今天尝试使用ffmpeg把pcm压缩成AAC编码。
第一步:初始化编码相关变量
寻找AAC的编码器
codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
初始化编码器上下文,主要通道数,采样率,采样格式
c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate audio codec context\n");
return false;
}
c->channels = m_PcmChannel;
c->channel_layout = av_get_default_channel_layout(m_PcmChannel);
c->sample_rate = m_PcmSampleRate;
c->sample_fmt = AV_SAMPLE_FMT_FLTP;//AV_SAMPLE_FMT_FLTP;
c->bit_rate = 64000;
/* Allow the use of the experimental AAC encoder. */
c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
打开编码器
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
return false;
}
设置格式转换,主要是AAC需要的采样格式位AV_SAMPLE_FMT_FLTP,而PCM格式位AV_SAMPLE_FMT_S16,所以需要进行格式的转换。
resample_context = swr_alloc_set_opts(NULL, c->channel_layout, c->sample_fmt,
c->sample_rate, c->channel_layout, m_PcmFormat, c->sample_rate, 0, NULL);
if (swr_init(resample_context) < 0)
{
fprintf(stderr, "Could not open resample context\n");
return false;
}
第二步:初始化相关工作做完之后,可以进行转码工作,首先丢进。
对PCM进行重新采样,转换成AAC需要的PCM格式
if (swr_convert(resample_context, frame->extended_data, frame->nb_samples, (const uint8_t**)m_PcmPointer, 1024)<0)
{
fprintf(stderr, "Could not convert input samples (error )\n");
if (NULL != frame)
{
av_frame_free(&frame);
}
return ;
}
放进编码器
ret = avcodec_send_frame(c, frame);
第三步:从编码器取出编码完的数据
int ret = avcodec_receive_packet(c, packet);
第四步:由于编码后的AAC文件没有头,导致写成文件无法识别,所以需要手动写入AAC头
// fill in ADTS data
m_pOutData[0] = 0xFF;
m_pOutData[1] = 0xF1;
m_pOutData[2] = ((profile) << 6) + (freqIdx << 2) + (chanCfg >> 2);
m_pOutData[3] = (((chanCfg & 3) << 6) + (packetLen >> 11));
m_pOutData[4] = ((packetLen & 0x7FF) >> 3);
m_pOutData[5] = (((packetLen & 7) << 5) + 0x1F);
m_pOutData[6] = 0xFC;
至此,PCM转成AAC的格式流程结束。
这里对AVSampleFormat格式进行一下介绍,
如果是以下格式:
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double
只能保存再AVFrame的uint8_t *data[0];
音频保持格式如下:
LRLRLR。。。。
如果是以下格式
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar
plane 0: LLLLLLLLLLLLLLLLLLLLLLLLLL...
plane 1: RRRRRRRRRRRRRRRRRRRR....
plane 0对于uint8_t *data[0];
plane 1对于uint8_t *data[1];
为了便于大家学习和研究, 工程采用VS2017开发,地址如下:
https://download.csdn.net/download/g0415shenw/10599101