libyuv對YUV數據處理

#include <libyuv.h>

// nv21 --> i420
void nv21ToI420(unsigned char* src_nv21_data, int width, int height, unsigned char* src_i420_data)
{
  int src_y_size = width * height;
  int src_u_size = (width >> 1) * (height >> 1);

  unsigned char* src_nv21_y_data = src_nv21_data;
  unsigned char* src_nv21_vu_data = src_nv21_data + src_y_size;

  unsigned char* src_i420_y_data = src_i420_data;
  unsigned char* src_i420_u_data = src_i420_data + src_y_size;
  unsigned char* src_i420_v_data = src_i420_data + src_y_size + src_u_size;

  libyuv::NV21ToI420((const uint8_t*)src_nv21_y_data, width,
                     (const uint8_t*)src_nv21_vu_data, width,
                     (uint8_t*)src_i420_y_data, width,
                     (uint8_t*)src_i420_u_data, width >> 1,
                     (uint8_t*)src_i420_v_data, width >> 1,
                     width, height);
}

// i420 --> nv21
void i420ToNv21(unsigned char* src_i420_data, int width, int height, unsigned char* src_nv21_data)
{
  int src_y_size = width * height;
  int src_u_size = (width >> 1) * (height >> 1);

  unsigned char* src_nv21_y_data = src_nv21_data;
  unsigned char* src_nv21_uv_data = src_nv21_data + src_y_size;

  unsigned char* src_i420_y_data = src_i420_data;
  unsigned char* src_i420_u_data = src_i420_data + src_y_size;
  unsigned char* src_i420_v_data = src_i420_data + src_y_size + src_u_size;

  libyuv::I420ToNV21(
    (const uint8_t*)src_i420_y_data, width,
    (const uint8_t*)src_i420_u_data, width >> 1,
    (const uint8_t*)src_i420_v_data, width >> 1,
    (uint8_t*)src_nv21_y_data, width,
    (uint8_t*)src_nv21_uv_data, width,
    width, height);
}

// nv12 --> i420 
void nv12ToI420(unsigned char* Src_data, int src_width, int src_height, unsigned char* Dst_data)
{
  // NV12 video size
  int NV12_Size = src_width * src_height * 3 / 2;
  int NV12_Y_Size = src_width * src_height;

  // YUV420 video size
  int I420_Size = src_width * src_height * 3 / 2;
  int I420_Y_Size = src_width * src_height;
  int I420_U_Size = (src_width >> 1) * (src_height >> 1);
  int I420_V_Size = I420_U_Size;

  // src: buffer address of Y channel and UV channel
  unsigned char* Y_data_Src = Src_data;
  unsigned char* UV_data_Src = Src_data + NV12_Y_Size;
  int src_stride_y = src_width;
  int src_stride_uv = src_width;

  //dst: buffer address of Y channel、U channel and V channel
  unsigned char* Y_data_Dst = Dst_data;
  unsigned char* U_data_Dst = Dst_data + I420_Y_Size;
  unsigned char* V_data_Dst = Dst_data + I420_Y_Size + I420_U_Size;
  int Dst_Stride_Y = src_width;
  int Dst_Stride_U = src_width >> 1;
  int Dst_Stride_V = Dst_Stride_U;

  libyuv::NV12ToI420((const uint8_t*)Y_data_Src, src_stride_y,
                     (const uint8_t*)UV_data_Src, src_stride_uv,
                     (uint8_t*)Y_data_Dst, Dst_Stride_Y,
                     (uint8_t*)U_data_Dst, Dst_Stride_U,
                     (uint8_t*)V_data_Dst, Dst_Stride_V,
                     src_width, src_height);
}

// i420 --> nv12 
void i420ToNv12(unsigned char* src_i420_data, int width, int height, unsigned char* src_nv12_data)
{
  int src_y_size = width * height;
  int src_u_size = (width >> 1) * (height >> 1);

  unsigned char* src_nv12_y_data = src_nv12_data;
  unsigned char* src_nv12_uv_data = src_nv12_data + src_y_size;

  unsigned char* src_i420_y_data = src_i420_data;
  unsigned char* src_i420_u_data = src_i420_data + src_y_size;
  unsigned char* src_i420_v_data = src_i420_data + src_y_size + src_u_size;

  libyuv::I420ToNV12(
    (const uint8_t*)src_i420_y_data, width,
    (const uint8_t*)src_i420_u_data, width >> 1,
    (const uint8_t*)src_i420_v_data, width >> 1,
    (uint8_t*)src_nv12_y_data, width,
    (uint8_t*)src_nv12_uv_data, width,
    width, height);
}

// 鏡像
void mirrorI420(unsigned char* src_i420_data, int width, int height, unsigned char* dst_i420_data)
{
  int src_i420_y_size = width * height;
  // int src_i420_u_size = (width >> 1) * (height >> 1);
  int src_i420_u_size = src_i420_y_size >> 2;

  unsigned char* src_i420_y_data = src_i420_data;
  unsigned char* src_i420_u_data = src_i420_data + src_i420_y_size;
  unsigned char* src_i420_v_data = src_i420_data + src_i420_y_size + src_i420_u_size;

  unsigned char* dst_i420_y_data = dst_i420_data;
  unsigned char* dst_i420_u_data = dst_i420_data + src_i420_y_size;
  unsigned char* dst_i420_v_data = dst_i420_data + src_i420_y_size + src_i420_u_size;

  libyuv::I420Mirror((const uint8_t*)src_i420_y_data, width,
                     (const uint8_t*)src_i420_u_data, width >> 1,
                     (const uint8_t*)src_i420_v_data, width >> 1,
                     (uint8_t*)dst_i420_y_data, width,
                     (uint8_t*)dst_i420_u_data, width >> 1,
                     (uint8_t*)dst_i420_v_data, width >> 1,
                     width, height);
}

// 旋轉
void rotateI420(unsigned char* src_i420_data, int width, int height, unsigned char* dst_i420_data, int degree)
{
  int src_i420_y_size = width * height;
  int src_i420_u_size = (width >> 1) * (height >> 1);

  unsigned char* src_i420_y_data = src_i420_data;
  unsigned char* src_i420_u_data = src_i420_data + src_i420_y_size;
  unsigned char* src_i420_v_data = src_i420_data + src_i420_y_size + src_i420_u_size;

  unsigned char* dst_i420_y_data = dst_i420_data;
  unsigned char* dst_i420_u_data = dst_i420_data + src_i420_y_size;
  unsigned char* dst_i420_v_data = dst_i420_data + src_i420_y_size + src_i420_u_size;

  //要注意這裏的width和height在旋轉之後是相反的
  if (degree == libyuv::kRotate90 || degree == libyuv::kRotate270)
  {
    libyuv::I420Rotate((const uint8_t*)src_i420_y_data, width,
                       (const uint8_t*)src_i420_u_data, width >> 1,
                       (const uint8_t*)src_i420_v_data, width >> 1,
                       (uint8_t*)dst_i420_y_data, height,
                       (uint8_t*)dst_i420_u_data, height >> 1,
                       (uint8_t*)dst_i420_v_data, height >> 1,
                       width, height,
                       (libyuv::RotationMode)degree);
  }
  else
  {
    libyuv::I420Rotate((const uint8_t*)src_i420_y_data, width,
                       (const uint8_t*)src_i420_u_data, width >> 1,
                       (const uint8_t*)src_i420_v_data, width >> 1,
                       (uint8_t*)dst_i420_y_data, width,
                       (uint8_t*)dst_i420_u_data, width >> 1,
                       (uint8_t*)dst_i420_v_data, width >> 1,
                       width, height,
                       (libyuv::RotationMode)degree);
  }
}

// 縮放
void scaleI420(unsigned char* src_i420_data, int width, int height, unsigned char* dst_i420_data, int dst_width,
               int dst_height, int mode)
{
  int src_i420_y_size = width * height;
  int src_i420_u_size = (width >> 1) * (height >> 1);
  unsigned char* src_i420_y_data = src_i420_data;
  unsigned char* src_i420_u_data = src_i420_data + src_i420_y_size;
  unsigned char* src_i420_v_data = src_i420_data + src_i420_y_size + src_i420_u_size;

  int dst_i420_y_size = dst_width * dst_height;
  int dst_i420_u_size = (dst_width >> 1) * (dst_height >> 1);
  unsigned char* dst_i420_y_data = dst_i420_data;
  unsigned char* dst_i420_u_data = dst_i420_data + dst_i420_y_size;
  unsigned char* dst_i420_v_data = dst_i420_data + dst_i420_y_size + dst_i420_u_size;

  libyuv::I420Scale((const uint8_t*)src_i420_y_data, width,
                    (const uint8_t*)src_i420_u_data, width >> 1,
                    (const uint8_t*)src_i420_v_data, width >> 1,
                    width, height,
                    (uint8_t*)dst_i420_y_data, dst_width,
                    (uint8_t*)dst_i420_u_data, dst_width >> 1,
                    (uint8_t*)dst_i420_v_data, dst_width >> 1,
                    dst_width, dst_height,
                    (libyuv::FilterMode)mode);
}

// 裁剪
void cropI420(unsigned char* src_i420_data, int src_length, int width, int height,
              unsigned char* dst_i420_data, int dst_width, int dst_height, int left, int top)
{
  int dst_i420_y_size = dst_width * dst_height;
  int dst_i420_u_size = (dst_width >> 1) * (dst_height >> 1);

  unsigned char* dst_i420_y_data = dst_i420_data;
  unsigned char* dst_i420_u_data = dst_i420_data + dst_i420_y_size;
  unsigned char* dst_i420_v_data = dst_i420_data + dst_i420_y_size + dst_i420_u_size;

  libyuv::ConvertToI420((const uint8_t*)src_i420_data, src_length,
                        (uint8_t*)dst_i420_y_data, dst_width,
                        (uint8_t*)dst_i420_u_data, dst_width >> 1,
                        (uint8_t*)dst_i420_v_data, dst_width >> 1,
                        left, top,
                        width, height,
                        dst_width, dst_height,
                        libyuv::kRotate0, libyuv::FOURCC_I420);
}


https://www.jianshu.com/p/bd0feaf4c0f9

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章