1. 初始化
AVCodecContext *m_avctx;
AVCodec *m_codec;
/* Init ffmpeg log */
ffmpeg_log_callback pcb_log = libffmpeg_log_callback;
av_log_set_level(AV_LOG_DEBUG);
av_log_set_flags(AV_LOG_SKIP_REPEATED);
av_log_set_callback(pcb_log);
printf("Current ffmpeg log_level = %d\n", av_log_get_level());
/* Open the encoder. */
m_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!m_codec){
printf("Codec not found\n");
exit(1);
}
m_avctx = avcodec_alloc_context3(m_codec);
if (!m_avctx) {
printf("Could not allocate audio codec context\n");
exit(1);
}
m_avctx->codec_type = AVMEDIA_TYPE_AUDIO;
m_avctx->codec_id = AV_CODEC_ID_AAC;
m_avctx->bit_rate = m_audio_bitrate;
m_avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
if (!check_sample_fmt(m_codec, m_avctx->sample_fmt)) {
printf("Encoder does not support sample format %s",
av_get_sample_fmt_name(m_avctx->sample_fmt));
exit(1);
}
m_avctx->sample_rate = m_audio_clock_rate;
m_avctx->channels = m_audio_channel_num;
m_avctx->channel_layout =
(m_audio_channel_num == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
m_avctx->time_base = (AVRational){1, m_avctx->sample_rate};
/* open it */
if (avcodec_open2(m_avctx, m_codec, NULL) < 0) {
printf("Could not open codec\n");
exit(1);
}
2. 调用
NOTE:
1. 这里只举了个简单的例子, PCM数据是用伪码实现的;
2. PCM的数据格式要和编码器相匹配,
即 编码器要求是: AV_SAMPLE_FMT_S16,则输入的PCM数据也要是 AV_SAMPLE_FMT_S16
通常,ffmpeg原生的AAC编码器 : AV_SAMPLE_FMT_FLT
libfaac : AV_SAMPLE_FMT_S16
libfdk-aac : AV_SAMPLE_FTM_FLTP
for (int i = 0 ; i < XXX; i++) {
/* Encode by Using ffmpeg-4.0 */
AVPacket *pkt;
AVFrame *frame;
uint16_t *samples;
pkt = av_packet_alloc();
if (!pkt) {
printf("could not allocate the packet\n");
exit(1);
}
/* frame containing input raw audio */
frame = av_frame_alloc();
if (!frame) {
printf("Could not allocate audio frame\n");
exit(1);
}
frame->nb_samples = m_avctx->frame_size;
frame->format = m_avctx->sample_fmt;
frame->channel_layout = m_avctx->channel_layout;
/* allocate the data buffers */
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
printf("Could not allocate audio data buffers\n");
exit(1);
}
/* make sure the frame is writable -- makes a copy if the encoder
* kept a reference internally */
ret = av_frame_make_writable(frame);
if (ret < 0){
exit(1);
}
samples = (uint16_t*)frame->data[0];
/* 复制一帧待编码的PCM数据 */
int in_pcm_buffer_size = 1024;
uint8_t *in_pcm_buffer; // 输入的数据
memcpy(samples, in_pcm_buffer, in_pcm_buffer_size);
/* send the frame for encoding */
ret = avcodec_send_frame(m_avctx, frame);
if (ret < 0) {
printf("Error sending the frame to the encoder\n");
exit(1);
}
ret = avcodec_receive_packet(m_avctx, pkt);
if (ret == AVERROR(EAGAIN) ){
printf("Encoding audio frame again! \n");
} else if (ret == AVERROR_EOF) {
printf("Encoding audio frame EOF! \n");
} else if (ret < 0) {
printf("Error encoding audio frame\n");
exit(1);
}
/* 将编码后的数据输出*/
if (pkt->size > 0){
memcpy(aac_buf, pkt->data, pkt->size);
aac_size = pkt->size;
}
av_packet_unref(pkt);
av_frame_free(&frame);
av_packet_free(&pkt);
}
/* 资源释放 */
if (m_avctx) {
avcodec_close(m_avctx);
av_free(m_avctx);
m_avctx = NULL;
}
基于FFmpeg-4.0 SDK的PCM编码成AAC
猜你喜欢
转载自blog.csdn.net/fireroll/article/details/83032148
今日推荐
周排行