Build a cmake project and test whether libyuv compiles successfully on github
Entire directory structure
Specific approach
- Create a
3rdparty
file, and create alibyuv
file inside. - Create three files
bin
include
lib
inlibyuv
- Copy the header files from the official libyuv in
include
- Copy the compiled
libyuv.a\ libyuv.so
to thelib
folder. - Copy
yuvconvert
to thebin
directory. If you don’t know how to compile libyuv, click here
2 Top-level directory added
CMakeLists.txt and main.cpp
Add to CMakeLists.txt
cmake_minimum_required (VERSION 2.8) project (TestLibyuv) set(CMAKE_C_COMPILER g++) add_definitions(-std=c++11) if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} ) message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." ) endif() option(WITH_OPENCV "with opencv" ON) set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/bin) ##OpenCV if(WITH_OPENCV) set(OpenCV_FIND_QUIETLY true) #find_package(OpenCV REQUIRED) //this will include opencv_ts which result in crash on centos find_package(OpenCV OPTIONAL_COMPONENTS imgcodecs) set(imgcodecs_libs ${OpenCV_LIBS}) find_package(OpenCV REQUIRED core imgproc highgui features2d) if(OpenCV_FOUND) if(imgcodecs_FOUND) list(APPEND OpenCV_LIBS imgcodecs_libs) endif() message(STATUS "HAVE_OPENCV enabled") message(STATUS "opencv libraries: ${OpenCV_LIBS}") set(HAVE_OPENCV true) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENCV") else() set (HAVE_OPENCV false) endif() else() set (HAVE_OPENCV false) endif() ##libyuv set(libyuv_LIBS yuv) include_directories(${PROJECT_SOURCE_DIR}/3rdparty/libyuv/include) include_directories(${PROJECT_SOURCE_DIR}/3rdparty/libyuv/include/libyuv) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libyuv/include) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libyuv/lib) add_executable(main main.cpp) target_link_libraries(main ${OpenCV_LIBS} ${libyuv_LIBS})
Add in main.cpp
#include <iostream> #include <assert.h> #include "libyuv.h" #include <cmath> #ifdef HAVE_OPENCV #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #if (CV_MAJOR_VERSION >= 3) #include "opencv2/imgcodecs/imgcodecs.hpp" #endif #else #error OpenCV required #endif void test_BGRAToI420(const cv::Mat & amp; matSrc, int width, int height, int size_frame, cv::Mat & amp; matDst); void test_BGRAToNV21(const cv::Mat & amp; matSrc, int width, int height, int size_frame, cv::Mat & amp; matDst); void test_BGRAToNV12(const cv::Mat & amp; matSrc, int width, int height, int size_frame, cv::Mat & amp; matDst); int main(int argc, char* argv[]) { cv::Mat matSrc = cv::imread("../../data/images/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()) & amp; & amp; (matI420.depth() == matNV12.depth())); assert((matI420.channels() == matNV21.channels()) & amp; & amp; (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 & amp; matSrc, int width, int height, int size_frame, cv::Mat & amp; 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 & amp; matSrc, int width, int height, int size_frame, cv::Mat & amp; 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 & amp; matSrc, int width, int height, int size_frame, cv::Mat & amp; 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; }
Test
mkdir build cd build cmake.. make ./bin/main