New method I420Buffer::Copy.

Needed to replace cricket::VideoFrame::MakeExclusive in chromium.

BUG=webrtc:5682

Review URL: https://codereview.webrtc.org/1822283002

Cr-Original-Commit-Position: refs/heads/master@{#12155}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 7cc9cc0460b9828fa5c139ecb79cf568824e6dac
diff --git a/common_video/i420_video_frame_unittest.cc b/common_video/i420_video_frame_unittest.cc
index 8273136..9b2bdd7 100644
--- a/common_video/i420_video_frame_unittest.cc
+++ b/common_video/i420_video_frame_unittest.cc
@@ -254,4 +254,14 @@
   EXPECT_EQ(20, frame.render_time_ms());
 }
 
+TEST(TestI420FrameBuffer, Copy) {
+  rtc::scoped_refptr<I420Buffer> buf1(
+      new rtc::RefCountedObject<I420Buffer>(20, 10));
+  memset(buf1->MutableData(kYPlane), 1, 200);
+  memset(buf1->MutableData(kUPlane), 2, 50);
+  memset(buf1->MutableData(kVPlane), 3, 50);
+  rtc::scoped_refptr<I420Buffer> buf2 = I420Buffer::Copy(buf1);
+  EXPECT_TRUE(test::FrameBufsEqual(buf1, buf2));
+}
+
 }  // namespace webrtc
diff --git a/common_video/include/video_frame_buffer.h b/common_video/include/video_frame_buffer.h
index 270f2d5..9cf57a4 100644
--- a/common_video/include/video_frame_buffer.h
+++ b/common_video/include/video_frame_buffer.h
@@ -81,6 +81,10 @@
   void* native_handle() const override;
   rtc::scoped_refptr<VideoFrameBuffer> NativeToI420Buffer() override;
 
+  // Create a new buffer and copy the pixel data.
+  static rtc::scoped_refptr<I420Buffer> Copy(
+      const rtc::scoped_refptr<VideoFrameBuffer>& buffer);
+
  protected:
   ~I420Buffer() override;
 
diff --git a/common_video/video_frame_buffer.cc b/common_video/video_frame_buffer.cc
index 19e44fe..6f49e8a 100644
--- a/common_video/video_frame_buffer.cc
+++ b/common_video/video_frame_buffer.cc
@@ -12,6 +12,7 @@
 
 #include "webrtc/base/checks.h"
 #include "webrtc/base/keep_ref_until_done.h"
+#include "libyuv/convert.h"
 
 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
 static const int kBufferAlignment = 64;
@@ -117,6 +118,23 @@
   return nullptr;
 }
 
+rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
+    const rtc::scoped_refptr<VideoFrameBuffer>& buffer) {
+  int width = buffer->width();
+  int height = buffer->height();
+  rtc::scoped_refptr<I420Buffer> copy =
+      new rtc::RefCountedObject<I420Buffer>(width, height);
+  RTC_CHECK(libyuv::I420Copy(buffer->data(kYPlane), buffer->stride(kYPlane),
+                             buffer->data(kUPlane), buffer->stride(kUPlane),
+                             buffer->data(kVPlane), buffer->stride(kVPlane),
+                             copy->MutableData(kYPlane), copy->stride(kYPlane),
+                             copy->MutableData(kUPlane), copy->stride(kUPlane),
+                             copy->MutableData(kVPlane), copy->stride(kVPlane),
+                             width, height) == 0);
+
+  return copy;
+}
+
 NativeHandleBuffer::NativeHandleBuffer(void* native_handle,
                                        int width,
                                        int height)
diff --git a/test/frame_utils.cc b/test/frame_utils.cc
index 13f358a..0f41144 100644
--- a/test/frame_utils.cc
+++ b/test/frame_utils.cc
@@ -47,5 +47,23 @@
                     f1.stride(webrtc::kVPlane), half_width, half_height);
 }
 
+bool FrameBufsEqual(const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f1,
+                    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f2) {
+  if (f1->width() != f2->width() || f1->height() != f2->height() ||
+      f1->stride(webrtc::kYPlane) != f2->stride(webrtc::kYPlane) ||
+      f1->stride(webrtc::kUPlane) != f2->stride(webrtc::kUPlane) ||
+      f1->stride(webrtc::kVPlane) != f2->stride(webrtc::kVPlane)) {
+    return false;
+  }
+  const int half_width = (f1->width() + 1) / 2;
+  const int half_height = (f1->height() + 1) / 2;
+  return EqualPlane(f1->data(webrtc::kYPlane), f2->data(webrtc::kYPlane),
+                    f1->stride(webrtc::kYPlane), f1->width(), f1->height()) &&
+         EqualPlane(f1->data(webrtc::kUPlane), f2->data(webrtc::kUPlane),
+                    f1->stride(webrtc::kUPlane), half_width, half_height) &&
+         EqualPlane(f1->data(webrtc::kVPlane), f2->data(webrtc::kVPlane),
+                    f1->stride(webrtc::kVPlane), half_width, half_height);
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/frame_utils.h b/test/frame_utils.h
index 42e2cba..668d999 100644
--- a/test/frame_utils.h
+++ b/test/frame_utils.h
@@ -11,9 +11,11 @@
 #define WEBRTC_TEST_FRAME_UTILS_H_
 
 #include "webrtc/base/basictypes.h"
+#include "webrtc/base/scoped_ref_ptr.h"
 
 namespace webrtc {
 class VideoFrame;
+class VideoFrameBuffer;
 namespace test {
 
 bool EqualPlane(const uint8_t* data1,
@@ -24,6 +26,9 @@
 
 bool FramesEqual(const webrtc::VideoFrame& f1, const webrtc::VideoFrame& f2);
 
+bool FrameBufsEqual(const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f1,
+                    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f2);
+
 }  // namespace test
 }  // namespace webrtc