用ffmpeg编码aac


FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,它提供了录制、转换以及流化音视频的完整解决方案。项目的名称来自MPEG视频编码标准,前面的"FF“代表"FastForward“。

前期准备 
    如果需要用FFmpeg转码音视频,那么第一步,是搭建ffmpeg环境,以及熟悉ffmpeg主要组成部分,以如何使用ffmpeg

参考网站
    FFmpeg官网:http://ffmpeg.org/documentation.html
    Libav官网:http://www.libav.org/
    FFmpeg wiki:https://trac.ffmpeg.org/ (该wiki有各个操作系统的详细的编译信息)

项目主要组成部分
    libavformat :用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;
    libavcodec :用于各种类型声音/图像编解码;
    libavutil :包含一些公共的工具函数;
    libswscale :用于视频场景比例缩放、色彩映射转换;
    libpostproc:用于后期效果处理;(目前没有用过)
    ffmpeg :该项目提供的一个工具,可用于格式转换、解码或电视卡即时编码等;
    ffsever :一个 HTTP 多媒体即时广播串流服务器;
    ffplay :是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;


其中hicam项目的客户端播放音视频就是用的ffplay来解码,pcm转aac需要用到的库有libavformat ,libavcodec , libavutil, libswscale

项目的exsample也是很重要的,新手本来就不熟悉ffmpeg,如果自己根据api来完成,也不容易,如果编译的是android,在confiure里--enable-doc,就能在指定的目录下看到exsample。

如果要转码为aac格式,ffmpeg是不支持aac的,还需要我们自己编译fdk-aac,或者vo-aac库(据说vo-aac的编解码的效率较高)

PCM转AAC

    PCM转AAC的流程中,重点在为编码器上下文和Swr_Context准备采样率,采样格式,声道等信息,再把源数据转为目标数据,最后填充每一帧frame,再把frame编码,就得到aac的包

1,注册编码格式,你可以注册所以的编码格式,也可以选择某些格式注册,并find AAC的编码器
   avcodec_register_all();
   AVCodec codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
   为AVCodeccodec 分配编码器的上下文
   codecContext = avcodec_alloc_context3(codec);
2,定义AAC音频格式采样率,采样格式,音频格式,比特率,声道。
    codecContext->codec_type=AVMEDIA_TYPE_AUDIO;
    codecContext->codec_id=AV_CODEC_ID_AAC;
    codecContext->sample_fmt= dst_sample_fmt;AV_SAMPLE_FMT_FLTP
    codecContext->sample_rate=sample_rate;//44100
    codecContext->channels=nb_channels;//2
    codecContext->bit_rate=64000;// 64000; //96000;
    codecContext->channel_layout=ch_layout;
    codecContext->profile=FF_PROFILE_AAC_LOW ;(可参考AAC格式简介)
    codecContext->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
    打开编码器
    avcodec_open2(incodecContext, codec, NULL);
3,为pcm转为aac的每一帧分配空间,设置参数
    frame = av_frame_alloc();
    frame->format = dst_sample_fmt;
    frame->nb_samples = codecContext->frame_size;
    frame->channel_layout = ch_layout; //AV_SAMPLE_FMT_FLTP
4,初始化SwrContext,为SwrContext设置转码前后的采样率,采样格式,声道
    swrContext = swr_alloc();
    av_opt_set_int(swrContext, "in_channel_layout",  ch_layout, 0);//AV_CH_LAYOUT_STEREO
    av_opt_set_int(swrContext, "out_channel_layout", ch_layout,  0);//AV_CH_LAYOUT_STEREO
    av_opt_set_int(swrContext, "in_sample_rate",     sample_rate, 0);
    av_opt_set_int(swrContext, "out_sample_rate",    sample_rate, 0);
    av_opt_set_sample_fmt(swrContext, "in_sample_fmt",  src_sample_fmt, 0);//AV_SAMPLE_FMT_S16
    av_opt_set_sample_fmt(swrContext, "out_sample_fmt",dst_sample_fmt,  0);//AV_SAMPLE_FMT_FLTP
    swr_init(swrContext);
5,为源数据和目标数据分配空间,空间大小跟声道,frame_size 采样格式相关,aac的frame_size一般为1024,frame_size为frame的样品数,由编码器决定,但是frame的真正字节数=frame_size*声道数*采样深度,可以根据下面的函数来为audio_data申请空间
    av_samples_alloc_array_and_samples( &src_data,&src_linesize,
                                        nb_channels,//number of audio channels
                                        codecContext->frame_size,//incodecContext->frame_size, //nb_samples  number of samples per channel
                                       src_sample_fmt,0);
    原型为:
    int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels,int nb_samples, enum AVSampleFormat sample_fmt, int align);
6,初始化AVPacket,最后的aac数据是通过把frame里面的数据编码,填充到packet里面
    av_init_packet(&packet);
    packet.data = NULL;
    packet.size = 0;
我的src_data的数据来自jni,如下:
    jbyte *_data = env->GetByteArrayElements(data, NULL);
    *src_data = (uint8_t *)_data;
     env->ReleaseByteArrayElements(data, _data, 0);
7,转码
    swr_convert(swrContext, dst_data,incodecContext->frame_size, (const uint8_t ** )src_data,incodecContext->frame_size);
    把转码后的sdt_data填充到frame里面
    dst_bufsize = av_samples_get_buffer_size(&dst_linesize, nb_channels,ret, dst_sample_fmt, 0);
    avcodec_fill_audio_frame(frame, nb_channels, dst_sample_fmt,*dst_data, dst_bufsize, 0);
8,编码
   avcodec_encode_audio2(incodecContext, &packet,frame, &got_output)
最后获取到的packet.data packet.size就为AAC数据和大小,按照上一篇文章加上aac header,保存为aac文件,就可以用ffplay进行播放了
### 如何使用 FFmpeg 进行 AAC 音频编码 #### 使用命令行工具进行 AAC 编码 可以利用 `ffmpeg` 的命令行功能来完成 AAC 音频的编码工作。以下是具体方法: 假设有一个输入音频文件名为 `input.wav`,目标是将其转换为 AAC 格式的音频文件 `output.aac`。 ```bash ffmpeg -i input.wav -c:a aac -b:a 128k output.aac ``` 上述命令中的参数解释如下: - `-i input.wav`: 指定输入文件为 `input.wav`。 - `-c:a aac`: 设置音频编码器为 AAC[^1]。 - `-b:a 128k`: 设定比特率为 128 kbps(可以根据需求调整)。 - `output.aac`: 输出文件名。 如果需要更高的质量或者更低的质量,可以通过修改比特率参数实现。例如,设置比特率为 64kbps 或者更高如 256kbps。 #### 支持的 AAC 编解码器检查 在实际操作前,建议先确认当前安装的 FFmpeg 是否支持所需的 AAC 编解码器。这一步非常重要,因为并非所有的 FFmpeg 版本都默认集成了高质量的 AAC 编码器(比如 libfdk_aac)。可以通过以下命令查询可用的编解码器列表: ```bash ffmpeg -codecs | grep aac ``` 此命令会返回一系列关于 AAC 编解码器的信息。常见的 AAC 编码器有以下几个选项: - **libfdk_aac**: 高质量商业级 AAC 编码器,需手动配置并重新编译 FFmpeg 才能启用。 - **aac**: 默认内置的 AAC 编码器,性能一般但兼容性强。 如果发现缺少某些特定的 AAC 编码器,则可能需要自行编译 FFmpeg 并加入额外的支持库。 #### C++ 环境下的 AAC 编码示例 对于希望在程序中调用 FFmpeg API 实现 AAC 编码的情况,下面提供了一个简单的 C++ 示例代码片段。需要注意的是,在 C++ 中引入 FFmpeg 头文件时应特别注意命名空间冲突问题,因此推荐使用 `extern "C"` 来包裹相关头文件声明[^4]。 ```cpp #include <iostream> extern "C" { #include <libavcodec/avcodec.h> #include <libavutil/channel_layout.h> #include <libavutil/common.h> #include <libavutil/frame.h> #include <libavutil/samplefmt.h> } int main() { const char* filename = "output.aac"; AVCodec *codec; AVCodecContext *c= NULL; int i, j, out_size, size, x, y, outbuf_size; FILE *f; /* find the MP2 encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!codec) { std::cerr << "Codec not found\n"; return -1; } c= avcodec_alloc_context3(codec); /* put sample parameters */ c->bit_rate = 64000; c->sample_fmt = AV_SAMPLE_FMT_FLTP; c->sample_rate = 44100; c->channel_layout = AV_CHANNEL_LAYOUT_STEREO; c->channels = av_get_channel_layout_nb_channels(c->channel_layout); c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /* open it */ if (avcodec_open2(c, codec, nullptr) < 0) { std::cerr << "Could not open codec\n"; return -1; } } ``` 以上代码展示了如何初始化一个基于 FFmpeg 库的 AAC 编码环境,并设置了基本的采样率、声道布局以及位深等重要属性。完整的编码过程还需要进一步补充数据填充逻辑等内容。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值