Revert "Add scaling interface to VideoFrameBuffer"

This reverts commit c79f1d8cfb48c348692320b05fa31598ed7067ca.

Reason for revert: Breaks downstream project.

Original change's description:
> Add scaling interface to VideoFrameBuffer
>
> This can be overriden for kNative frame types to perform scaling efficiently.
>
> Default implementations for existing buffer types require actual
> buffer implementation, thus this CL also merges "video_frame"
> with "video_frame_I420" build targets.
>
> Bug: webrtc:11976, chromium:1132299
> Change-Id: I3bf5f6bf179db5e7ab165b1c2301980043a08765
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186303
> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
> Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
> Reviewed-by: Niels Moller <nisse@webrtc.org>
> Reviewed-by: Evan Shrubsole <eshr@google.com>
> Cr-Commit-Position: refs/heads/master@{#32352}

TBR=mbonadei@webrtc.org,sakal@webrtc.org,ilnik@webrtc.org,nisse@webrtc.org,stefan@webrtc.org,eshr@google.com

Change-Id: I86ac697bf963ef7e2c4f2ed34c3a7bf04f4f1ce1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:11976
Bug: chromium:1132299
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/187344
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32354}
diff --git a/api/video/BUILD.gn b/api/video/BUILD.gn
index f4069d2..fd8363a 100644
--- a/api/video/BUILD.gn
+++ b/api/video/BUILD.gn
@@ -42,8 +42,6 @@
 rtc_library("video_frame") {
   visibility = [ "*" ]
   sources = [
-    "i420_buffer.cc",
-    "i420_buffer.h",
     "video_codec_type.h",
     "video_frame.cc",
     "video_frame.h",
@@ -61,9 +59,7 @@
     "..:scoped_refptr",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
-    "../../rtc_base/memory:aligned_malloc",
     "../../rtc_base/system:rtc_export",
-    "//third_party/libyuv",
   ]
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
@@ -74,47 +70,6 @@
   }
 }
 
-# Deprecated empty target. Use "video_frame" instead.
-rtc_source_set("video_frame_i420") {
-  visibility = [ "*" ]
-  sources = []
-  deps = [ ":video_frame" ]
-}
-
-rtc_library("video_frame_i010") {
-  visibility = [ "*" ]
-  sources = [
-    "i010_buffer.cc",
-    "i010_buffer.h",
-  ]
-  deps = [
-    ":video_frame",
-    ":video_rtp_headers",
-    "..:scoped_refptr",
-    "../../rtc_base",
-    "../../rtc_base:checks",
-    "../../rtc_base/memory:aligned_malloc",
-    "//third_party/libyuv",
-  ]
-}
-
-rtc_library("video_frame_nv12") {
-  visibility = [ "*" ]
-  sources = [
-    "nv12_buffer.cc",
-    "nv12_buffer.h",
-  ]
-  deps = [
-    ":video_frame",
-    "..:scoped_refptr",
-    "../../rtc_base",
-    "../../rtc_base:checks",
-    "../../rtc_base/memory:aligned_malloc",
-    "../../rtc_base/system:rtc_export",
-    "//third_party/libyuv",
-  ]
-}
-
 rtc_source_set("recordable_encoded_frame") {
   visibility = [ "*" ]
   sources = [ "recordable_encoded_frame.h" ]
@@ -135,6 +90,60 @@
   sources = [ "video_frame_type.h" ]
 }
 
+rtc_library("video_frame_i420") {
+  visibility = [ "*" ]
+  sources = [
+    "i420_buffer.cc",
+    "i420_buffer.h",
+  ]
+  deps = [
+    ":video_frame",
+    ":video_rtp_headers",
+    "..:scoped_refptr",
+    "../../rtc_base",
+    "../../rtc_base:checks",
+    "../../rtc_base/memory:aligned_malloc",
+    "../../rtc_base/system:rtc_export",
+    "//third_party/libyuv",
+  ]
+}
+
+rtc_library("video_frame_i010") {
+  visibility = [ "*" ]
+  sources = [
+    "i010_buffer.cc",
+    "i010_buffer.h",
+  ]
+  deps = [
+    ":video_frame",
+    ":video_frame_i420",
+    ":video_rtp_headers",
+    "..:scoped_refptr",
+    "../../rtc_base",
+    "../../rtc_base:checks",
+    "../../rtc_base/memory:aligned_malloc",
+    "//third_party/libyuv",
+  ]
+}
+
+rtc_library("video_frame_nv12") {
+  visibility = [ "*" ]
+  sources = [
+    "nv12_buffer.cc",
+    "nv12_buffer.h",
+  ]
+  deps = [
+    ":video_frame",
+    ":video_frame_i420",
+    "..:scoped_refptr",
+    "../../rtc_base",
+    "../../rtc_base:checks",
+    "../../rtc_base/memory:aligned_malloc",
+    "../../rtc_base/system:rtc_export",
+    "//third_party/libyuv",
+  ]
+}
+
 rtc_library("encoded_image") {
   visibility = [ "*" ]
   sources = [
diff --git a/api/video/nv12_buffer.cc b/api/video/nv12_buffer.cc
index cfa85ac..d6f0183 100644
--- a/api/video/nv12_buffer.cc
+++ b/api/video/nv12_buffer.cc
@@ -14,7 +14,6 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/ref_counted_object.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
-#include "third_party/libyuv/include/libyuv/scale.h"
 
 namespace webrtc {
 
@@ -123,35 +122,4 @@
   memset(data_.get(), 0, NV12DataSize(height_, stride_y_, stride_uv_));
 }
 
-void NV12Buffer::CropAndScaleFrom(const NV12BufferInterface& src,
-                                  int offset_x,
-                                  int offset_y,
-                                  int crop_width,
-                                  int crop_height) {
-  RTC_CHECK_LE(crop_width, src.width());
-  RTC_CHECK_LE(crop_height, src.height());
-  RTC_CHECK_LE(crop_width + offset_x, src.width());
-  RTC_CHECK_LE(crop_height + offset_y, src.height());
-  RTC_CHECK_GE(offset_x, 0);
-  RTC_CHECK_GE(offset_y, 0);
-
-  // Make sure offset is even so that u/v plane becomes aligned.
-  const int uv_offset_x = offset_x / 2;
-  const int uv_offset_y = offset_y / 2;
-  offset_x = uv_offset_x * 2;
-  offset_y = uv_offset_y * 2;
-
-  const uint8_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x;
-  const uint8_t* uv_plane =
-      src.DataUV() + src.StrideUV() * uv_offset_y + uv_offset_x * 2;
-
-  // kFilterBox is unsupported in libyuv, so using kFilterBilinear instead.
-  int res = libyuv::NV12Scale(y_plane, src.StrideY(), uv_plane, src.StrideUV(),
-                              crop_width, crop_height, MutableDataY(),
-                              StrideY(), MutableDataUV(), StrideUV(), width(),
-                              height(), libyuv::kFilterBilinear);
-
-  RTC_DCHECK_EQ(res, 0);
-}
-
 }  // namespace webrtc
diff --git a/api/video/nv12_buffer.h b/api/video/nv12_buffer.h
index cb989e8..039f767 100644
--- a/api/video/nv12_buffer.h
+++ b/api/video/nv12_buffer.h
@@ -56,14 +56,6 @@
   // are resolved in a better way. Or in the mean time, use SetBlack.
   void InitializeData();
 
-  // Scale the cropped area of |src| to the size of |this| buffer, and
-  // write the result into |this|.
-  void CropAndScaleFrom(const NV12BufferInterface& src,
-                        int offset_x,
-                        int offset_y,
-                        int crop_width,
-                        int crop_height);
-
  protected:
   NV12Buffer(int width, int height);
   NV12Buffer(int width, int height, int stride_y, int stride_uv);
diff --git a/api/video/test/BUILD.gn b/api/video/test/BUILD.gn
index 72f5049..d46b48e 100644
--- a/api/video/test/BUILD.gn
+++ b/api/video/test/BUILD.gn
@@ -20,6 +20,7 @@
     "..:video_adaptation",
     "..:video_bitrate_allocation",
     "..:video_frame",
+    "..:video_frame_i420",
     "..:video_frame_nv12",
     "..:video_rtp_headers",
     "../../../test:frame_utils",
diff --git a/api/video/video_frame_buffer.cc b/api/video/video_frame_buffer.cc
index 64f3394..e7418cb 100644
--- a/api/video/video_frame_buffer.cc
+++ b/api/video/video_frame_buffer.cc
@@ -10,25 +10,10 @@
 
 #include "api/video/video_frame_buffer.h"
 
-#include "api/video/i420_buffer.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
 
-rtc::scoped_refptr<VideoFrameBuffer> VideoFrameBuffer::CropAndScale(
-    int offset_x,
-    int offset_y,
-    int crop_width,
-    int crop_height,
-    int scaled_width,
-    int scaled_height) {
-  rtc::scoped_refptr<I420Buffer> result =
-      I420Buffer::Create(scaled_width, scaled_height);
-  result->CropAndScaleFrom(*this->ToI420(), offset_x, offset_y, crop_width,
-                           crop_height);
-  return result;
-}
-
 const I420BufferInterface* VideoFrameBuffer::GetI420() const {
   // Overridden by subclasses that can return an I420 buffer without any
   // conversion, in particular, I420BufferInterface.
@@ -139,4 +124,5 @@
 int NV12BufferInterface::ChromaHeight() const {
   return (height() + 1) / 2;
 }
+
 }  // namespace webrtc
diff --git a/api/video/video_frame_buffer.h b/api/video/video_frame_buffer.h
index 67b8797..5a46c2e 100644
--- a/api/video/video_frame_buffer.h
+++ b/api/video/video_frame_buffer.h
@@ -79,24 +79,6 @@
   // behave as the other GetXXX methods below.
   virtual const I420BufferInterface* GetI420() const;
 
-  // A format specific scale function. Default implementation works by
-  // converting to I420. But more efficient implementations may override it,
-  // especially for kNative.
-  // First, the image is cropped to |crop_width| and |crop_height| and then
-  // scaled to |scaled_width| and |scaled_height|.
-  virtual rtc::scoped_refptr<VideoFrameBuffer> CropAndScale(int offset_x,
-                                                            int offset_y,
-                                                            int crop_width,
-                                                            int crop_height,
-                                                            int scaled_width,
-                                                            int scaled_height);
-
-  // Alias for common use case.
-  rtc::scoped_refptr<VideoFrameBuffer> Scale(int scaled_width,
-                                             int scaled_height) {
-    return CropAndScale(0, 0, width(), height(), scaled_width, scaled_height);
-  }
-
   // These functions should only be called if type() is of the correct type.
   // Calling with a different type will result in a crash.
   const I420ABufferInterface* GetI420A() const;
diff --git a/api/video_codecs/BUILD.gn b/api/video_codecs/BUILD.gn
index a990276..1569125 100644
--- a/api/video_codecs/BUILD.gn
+++ b/api/video_codecs/BUILD.gn
@@ -137,7 +137,7 @@
   deps = [
     ":video_codecs_api",
     "..:fec_controller_api",
-    "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../media:rtc_h264_profile_id",
     "../../media:rtc_media_base",
     "../../modules/video_coding:video_codec_interface",
diff --git a/api/video_codecs/test/BUILD.gn b/api/video_codecs/test/BUILD.gn
index c47e5b9..10b18b6 100644
--- a/api/video_codecs/test/BUILD.gn
+++ b/api/video_codecs/test/BUILD.gn
@@ -36,6 +36,7 @@
       "../../video:encoded_image",
       "../../video:video_bitrate_allocation",
       "../../video:video_frame",
+      "../../video:video_frame_i420",
       "../../video:video_rtp_headers",
       "//testing/gtest",
     ]
diff --git a/common_video/BUILD.gn b/common_video/BUILD.gn
index bea8530..9cb6f45 100644
--- a/common_video/BUILD.gn
+++ b/common_video/BUILD.gn
@@ -49,6 +49,7 @@
     "../api/video:video_bitrate_allocation",
     "../api/video:video_bitrate_allocator",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_frame_nv12",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:bitstream_parser_api",
@@ -104,7 +105,7 @@
       "../api/units:time_delta",
       "../api/video:video_frame",
       "../api/video:video_frame_i010",
-      "../api/video:video_frame_nv12",
+      "../api/video:video_frame_i420",
       "../api/video:video_rtp_headers",
       "../media:rtc_h264_profile_id",
       "../rtc_base",
diff --git a/common_video/video_frame_unittest.cc b/common_video/video_frame_unittest.cc
index 9a7a5e2..225a7d3 100644
--- a/common_video/video_frame_unittest.cc
+++ b/common_video/video_frame_unittest.cc
@@ -15,7 +15,6 @@
 
 #include "api/video/i010_buffer.h"
 #include "api/video/i420_buffer.h"
-#include "api/video/nv12_buffer.h"
 #include "rtc_base/bind.h"
 #include "rtc_base/time_utils.h"
 #include "test/fake_texture_frame.h"
@@ -158,29 +157,6 @@
   return I010Buffer::Copy(*buffer);
 }
 
-rtc::scoped_refptr<NV12BufferInterface> CreateNV12Gradient(int width,
-                                                           int height) {
-  rtc::scoped_refptr<NV12Buffer> buffer(NV12Buffer::Create(width, height));
-  // Initialize with gradient, Y = 128(x/w + y/h), U = 256 x/w, V = 256 y/h
-  for (int x = 0; x < width; x++) {
-    for (int y = 0; y < height; y++) {
-      buffer->MutableDataY()[x + y * width] =
-          128 * (x * height + y * width) / (width * height);
-    }
-  }
-  int chroma_width = buffer->ChromaWidth();
-  int chroma_height = buffer->ChromaHeight();
-  for (int x = 0; x < chroma_width; x++) {
-    for (int y = 0; y < chroma_height; y++) {
-      buffer->MutableDataUV()[x * 2 + y * buffer->StrideUV()] =
-          255 * x / (chroma_width - 1);
-      buffer->MutableDataUV()[x * 2 + 1 + y * buffer->StrideUV()] =
-          255 * y / (chroma_height - 1);
-    }
-  }
-  return buffer;
-}
-
 // The offsets and sizes describe the rectangle extracted from the
 // original (gradient) frame, in relative coordinates where the
 // original frame correspond to the unit square, 0.0 <= x, y < 1.0.
@@ -519,35 +495,6 @@
                          ::testing::Values(VideoFrameBuffer::Type::kI420,
                                            VideoFrameBuffer::Type::kI010));
 
-TEST(TestNV12Buffer, CropAndScale) {
-  const int kSourceWidth = 640;
-  const int kSourceHeight = 480;
-  const int kScaledWidth = 320;
-  const int kScaledHeight = 240;
-  const int kCropLeft = 40;
-  const int kCropTop = 30;
-  const int kCropRight = 0;
-  const int kCropBottom = 30;
-
-  rtc::scoped_refptr<VideoFrameBuffer> buf =
-      CreateNV12Gradient(kSourceWidth, kSourceHeight);
-
-  rtc::scoped_refptr<VideoFrameBuffer> scaled_buffer = buf->CropAndScale(
-      kCropLeft, kCropTop, kSourceWidth - kCropLeft - kCropRight,
-      kSourceHeight - kCropTop - kCropBottom, kScaledWidth, kScaledHeight);
-
-  // Parameters to CheckCrop indicate what part of the source frame is in the
-  // scaled frame.
-  const float kOffsetX = (kCropLeft + 0.0) / kSourceWidth;
-  const float kOffsetY = (kCropTop + 0.0) / kSourceHeight;
-  const float kRelativeWidth =
-      (kSourceWidth - kCropLeft - kCropRight + 0.0) / kSourceWidth;
-  const float kRelativeHeight =
-      (kSourceHeight - kCropTop - kCropBottom + 0.0) / kSourceHeight;
-  CheckCrop(*scaled_buffer->ToI420(), kOffsetX, kOffsetY, kRelativeWidth,
-            kRelativeHeight);
-}
-
 class TestPlanarYuvBufferRotate
     : public ::testing::TestWithParam<
           std::tuple<webrtc::VideoRotation, VideoFrameBuffer::Type>> {};
diff --git a/examples/BUILD.gn b/examples/BUILD.gn
index 4315e0c..c7b113a 100644
--- a/examples/BUILD.gn
+++ b/examples/BUILD.gn
@@ -667,7 +667,7 @@
       "../api:scoped_refptr",
       "../api/audio:audio_mixer_api",
       "../api/audio_codecs:audio_codecs_api",
-      "../api/video:video_frame",
+      "../api/video:video_frame_i420",
       "../api/video:video_rtp_headers",
       "../api/video_codecs:video_codecs_api",
       "../media:rtc_media_base",
diff --git a/media/BUILD.gn b/media/BUILD.gn
index 212ccf9..b736612 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -99,6 +99,7 @@
     "../api/video:video_bitrate_allocation",
     "../api/video:video_bitrate_allocator_factory",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:video_codecs_api",
     "../call:call_interfaces",
@@ -184,6 +185,7 @@
     "../api:scoped_refptr",
     "../api/video:video_codec_constants",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:rtc_software_fallback_wrappers",
     "../api/video_codecs:video_codecs_api",
@@ -297,6 +299,7 @@
     "../api/video:video_bitrate_allocator_factory",
     "../api/video:video_codec_constants",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:rtc_software_fallback_wrappers",
     "../api/video_codecs:video_codecs_api",
@@ -463,6 +466,7 @@
       "../api/video:encoded_image",
       "../api/video:video_bitrate_allocation",
       "../api/video:video_frame",
+      "../api/video:video_frame_i420",
       "../api/video:video_rtp_headers",
       "../api/video_codecs:video_codecs_api",
       "../call:call_interfaces",
@@ -564,6 +568,7 @@
       "../api/video:builtin_video_bitrate_allocator_factory",
       "../api/video:video_bitrate_allocation",
       "../api/video:video_frame",
+      "../api/video:video_frame_i420",
       "../api/video:video_rtp_headers",
       "../api/video_codecs:builtin_video_decoder_factory",
       "../api/video_codecs:builtin_video_encoder_factory",
diff --git a/modules/video_capture/BUILD.gn b/modules/video_capture/BUILD.gn
index b63a78a..9822981 100644
--- a/modules/video_capture/BUILD.gn
+++ b/modules/video_capture/BUILD.gn
@@ -30,6 +30,7 @@
     "..:module_api",
     "../../api:scoped_refptr",
     "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_rtp_headers",
     "../../common_video",
     "../../media:rtc_media_base",
@@ -131,6 +132,7 @@
         ":video_capture_module",
         "../../api:scoped_refptr",
         "../../api/video:video_frame",
+        "../../api/video:video_frame_i420",
         "../../api/video:video_rtp_headers",
         "../../common_video",
         "../../rtc_base:rtc_base_approved",
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 86bd166..7cbd1fc 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -20,6 +20,7 @@
     ":video_codec_interface",
     "../../api/video:encoded_image",
     "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_rtp_headers",
     "../../modules:module_api_public",
     "../../modules/rtp_rtcp:rtp_video_header",
@@ -185,6 +186,7 @@
     "../../api/video:video_adaptation",
     "../../api/video:video_bitrate_allocator",
     "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_frame_type",
     "../../api/video:video_rtp_headers",
     "../../api/video_codecs:video_codecs_api",
@@ -378,6 +380,7 @@
     ":video_coding_utility",
     "../../api/video:video_frame",
     "../../api/video:video_frame_i010",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_rtp_headers",
     "../../api/video_codecs:video_codecs_api",
     "../../common_video",
@@ -425,6 +428,7 @@
     "../../api:scoped_refptr",
     "../../api/video:encoded_image",
     "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_rtp_headers",
     "../../api/video_codecs:video_codecs_api",
     "../../common_video",
@@ -459,6 +463,7 @@
     "../../api:scoped_refptr",
     "../../api/video:encoded_image",
     "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_rtp_headers",
     "../../api/video_codecs:video_codecs_api",
     "../../api/video_codecs:vp8_temporal_layers_factory",
@@ -655,6 +660,7 @@
       "../../api:simulcast_test_fixture_api",
       "../../api/video:encoded_image",
       "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video:video_rtp_headers",
       "../../api/video_codecs:video_codecs_api",
       "../../common_video",
@@ -692,6 +698,7 @@
       "../../api/video:video_bitrate_allocator",
       "../../api/video:video_bitrate_allocator_factory",
       "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video:video_rtp_headers",
       "../../api/video_codecs:video_codecs_api",
       "../../common_video",
@@ -843,6 +850,7 @@
       "../../api/test/video:function_video_factory",
       "../../api/video:encoded_image",
       "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video:video_rtp_headers",
       "../../api/video_codecs:rtc_software_fallback_wrappers",
       "../../api/video_codecs:video_codecs_api",
@@ -974,6 +982,7 @@
       "../../api/video:video_bitrate_allocator",
       "../../api/video:video_bitrate_allocator_factory",
       "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video:video_frame_type",
       "../../api/video:video_rtp_headers",
       "../../api/video_codecs:video_codecs_api",
diff --git a/modules/video_coding/codecs/av1/BUILD.gn b/modules/video_coding/codecs/av1/BUILD.gn
index 6c64953..a1d2f6e 100644
--- a/modules/video_coding/codecs/av1/BUILD.gn
+++ b/modules/video_coding/codecs/av1/BUILD.gn
@@ -22,7 +22,7 @@
       "../..:video_codec_interface",
       "../../../../api:scoped_refptr",
       "../../../../api/video:encoded_image",
-      "../../../../api/video:video_frame",
+      "../../../../api/video:video_frame_i420",
       "../../../../common_video",
       "../../../../rtc_base:logging",
       "//third_party/libaom",
@@ -116,6 +116,7 @@
       "../../../../api:scoped_refptr",
       "../../../../api/video:encoded_image",
       "../../../../api/video:video_frame",
+      "../../../../api/video:video_frame_i420",
       "../../../../common_video",
       "../../../../rtc_base:checks",
       "../../../../rtc_base:logging",
@@ -160,7 +161,7 @@
         "../../../../api:mock_video_encoder",
         "../../../../api/units:data_size",
         "../../../../api/units:time_delta",
-        "../../../../api/video:video_frame",
+        "../../../../api/video:video_frame_i420",
         "../../../../api/video_codecs:video_codecs_api",
         "../../../../test:test_support",
       ]
diff --git a/modules/video_processing/BUILD.gn b/modules/video_processing/BUILD.gn
index 871012a..abc9f03 100644
--- a/modules/video_processing/BUILD.gn
+++ b/modules/video_processing/BUILD.gn
@@ -29,6 +29,7 @@
     "..:module_api",
     "../../api:scoped_refptr",
     "../../api/video:video_frame",
+    "../../api/video:video_frame_i420",
     "../../api/video:video_rtp_headers",
     "../../common_audio",
     "../../common_video",
@@ -99,6 +100,7 @@
       ":video_processing",
       "../../api:scoped_refptr",
       "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video:video_rtp_headers",
       "../../common_video",
       "../../test:fileutils",
diff --git a/rtc_tools/BUILD.gn b/rtc_tools/BUILD.gn
index 8a10d14..ae1c930 100644
--- a/rtc_tools/BUILD.gn
+++ b/rtc_tools/BUILD.gn
@@ -56,6 +56,7 @@
   deps = [
     "../api:scoped_refptr",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../rtc_base:checks",
     "../rtc_base:rtc_base_approved",
@@ -75,6 +76,7 @@
     ":video_file_reader",
     "../api:scoped_refptr",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../rtc_base:rtc_base_approved",
   ]
@@ -103,6 +105,7 @@
     "../api:array_view",
     "../api:scoped_refptr",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../common_video",
     "../rtc_base:checks",
@@ -484,6 +487,7 @@
       ":video_quality_analysis",
       "../api:scoped_refptr",
       "../api/video:video_frame",
+      "../api/video:video_frame_i420",
       "../api/video:video_rtp_headers",
       "../common_video",
       "../rtc_base",
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 2a80c65..14b2bca 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -383,6 +383,7 @@
         "../api:libjingle_peerconnection_api",
         "../api:media_stream_interface",
         "../api/video:video_frame",
+        "../api/video:video_frame_i420",
         "../api/video:video_rtp_headers",
         "../common_video",
         "../media:rtc_media_base",
@@ -411,6 +412,7 @@
       deps = [
         ":base_objc",
         "//api/video:video_frame",
+        "//api/video:video_frame_i420",
         "//api/video:video_rtp_headers",
         "//common_video",
         "//rtc_base:checks",
@@ -1128,7 +1130,7 @@
             ":videotoolbox_objc",
             "../api:scoped_refptr",
             "../api/task_queue:default_task_queue_factory",
-            "../api/video:video_frame",
+            "../api/video:video_frame_i420",
             "../common_video",
             "../media:rtc_media_base",
             "../media:rtc_media_tests_utils",
@@ -1654,6 +1656,7 @@
         ":vpx_codec_constants",
         ":wrapped_native_codec_objc",
         "../api/video:video_frame",
+        "../api/video:video_frame_i420",
         "../api/video:video_rtp_headers",
         "../api/video_codecs:video_codecs_api",
         "../common_video",
diff --git a/sdk/android/api/org/webrtc/VideoFrame.java b/sdk/android/api/org/webrtc/VideoFrame.java
index 49c75fa..a0a0d4e 100644
--- a/sdk/android/api/org/webrtc/VideoFrame.java
+++ b/sdk/android/api/org/webrtc/VideoFrame.java
@@ -54,6 +54,7 @@
      * Crops a region defined by |cropx|, |cropY|, |cropWidth| and |cropHeight|. Scales it to size
      * |scaleWidth| x |scaleHeight|.
      */
+    @CalledByNative("Buffer")
     Buffer cropAndScale(
         int cropX, int cropY, int cropWidth, int cropHeight, int scaleWidth, int scaleHeight);
   }
diff --git a/sdk/android/src/jni/video_frame.cc b/sdk/android/src/jni/video_frame.cc
index ca33c5c..d57fe8f 100644
--- a/sdk/android/src/jni/video_frame.cc
+++ b/sdk/android/src/jni/video_frame.cc
@@ -152,6 +152,19 @@
   return j_video_frame_buffer_;
 }
 
+rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBuffer::CropAndScale(
+    JNIEnv* jni,
+    int crop_x,
+    int crop_y,
+    int crop_width,
+    int crop_height,
+    int scale_width,
+    int scale_height) {
+  return Adopt(jni, Java_Buffer_cropAndScale(jni, j_video_frame_buffer_, crop_x,
+                                             crop_y, crop_width, crop_height,
+                                             scale_width, scale_height));
+}
+
 VideoFrameBuffer::Type AndroidVideoBuffer::type() const {
   return Type::kNative;
 }
diff --git a/sdk/android/src/jni/video_frame.h b/sdk/android/src/jni/video_frame.h
index cb0ff0e..f6b569a 100644
--- a/sdk/android/src/jni/video_frame.h
+++ b/sdk/android/src/jni/video_frame.h
@@ -40,6 +40,16 @@
 
   const ScopedJavaGlobalRef<jobject>& video_frame_buffer() const;
 
+  // Crops a region defined by |crop_x|, |crop_y|, |crop_width| and
+  // |crop_height|. Scales it to size |scale_width| x |scale_height|.
+  rtc::scoped_refptr<AndroidVideoBuffer> CropAndScale(JNIEnv* jni,
+                                                      int crop_x,
+                                                      int crop_y,
+                                                      int crop_width,
+                                                      int crop_height,
+                                                      int scale_width,
+                                                      int scale_height);
+
  protected:
   // Should not be called directly. Adopts the Java VideoFrame.Buffer. Use
   // Create() or Adopt() instead for clarity.
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 9fa0e00..58d3dab 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -52,6 +52,7 @@
     "../api/video:encoded_image",
     "../api/video:video_frame",
     "../api/video:video_frame_i010",
+    "../api/video:video_frame_i420",
     "../api/video:video_frame_nv12",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:video_codecs_api",
@@ -85,6 +86,7 @@
   deps = [
     "../api:scoped_refptr",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
   ]
 }
 
@@ -111,6 +113,8 @@
     "../api:scoped_refptr",
     "../api/task_queue",
     "../api/video:video_frame",
+    "../api/video:video_frame_i010",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:video_codecs_api",
     "../common_video",
@@ -357,6 +361,7 @@
     "../api:scoped_refptr",
     "../api/video:encoded_image",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video_codecs:video_codecs_api",
     "../common_video",
     "../media:rtc_media_base",
@@ -512,6 +517,7 @@
       "../api/test/video:function_video_factory",
       "../api/video:encoded_image",
       "../api/video:video_frame",
+      "../api/video:video_frame_i420",
       "../api/video_codecs:video_codecs_api",
       "../call:video_stream_api",
       "../common_video",
@@ -757,6 +763,7 @@
     "../api/video:encoded_image",
     "../api/video:video_bitrate_allocation",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video_codecs:video_codecs_api",
     "../api/video_codecs:vp8_temporal_layers_factory",
diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn
index 3901297..5c9e259 100644
--- a/test/pc/e2e/BUILD.gn
+++ b/test/pc/e2e/BUILD.gn
@@ -124,7 +124,10 @@
       "analyzer/video/simulcast_dummy_buffer_helper.cc",
       "analyzer/video/simulcast_dummy_buffer_helper.h",
     ]
-    deps = [ "../../../api/video:video_frame" ]
+    deps = [
+      "../../../api/video:video_frame",
+      "../../../api/video:video_frame_i420",
+    ]
   }
 
   rtc_library("quality_analyzing_video_decoder") {
@@ -141,6 +144,7 @@
       "../../../api:video_quality_analyzer_api",
       "../../../api/video:encoded_image",
       "../../../api/video:video_frame",
+      "../../../api/video:video_frame_i420",
       "../../../api/video:video_rtp_headers",
       "../../../api/video_codecs:video_codecs_api",
       "../../../modules/video_coding:video_codec_interface",
@@ -518,6 +522,7 @@
         "../../../api:rtp_packet_info",
         "../../../api/video:encoded_image",
         "../../../api/video:video_frame",
+        "../../../api/video:video_frame_i420",
         "../../../common_video",
         "../../../modules/rtp_rtcp:rtp_rtcp_format",
         "../../../rtc_base:stringutils",
@@ -640,6 +645,7 @@
       "../../../api/units:timestamp",
       "../../../api/video:encoded_image",
       "../../../api/video:video_frame",
+      "../../../api/video:video_frame_i420",
       "../../../api/video:video_rtp_headers",
       "../../../common_video",
       "../../../rtc_base:criticalsection",
diff --git a/test/scenario/BUILD.gn b/test/scenario/BUILD.gn
index f5c22fc..2ec9d63 100644
--- a/test/scenario/BUILD.gn
+++ b/test/scenario/BUILD.gn
@@ -97,6 +97,7 @@
       "../../api/units:timestamp",
       "../../api/video:builtin_video_bitrate_allocator_factory",
       "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video:video_rtp_headers",
       "../../api/video_codecs:video_codecs_api",
       "../../audio",
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 115c71a..f195883 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -86,6 +86,7 @@
     "../api/video:video_bitrate_allocator",
     "../api/video:video_codec_constants",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video:video_stream_encoder",
     "../api/video:video_stream_encoder_create",
@@ -226,6 +227,7 @@
     "../api/video:video_bitrate_allocator_factory",
     "../api/video:video_codec_constants",
     "../api/video:video_frame",
+    "../api/video:video_frame_i420",
     "../api/video:video_rtp_headers",
     "../api/video:video_stream_encoder",
     "../api/video_codecs:video_codecs_api",
@@ -595,6 +597,7 @@
       "../api/video:video_adaptation",
       "../api/video:video_bitrate_allocation",
       "../api/video:video_frame",
+      "../api/video:video_frame_i420",
       "../api/video:video_frame_nv12",
       "../api/video:video_frame_type",
       "../api/video:video_rtp_headers",
diff --git a/video/adaptation/BUILD.gn b/video/adaptation/BUILD.gn
index a96f4cf..2a60ead 100644
--- a/video/adaptation/BUILD.gn
+++ b/video/adaptation/BUILD.gn
@@ -80,7 +80,7 @@
       "../../api/task_queue:task_queue",
       "../../api/video:encoded_image",
       "../../api/video:video_adaptation",
-      "../../api/video:video_frame",
+      "../../api/video:video_frame_i420",
       "../../api/video_codecs:video_codecs_api",
       "../../call/adaptation:resource_adaptation",
       "../../call/adaptation:resource_adaptation_test_utilities",