FFmpeg API进行AAC编码
Posted 顾文繁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFmpeg API进行AAC编码相关的知识,希望对你有一定的参考价值。
FFmpeg API进行AAC编码步骤
1 注册设备
avdevice_register_all();
2 查找格式并打开输入
av_find_input_format("avfoundation");
avformat_open_input(&fmt_ctx, devicename, iformat, &options))
3 编码器
//avcodec_find_encoder(AV_CODEC_ID_AAC);
AVCodec *codec = avcodec_find_encoder_by_name("libfdk_aac");
//创建 codec 上下文
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16; //输入音频的采样大小
codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO; //输入音频的channel layout
codec_ctx->channels = 2; //输入音频 channel 个数
codec_ctx->sample_rate = 44100; //输入音频的采样率
codec_ctx->bit_rate = 0; //AAC_LC: 128K, AAC HE: 64K, AAC HE V2: 32K
codec_ctx->profile = FF_PROFILE_AAC_HE_V2; //阅读 ffmpeg 代码
//打开编码器
avcodec_open2(codec_ctx, codec, NULL)
4 初始化重采样上下文
//channel, number/
swr_ctx = swr_alloc_set_opts(NULL, //ctx
AV_CH_LAYOUT_STEREO, //输出channel布局
AV_SAMPLE_FMT_S16, //输出的采样格式
44100, //采样率
AV_CH_LAYOUT_STEREO, //输入channel布局
AV_SAMPLE_FMT_FLT, //输入的采样格式
44100, //输入的采样率
0, NULL);
5 创建frame
//音频输入数据
frame = av_frame_alloc();
if(!frame){
printf("Error, No Memory!\\n");
goto __ERROR;
}
6 给frame设置参数
frame->nb_samples = 512; //单通道一个音频帧的采样数
frame->format = AV_SAMPLE_FMT_S16; //每个采样的大小
frame->channel_layout = AV_CH_LAYOUT_STEREO; //channel layout
7 给frame分配真实缓冲
av_frame_get_buffer(frame, 0); // 512 * 2 * = 2048
if(!frame->data[0]){
printf("Error, Failed to alloc buf in frame!\\n");
//内存泄漏
goto __ERROR;
}
8 分配编码后的数据空间AVPacket
packet = av_packet_alloc()
9 创建输入输出缓冲区
av_samples_alloc_array_and_samples(src_data, //输输入缓冲区地址
src_linesize, //缓冲区的大小
2, //通道个数
512, //单通道采样个数
AV_SAMPLE_FMT_FLT, //采样格式
0);
av_samples_alloc_array_and_samples(dst_data, //输出缓冲区地址
dst_linesize, //缓冲区的大小
2, //通道个数
512, //单通道采样个数
AV_SAMPLE_FMT_S16, //采样格式
0);
10 不断接受数据进行重采样然后进行编码,然后写入文件中
while((ret = av_read_frame(fmt_ctx, &pkt)) == 0 && rec_status) {
//进行内存拷贝,按字节拷贝的
memcpy((void*)src_data[0], (void*)pkt.data, pkt.size);
//重采样
swr_convert(swr_ctx, //重采样的上下文
dst_data, //输出结果缓冲区
512, //每个通道的采样数
(const uint8_t **)src_data, //输入缓冲区
512); //输入单个通道的采样数
//将重采样的数据拷贝到 frame 中
memcpy((void *)frame->data[0], dst_data[0], dst_linesize);
//进行编码
//将数据送编码器
ret = avcodec_send_frame(ctx, frame);
//如果ret>=0说明数据设置成功
while(ret >= 0){
//获取编码后的音频数据,如果成功,需要重复获取,直到失败为止
ret = avcodec_receive_packet(ctx, pkt);
//write file
fwrite(pkt->data, 1, pkt->size, output);
fflush(output);
}
//release pkt
av_packet_unref(&pkt);
}
这里需要注意,由于有缓冲的存在,当停止时,应将缓冲区的数据刷出。
//强制将编码器缓冲区中的音频进行编码输出
while(ret >= 0){
//获取编码后的音频数据,如果成功,需要重复获取,直到失败为止
ret = avcodec_receive_packet(ctx, pkt);
//write file
fwrite(pkt->data, 1, pkt->size, output);
fflush(output);
}
11 释放空间
以上是关于FFmpeg API进行AAC编码的主要内容,如果未能解决你的问题,请参考以下文章