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];