将原始视频图像转换为I420以用于vpx编码器

时间:2018-04-29 02:58:23

标签: c++ libvpx libyuv

我试图将原始视频帧提供给libyuv以将UYVY视频转换为I420,但是当我使用libyuv转换帧时,我只得到视频的左上角我试图从我的decklink卡捕获。

这是使用

的函数的代码
int vpx_img_read(vpx_image_t *img, void *raw) {
  int plane;

  unsigned char *buf0 = img->planes[0];
  unsigned char *buf1 = img->planes[1];
  unsigned char *buf2 = img->planes[2];
  const int stride0 = img->stride[0];
  const int stride1 = img->stride[1];
  const int stride2 = img->stride[2];
  UYVYToI420(raw    , stride0,
             buf0, stride0,
             buf1, stride1,
             buf2, stride2,
             1920, 1080);


  return 1;
}

我怎样才能让它显示整个画面? 谢谢!!!

1 个答案:

答案 0 :(得分:0)

我必须为我需要的格式重写转换器,这是我的解决方案

// Copy row of UYVY Y's (422) into Y (420/422).
void UYVYToYRow_CD(const uint8* src_uyvy, uint8* dst_y, int width) {
  // Output a row of Y values.
  int x;
  for (x = 0; x < width - 1; x += 2) {
    dst_y[x] = src_uyvy[1];
    dst_y[x + 1] = src_uyvy[3];
    //if (x%4==0){
    src_uyvy += 4;

//}  
}
  if (width & 1) {
    dst_y[width - 1] = src_uyvy[1];
  }
}
// Filter 2 rows of UYVY UV's (422) into U and V (420).
void UYVYToUVRow_CD(const uint8* src_uyvy, int src_stride_uyvy,
                   uint8* dst_u, uint8* dst_v, int width) {
  // Output a row of UV values.
  int x;
  for (x = 0; x < width; x += 2) {
    dst_u[0] = (src_uyvy[0] + src_uyvy[src_stride_uyvy + 0+1920] + 1) >> 1;
    dst_v[0] = (src_uyvy[2] + src_uyvy[src_stride_uyvy + 2+1920] + 1) >> 1;
//  if (x%4==0){
   src_uyvy += 4;
//}

   dst_u += 1;
    dst_v += 1;
  }
}
// Convert UYVY to I420.
LIBYUV_API
int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy,
               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) {
  int y;
  void (*UYVYToUVRow)(const uint8* src_uyvy, int src_stride_uyvy,
      uint8* dst_u, uint8* dst_v, int width) = UYVYToUVRow_C;
  void (*UYVYToYRow)(const uint8* src_uyvy,
      uint8* dst_y, int width) = UYVYToYRow_C;
  // Negative height means invert the image.
  if (height < 0) {
    height = -height;
    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
    src_stride_uyvy = -src_stride_uyvy;
  }
#if defined(HAS_UYVYTOYROW_SSE2)
  if (TestCpuFlag(kCpuHasSSE2)) {
    UYVYToUVRow = UYVYToUVRow_Any_SSE2;
    UYVYToYRow = UYVYToYRow_Any_SSE2;
    if (IS_ALIGNED(width, 16)) {
      UYVYToUVRow = UYVYToUVRow_SSE2;
      UYVYToYRow = UYVYToYRow_SSE2;
    }
  }
#endif
#if defined(HAS_UYVYTOYROW_AVX2)
  if (TestCpuFlag(kCpuHasAVX2)) {
    UYVYToUVRow = UYVYToUVRow_Any_AVX2;
    UYVYToYRow = UYVYToYRow_Any_AVX2;
    if (IS_ALIGNED(width, 32)) {
      UYVYToUVRow = UYVYToUVRow_AVX2;
      UYVYToYRow = UYVYToYRow_AVX2;
    }
  }
#endif
#if defined(HAS_UYVYTOYROW_NEON)
  if (TestCpuFlag(kCpuHasNEON)) {
    UYVYToYRow = UYVYToYRow_Any_NEON;
    UYVYToUVRow = UYVYToUVRow_Any_NEON;
    if (IS_ALIGNED(width, 16)) {
      UYVYToYRow = UYVYToYRow_NEON;
      UYVYToUVRow = UYVYToUVRow_NEON;
    }
  }
#endif

  for (y = 0; y < height - 1; y += 1) {
    UYVYToUVRow_CD(src_uyvy, src_stride_uyvy, dst_u, dst_v, width);
    UYVYToYRow_CD(src_uyvy, dst_y+ dst_stride_y + 960, width);
    UYVYToYRow_CD(src_uyvy + src_stride_uyvy, dst_y + dst_stride_y + 960, width);
    src_uyvy += src_stride_uyvy * 2;

    dst_y += dst_stride_y * 1;
 if (y%2==0)
{
   dst_u += dst_stride_u;
    dst_v += dst_stride_v;
} 
 }
  if (height & 1) {
    UYVYToUVRow_CD(src_uyvy, 0, dst_u, dst_v , width);
    UYVYToYRow_CD(src_uyvy, dst_y, width);
  }
  return 0;
}