libyuv stable source code:
https://chromium.googlesource.com/libyuv/libyuv/+/refs/heads/stable
一、测试用例:
/** * auther : by dujingning * */
#include <array>
#include <vector>
#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"
void readFromFile( const char *FileName, std::vector<uint8_t> &data) {
printf("read from file %s\t:%d\r\n", FileName, data.size());
FILE *fp = fopen(FileName, "rb");
if (fp == nullptr) {
printf("failed!!! write to file %s\t:%d\r\n", FileName, data.size());
return;
}
fread(data.data(), data.size(), 1, fp);
fclose(fp);
}
void saveToFile( const char *FileName, std::vector<uint8_t> &data){
printf("write to file %s\t:%d\r\n", FileName, data.size());
FILE *fp = fopen(FileName, "wb");
if (fp == nullptr) {
printf("failed!!! write to file %s\t:%d\r\n", FileName, data.size());
return;
}
fwrite(data.data(), data.size(), 1, fp);
fclose(fp);
}
/* int ConvertToI420(const uint8* src_frame, size_t src_size, uint8* dst_y, int dst_stride_y, uint8* dst_u, int dst_stride_u, uint8* dst_v, int dst_stride_v, int crop_x, int crop_y, int src_width, int src_height, int crop_width, int crop_height, enum RotationMode rotation, uint32 format); */
void clip(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, int cropX, int cropY, int cropWidth, int cropHeight) {
ConvertToI420(
srcYuvData, width*height*3/2,
dstYuvData, cropWidth,
dstYuvData + cropWidth*cropHeight, (cropWidth+1)/2,
dstYuvData + cropWidth*cropHeight + ((cropWidth+1)/2)*((cropHeight+1)/2), (cropWidth+1)/2,
cropX, cropY,
width, height,
cropWidth, cropHeight,
libyuv::kRotate0,
libyuv::FOURCC_YU12);
}
/* int I420Mirror(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, uint8* dst_y, int dst_stride_y, uint8* dst_u, int dst_stride_u, uint8* dst_v, int dst_stride_v, int width, int height); */
void mirror(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height){
libyuv::I420Mirror(
srcYuvData , width,
srcYuvData + width*height, width/2,
srcYuvData + width*height + (width/2)*(height/2), width/2,
dstYuvData , width,
dstYuvData + width*height, width/2,
dstYuvData + width*height + (width/2)*(height/2), width/2,
width, height); // 180度旋转: -height
}
/* int I420Rotate(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, uint8* dst_y, int dst_stride_y, uint8* dst_u, int dst_stride_u, uint8* dst_v, int dst_stride_v, int src_width, int src_height, enum RotationMode mode); */
void rotate_(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, enum libyuv::RotationMode mode){
int destStride = width;
switch(mode){
case libyuv::kRotate90:
case libyuv::kRotate270:
destStride = height;
}
libyuv::I420Rotate(
srcYuvData , width,
srcYuvData + width*height, width/2,
srcYuvData + width*height + (width/2)*(height/2), width/2,
dstYuvData , destStride,
dstYuvData + width*height, destStride/2,
dstYuvData + width*height + (width/2)*(height/2), destStride/2,
width, height,
mode );
/* mode support : 顺时针旋转 kRotate0 = 0, // No rotation. kRotate90 = 90, // Rotate 90 degrees clockwise. kRotate180 = 180, // Rotate 180 degrees. kRotate270 = 270, // Rotate 270 degrees clockwise. */
}
/* int ConvertToARGB(const uint8* src_frame, size_t src_size, uint8* dst_argb, int dst_stride_argb, int crop_x, int crop_y, int src_width, int src_height, int crop_width, int crop_height, enum RotationMode rotation, uint32 format); */
void toBGRA(uint8_t *srcYuvData, size_t srcSize, uint8_t *dstYuvData, int width, int height){
ConvertToARGB(
srcYuvData, srcSize,
dstYuvData, width*4,
0,0,
width, height,
width, height,
libyuv::kRotate0, // 是否旋转
libyuv::FOURCC_I420); // 输入yuv的格式
}
/* int I420Scale(const uint8_t* src_y, int src_stride_y, const uint8_t* src_u, int src_stride_u, const uint8_t* src_v, int src_stride_v, int src_width, int src_height, uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u, int dst_stride_u, uint8_t* dst_v, int dst_stride_v, int dst_width, int dst_height, enum FilterMode filtering); */
void scale(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, int destWidth, int destHeight){
I420Scale(
srcYuvData , width,
srcYuvData + width*height, width/2,
srcYuvData + width*height + (width/2)*(height/2), width/2,
width, height,
dstYuvData , destWidth,
dstYuvData + destWidth*destHeight, destWidth/2,
dstYuvData + destWidth*destHeight + (destWidth/2)*(destHeight/2), destWidth/2,
destWidth, destHeight,
libyuv::kFilterBox);
/* supported filtering. typedef enum FilterMode { kFilterNone = 0, // Point sample; Fastest. kFilterLinear = 1, // Filter horizontally only. kFilterBilinear = 2, // Faster than box, but lower quality scaling down. kFilterBox = 3 // Highest quality. } FilterModeEnum; */
}
/* 先编译库: cmake -DCMAKE_INSTALL_PREFIX=$PWD/../libyuvInstall .. make && make install * */
/* * compile : g++ -std=c++11 libyuvExample.cpp -I./include -L./lib -lyuv -Wl,-rpath=./lib -g * */
int main() {
constexpr uint32_t width = 1920, height = 1080;
// read from file
std::vector<uint8_t> YUV(width*height*3 >> 1);
readFromFile("input.1920x1080.420p.yuv", YUV);
{
/// clip, play: ffplay -f rawvideo -pixel_format yuv420p -video_size 192*108 yuv420p-clip.yuv
constexpr uint32_t clipWidth = 192, clipHeight = 108;
std::vector<uint8_t> YUV_CLIP(clipWidth*clipHeight*3 >> 1);
clip(YUV.data(), YUV_CLIP.data(), width, height, 0, 0, clipWidth, clipHeight);
saveToFile("yuv420p-clip.yuv", YUV_CLIP);
}
{
/// mirror, play: ffplay -f rawvideo -pixel_format yuv420p -video_size 1920*1080 yuv420p-mirror.yuv
std::vector<uint8_t> YUV_MIRROR(width*height*3 >> 1);
mirror(YUV.data(), YUV_MIRROR.data(), width, height);
saveToFile("yuv420p-mirror.yuv", YUV_MIRROR);
}
{
/// Rotate , play: ffplay -f rawvideo -pixel_format yuv420p -video_size 1080*1920 yuv420p-rotate.yuv
std::vector<uint8_t> YUV_ROTATE(width*height*3 >> 1);
rotate_(YUV.data(), YUV_ROTATE.data(), width, height, libyuv::kRotate90);
saveToFile("yuv420p-rotate.yuv", YUV_ROTATE);
}
{
/// to RGB, play :ffplay -f rawvideo -pixel_format bgra -video_size 1920*1080 yuv420p-to-argb.argb
std::vector<uint8_t> RGB(width*height*4);
toBGRA( YUV.data(), YUV.size(), RGB.data(), width, height);
saveToFile("yuv420p-to-argb.argb", RGB);
}
{
/// scale, play : ffplay -f rawvideo -pixel_format yuv420p -video_size 3840*2160 yuv420p-scale.yuv
int destWidth = 1920*2, destHeight = 1080*2;
std::vector<uint8_t> YUV_SCALE(destWidth*destHeight*3 >> 1);
scale(YUV.data(), YUV_SCALE.data(), width, height, destWidth, destHeight);
saveToFile("yuv420p-scale.yuv", YUV_SCALE);
}
#ifdef HAVE_JPEG
printf("have jpeg\r\n");
#endif
return 0;
}
the end~
文章评论