libyuv 操作 YUV420P ,如镜像、旋转、缩放等示例代码

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~


- 推荐文章 -

C++

音视频


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值