关键词:CPU、SIMD、 C++、 FFMPEG、OPENCV
一. 引言
在上一期的【DLL】基于Python与C++的FFmpeg与OpenCV实践中实现了在cpu中使用ffmpeg和python进行读取相机获取图像数据进行推流操作,今日刷微信公众号发现一段文字提醒了我:仅考虑CPU解码,使用FFMPEG可以配合nasm编译(--enable_asm)支持CPU的SIMD流指令集(SSE、AVX、MMX),比默认VideoCapture配置的ffmpeg性能更好。同时还可以根据需要配置解码所使用的线程数,控制sws_scale、decode的消耗。这不禁勾起我优化的欲望。
二. 实现
鉴于本人在cpu底层的造诣颇浅,但手下有deepseek这位高效率员工,于是我去指挥ds进行优化。输入优化指令如下图所示:
以下是针对SIMD指令集和性能优化的代码修改及配置说明:
1. FFmpeg编译配置(关键)
确保FFmpeg库编译时启用所有SIMD优化:
./configure --enable-gpl --enable-nonfree --enable-asm --enable-x86asm --enable-avx --enable-avx2 --enable-sse4 --enable-mmxe --enable-shared
若使用预编译库,需确认编译时启用了这些选项
2. 代码优化修改
修改set_codec_params函数(utils.h):
void set_codec_params(...) {
// 原有代码...
codec_ctx->thread_count = 6; // 根据CPU核心数设置(i5-11400F为6核)
codec_ctx->thread_type = FF_THREAD_SLICE; // 启用多线程切片
codec_ctx->flags2 |= AV_CODEC_FLAG2_FAST; // 启用快速编码模式
}
修改initialize_sample_scaler函数(utils.h):
SwsContext* initialize_sample_scaler(...) {
SwsContext* swsctx = sws_getContext(
width, height, AV_PIX_FMT_BGR24,
width, height, codec_ctx->pix_fmt,
SWS_FAST_BILINEAR, // 更快的缩放算法
nullptr, nullptr, nullptr
);
// ...
}
#### 修改`allocate_frame_buffer`函数(utils.h):
```shell
AVFrame* allocate_frame_buffer(...) {
// 替换new为av_malloc确保内存对齐
uint8_t* framebuf = static_cast<uint8_t*>(av_malloc(i + AV_INPUT_BUFFER_PADDING_SIZE));
// ...
}
3.编码器参数优化
由于ds的回答有些许失误。它将如下所示的代码模块修改放置在demo.cpp中进行修改,实际应为在utils.h中进行修改
4. 关键优化点说明
| 优化项 | 作用 |
|---|---|
| 多线程切片编码 | 充分利用6核CPU的并行能力 |
| 快速Bilinear缩放 | 比Bicubic快30%以上,适合实时场景 |
| 内存对齐分配 | 确保SIMD指令能高效访问内存 |
| Ultrafast预设 | 显著降低编码复杂度(但会增大体积) |
| X264高级参数 | 禁用宏块树、分片线程等进一步降低延迟 |
实测
对代码进行编译后,使用nginx开启端口后运行demo.exe可以看见如下日志信息:
根据日志信息中的using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 AVX512可以知道:FFmpeg 使用了 libx264 编码器,并且列出了当前 CPU 支持的所有 SIMD(单指令多数据流)扩展。这些扩展有助于加速视频编码过程。
后期的其它深度优化以及纠正待续......