http://blog.csdn.net/fengbingchun/article/details/50323273

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 x64工程,不需要额外的配置;

3.        打开Project.sln工程,重新编译,即可生成yuv.lib静态库;

4.    新添加一个test_libyuv控制台工程,用于测试yuv.lib的正确性,测试代码如下:

[cpp] view plaincopy
  1. #include <iostream>
  2. #include <assert.h>
  3. #include "libyuv.h"
  4. #include <cmath>
  5. #include <opencv2/opencv.hpp>
  6. void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
  7. void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
  8. void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
  9. int main(int argc, char* argv[])
  10. {
  11. cv::Mat matSrc = cv::imread("cat.jpg");
  12. if (!matSrc.data) {
  13. std::cout << "read src image error" << std::endl;
  14. return -1;
  15. }
  16. //cv::resize(matSrc, matSrc, cv::Size(500, 111));
  17. int width = matSrc.cols;
  18. int height = matSrc.rows;
  19. int size_frame = width * height;
  20. cv::Mat matI420, matNV21, matNV12;
  21. test_BGRAToI420(matSrc, width, height, size_frame, matI420);
  22. test_BGRAToNV21(matSrc, width, height, size_frame, matNV21);
  23. test_BGRAToNV12(matSrc, width, height, size_frame, matNV12);
  24. assert((matI420.depth() == matNV21.depth()) && (matI420.depth() == matNV12.depth()));
  25. assert((matI420.channels() == matNV21.channels()) && (matI420.channels() == matNV12.channels()));
  26. for (int i = 0; i < height; i++) {
  27. const unsigned char* pI420 = matI420.ptr(i);
  28. const unsigned char* pNV21 = matNV21.ptr(i);
  29. const unsigned char* pNV12 = matNV12.ptr(i);
  30. for (int j = 0, m = 0; j < width; j++, m+=4) {
  31. if ((pI420[m] != pNV21[m]) || (pI420[m] != pNV12[m]) ||
  32. (pI420[m + 1] != pNV21[m + 1]) || (pI420[m + 1] != pNV12[m + 1]) ||
  33. (pI420[m + 2] != pNV21[m + 2]) || (pI420[m + 2] != pNV12[m + 2]) ||
  34. (pI420[m + 3] != pNV21[m + 3]) || (pI420[m + 3] != pNV12[m + 3])) {
  35. std::cout << "convert error" << std::endl;
  36. }
  37. }
  38. }
  39. std::cout << "ok" << std::endl;
  40. return 0;
  41. }
  42. void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
  43. {
  44. // BGRA <--> I420(YUV420P)
  45. cv::Mat matBGRA, matI420, matARGB;
  46. cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
  47. matARGB = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
  48. libyuv::BGRAToARGB(matBGRA.data, width * 4, matARGB.data, width * 4, width, height);
  49. uchar* pI420 = new uchar[width * height + (width + 1) / 2 * (height + 1) / 2 * 2];
  50. memset(pI420, 0, sizeof(uchar) * (width * height + (width + 1) / 2 * (height + 1) / 2 * 2));
  51. uchar* dst_y = pI420;
  52. int dst_y_stride = width;
  53. uchar* dst_u = pI420 + size_frame;
  54. int dst_u_stride = (width + 1) / 2;
  55. uchar* dst_v = pI420 + size_frame + dst_u_stride * (height + 1) / 2;
  56. int dst_v_stride = (width + 1) / 2;
  57. libyuv::BGRAToI420(matARGB.data, width * 4, dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, width, height);
  58. matI420 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
  59. libyuv::I420ToBGRA(dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, matI420.data, width * 4, width, height);
  60. cv::Mat matBGRA_ = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
  61. libyuv::ARGBToBGRA(matI420.data, width * 4, matBGRA_.data, width * 4, width, height);
  62. cv::imwrite("I420_bgra.jpg", matBGRA_);
  63. matBGRA_.copyTo(matDst);
  64. int count_diff = 0;
  65. int max_diff = 0;
  66. int threshold = 20;//
  67. for (int i = 0; i < height; i++) {
  68. uchar* pSrc = matBGRA.ptr(i);
  69. uchar* pDst = matBGRA_.ptr(i);
  70. for (int j = 0, m = 0; j < width; j++, m += 4) {
  71. int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
  72. tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
  73. if (tmp > max_diff)
  74. max_diff = tmp;
  75. if (abs(pSrc[m] - pDst[m]) > threshold ||
  76. abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
  77. abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
  78. count_diff++;
  79. //std::cout << i << "    " << j << std::endl;
  80. }
  81. }
  82. }
  83. std::cout << "convert I420 to BGRA diff max: " << max_diff << std::endl;
  84. if (count_diff > width + height) {//
  85. std::cout << "convert I420 to BGRA error." << std::endl;
  86. std::cout << "diff num: " << count_diff << std::endl;
  87. }
  88. delete[] pI420;
  89. }
  90. void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
  91. {
  92. // BGRA <--> NV12
  93. cv::Mat matBGRA, matNV12;
  94. cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
  95. uchar* pNV12 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];
  96. memset(pNV12, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));
  97. uchar* dst_y = pNV12;
  98. int dst_y_stride = width;
  99. uchar* dst_vu = pNV12 + size_frame;
  100. int dst_vu_stride = (width + 1) / 2 * 2;
  101. libyuv::ARGBToNV12(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);
  102. matNV12 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
  103. libyuv::NV12ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV12.data, width * 4, width, height);
  104. cv::imwrite("NV12_bgra.jpg", matNV12);
  105. matNV12.copyTo(matDst);
  106. int count_diff = 0;
  107. int max_diff = 0;
  108. int threshold = 20;//
  109. for (int i = 0; i < height; i++) {
  110. uchar* pSrc = matBGRA.ptr(i);
  111. uchar* pDst = matNV12.ptr(i);
  112. for (int j = 0, m = 0; j < width; j++, m += 4) {
  113. int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
  114. tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
  115. if (tmp > max_diff)
  116. max_diff = tmp;
  117. if (abs(pSrc[m] - pDst[m]) > threshold ||
  118. abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
  119. abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
  120. count_diff++;
  121. //std::cout << i << "    " << j << std::endl;
  122. }
  123. }
  124. }
  125. std::cout << "convert NV12 to BGRA diff max: " << max_diff << std::endl;
  126. if (count_diff > width + height) {//
  127. std::cout << "convert NV12 to BGRA error." << std::endl;
  128. std::cout << "diff num: " << count_diff << std::endl;
  129. }
  130. delete[] pNV12;
  131. }
  132. void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
  133. {
  134. // BGRA <--> NV21
  135. cv::Mat matBGRA, matNV21;
  136. cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
  137. uchar* pNV21 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];
  138. memset(pNV21, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));
  139. uchar* dst_y = pNV21;
  140. int dst_y_stride = width;
  141. uchar* dst_vu = pNV21 + size_frame;
  142. int dst_vu_stride = (width + 1) / 2 * 2;
  143. libyuv::ARGBToNV21(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);
  144. matNV21 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
  145. libyuv::NV21ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV21.data, width * 4, width, height);
  146. cv::imwrite("NV21_bgra.jpg", matNV21);
  147. matNV21.copyTo(matDst);
  148. int count_diff = 0;
  149. int max_diff = 0;
  150. int threshold = 20;//
  151. for (int i = 0; i < height; i++) {
  152. uchar* pSrc = matBGRA.ptr(i);
  153. uchar* pDst = matNV21.ptr(i);
  154. for (int j = 0, m = 0; j < width; j++, m += 4) {
  155. int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
  156. tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
  157. if (tmp > max_diff)
  158. max_diff = tmp;
  159. if (abs(pSrc[m] - pDst[m]) > threshold ||
  160. abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
  161. abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
  162. count_diff++;
  163. //std::cout << i << "    " << j << std::endl;
  164. }
  165. }
  166. }
  167. std::cout << "convert NV21 to BGRA diff max: " << max_diff << std::endl;
  168. if (count_diff > width + height) {//
  169. std::cout << "convert NV21 to BGRA error." << std::endl;
  170. std::cout << "diff num: " << count_diff << std::endl;
  171. }
  172. delete[] pNV21;
  173. }

音视频基础——libyuv格式转换相关推荐

  1. 音视频基础——封装格式

    封装格式 概念 封装格式(也叫容器)就是将已经编码压缩好的视频流.音频流及字幕按照一定的方案放到一个文件中,便于播放软件播放.一般来说,视频文件的后缀名就是它的封装格式. 封装的格式不一样,后缀名也就 ...

  2. 音视频流媒体高级开发进阶:从音视频基础知识到技术实践

    站在音视频行业风口 站在风口,猪也能飞".在已经到来的2022年,音视频行业依旧是怎么也绕不过去的风口. 一方面,随着各项5G政策的落实,音视频+5G风口,将会深入挖掘音视频产业的无限潜力, ...

  3. 音视频基础知识---像素格式RGB

    音视频基础知识汇总: 音视频基础知识---协议相关RTSP RTMP HLS 音视频基础知识---封装格式 音视频基础知识---视频编码格式 音视频基础知识---音频编码格式 音视频基础知识---像素 ...

  4. ffmpeg音视频基础知识

    ffmpeg音视频基础知识 前言 一.图像的基础知识 二.视频编码基础知识 1.视频和图片之间的关系 2.为什么要编码? 3.什么是编码? 视频相关专业术语 提示:文章写完后,目录可以自动生成,如何生 ...

  5. 【音视频基础】视频基础理论

    [音视频基础]视频基础理论 图像基本概念 图像 屏幕 图像码流如何计算? 分辨率 帧率 码流计算 图像显示 YUV YUV格式 RGB与YUV的转换 YUV存储 YUV查看工具 参考资料 个人简介

  6. 音视频基础学习之【01.基于ffmpeg的简单播放器demo实现】

    目录 1.项目配置 2.显示界面设计 3.视频解码显示 流程描述 4.演示 最近在学习音视频基础知识,在这里感谢雷神留下的一系列指引新手入门的宝贵资源,虽然他英年早逝,但他的硕果永存.不由感慨真是天妒 ...

  7. 音视频开发--音视频基础

    音视频基础 一.音视频录制原理 视频录制流程 1.准备摄像头 2.图像帧阶段 从摄像头采集视频数据(图像帧),采集数据格式:YUV或者RGB,YUV和RGB细分的话还包括YUV 4:4:4.YUV 4 ...

  8. 《音视频开发进阶指南》读书笔记(一) —— 音视频基础概念

    前言 最近要学音视频,在图书馆借到这本<音视频开发进阶指南>,读了一段时间觉得挺好就在某宝买了. 以后一段时间应该都会沉浸在研究音视频中,开个专题记录哈每一章的读书笔记吧(以iOS开发的角 ...

  9. 【网络通信 -- 直播】音视频常见封装格式 -- MEPG2 TS

    [网络通信 -- 直播]音视频常见封装格式 -- MEPG2 TS [1]相关码流基本概念 ES 流(Elementary Stream)基本码流,直接取自编码器的数据流,可以为音频(AAC 等).视 ...

最新文章

  1. AutoCAD如何输入文字
  2. 【软考-软件设计师】汇编程序基本原理
  3. java 日期处理 口诀_java时间处理常用方法工具类
  4. 第十一周项目3-程序的多文件组织
  5. ajax获取qq音乐源码,ajax请求QQ音乐
  6. mysql数据库开发要求_MYSQL数据库开发规范
  7. lazarus开发android应用程序指南,Lazarus开发Android应用程序指南(2)
  8. Visual Basic十年风云
  9. 电子商务数据运营的五大应用
  10. 软件测试自学好还是培训好?软件测试自学与培训的优劣势对比
  11. TextInput组件练习 - QQLogin界面
  12. haimeiktv服务器系统,海媚 Haimei KTV8001 智能网络效果器
  13. python用turtle画一个苹果
  14. T检验是做什么的? --ttest--ttest2--matlab
  15. 隐语义模型(Latent Factor Model, LFM)原理以及代码实现
  16. java实现二维码的生成和解析包含工具类
  17. 个人发卡程序手机版自适应源码 完美版对接免签约支付
  18. [网络安全课程实验]:基于nmap 的网络扫描和信息分析
  19. 神经网络与深度学习(入门篇)
  20. 【算法基础四】C语言小项目实战---通讯录管理系统(单链表)

热门文章

  1. gmod服务器文件,Garry’s Mod|Gmod服务器架设教程(四)挂载创意工坊插件
  2. python selenium 点击 报错v_python执行selenium报错
  3. Kubernetes探针检测
  4. mysql timestamp 比较_解析mysql TIMESTAMP(时间戳)和datetime不同之处比较
  5. ProxmoxVE7.0+Ceph15.2集群搭建
  6. stm32f103rct6引脚功能表格
  7. Android:技术在线面试还是屡次撞板,过来人告诉你不及时
  8. IE8适配总结(一)
  9. maven安装异常 Failure to find xxx in 中央仓库
  10. 什么是大数据?大数据能做什么?