convert raw video image to I420 for vpx encoder

352 views Asked by At

im trying to feed raw video frames to libyuv to convert UYVY video to I420 but when i use libyuv to convert the frames i only get the to left hand corner of the video im trying to capture from my decklink card.

here is the code of the function im using

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;
}

how can i get it to show the entire frame?? Thank You!!!

1

There are 1 answers

0
Matthew On

i had to rewrite the converter for the format i needed, here is my solution

// 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;
}