Revert "Add callback to copy texture backed frames in WebRtcVideoFrameAdapter"

This CL reverts the commit on https://codereview.chromium.org/2456443002. We found
that this can cause a deadlock because of the dependency between threads, see the
bug for details. Instead of copying texture content, we generate a black frame.

Bug: 663452
Change-Id: Ifb2195cbf123dde8a8f9260d606a28df26b39121
Reviewed-on: https://chromium-review.googlesource.com/900663
Reviewed-by: Christian Fremerey <chfremer@chromium.org>
Reviewed-by: Magnus Jedvert <magjed@chromium.org>
Commit-Queue: Emircan Uysaler <emircan@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#535529}(cherry picked from commit 03970a908a4ff71f39147348b13b0dde37a11787)
Reviewed-on: https://chromium-review.googlesource.com/941502
Reviewed-by: Emircan Uysaler <emircan@chromium.org>
Cr-Commit-Position: refs/branch-heads/3325@{#625}
Cr-Branched-From: bc084a8b5afa3744a74927344e304c02ae54189f-refs/heads/master@{#530369}
diff --git a/content/renderer/media/gpu/rtc_video_decoder.cc b/content/renderer/media/gpu/rtc_video_decoder.cc
index c0756fb..48202fd 100644
--- a/content/renderer/media/gpu/rtc_video_decoder.cc
+++ b/content/renderer/media/gpu/rtc_video_decoder.cc
@@ -421,9 +421,8 @@
 
   // Create a WebRTC video frame.
   webrtc::VideoFrame decoded_image(
-      new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
-          frame, WebRtcVideoFrameAdapter::CopyTextureFrameCallback()),
-      timestamp, 0, webrtc::kVideoRotation_0);
+      new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame), timestamp, 0,
+      webrtc::kVideoRotation_0);
 
   // Invoke decode callback. WebRTC expects no callback after Release.
   {
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
index b5eaa24..9982c25 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -5,19 +5,12 @@
 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 
 #include "base/bind.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/paint/skia_paint_canvas.h"
 #include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
-#include "content/renderer/render_thread_impl.h"
 #include "media/base/timestamp_constants.h"
 #include "media/base/video_util.h"
-#include "media/renderers/paint_canvas_video_renderer.h"
-#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/libyuv/include/libyuv/convert.h"
 #include "third_party/libyuv/include/libyuv/convert_from.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
 #include "third_party/webrtc/api/video/video_rotation.h"
@@ -32,127 +25,12 @@
 void CapturerReleaseOriginalFrame(
     const scoped_refptr<media::VideoFrame>& frame) {}
 
-// Helper class that signals a WaitableEvent when it goes out of scope.
-class ScopedWaitableEvent {
- public:
-  explicit ScopedWaitableEvent(base::WaitableEvent* event) : event_(event) {}
-  ~ScopedWaitableEvent() {
-    if (event_)
-      event_->Signal();
-  }
-
- private:
-  base::WaitableEvent* const event_;
-};
-
 }  // anonymous namespace
 
-// Initializes the GL context environment and provides a method for copying
-// texture backed frames into CPU mappable memory.
-// The class is created and destroyed on the main render thread.
-class WebRtcVideoCapturerAdapter::TextureFrameCopier
-    : public base::RefCounted<WebRtcVideoCapturerAdapter::TextureFrameCopier> {
- public:
-  TextureFrameCopier()
-      : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-        canvas_video_renderer_(new media::PaintCanvasVideoRenderer) {
-    RenderThreadImpl* const main_thread = RenderThreadImpl::current();
-    if (main_thread)
-      provider_ = main_thread->SharedMainThreadContextProvider();
-  }
-
-  // Synchronous call to copy a texture backed |frame| into a CPU mappable
-  // |new_frame|. If it is not called on the main render thread, this call posts
-  // a task on main thread by calling CopyTextureFrameOnMainThread() and blocks
-  // until it is completed.
-  void CopyTextureFrame(const scoped_refptr<media::VideoFrame>& frame,
-                        scoped_refptr<media::VideoFrame>* new_frame) {
-    if (main_thread_task_runner_->BelongsToCurrentThread()) {
-      CopyTextureFrameOnMainThread(frame, new_frame, nullptr);
-      return;
-    }
-
-    base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
-                               base::WaitableEvent::InitialState::NOT_SIGNALED);
-    main_thread_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&TextureFrameCopier::CopyTextureFrameOnMainThread, this,
-                       frame, new_frame, &waiter));
-    waiter.Wait();
-  }
-
- private:
-  friend class base::RefCounted<TextureFrameCopier>;
-  ~TextureFrameCopier() {
-    // |canvas_video_renderer_| should be deleted on the thread it was created.
-    if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-      main_thread_task_runner_->DeleteSoon(FROM_HERE,
-                                           canvas_video_renderer_.release());
-    }
-  }
-
-  void CopyTextureFrameOnMainThread(
-      const scoped_refptr<media::VideoFrame>& frame,
-      scoped_refptr<media::VideoFrame>* new_frame,
-      base::WaitableEvent* waiter) {
-    DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
-    DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB ||
-           frame->format() == media::PIXEL_FORMAT_XRGB ||
-           frame->format() == media::PIXEL_FORMAT_I420 ||
-           frame->format() == media::PIXEL_FORMAT_UYVY ||
-           frame->format() == media::PIXEL_FORMAT_NV12);
-    ScopedWaitableEvent event(waiter);
-
-    if (!provider_) {
-      // Return a black frame (yuv = {0, 0x80, 0x80}).
-      *new_frame = media::VideoFrame::CreateColorFrame(
-          frame->visible_rect().size(), 0u, 0x80, 0x80, frame->timestamp());
-      return;
-    }
-
-    SkBitmap bitmap;
-    bitmap.allocPixels(SkImageInfo::MakeN32Premul(
-        frame->visible_rect().width(), frame->visible_rect().height()));
-    cc::SkiaPaintCanvas paint_canvas(bitmap);
-
-    *new_frame = media::VideoFrame::CreateFrame(
-        media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(),
-        frame->natural_size(), frame->timestamp());
-    DCHECK(provider_->ContextGL());
-    canvas_video_renderer_->Copy(
-        frame.get(), &paint_canvas,
-        media::Context3D(provider_->ContextGL(), provider_->GrContext()));
-
-    SkPixmap pixmap;
-    const bool result = bitmap.peekPixels(&pixmap);
-    DCHECK(result) << "Error trying to access SkBitmap's pixels";
-    const uint32 source_pixel_format =
-        (kN32_SkColorType == kRGBA_8888_SkColorType) ? cricket::FOURCC_ABGR
-                                                     : cricket::FOURCC_ARGB;
-    libyuv::ConvertToI420(
-        static_cast<const uint8*>(pixmap.addr(0, 0)), pixmap.computeByteSize(),
-        (*new_frame)->visible_data(media::VideoFrame::kYPlane),
-        (*new_frame)->stride(media::VideoFrame::kYPlane),
-        (*new_frame)->visible_data(media::VideoFrame::kUPlane),
-        (*new_frame)->stride(media::VideoFrame::kUPlane),
-        (*new_frame)->visible_data(media::VideoFrame::kVPlane),
-        (*new_frame)->stride(media::VideoFrame::kVPlane), 0 /* crop_x */,
-        0 /* crop_y */, pixmap.width(), pixmap.height(),
-        (*new_frame)->visible_rect().width(),
-        (*new_frame)->visible_rect().height(), libyuv::kRotate0,
-        source_pixel_format);
-  }
-
-  const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  scoped_refptr<ui::ContextProviderCommandBuffer> provider_;
-  std::unique_ptr<media::PaintCanvasVideoRenderer> canvas_video_renderer_;
-};
-
 WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(
     bool is_screencast,
     blink::WebMediaStreamTrack::ContentHintType content_hint)
-    : texture_copier_(new WebRtcVideoCapturerAdapter::TextureFrameCopier()),
-      is_screencast_(is_screencast),
+    : is_screencast_(is_screencast),
       content_hint_(content_hint),
       running_(false) {
   thread_checker_.DetachFromThread();
@@ -203,9 +81,7 @@
   // cropping support for texture yet. See http://crbug/503653.
   if (frame->HasTextures()) {
     OnFrame(webrtc::VideoFrame(
-                new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
-                    frame, base::Bind(&TextureFrameCopier::CopyTextureFrame,
-                                      texture_copier_)),
+                new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame),
                 webrtc::kVideoRotation_0, translated_camera_time_us),
             orig_width, orig_height);
     return;
@@ -233,9 +109,7 @@
   // If no scaling is needed, return a wrapped version of |frame| directly.
   if (video_frame->natural_size() == video_frame->visible_rect().size()) {
     OnFrame(webrtc::VideoFrame(
-                new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
-                    video_frame,
-                    WebRtcVideoFrameAdapter::CopyTextureFrameCallback()),
+                new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(video_frame),
                 webrtc::kVideoRotation_0, translated_camera_time_us),
             orig_width, orig_height);
     return;
@@ -274,9 +148,7 @@
   }
 
   OnFrame(webrtc::VideoFrame(
-              new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
-                  scaled_frame,
-                  WebRtcVideoFrameAdapter::CopyTextureFrameCallback()),
+              new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(scaled_frame),
               webrtc::kVideoRotation_0, translated_camera_time_us),
           orig_width, orig_height);
 }
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
index 4e5c55d..bd81bff 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
@@ -58,10 +58,6 @@
 
   bool ShouldAdaptResolution() const;
 
-  // Helper class used for copying texture backed frames.
-  class TextureFrameCopier;
-  const scoped_refptr<TextureFrameCopier> texture_copier_;
-
   // |thread_checker_| is bound to the libjingle worker thread.
   base::ThreadChecker thread_checker_;
 
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
index 2133e8a..e076b3d 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
@@ -4,21 +4,13 @@
 
 #include <algorithm>
 
-#include "base/bind.h"
-#include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_task_environment.h"
-#include "content/child/child_process.h"
 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 #include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
-#include "gpu/command_buffer/common/mailbox_holder.h"
 #include "media/base/video_frame.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace {
-static void ReleaseMailboxCB(const gpu::SyncToken& sync_token) {}
-}  // anonymous namespace
-
 namespace content {
 
 class WebRtcVideoCapturerAdapterTest
@@ -26,9 +18,7 @@
       public ::testing::Test {
  public:
   WebRtcVideoCapturerAdapterTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO),
-        adapter_(new WebRtcVideoCapturerAdapter(
+      : adapter_(new WebRtcVideoCapturerAdapter(
             false,
             blink::WebMediaStreamTrack::ContentHintType::kNone)),
         output_frame_width_(0),
@@ -57,37 +47,8 @@
     EXPECT_EQ(natural_height, output_frame_height_);
   }
 
-  void TestSourceTextureFrame() {
-    EXPECT_TRUE(scoped_task_environment_.GetMainThreadTaskRunner()
-                    ->BelongsToCurrentThread());
-    gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes] = {
-        gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 5)};
-    scoped_refptr<media::VideoFrame> frame =
-        media::VideoFrame::WrapNativeTextures(
-            media::PIXEL_FORMAT_ARGB, holders, base::Bind(&ReleaseMailboxCB),
-            gfx::Size(10, 10), gfx::Rect(10, 10), gfx::Size(10, 10),
-            base::TimeDelta());
-    adapter_->OnFrameCaptured(frame);
-    ASSERT_TRUE(output_frame_);
-    rtc::scoped_refptr<webrtc::VideoFrameBuffer> texture_frame =
-        output_frame_->video_frame_buffer();
-    EXPECT_EQ(webrtc::VideoFrameBuffer::Type::kNative, texture_frame->type());
-    EXPECT_EQ(media::VideoFrame::STORAGE_OPAQUE,
-              static_cast<WebRtcVideoFrameAdapter*>(texture_frame.get())
-                  ->getMediaVideoFrame()
-                  ->storage_type());
-
-    rtc::scoped_refptr<webrtc::I420BufferInterface> copied_frame =
-        texture_frame->ToI420();
-    EXPECT_TRUE(copied_frame);
-    EXPECT_TRUE(copied_frame->DataY());
-    EXPECT_TRUE(copied_frame->DataU());
-    EXPECT_TRUE(copied_frame->DataV());
-  }
-
   // rtc::VideoSinkInterface
   void OnFrame(const webrtc::VideoFrame& frame) override {
-    output_frame_ = base::Optional<webrtc::VideoFrame>(frame);
     output_frame_width_ = frame.width();
     output_frame_height_ = frame.height();
   }
@@ -139,13 +100,7 @@
   }
 
  private:
-  // The ScopedTaskEnvironment prevents the ChildProcess from leaking a
-  // TaskScheduler.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  const ChildProcess child_process_;
-
   std::unique_ptr<WebRtcVideoCapturerAdapter> adapter_;
-  base::Optional<webrtc::VideoFrame> output_frame_;
   int output_frame_width_;
   int output_frame_height_;
 };
@@ -162,10 +117,6 @@
   TestSourceCropFrame(1280, 720, 1280, 720, 640, 360);
 }
 
-TEST_F(WebRtcVideoCapturerAdapterTest, SendsWithCopyTextureFrameCallback) {
-  TestSourceTextureFrame();
-}
-
 TEST_F(WebRtcVideoCapturerAdapterTest,
        NonScreencastAdapterDoesNotAdaptContentHintDetail) {
   // Non-screenshare adapter should not adapt frames when detail is set.
diff --git a/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc b/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
index d65c73fa..bfa7ba1 100644
--- a/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
+++ b/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
@@ -86,9 +86,8 @@
 namespace content {
 
 WebRtcVideoFrameAdapter::WebRtcVideoFrameAdapter(
-    const scoped_refptr<media::VideoFrame>& frame,
-    const CopyTextureFrameCallback& copy_texture_callback)
-    : frame_(frame), copy_texture_callback_(copy_texture_callback) {}
+    const scoped_refptr<media::VideoFrame>& frame)
+    : frame_(frame) {}
 
 WebRtcVideoFrameAdapter::~WebRtcVideoFrameAdapter() {
 }
@@ -107,17 +106,14 @@
 
 rtc::scoped_refptr<webrtc::I420BufferInterface>
 WebRtcVideoFrameAdapter::ToI420() {
+  // We cant convert texture synchronously due to threading issues, see
+  // https://crbug.com/663452. Instead, return a black frame (yuv = {0, 0x80,
+  // 0x80}).
   if (frame_->HasTextures()) {
-    if (copy_texture_callback_.is_null()) {
-      DLOG(ERROR) << "Texture backed frame cannot be copied.";
-      return nullptr;
-    }
-
-    scoped_refptr<media::VideoFrame> new_frame;
-    copy_texture_callback_.Run(frame_, &new_frame);
-    if (!new_frame)
-      return nullptr;
-    frame_ = new_frame;
+    DLOG(ERROR) << "Texture backed frame cannot be accessed.";
+    return new rtc::RefCountedObject<FrameAdapter<webrtc::I420BufferInterface>>(
+        media::VideoFrame::CreateColorFrame(frame_->visible_rect().size(), 0u,
+                                            0x80, 0x80, frame_->timestamp()));
   }
 
   IsValidFrame(frame_);
diff --git a/content/renderer/media/webrtc/webrtc_video_frame_adapter.h b/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
index 1f1f836..e20b215 100644
--- a/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
+++ b/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include "base/callback.h"
 #include "media/base/video_frame.h"
 #include "third_party/webrtc/api/video/video_frame_buffer.h"
 
@@ -18,13 +17,7 @@
 // different threads, but that's safe since it's read-only.
 class WebRtcVideoFrameAdapter : public webrtc::VideoFrameBuffer {
  public:
-  using CopyTextureFrameCallback =
-      base::Callback<void(const scoped_refptr<media::VideoFrame>&,
-                          scoped_refptr<media::VideoFrame>*)>;
-
-  WebRtcVideoFrameAdapter(
-      const scoped_refptr<media::VideoFrame>& frame,
-      const CopyTextureFrameCallback& copy_texture_callback);
+  WebRtcVideoFrameAdapter(const scoped_refptr<media::VideoFrame>& frame);
 
   scoped_refptr<media::VideoFrame> getMediaVideoFrame() const { return frame_; }
 
@@ -39,7 +32,6 @@
   ~WebRtcVideoFrameAdapter() override;
 
   scoped_refptr<media::VideoFrame> frame_;
-  const CopyTextureFrameCallback copy_texture_callback_;
 };
 
 }  // namespace content