Delete wrapper API ConvertToI420 for YUV conversion to I420

Directly use the libyuv API for YUV conversion to I420

Bug: None
Change-Id: Iea6e8fa8f7179c800ea850305170002398cb00dc
Reviewed-on: https://webrtc-review.googlesource.com/17260
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Alex Glaznev <glaznev@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20681}
diff --git a/AUTHORS b/AUTHORS
index 285cde4..3a73bd61 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -28,6 +28,7 @@
 Jiawei Ou <jiawei.ou@gmail.com>
 Jie Mao <maojie0924@gmail.com>
 Luke Weber <luke.weber@gmail.com>
+Mallikarjuna Rao V <vm.arjun@samsung.com>
 Manish Jethani <manish.jethani@gmail.com>
 Martin Storsjo <martin@martin.st>
 Matthias Liebig <matthias.gcode@gmail.com>
diff --git a/common_video/libyuv/include/webrtc_libyuv.h b/common_video/libyuv/include/webrtc_libyuv.h
index 8230c1f..5b2a3af 100644
--- a/common_video/libyuv/include/webrtc_libyuv.h
+++ b/common_video/libyuv/include/webrtc_libyuv.h
@@ -24,7 +24,6 @@
 
 namespace webrtc {
 
-class I420Buffer;
 
 // This is the max PSNR value our algorithms can return.
 const double kPerfectPSNR = 48.0f;
@@ -64,34 +63,6 @@
                   size_t size,
                   uint8_t* buffer);
 int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer);
-// Convert To I420
-// Input:
-//   - src_video_type   : Type of input video.
-//   - src_frame        : Pointer to a source frame.
-//   - crop_x/crop_y    : Starting positions for cropping (0 for no crop).
-//   - src_width        : src width in pixels.
-//   - src_height       : src height in pixels.
-//   - sample_size      : Required only for the parsing of MJPG (set to 0 else).
-//   - rotate           : Rotation mode of output image.
-// Output:
-//   - dst_buffer       : Reference to a destination frame buffer.
-// Return value: 0 if OK, < 0 otherwise.
-
-// TODO(nisse): Delete this wrapper, and let users call libyuv directly. Most
-// calls pass |src_video_type| == kI420, and should use libyuv::I420Copy. Also
-// remember to delete the I420Buffer forward declaration above. The only
-// exception at the time of this writing is VideoCaptureImpl::IncomingFrame,
-// which still needs libyuv::ConvertToI420.
-int ConvertToI420(VideoType src_video_type,
-                  const uint8_t* src_frame,
-                  int crop_x,
-                  int crop_y,
-                  int src_width,
-                  int src_height,
-                  size_t sample_size,
-                  VideoRotation rotation,
-                  I420Buffer* dst_buffer);
-
 // Convert From I420
 // Input:
 //   - src_frame        : Reference to a source frame.
@@ -147,6 +118,9 @@
   std::vector<uint8_t> tmp_uv_planes_;
 };
 
+// Convert VideoType to libyuv FourCC type
+int ConvertVideoType(VideoType video_type);
+
 }  // namespace webrtc
 
 #endif  // COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_
diff --git a/common_video/libyuv/libyuv_unittest.cc b/common_video/libyuv/libyuv_unittest.cc
index 4e3a1ac..e5a09bf 100644
--- a/common_video/libyuv/libyuv_unittest.cc
+++ b/common_video/libyuv/libyuv_unittest.cc
@@ -16,6 +16,7 @@
 #include "api/video/i420_buffer.h"
 #include "api/video/video_frame.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "libyuv.h"  // NOLINT
 #include "test/frame_utils.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -96,9 +97,16 @@
   std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]);
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kI420, 0,
                                out_i420_buffer.get()));
-  EXPECT_EQ(0,
-            ConvertToI420(VideoType::kI420, out_i420_buffer.get(), 0, 0, width_,
-                          height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+  int y_size = width_ * height_;
+  int u_size = res_i420_buffer->ChromaWidth() * res_i420_buffer->ChromaHeight();
+  int ret = libyuv::I420Copy(
+      out_i420_buffer.get(), width_, out_i420_buffer.get() + y_size,
+      width_ >> 1, out_i420_buffer.get() + y_size + u_size, width_ >> 1,
+      res_i420_buffer.get()->MutableDataY(), res_i420_buffer.get()->StrideY(),
+      res_i420_buffer.get()->MutableDataU(), res_i420_buffer.get()->StrideU(),
+      res_i420_buffer.get()->MutableDataV(), res_i420_buffer.get()->StrideV(),
+      width_, height_);
+  EXPECT_EQ(0, ret);
 
   if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
     return;
@@ -119,10 +127,15 @@
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kRGB24, 0,
                                res_rgb_buffer2.get()));
 
-  EXPECT_EQ(
-      0, ConvertToI420(VideoType::kRGB24, res_rgb_buffer2.get(), 0, 0, width_,
-                       height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+  ret = libyuv::ConvertToI420(
+      res_rgb_buffer2.get(), 0, res_i420_buffer.get()->MutableDataY(),
+      res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+      res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+      res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+      ConvertVideoType(VideoType::kRGB24));
 
+  EXPECT_EQ(0, ret);
   if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
     return;
   }
@@ -137,9 +150,16 @@
   std::unique_ptr<uint8_t[]> out_uyvy_buffer(new uint8_t[width_ * height_ * 2]);
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kUYVY, 0,
                                out_uyvy_buffer.get()));
-  EXPECT_EQ(0,
-            ConvertToI420(VideoType::kUYVY, out_uyvy_buffer.get(), 0, 0, width_,
-                          height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+
+  ret = libyuv::ConvertToI420(
+      out_uyvy_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+      res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+      res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+      res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+      ConvertVideoType(VideoType::kUYVY));
+
+  EXPECT_EQ(0, ret);
   psnr =
       I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
   EXPECT_EQ(48.0, psnr);
@@ -153,9 +173,15 @@
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kYUY2, 0,
                                out_yuy2_buffer.get()));
 
-  EXPECT_EQ(0,
-            ConvertToI420(VideoType::kYUY2, out_yuy2_buffer.get(), 0, 0, width_,
-                          height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+  ret = libyuv::ConvertToI420(
+      out_yuy2_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+      res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+      res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+      res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+      ConvertVideoType(VideoType::kYUY2));
+
+  EXPECT_EQ(0, ret);
 
   if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
     return;
@@ -171,9 +197,15 @@
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kRGB565, 0,
                                out_rgb565_buffer.get()));
 
-  EXPECT_EQ(0, ConvertToI420(VideoType::kRGB565, out_rgb565_buffer.get(), 0, 0,
-                             width_, height_, 0, kVideoRotation_0,
-                             res_i420_buffer.get()));
+  ret = libyuv::ConvertToI420(
+      out_rgb565_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+      res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+      res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+      res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+      ConvertVideoType(VideoType::kRGB565));
+
+  EXPECT_EQ(0, ret);
   if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
     return;
   }
@@ -192,9 +224,15 @@
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kARGB, 0,
                                out_argb8888_buffer.get()));
 
-  EXPECT_EQ(0, ConvertToI420(VideoType::kARGB, out_argb8888_buffer.get(), 0, 0,
-                             width_, height_, 0, kVideoRotation_0,
-                             res_i420_buffer.get()));
+  ret = libyuv::ConvertToI420(
+      out_argb8888_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+      res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+      res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+      res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+      ConvertVideoType(VideoType::kARGB));
+
+  EXPECT_EQ(0, ret);
 
   if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
     return;
@@ -227,9 +265,17 @@
   std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]);
   EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kI420, 0,
                                out_i420_buffer.get()));
-  EXPECT_EQ(0,
-            ConvertToI420(VideoType::kI420, out_i420_buffer.get(), 0, 0, width_,
-                          height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+  int y_size = width_ * height_;
+  int u_size = res_i420_buffer->ChromaWidth() * res_i420_buffer->ChromaHeight();
+  int ret = libyuv::I420Copy(
+      out_i420_buffer.get(), width_, out_i420_buffer.get() + y_size,
+      width_ >> 1, out_i420_buffer.get() + y_size + u_size, width_ >> 1,
+      res_i420_buffer.get()->MutableDataY(), res_i420_buffer.get()->StrideY(),
+      res_i420_buffer.get()->MutableDataU(), res_i420_buffer.get()->StrideU(),
+      res_i420_buffer.get()->MutableDataV(), res_i420_buffer.get()->StrideV(),
+      width_, height_);
+
+  EXPECT_EQ(0, ret);
 
   if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
     return;
@@ -239,33 +285,6 @@
   EXPECT_EQ(48.0, psnr);
 }
 
-TEST_F(TestLibYuv, RotateTest) {
-  // Use ConvertToI420 for multiple rotations - see that nothing breaks, all
-  // memory is properly allocated and end result is equal to the starting point.
-  int rotated_width = height_;
-  int rotated_height = width_;
-  int stride_y;
-  int stride_uv;
-
-  // Assume compact layout, no padding.
-  const uint8_t* orig_buffer =
-      orig_frame_->video_frame_buffer()->GetI420()->DataY();
-
-  Calc16ByteAlignedStride(rotated_width, &stride_y, &stride_uv);
-  rtc::scoped_refptr<I420Buffer> rotated_res_i420_buffer = I420Buffer::Create(
-      rotated_width, rotated_height, stride_y, stride_uv, stride_uv);
-  EXPECT_EQ(
-      0, ConvertToI420(VideoType::kI420, orig_buffer, 0, 0, width_, height_, 0,
-                       kVideoRotation_90, rotated_res_i420_buffer.get()));
-  EXPECT_EQ(
-      0, ConvertToI420(VideoType::kI420, orig_buffer, 0, 0, width_, height_, 0,
-                       kVideoRotation_270, rotated_res_i420_buffer.get()));
-  rotated_res_i420_buffer = I420Buffer::Create(width_, height_);
-  EXPECT_EQ(
-      0, ConvertToI420(VideoType::kI420, orig_buffer, 0, 0, width_, height_, 0,
-                       kVideoRotation_180, rotated_res_i420_buffer.get()));
-}
-
 static uint8_t Average(int a, int b, int c, int d) {
   return (a + b + c + d + 2) / 4;
 }
diff --git a/common_video/libyuv/webrtc_libyuv.cc b/common_video/libyuv/webrtc_libyuv.cc
index 4cb8686..4384b85 100644
--- a/common_video/libyuv/webrtc_libyuv.cc
+++ b/common_video/libyuv/webrtc_libyuv.cc
@@ -13,7 +13,6 @@
 #include <string.h>
 
 #include "rtc_base/checks.h"
-// TODO(nisse): Only needed for the deprecated ConvertToI420.
 #include "api/video/i420_buffer.h"
 
 // NOTE(ajm): Path provided by gn.
@@ -155,21 +154,6 @@
                              width, height);
 }
 
-libyuv::RotationMode ConvertRotationMode(VideoRotation rotation) {
-  switch (rotation) {
-    case kVideoRotation_0:
-      return libyuv::kRotate0;
-    case kVideoRotation_90:
-      return libyuv::kRotate90;
-    case kVideoRotation_180:
-      return libyuv::kRotate180;
-    case kVideoRotation_270:
-      return libyuv::kRotate270;
-  }
-  RTC_NOTREACHED();
-  return libyuv::kRotate0;
-}
-
 int ConvertVideoType(VideoType video_type) {
   switch (video_type) {
     case VideoType::kUnknown:
@@ -208,35 +192,6 @@
   return libyuv::FOURCC_ANY;
 }
 
-// TODO(nisse): Delete this wrapper, let callers use libyuv directly.
-int ConvertToI420(VideoType src_video_type,
-                  const uint8_t* src_frame,
-                  int crop_x,
-                  int crop_y,
-                  int src_width,
-                  int src_height,
-                  size_t sample_size,
-                  VideoRotation rotation,
-                  I420Buffer* dst_buffer) {
-  int dst_width = dst_buffer->width();
-  int dst_height = dst_buffer->height();
-  // LibYuv expects pre-rotation values for dst.
-  // Stride values should correspond to the destination values.
-  if (rotation == kVideoRotation_90 || rotation == kVideoRotation_270) {
-    std::swap(dst_width, dst_height);
-  }
-  return libyuv::ConvertToI420(
-      src_frame, sample_size,
-      dst_buffer->MutableDataY(), dst_buffer->StrideY(),
-      dst_buffer->MutableDataU(), dst_buffer->StrideU(),
-      dst_buffer->MutableDataV(), dst_buffer->StrideV(),
-      crop_x, crop_y,
-      src_width, src_height,
-      dst_width, dst_height,
-      ConvertRotationMode(rotation),
-      ConvertVideoType(src_video_type));
-}
-
 int ConvertFromI420(const VideoFrame& src_frame,
                     VideoType dst_video_type,
                     int dst_sample_size,
diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
index 6a24f80..1eb77ee 100644
--- a/modules/video_capture/video_capture_impl.cc
+++ b/modules/video_capture/video_capture_impl.cc
@@ -14,6 +14,7 @@
 
 #include "api/video/i420_buffer.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "libyuv.h"  // NOLINT
 #include "modules/include/module_common_types.h"
 #include "modules/video_capture/video_capture_config.h"
 #include "rtc_base/logging.h"
@@ -164,10 +165,32 @@
   // TODO(nisse): Use a pool?
   rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(
       target_width, abs(target_height), stride_y, stride_uv, stride_uv);
-  const int conversionResult = ConvertToI420(
-      frameInfo.videoType, videoFrame, 0, 0,  // No cropping
-      width, height, videoFrameLength,
-      apply_rotation ? _rotateFrame : kVideoRotation_0, buffer.get());
+
+  libyuv::RotationMode rotation_mode = libyuv::kRotate0;
+  if (apply_rotation) {
+    switch (_rotateFrame) {
+      case kVideoRotation_0:
+        rotation_mode = libyuv::kRotate0;
+        break;
+      case kVideoRotation_90:
+        rotation_mode = libyuv::kRotate90;
+        break;
+      case kVideoRotation_180:
+        rotation_mode = libyuv::kRotate180;
+        break;
+      case kVideoRotation_270:
+        rotation_mode = libyuv::kRotate270;
+        break;
+    }
+  }
+
+  const int conversionResult = libyuv::ConvertToI420(
+      videoFrame, videoFrameLength, buffer.get()->MutableDataY(),
+      buffer.get()->StrideY(), buffer.get()->MutableDataU(),
+      buffer.get()->StrideU(), buffer.get()->MutableDataV(),
+      buffer.get()->StrideV(), 0, 0,  // No Cropping
+      width, height, target_width, target_height, rotation_mode,
+      ConvertVideoType(frameInfo.videoType));
   if (conversionResult < 0) {
     RTC_LOG(LS_ERROR) << "Failed to convert capture frame from type "
                       << static_cast<int>(frameInfo.videoType) << "to I420.";
diff --git a/modules/video_coding/codecs/i420/i420.cc b/modules/video_coding/codecs/i420/i420.cc
index 2749d0e..8c8c3f0 100644
--- a/modules/video_coding/codecs/i420/i420.cc
+++ b/modules/video_coding/codecs/i420/i420.cc
@@ -15,6 +15,7 @@
 
 #include "api/video/i420_buffer.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "libyuv.h"  // NOLINT
 
 namespace {
 const size_t kI420HeaderSize = 4;
@@ -204,8 +205,16 @@
       I420Buffer::Create(_width, _height);
 
   // Converting from raw buffer I420Buffer.
-  int ret = ConvertToI420(VideoType::kI420, buffer, 0, 0, _width, _height, 0,
-                          kVideoRotation_0, frame_buffer.get());
+  int y_stride = 16 * ((_width + 15) / 16);
+  int uv_stride = 16 * ((_width + 31) / 32);
+  int y_size = y_stride * height;
+  int u_size = uv_stride * frame_buffer->ChromaHeight();
+  int ret = libyuv::I420Copy(
+      buffer, y_stride, buffer + y_size, uv_stride, buffer + y_size + u_size,
+      uv_stride, frame_buffer.get()->MutableDataY(),
+      frame_buffer.get()->StrideY(), frame_buffer.get()->MutableDataU(),
+      frame_buffer.get()->StrideU(), frame_buffer.get()->MutableDataV(),
+      frame_buffer.get()->StrideV(), _width, _height);
   if (ret < 0) {
     return WEBRTC_VIDEO_CODEC_MEMORY;
   }