libyuv库的使用
libyuv是Google开源的实现各种YUV与RGB之间相互转换、旋转、缩放的库。它是跨平台的,可在Windows、Linux、Mac、Android等操作系统。x86、x64、arm架构上进行编译执行,支持SSE、AVX、NEON等SIMD指令加速。
以下说一下libyuv在Windows7VS2013 x64上的编译步骤及使用:
1. 从https://code.google.com/p/libyuv/source/checkout或者https://github.com/lemenkov/libyuv下载libyuv源代码;我是通过svn直接从google下载的,版本是1433,更新日期2015年6月13日。
2. 通过cmake gui生成vs2013 x64project,不须要额外的配置;
3. 打开Project.slnproject,又一次编译,就可以生成yuv.lib静态库。
4. 新加入一个test_libyuv控制台project。用于測试yuv.lib的正确性。測试代码例如以下:
#include <iostream>
#include <assert.h>
#include "libyuv.h"
#include <cmath>
#include <opencv2/opencv.hpp> void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst); int main(int argc, char* argv[])
{
cv::Mat matSrc = cv::imread("cat.jpg");
if (!matSrc.data) {
std::cout << "read src image error" << std::endl;
return -1;
} //cv::resize(matSrc, matSrc, cv::Size(500, 111)); int width = matSrc.cols;
int height = matSrc.rows;
int size_frame = width * height; cv::Mat matI420, matNV21, matNV12; test_BGRAToI420(matSrc, width, height, size_frame, matI420);
test_BGRAToNV21(matSrc, width, height, size_frame, matNV21);
test_BGRAToNV12(matSrc, width, height, size_frame, matNV12); assert((matI420.depth() == matNV21.depth()) && (matI420.depth() == matNV12.depth()));
assert((matI420.channels() == matNV21.channels()) && (matI420.channels() == matNV12.channels())); for (int i = 0; i < height; i++) {
const unsigned char* pI420 = matI420.ptr(i);
const unsigned char* pNV21 = matNV21.ptr(i);
const unsigned char* pNV12 = matNV12.ptr(i); for (int j = 0, m = 0; j < width; j++, m+=4) {
if ((pI420[m] != pNV21[m]) || (pI420[m] != pNV12[m]) ||
(pI420[m + 1] != pNV21[m + 1]) || (pI420[m + 1] != pNV12[m + 1]) ||
(pI420[m + 2] != pNV21[m + 2]) || (pI420[m + 2] != pNV12[m + 2]) ||
(pI420[m + 3] != pNV21[m + 3]) || (pI420[m + 3] != pNV12[m + 3])) {
std::cout << "convert error" << std::endl;
}
}
} std::cout << "ok" << std::endl;
return 0;
} void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
{
// BGRA <--> I420(YUV420P)
cv::Mat matBGRA, matI420, matARGB;
cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
matARGB = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
libyuv::BGRAToARGB(matBGRA.data, width * 4, matARGB.data, width * 4, width, height); uchar* pI420 = new uchar[width * height + (width + 1) / 2 * (height + 1) / 2 * 2];
memset(pI420, 0, sizeof(uchar) * (width * height + (width + 1) / 2 * (height + 1) / 2 * 2));
uchar* dst_y = pI420;
int dst_y_stride = width;
uchar* dst_u = pI420 + size_frame;
int dst_u_stride = (width + 1) / 2;
uchar* dst_v = pI420 + size_frame + dst_u_stride * (height + 1) / 2;
int dst_v_stride = (width + 1) / 2; libyuv::BGRAToI420(matARGB.data, width * 4, dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, width, height);
matI420 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
libyuv::I420ToBGRA(dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, matI420.data, width * 4, width, height);
cv::Mat matBGRA_ = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
libyuv::ARGBToBGRA(matI420.data, width * 4, matBGRA_.data, width * 4, width, height);
cv::imwrite("I420_bgra.jpg", matBGRA_);
matBGRA_.copyTo(matDst); int count_diff = 0;
int max_diff = 0;
int threshold = 20;//
for (int i = 0; i < height; i++) {
uchar* pSrc = matBGRA.ptr(i);
uchar* pDst = matBGRA_.ptr(i);
for (int j = 0, m = 0; j < width; j++, m += 4) {
int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
if (tmp > max_diff)
max_diff = tmp; if (abs(pSrc[m] - pDst[m]) > threshold ||
abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
count_diff++;
//std::cout << i << " " << j << std::endl;
} }
} std::cout << "convert I420 to BGRA diff max: " << max_diff << std::endl;
if (count_diff > width + height) {//
std::cout << "convert I420 to BGRA error." << std::endl;
std::cout << "diff num: " << count_diff << std::endl;
} delete[] pI420;
} void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
{
// BGRA <--> NV12
cv::Mat matBGRA, matNV12;
cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA); uchar* pNV12 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];
memset(pNV12, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));
uchar* dst_y = pNV12;
int dst_y_stride = width;
uchar* dst_vu = pNV12 + size_frame;
int dst_vu_stride = (width + 1) / 2 * 2; libyuv::ARGBToNV12(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);
matNV12 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
libyuv::NV12ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV12.data, width * 4, width, height);
cv::imwrite("NV12_bgra.jpg", matNV12);
matNV12.copyTo(matDst); int count_diff = 0;
int max_diff = 0;
int threshold = 20;//
for (int i = 0; i < height; i++) {
uchar* pSrc = matBGRA.ptr(i);
uchar* pDst = matNV12.ptr(i);
for (int j = 0, m = 0; j < width; j++, m += 4) {
int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
if (tmp > max_diff)
max_diff = tmp; if (abs(pSrc[m] - pDst[m]) > threshold ||
abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
count_diff++;
//std::cout << i << " " << j << std::endl;
}
}
} std::cout << "convert NV12 to BGRA diff max: " << max_diff << std::endl;
if (count_diff > width + height) {//
std::cout << "convert NV12 to BGRA error." << std::endl;
std::cout << "diff num: " << count_diff << std::endl;
} delete[] pNV12;
} void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
{
// BGRA <--> NV21
cv::Mat matBGRA, matNV21;
cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA); uchar* pNV21 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];
memset(pNV21, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));
uchar* dst_y = pNV21;
int dst_y_stride = width;
uchar* dst_vu = pNV21 + size_frame;
int dst_vu_stride = (width + 1) / 2 * 2; libyuv::ARGBToNV21(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);
matNV21 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
libyuv::NV21ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV21.data, width * 4, width, height);
cv::imwrite("NV21_bgra.jpg", matNV21);
matNV21.copyTo(matDst); int count_diff = 0;
int max_diff = 0;
int threshold = 20;//
for (int i = 0; i < height; i++) {
uchar* pSrc = matBGRA.ptr(i);
uchar* pDst = matNV21.ptr(i);
for (int j = 0, m = 0; j < width; j++, m += 4) {
int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
if (tmp > max_diff)
max_diff = tmp; if (abs(pSrc[m] - pDst[m]) > threshold ||
abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
count_diff++;
//std::cout << i << " " << j << std::endl;
}
}
} std::cout << "convert NV21 to BGRA diff max: " << max_diff << std::endl;
if (count_diff > width + height) {//
std::cout << "convert NV21 to BGRA error." << std::endl;
std::cout << "diff num: " << count_diff << std::endl;
} delete[] pNV21;
}
libyuv库的使用的更多相关文章
- ffmpeg编解码视频导致噪声增大的一种解决方法
一.前言 ffmpeg在视音频编解码领域算是一个比较成熟的解决方案了.公司的一款视频编辑软件正是基于ffmpeg做了二次封装,并在此基础上进行音视频的编解码处理.然而,在观察编码后的视频质量时,发现图 ...
- webrtc (6) 在Webrtc中集成VideoToolbox
来源:http://blog.csdn.net/wangruihit/article/details/46550853 VideoToolbox是iOS平台在iOS8之后开放的一个Framework, ...
- 一步一步搭建基于ffmpeg和sdl2的流媒体播放器
一. 背景: 一步一步从资料收集.技术选型.代码编写.性能优化,动手搭建一款支持rtsp.rtmp等常用流媒体格式的视频播放器,ffmpeg用于流媒体解码,sdl2用于视频画面渲染和声音播放. 二. ...
- libyuv颜色空间转换开源库
libyuv据说在缩放和颜色空间转换,比ffmpeg效率高很多倍.不知道和我们的PP库比起来怎么样.同样有neon指令集优化.支持移动设备.
- Facebook Paper使用的第三方库
Facebook Paper使用的第三方库 第三方库名 简介 链接 ACE code editor https://github.com/ajaxorg/ace Appirater 用户评分组件 ht ...
- libyuv 编译for ios
这里有编译好的库 https://bintray.com/yarr/ios/libyuv-ios# lipo -info libyuv.a Architectures in the fat file ...
- FreeSWITCH第三方库(视频)的简单介绍(二)
FreeSWITCH使用了大量的第三方库,本文档主要介绍视频相关库的信息: 音频相关库的信息介绍参考:http://www.cnblogs.com/yoyotl/p/5486753.html 其他相关 ...
- ios paper for facebook 使用第三方库
facebook paper使用的第三方库 Facebook Paper使用的第三方库 第三方库名 简介 链接 ACE code editor https://github.com/ajaxorg/a ...
- Android libyuv应用系列(二)libyuv的使用
上篇文章Android libyuv使用系列(一)Android常用的几种格式:NV21/NV12/YV12/YUV420P的区别中我们了解了YUV相关的知识,而本篇文章我会介绍libyuv是什么,以 ...
随机推荐
- Newtonsoft.Json 序列化日期问题解决
上代码 其中的使用方法和UserInfo实体对象就不贴代码了. /// <summary> /// 把对象转成json字符串 /// </summary> /// <pa ...
- Android PopWindow的替代品BasePopup
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/109 背景描述 最近一段时间,又看到了这个开源项目Base ...
- python 8:list.sort(reverse=false)、sorted(list, reverse=false)(对列表进行不可恢复排序;对列表进行可恢复排序)
bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles) print(sorted(bicycles)) ...
- Java学习笔记之从C++转Java
之前一直是做C++后台开发的,习惯了命令行和g++,由于工作原因现在开始转java. 1.参考书籍:java编程思想(think in java),java核心技术(core java); 2.怎么在 ...
- BZOJ 4517 组合数+错排
思路: 预处理错排 然后C(n,m)*s[n-m-1]就是答案了 特判n-m-1<0 //By SiriusRen #include <cstdio> using namespace ...
- Foeach 时修改集合的值报错
就是"集合已修改:可能无法执行枚举操作 foreach" 啥的, 不让我改 百度到Foreach是只读的,只供取值用,无法进行新增,修改,删除(仅引用,实际待验证) 解决办法:将F ...
- 联想VIBE Shot(Z90-7/全网通) 解锁BootLoader
工具下载链接: http://pan.baidu.com/s/1dF7zGTb 备用下载链接: http://pan.baidu.com/s/1i4UHP4L 本篇教程教你如何傻瓜式解锁BootLoa ...
- Leetcode0092 & 0206--Reverse Linked List 链表逆转
[转载请注明]http://www.cnblogs.com/igoslly/p/8670038.html 链表逆序在链表题目中还是较为常见的,这里将Leetcode中的两道题放在一起,分别是 0092 ...
- PL/SQL之高级篇
原文地址:http://www.cnblogs.com/sin90lzc/archive/2012/08/30/2661117.html 参考文献:<Oracle完全学习手册> 1.概述 ...
- win7 64位装sql2000
1.运行不了安装程序 右击安装exe文件->属性->兼容性->以xp sp3兼容和管理员身份 2.安装过程中提示“被挂起”的故障 解决:打开注册表编辑器,在HKEY_LOCAL_MA ...