Implement RenderWidgetHostViewEfl::CopyFromCompositingSurfaceToVideoFrame
authorMurugappan Nataraj <m.nataraj@samsung.com>
Tue, 8 Apr 2014 12:55:21 +0000 (18:25 +0530)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
This commit is part of EFL port P0 API implementation.
Borrowed the implementation from GTK+ port, six new functions were added.
Implementation provided to copy compositing surface to video frame.

Additionally, this commit incorporates an API change in new chromium:

- old (34.0.1809.0)
void content::ReadbackYUVInterface::ReadbackYUV(
  const signed char*, unsigned int, media::VideoFrame*,
  base::Callback<void(bool)>&)

- new (34.0.1847.76)
virtual void content::ReadbackYUVInterface::ReadbackYUV(
  const gpu::Mailbox&, unsigned int, const scoped_refptr<media::VideoFrame>&,
  const base::Callback<void(bool)>&)

Change-Id: I5e2ffe2ca8d0dad28d5120b1e0f2f0d937574c08

tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.cc
tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.h

index 7d76303..900dc04 100644 (file)
@@ -4,6 +4,15 @@
 
 #include "browser/renderer_host/render_widget_host_view_efl.h"
 
+#include "base/auto_reset.h"
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
+
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "browser/renderer_host/im_context_efl.h"
 #include "content/browser/renderer_host/ui_events_helper.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/browser/renderer_host/dip_util.h"
+#include "content/common/gpu/client/gl_helper.h"
+#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
+#include "content/public/common/content_switches.h"
 #include "content/common/view_messages.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "common/render_messages_efl.h"
 #include "eweb_context.h"
+#include "media/base/video_util.h"
 #include "selection_controller_efl.h"
+#include "skia/ext/image_operations.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
 #include "third_party/WebKit/public/web/WebTouchPoint.h"
@@ -309,6 +324,187 @@ void RenderWidgetHostViewEfl::CopyFromCompositingSurface(
   // host_->GetSnapshotFromRenderer(src_subrect, callback);
 }
 
+// CopyFromCompositingSurfaceToVideoFrame implementation borrowed from Aura port
+bool RenderWidgetHostViewEfl::CanSubscribeFrame() const {
+  return true;
+}
+
+void RenderWidgetHostViewEfl::BeginFrameSubscription(
+    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
+  frame_subscriber_ = subscriber.Pass();
+}
+
+void RenderWidgetHostViewEfl::EndFrameSubscription() {
+  idle_frame_subscriber_textures_.clear();
+  frame_subscriber_.reset();
+}
+
+void RenderWidgetHostViewEfl::ReturnSubscriberTexture(
+    base::WeakPtr<RenderWidgetHostViewEfl> rwhvefl,
+    scoped_refptr<OwnedMailbox> subscriber_texture,
+    uint32 sync_point) {
+  if (!subscriber_texture.get())
+    return;
+  if (!rwhvefl)
+    return;
+  DCHECK_NE(
+      rwhvefl->active_frame_subscriber_textures_.count(subscriber_texture.get()),
+      0u);
+
+  subscriber_texture->UpdateSyncPoint(sync_point);
+
+  rwhvefl->active_frame_subscriber_textures_.erase(subscriber_texture.get());
+  if (rwhvefl->frame_subscriber_ && subscriber_texture->texture_id())
+    rwhvefl->idle_frame_subscriber_textures_.push_back(subscriber_texture);
+}
+
+void RenderWidgetHostViewEfl::CopyFromCompositingSurfaceFinishedForVideo(
+    base::WeakPtr<RenderWidgetHostViewEfl> rwhvefl,
+    const base::Callback<void(bool)>& callback,
+    scoped_refptr<OwnedMailbox> subscriber_texture,
+    scoped_ptr<cc::SingleReleaseCallback> release_callback,
+    bool result) {
+  callback.Run(result);
+
+  GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+  uint32 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0;
+  if (release_callback) {
+    // A release callback means the texture came from the compositor, so there
+    // should be no |subscriber_texture|.
+    DCHECK(!subscriber_texture);
+    release_callback->Run(sync_point, false);
+  }
+  ReturnSubscriberTexture(rwhvefl, subscriber_texture, sync_point);
+}
+
+void RenderWidgetHostViewEfl::CopyFromCompositingSurfaceHasResultForVideo(
+    base::WeakPtr<RenderWidgetHostViewEfl> rwhvefl,
+    scoped_refptr<OwnedMailbox> subscriber_texture,
+    scoped_refptr<media::VideoFrame> video_frame,
+    const base::Callback<void(bool)>& callback,
+    scoped_ptr<cc::CopyOutputResult> result) {
+  base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
+  base::ScopedClosureRunner scoped_return_subscriber_texture(
+      base::Bind(&ReturnSubscriberTexture, rwhvefl, subscriber_texture, 0));
+
+  if (!rwhvefl)
+    return;
+  if (result->IsEmpty())
+    return;
+  if (result->size().IsEmpty())
+    return;
+
+  // Compute the dest size we want after the letterboxing resize. Make the
+  // coordinates and sizes even because we letterbox in YUV space
+  // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
+  // line up correctly.
+  // The video frame's coded_size() and the result's size() are both physical
+  // pixels.
+  gfx::Rect region_in_frame =
+      media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
+                                    result->size());
+  region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
+                              region_in_frame.y() & ~1,
+                              region_in_frame.width() & ~1,
+                              region_in_frame.height() & ~1);
+  if (region_in_frame.IsEmpty())
+    return;
+
+  if (!result->HasTexture()) {
+    DCHECK(result->HasBitmap());
+    scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
+    // Scale the bitmap to the required size, if necessary.
+    SkBitmap scaled_bitmap;
+    if (result->size().width() != region_in_frame.width() ||
+        result->size().height() != region_in_frame.height()) {
+      skia::ImageOperations::ResizeMethod method =
+          skia::ImageOperations::RESIZE_GOOD;
+      scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
+                                                    region_in_frame.width(),
+                                                    region_in_frame.height());
+    } else {
+      scaled_bitmap = *bitmap.get();
+    }
+
+    {
+      SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
+
+      media::CopyRGBToVideoFrame(
+          reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
+          scaled_bitmap.rowBytes(),
+          region_in_frame,
+          video_frame.get());
+    }
+    ignore_result(scoped_callback_runner.Release());
+    callback.Run(true);
+    return;
+  }
+
+  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+  GLHelper* gl_helper = factory->GetGLHelper();
+  if (!gl_helper)
+    return;
+  if (subscriber_texture.get() && !subscriber_texture->texture_id())
+    return;
+
+  cc::TextureMailbox texture_mailbox;
+  scoped_ptr<cc::SingleReleaseCallback> release_callback;
+  result->TakeTexture(&texture_mailbox, &release_callback);
+  DCHECK(texture_mailbox.IsTexture());
+  if (!texture_mailbox.IsTexture())
+    return;
+
+  gfx::Rect result_rect(result->size());
+
+  content::ReadbackYUVInterface* yuv_readback_pipeline =
+      rwhvefl->yuv_readback_pipeline_.get();
+  if (yuv_readback_pipeline == NULL ||
+      yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
+      yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
+      yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
+    GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
+    std::string quality_switch = switches::kTabCaptureDownscaleQuality;
+    // If we're scaling up, we can use the "best" quality.
+    if (result_rect.size().width() < region_in_frame.size().width() &&
+        result_rect.size().height() < region_in_frame.size().height())
+      quality_switch = switches::kTabCaptureUpscaleQuality;
+
+    std::string switch_value =
+        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
+    if (switch_value == "fast")
+      quality = GLHelper::SCALER_QUALITY_FAST;
+    else if (switch_value == "good")
+      quality = GLHelper::SCALER_QUALITY_GOOD;
+    else if (switch_value == "best")
+      quality = GLHelper::SCALER_QUALITY_BEST;
+
+    rwhvefl->yuv_readback_pipeline_.reset(
+        gl_helper->CreateReadbackPipelineYUV(quality,
+                                             result_rect.size(),
+                                             result_rect,
+                                             video_frame->coded_size(),
+                                             region_in_frame,
+                                             true,
+                                             true));
+    yuv_readback_pipeline = rwhvefl->yuv_readback_pipeline_.get();
+  }
+
+  ignore_result(scoped_callback_runner.Release());
+  ignore_result(scoped_return_subscriber_texture.Release());
+  base::Callback<void(bool result)> finished_callback = base::Bind(
+      &RenderWidgetHostViewEfl::CopyFromCompositingSurfaceFinishedForVideo,
+      rwhvefl->AsWeakPtr(),
+      callback,
+      subscriber_texture,
+      base::Passed(&release_callback));
+  yuv_readback_pipeline->ReadbackYUV(
+      texture_mailbox.mailbox(),
+      texture_mailbox.sync_point(),
+      video_frame,
+      finished_callback);
+}
+
+// Efl port - Implementation done, will enable this function after getting video test site to verify
 void RenderWidgetHostViewEfl::CopyFromCompositingSurfaceToVideoFrame(
   const gfx::Rect& src_subrect,
   const scoped_refptr<media::VideoFrame>& target,
@@ -318,6 +514,8 @@ void RenderWidgetHostViewEfl::CopyFromCompositingSurfaceToVideoFrame(
 }
 
 bool RenderWidgetHostViewEfl::CanCopyToVideoFrame() const {
+#warning "[M37] host_ no longer has is_accelerated_compositing_active function"
+  //return host_->is_accelerated_compositing_active();
   return false;
 }
 
index ff6714e..03aa95e 100644 (file)
@@ -9,6 +9,17 @@
 #include "base/format_macros.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "content/common/content_export.h"
+#include "cc/layers/delegated_frame_provider.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
+#include "cc/resources/single_release_callback.h"
+#include "cc/resources/texture_mailbox.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/compositor/image_transport_factory.h"
+#include "content/browser/compositor/owned_mailbox.h"
 #include "eweb_view.h"
 #include <Evas.h>
 #include <Ecore_Evas.h>
@@ -27,9 +38,13 @@ namespace content {
 class IMContextEfl;
 class RenderWidgetHostImpl;
 class RenderWidgetHostView;
+class ReadbackYUVInterface;
 
 // RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
-class RenderWidgetHostViewEfl : public RenderWidgetHostViewBase, public IPC::Sender {
+class RenderWidgetHostViewEfl
+  : public RenderWidgetHostViewBase,
+    public base::SupportsWeakPtr<RenderWidgetHostViewEfl>,
+    public IPC::Sender {
  public:
   // RenderWidgetHostViewBase implementation.
   explicit RenderWidgetHostViewEfl(RenderWidgetHost*);
@@ -86,6 +101,10 @@ class RenderWidgetHostViewEfl : public RenderWidgetHostViewBase, public IPC::Sen
     const base::Callback<void(bool)>&) OVERRIDE;
 
   virtual bool CanCopyToVideoFrame() const OVERRIDE;
+  virtual bool CanSubscribeFrame() const OVERRIDE;
+  virtual void BeginFrameSubscription(
+      scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
+  virtual void EndFrameSubscription() OVERRIDE;
   virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
   virtual void AcceleratedSurfaceInitialized(int, int) OVERRIDE;
   virtual void AcceleratedSurfaceBuffersSwapped(
@@ -158,6 +177,23 @@ class RenderWidgetHostViewEfl : public RenderWidgetHostViewBase, public IPC::Sen
   void OnDidChangePageScaleFactor(double);
   void OnDidChangePageScaleRange(double, double);
 
+  static void CopyFromCompositingSurfaceHasResultForVideo(
+      base::WeakPtr<RenderWidgetHostViewEfl> rwhvefl,
+      scoped_refptr<OwnedMailbox> subscriber_texture,
+      scoped_refptr<media::VideoFrame> video_frame,
+      const base::Callback<void(bool)>& callback,
+      scoped_ptr<cc::CopyOutputResult> result);
+  static void CopyFromCompositingSurfaceFinishedForVideo(
+      base::WeakPtr<RenderWidgetHostViewEfl> rwhvefl,
+      const base::Callback<void(bool)>& callback,
+      scoped_refptr<OwnedMailbox> subscriber_texture,
+      scoped_ptr<cc::SingleReleaseCallback> release_callback,
+      bool result);
+  static void ReturnSubscriberTexture(
+      base::WeakPtr<RenderWidgetHostViewEfl> rwhvefl,
+      scoped_refptr<OwnedMailbox> subscriber_texture,
+      uint32 sync_point);
+
   RenderWidgetHostImpl* host_;
   EWebView* web_view_;
   IMContextEfl* im_context_;
@@ -169,6 +205,15 @@ class RenderWidgetHostViewEfl : public RenderWidgetHostViewBase, public IPC::Sen
   typedef std::map<gfx::PluginWindowHandle, Ecore_X_Window> PluginWindowToWidgetMap;
   PluginWindowToWidgetMap plugin_window_to_widget_map_;
 
+  // YUV readback pipeline.
+  scoped_ptr<content::ReadbackYUVInterface>
+      yuv_readback_pipeline_;
+
+  // Subscriber that listens to frame presentation events.
+  scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
+  std::vector<scoped_refptr<OwnedMailbox> > idle_frame_subscriber_textures_;
+  std::set<OwnedMailbox*> active_frame_subscriber_textures_;
+
   // The touch-event. Its touch-points are updated as necessary. A new
   // touch-point is added from an ET_TOUCH_PRESSED event, and a touch-point is
   // removed from the list on an ET_TOUCH_RELEASED event.