libyuv 入门指南:高性能图像处理库
·
libyuv 入门指南:高性能图像处理库
libyuv 是 Google 开源的高性能跨平台图像处理库,提供 YUV/RGB 转换、缩放、旋转等功能,广泛应用于 WebRTC、Chromium 等项目。
一、简介
libyuv 是一个开源跨平台 C/C++ 库,专注于图像和视频的处理加速。它提供了丰富的函数接口,可实现颜色空间转换、图像旋转、缩放、镜像等操作。
项目地址:https://chromium.googlesource.com/libyuv/libyuv/
主要特点:
| 特性 | 说明 |
|---|---|
| 高性能 | 优化算法 + SIMD 指令集(SSE/AVX/NEON) |
| 跨平台 | Windows、Linux、macOS、Android、iOS |
| 跨架构 | x86、x64、ARM、ARM64 |
| 易集成 | 简单 API,无外部依赖 |
| 开源免费 | Apache 2.0 协议 |
二、核心功能
2.1 颜色空间转换
支持多种格式之间的相互转换:
YUV ↔ RGB:
- I420、I422、I444 ↔ RGB24、RGBA、ARGB
- NV12、NV21 ↔ RGB 系列
YUV 格式互转:
- I420 ↔ NV12/NV21
- I420 ↔ I422/I444
2.2 图像缩放
支持多种缩放算法:
| 算法 | 特点 | 适用场景 |
|---|---|---|
| kFilterNone | 最近邻插值 | 速度快,质量一般 |
| kFilterLinear | 双线性插值 | 平衡速度与质量 |
| kFilterBilinear | 双线性插值 | 同上 |
| kFilterBox | 盒滤波 | 缩小时效果好 |
2.3 图像旋转
支持任意角度旋转:
- 0°、90°、180°、270° 快速旋转
- 镜像翻转(水平/垂直)
2.4 其他功能
- 图像裁剪
- 图像复制
- 原始数据转换
三、编译与集成
3.1 CMake 编译
git clone https://chromium.googlesource.com/libyuv/libyuv
cd libyuv
mkdir build && cd build
cmake ..
make -j4
make install
3.2 Windows 编译
使用 Visual Studio 打开 CMakeLists.txt 或直接使用 CMake GUI。
3.3 集成到项目
# CMakeLists.txt
find_package(libyuv REQUIRED)
target_link_libraries(your_target libyuv::yuv)
四、常用 API 示例
4.1 I420 → RGB24 转换
#include "libyuv.h"
int i420_to_rgb24(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_rgb24,
int width,
int height) {
int src_stride_y = width;
int src_stride_uv = width / 2;
int dst_stride_rgb24 = width * 3;
return I420ToRGB24(src_y, src_stride_y,
src_u, src_stride_uv,
src_v, src_stride_uv,
dst_rgb24, dst_stride_rgb24,
width, height);
}
4.2 图像缩放
#include "libyuv.h"
int scale_i420(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_y,
uint8_t* dst_u,
uint8_t* dst_v,
int src_width, int src_height,
int dst_width, int dst_height) {
int src_stride_y = src_width;
int src_stride_uv = src_width / 2;
int dst_stride_y = dst_width;
int dst_stride_uv = dst_width / 2;
return I420Scale(src_y, src_stride_y,
src_u, src_stride_uv,
src_v, src_stride_uv,
src_width, src_height,
dst_y, dst_stride_y,
dst_u, dst_stride_uv,
dst_v, dst_stride_uv,
dst_width, dst_height,
kFilterBilinear);
}
4.3 图像旋转
#include "libyuv.h"
int rotate_i420(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_y,
uint8_t* dst_u,
uint8_t* dst_v,
int width, int height,
int rotation) { // 0, 90, 180, 270
int src_stride_y = width;
int src_stride_uv = width / 2;
// 旋转后宽高可能互换
int dst_width = (rotation == 90 || rotation == 270) ? height : width;
int dst_height = (rotation == 90 || rotation == 270) ? width : height;
int dst_stride_y = dst_width;
int dst_stride_uv = dst_width / 2;
return I420Rotate(src_y, src_stride_y,
src_u, src_stride_uv,
src_v, src_stride_uv,
dst_y, dst_stride_y,
dst_u, dst_stride_uv,
dst_v, dst_stride_uv,
width, height,
(enum RotationMode)rotation);
}
4.4 NV12 → I420 转换
#include "libyuv.h"
int nv12_to_i420(const uint8_t* src_y,
const uint8_t* src_uv,
uint8_t* dst_y,
uint8_t* dst_u,
uint8_t* dst_v,
int width, int height) {
int src_stride_y = width;
int src_stride_uv = width;
int dst_stride_y = width;
int dst_stride_uv = width / 2;
return NV12ToI420(src_y, src_stride_y,
src_uv, src_stride_uv,
dst_y, dst_stride_y,
dst_u, dst_stride_uv,
dst_v, dst_stride_uv,
width, height);
}
五、libyuv vs libswscale 性能对比
5.1 性能测试数据
| 操作 | 图像尺寸 | libyuv | libswscale | 性能比 |
|---|---|---|---|---|
| RGB → YUV 转换 | 4096×4096 | 快 | 慢 | 11:1 |
| 缩放 | 4096×4096 → 2048×2048 | 快 | 慢 | 6:1 |
数据来源:https://www.nxrte.com/jishu/50785.html
5.2 功能对比
| 特性 | libyuv | libswscale |
|---|---|---|
| 性能 | 极高(SIMD 优化) | 较高 |
| 缩放算法 | 较少 | 丰富 |
| 颜色空间支持 | 主流格式 | 非常全面 |
| 多线程 | 需自行实现 | 内置支持 |
| 依赖 | 无 | 依赖 FFmpeg |
| 授权 | Apache 2.0 | LGPL/GPL |
5.3 选型建议
选择 libyuv:
- 实时视频处理(WebRTC、直播)
- 嵌入式设备(资源受限)
- 对性能要求极高的场景
- 只需常见格式转换
选择 libswscale:
- 需要支持冷门格式
- 需要多种缩放算法
- 已集成 FFmpeg 的项目
- 对性能不敏感的场景
注意:
- libswscale 可通过多线程达到与 libyuv 相近的性能,但 CPU 占用更高
- 实际场景建议分别测试,根据具体需求选择
六、性能优化建议
6.1 内存对齐
// 分配对齐内存,提升 SIMD 访问效率
uint8_t* aligned_buffer = (uint8_t*)aligned_malloc(width * height * 3 / 2, 16);
6.2 批量处理
// 批量处理多帧,减少函数调用开销
for (int i = 0; i < frame_count; i++) {
I420ToRGB24(frames[i].y, frames[i].stride_y, ...);
}
6.3 多线程处理
// 多线程处理不同区域
#pragma omp parallel for
for (int row = 0; row < height; row += 16) {
// 处理 16 行
}
七、常见问题
Q1:libyuv 支持哪些 YUV 格式?
主要支持:
- Planar:I420、I422、I444、YV12、YV16、YV24
- Semi-Planar:NV12、NV21、NV16、NV24
- Packed:YUY2、UYVY、UYVY
Q2:如何判断编译时是否启用了 SIMD?
#ifdef LIBYUV_ENABLE_NEON
printf("NEON enabled\n");
#endif
#ifdef LIBYUV_ENABLE_SSE2
printf("SSE2 enabled\n");
#endif
#ifdef LIBYUV_ENABLE_AVX2
printf("AVX2 enabled\n");
#endif
Q3:libyuv 线程安全吗?
大部分函数是线程安全的,但不要同时操作同一块内存区域。
参考资源
官方资源:
- 源码:https://chromium.googlesource.com/libyuv/libyuv/
- API 文档:https://chromium.googlesource.com/libyuv/libyuv/+/main/include/libyuv.h
推荐阅读:
- libyuv 详解:https://blog.csdn.net/gitblog_00062/article/details/136704290
- 使用示例:https://www.cnblogs.com/eastgeneral/p/16590622.html
- libyuv vs libswscale:https://www.nxrte.com/jishu/50785.html
[本文整理自学习笔记,如有疏漏欢迎指正]
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)