[M108 Migration] Enable video hole feature 95/287095/9
authorVenugopal S M <sm.venugopal@samsung.com>
Thu, 19 Jan 2023 13:45:46 +0000 (19:15 +0530)
committerBot Blink <blinkbot@samsung.com>
Wed, 15 Feb 2023 14:18:13 +0000 (14:18 +0000)
- Video Hole feature for ESPP renderer
- Enable Video Hole for HbbTV.
- Support 4K video using the h264 codec
- Support Video hole for onscreen rendering mode

Reference:
https://review.tizen.org/gerrit/275372
https://review.tizen.org/gerrit/271981
https://review.tizen.org/gerrit/275415
https://review.tizen.org/gerrit/275793
https://review.tizen.org/gerrit/278370
https://review.tizen.org/gerrit/278413
https://review.tizen.org/gerrit/279187
https://review.tizen.org/gerrit/281153
https://review.tizen.org/gerrit/283850
https://review.tizen.org/gerrit/287464

Change-Id: I86fce9652e25ab8c94b8802717cec9b4fdf938a5
Signed-off-by: Venugopal S M <sm.venugopal@samsung.com>
87 files changed:
cc/layers/video_frame_provider.h
cc/layers/video_frame_provider_client_impl.cc
cc/layers/video_frame_provider_client_impl.h
cc/layers/video_layer_impl.cc
cc/layers/video_layer_impl.h
components/cast_streaming/renderer/playback_command_forwarding_renderer.cc
content/browser/renderer_host/render_widget_host_impl.cc
content/browser/renderer_host/render_widget_host_impl.h
content/renderer/media/media_factory.cc
content/renderer/media/media_factory.h
content/renderer/render_frame_impl.cc
media/base/pipeline.h
media/base/pipeline_impl.cc
media/base/pipeline_impl.h
media/base/renderer.h
media/base/video_frame.cc
media/base/video_frame.h
media/filters/pipeline_controller.cc
media/filters/pipeline_controller.h
media/mojo/clients/mojo_renderer.cc
media/mojo/clients/mojo_renderer.h
media/mojo/clients/mojo_renderer_wrapper.cc
media/mojo/clients/mojo_renderer_wrapper.h
media/mojo/mojom/BUILD.gn
media/mojo/mojom/renderer.mojom
media/mojo/services/mojo_renderer_service.cc
media/mojo/services/mojo_renderer_service.h
media/renderers/video_resource_updater.cc
media/renderers/video_resource_updater.h
third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
third_party/blink/public/common/web_preferences/web_preferences.h
third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
third_party/blink/public/mojom/BUILD.gn
third_party/blink/public/mojom/webpreferences/web_preferences.mojom
third_party/blink/public/mojom/widget/platform_widget.mojom
third_party/blink/public/platform/media/video_frame_compositor.h
third_party/blink/public/platform/media/web_media_player_builder.h
third_party/blink/public/web/web_settings.h
third_party/blink/public/web/web_view.h
third_party/blink/renderer/core/exported/web_settings_impl.cc
third_party/blink/renderer/core/exported/web_settings_impl.h
third_party/blink/renderer/core/exported/web_view_impl.cc
third_party/blink/renderer/core/exported/web_view_impl.h
third_party/blink/renderer/core/frame/settings.json5
third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
third_party/blink/renderer/core/frame/web_frame_widget_impl.h
third_party/blink/renderer/core/page/chrome_client.h
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
third_party/blink/renderer/platform/media/video_frame_compositor.cc
third_party/blink/renderer/platform/media/web_media_player_builder.cc
third_party/blink/renderer/platform/media/web_media_player_impl.cc
third_party/blink/renderer/platform/media/web_media_player_impl.h
third_party/blink/renderer/platform/widget/widget_base.cc
third_party/blink/renderer/platform/widget/widget_base.h
third_party/blink/renderer/platform/widget/widget_base_client.h
tizen_src/build/config/BUILD.gn
tizen_src/build/config/tizen_features.gni
tizen_src/build/gn_chromiumefl.sh
tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc
tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc
tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h
tizen_src/chromium_impl/media/base/efl/media_player_efl.h
tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.cc
tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h
tizen_src/chromium_impl/media/base/tizen/video_plane_controller.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h [new file with mode: 0644]
tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h [new file with mode: 0644]
tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h [new file with mode: 0644]
tizen_src/chromium_impl/media/filters/esplusplayer_util.cc
tizen_src/chromium_impl/media/filters/esplusplayer_util.h
tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h
tizen_src/chromium_impl/media/media_efl.gni
tizen_src/chromium_impl/ui/ozone/platform/efl/efl_window.cc
tizen_src/ewk/efl_integration/common/render_messages_ewk.h
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/public/ewk_view.cc
tizen_src/ewk/efl_integration/public/ewk_view.h
tizen_src/ewk/ubrowser/browser.cc
tizen_src/ewk/ubrowser/browser.h
tizen_src/ewk/ubrowser/main.cc
tizen_src/ewk/ubrowser/window.cc

index f1f6f83..777655d 100644 (file)
@@ -9,12 +9,25 @@
 #include "base/time/time.h"
 #include "cc/cc_export.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "base/callback.h"
+
+namespace gfx {
+class Rect;
+}
+#endif
+
 namespace media {
 class VideoFrame;
 }
 
 namespace cc {
 
+#if defined(TIZEN_VIDEO_HOLE)
+using DrawableContentRectChangedCallback =
+    base::RepeatingCallback<void(gfx::Rect, bool)>;
+#endif
+
 // VideoFrameProvider and VideoFrameProvider::Client define the relationship by
 // which video frames are exchanged between a provider and client.
 //
@@ -101,6 +114,14 @@ class CC_EXPORT VideoFrameProvider {
   // the current frame if it's invald.
   virtual void OnContextLost() = 0;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetDrawableContentRectChangedCallback(
+      DrawableContentRectChangedCallback cb) = 0;
+
+  // Notifies the client of video plane geometry to be use.
+  virtual void OnDrawableContentRectChanged(const gfx::Rect&) = 0;
+#endif
+
  protected:
   virtual ~VideoFrameProvider() {}
 };
index 1b10337..d9c5e96 100644 (file)
@@ -89,6 +89,16 @@ void VideoFrameProviderClientImpl::PutCurrentFrame() {
   needs_put_current_frame_ = false;
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void VideoFrameProviderClientImpl::OnDrawableContentRectChanged(
+    const gfx::Rect rect) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (provider_)
+    provider_->OnDrawableContentRectChanged(rect);
+}
+#endif
+
 void VideoFrameProviderClientImpl::ReleaseLock() {
   DCHECK(thread_checker_.CalledOnValidThread());
   provider_lock_.Release();
index e07ada9..b30c35e 100644 (file)
@@ -66,6 +66,10 @@ class CC_EXPORT VideoFrameProviderClientImpl
   void DidReceiveFrame() override;
   bool IsDrivingFrameUpdates() const override;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void OnDrawableContentRectChanged(const gfx::Rect);
+#endif
+
   const VideoFrameProvider* get_provider_for_testing() const {
     return provider_;
   }
index 96080d7..0d829c1 100644 (file)
@@ -250,6 +250,19 @@ void VideoLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
                         visible_quad_rect, draw_properties().mask_filter_info,
                         clip_rect_opt, contents_opaque(), draw_opacity(),
                         GetSortingContextId());
+
+#if defined(TIZEN_VIDEO_HOLE)
+  const gfx::Rect video_rect =
+      cc::MathUtil::MapEnclosingClippedRect(transform, gfx::Rect(rotated_size));
+  if (previous_visible_rect_ != video_rect) {
+#if defined(USE_TTRACE)
+    TTRACE(TTRACE_TAG_WEB,
+           "VideoResourceUpdater::AppendQuads -> rect change start!");
+#endif
+    previous_visible_rect_ = video_rect;
+    provider_client_impl_->OnDrawableContentRectChanged(video_rect);
+  }
+#endif  // defined(TIZEN_VIDEO_HOLE)
 }
 
 void VideoLayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) {
index 99c89dc..9b1fa01 100644 (file)
@@ -16,6 +16,9 @@
 #if defined(TIZEN_TBM_SUPPORT)
 #include "components/viz/common/gpu/context_provider.h"
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+#include "ui/gfx/geometry/rect.h"
+#endif
 
 namespace media {
 class VideoFrame;
@@ -74,6 +77,9 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
       const gpu::SyncToken& sync_token,
       bool lost_resource);
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  gfx::Rect previous_visible_rect_;
+#endif
 
   scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl_;
 
index b276199..c364dfd 100644 (file)
@@ -74,6 +74,11 @@ class RendererCommandForwarder : public media::mojom::Renderer {
     owning_renderer_->MojoRendererSetCdm(cdm_id, std::move(callback));
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) override {}
+  void SetMediaGeometry(const gfx::RectF& rect) override {}
+#endif
+
  private:
   PlaybackCommandForwardingRenderer* const owning_renderer_;
   mojo::Receiver<media::mojom::Renderer> playback_controller_;
index 4381130..2dcf337 100644 (file)
@@ -1025,6 +1025,12 @@ void RenderWidgetHostImpl::PrintToPdf(int width,
 }
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+void RenderWidgetHostImpl::SetVideoHoleForRender(bool enable) {
+  blink_widget_->SetVideoHoleForRender(enable);
+}
+#endif
+
 blink::VisualProperties RenderWidgetHostImpl::GetInitialVisualProperties() {
   blink::VisualProperties initial_props = GetVisualProperties();
 
index fc9598a..3e509d3 100644 (file)
@@ -452,6 +452,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl
   void PrintToPdf(int width, int height, const base::FilePath& filename);
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHoleForRender(bool enable);
+#endif
+
   // Returns true if the RenderWidget is hidden.
   bool is_hidden() const { return is_hidden_; }
 
index 7848a79..b949d09 100644 (file)
@@ -376,6 +376,9 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
     const cc::LayerTreeSettings& settings,
     scoped_refptr<base::SingleThreadTaskRunner>
         main_thread_compositor_task_runner,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool is_video_hole,
+#endif
     scoped_refptr<base::TaskRunner> compositor_worker_task_runner) {
   blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
   auto* delegate = GetWebMediaPlayerDelegate();
@@ -523,6 +526,9 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
                      parent_frame_sink_id,
                      blink::WebSurfaceLayerBridge::ContainsVideo::kYes),
       RenderThreadImpl::current()->SharedMainThreadContextProvider(),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole,
+#endif
       use_surface_layer,
       render_frame_->GetRenderFrameMediaPlaybackOptions()
           .is_background_suspend_enabled,
index ff560af..cacc42e 100644 (file)
@@ -106,6 +106,9 @@ class MediaFactory {
       const cc::LayerTreeSettings& settings,
       scoped_refptr<base::SingleThreadTaskRunner>
           main_thread_compositor_task_runner,
+#if defined(TIZEN_VIDEO_HOLE)
+      bool is_video_hole,
+#endif
       scoped_refptr<base::TaskRunner> compositor_worker_task_runner);
 
   // Provides an EncryptedMediaClient to connect blink's EME layer to media's
index b5b806f..3593383 100644 (file)
@@ -3236,10 +3236,19 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
     const blink::WebString& sink_id,
     const cc::LayerTreeSettings& settings,
     scoped_refptr<base::TaskRunner> compositor_worker_task_runner) {
+#if defined(TIZEN_VIDEO_HOLE)
+  bool is_video_hole = false;
+  if (frame_ && frame_->View())
+    is_video_hole = frame_->View()->IsVideoHoleForRender();
+#endif
+
   return media_factory_.CreateMediaPlayer(
       source, client, inspector_context, encrypted_client, initial_cdm, sink_id,
       GetLocalRootWebFrameWidget()->GetFrameSinkId(), settings,
       agent_scheduling_group_.agent_group_scheduler().CompositorTaskRunner(),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole,
+#endif
       std::move(compositor_worker_task_runner));
 }
 
index d97fb4a..83a965e 100644 (file)
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "ui/gfx/geometry/rect_f.h"
+#endif
+
 namespace media {
 
 class CdmContext;
@@ -264,6 +268,10 @@ class MEDIA_EXPORT Pipeline {
   using CdmAttachedCB = base::OnceCallback<void(bool)>;
   virtual void SetCdm(CdmContext* cdm_context,
                       CdmAttachedCB cdm_attached_cb) = 0;
+
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetMediaGeometry(const gfx::RectF rect_f) = 0;
+#endif
 };
 
 }  // namespace media
index 30159d7..eef4c7b 100644 (file)
@@ -63,6 +63,9 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
  public:
   RendererWrapper(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
                   scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+#if defined(TIZEN_VIDEO_HOLE)
+                  bool is_video_hole,
+#endif
                   MediaLog* media_log);
 
   RendererWrapper(const RendererWrapper&) = delete;
@@ -89,6 +92,10 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
   PipelineStatistics GetStatistics() const;
   void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetMediaGeometry(const gfx::RectF rect_f);
+#endif
+
   // |enabled_track_ids| contains track ids of enabled audio tracks.
   void OnEnabledAudioTracksChanged(
       const std::vector<MediaTrack::Id>& enabled_track_ids,
@@ -230,6 +237,10 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
   // reset the pipeline state, and restore this to PIPELINE_OK.
   PipelineStatus status_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool is_video_hole_;
+#endif
+
   // Whether we've received the audio/video/text ended events.
   bool renderer_ended_;
   bool text_renderer_ended_;
@@ -250,6 +261,9 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
 PipelineImpl::RendererWrapper::RendererWrapper(
     scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool is_video_hole,
+#endif
     MediaLog* media_log)
     : media_task_runner_(std::move(media_task_runner)),
       main_task_runner_(std::move(main_task_runner)),
@@ -260,6 +274,9 @@ PipelineImpl::RendererWrapper::RendererWrapper(
       cdm_context_(nullptr),
       state_(kCreated),
       status_(PIPELINE_OK),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole_(is_video_hole),
+#endif
       renderer_ended_(false),
       text_renderer_ended_(false) {}
 
@@ -584,6 +601,14 @@ void PipelineImpl::RendererWrapper::SetCdm(CdmContext* cdm_context,
     CreateRendererInternal(std::move(create_renderer_done_cb_));
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void PipelineImpl::RendererWrapper::SetMediaGeometry(const gfx::RectF rect_f) {
+  LOG(INFO) << __func__;
+  if (shared_state_.renderer)
+    shared_state_.renderer->SetMediaGeometry(rect_f);
+}
+#endif
+
 void PipelineImpl::RendererWrapper::CreateRendererInternal(
     PipelineStatusCallback done_cb) {
   DVLOG(1) << __func__;
@@ -1137,6 +1162,11 @@ void PipelineImpl::RendererWrapper::InitializeRenderer(
       was_played_with_user_activation_);
 
   shared_state_.renderer->Initialize(demuxer_, this, std::move(done_cb));
+
+#if defined(TIZEN_VIDEO_HOLE)
+  LOG(INFO) << __func__ << " call SetVideoHole : " << is_video_hole_;
+  shared_state_.renderer->SetVideoHole(is_video_hole_);
+#endif
 }
 
 void PipelineImpl::RendererWrapper::DestroyRenderer() {
@@ -1231,6 +1261,9 @@ PipelineImpl::PipelineImpl(
     scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     CreateRendererCB create_renderer_cb,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool is_video_hole,
+#endif
     MediaLog* media_log)
     : media_task_runner_(media_task_runner),
       create_renderer_cb_(create_renderer_cb),
@@ -1243,7 +1276,11 @@ PipelineImpl::PipelineImpl(
   DCHECK(create_renderer_cb_);
 
   renderer_wrapper_ = std::make_unique<RendererWrapper>(
-      media_task_runner_, std::move(main_task_runner), media_log_);
+      media_task_runner_, std::move(main_task_runner),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole,
+#endif
+      media_log_);
 }
 
 PipelineImpl::~PipelineImpl() {
@@ -1540,6 +1577,15 @@ void PipelineImpl::SetCdm(CdmContext* cdm_context,
                      BindToCurrentLoop(std::move(cdm_attached_cb))));
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void PipelineImpl::SetMediaGeometry(const gfx::RectF rect_f) {
+  media_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&RendererWrapper::SetMediaGeometry,
+                     base::Unretained(renderer_wrapper_.get()), rect_f));
+}
+#endif
+
 #define RETURN_STRING(state) \
   case state:                \
     return #state;
index 04d1fa6..d6bfd5d 100644 (file)
@@ -86,6 +86,9 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline {
   PipelineImpl(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
                scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
                CreateRendererCB create_renderer_cb,
+#if defined(TIZEN_VIDEO_HOLE)
+               bool is_video_hole,
+#endif
                MediaLog* media_log);
 
   PipelineImpl(const PipelineImpl&) = delete;
@@ -119,6 +122,10 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline {
   PipelineStatistics GetStatistics() const override;
   void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb) override;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetMediaGeometry(const gfx::RectF rect_f) override;
+#endif
+
   // |enabled_track_ids| contains track ids of enabled audio tracks.
   void OnEnabledAudioTracksChanged(
       const std::vector<MediaTrack::Id>& enabled_track_ids,
index 8fdc608..9b1d7f5 100644 (file)
 #include "media/base/pipeline_status.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "ui/gfx/geometry/rect_f.h"
+#endif
+
 namespace media {
 
 class CdmContext;
@@ -67,6 +71,11 @@ class MEDIA_EXPORT Renderer {
   // Discards any buffered data, executing |flush_cb| when completed.
   virtual void Flush(base::OnceClosure flush_cb) = 0;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetVideoHole(bool is_video_hole) {}
+  virtual void SetMediaGeometry(const gfx::RectF& rect) {}
+#endif
+
   // Starts rendering from |time|.
   virtual void StartPlayingFrom(base::TimeDelta time) = 0;
 
index ef1213f..fd0dd69 100644 (file)
@@ -90,6 +90,10 @@ std::string VideoFrame::StorageTypeToString(
     case VideoFrame::STORAGE_TBM_SURFACE:
       return "TBM_SURFACE";
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+    case VideoFrame::STORAGE_HOLE:
+      return "HOLE";
+#endif
     case VideoFrame::STORAGE_GPU_MEMORY_BUFFER:
       return "GPU_MEMORY_BUFFER";
   }
@@ -1010,6 +1014,22 @@ scoped_refptr<VideoFrame> VideoFrame::CreateTransparentFrame(
   return frame;
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+// This block and other blocks wrapped around #if defined(TIZEN_VIDEO_HOLE) is
+// not maintained by the general compositor team. Please contact
+// wonsik@chromium.org .
+
+// static
+scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
+    const gfx::Size& natural_size) {
+  auto layout = VideoFrameLayout::Create(PIXEL_FORMAT_UNKNOWN, natural_size);
+  scoped_refptr<VideoFrame> frame =
+      new VideoFrame(*layout, StorageType::STORAGE_HOLE,
+                     gfx::Rect(natural_size), natural_size, base::TimeDelta());
+  return frame;
+}
+#endif  // defined(TIZEN_VIDEO_HOLE)
+
 // static
 size_t VideoFrame::NumPlanes(VideoPixelFormat format) {
   return VideoFrameLayout::NumPlanes(format);
index ffeb81e..b856464 100644 (file)
@@ -108,13 +108,17 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
     // STORAGE_UNOWNED_MEMORY) and handle it appropriately in all cases.
     STORAGE_DMABUFS = 5,  // Each plane is stored into a DmaBuf.
 #endif
-    STORAGE_GPU_MEMORY_BUFFER = 6,
 #if defined(TIZEN_TBM_SUPPORT)
-    STORAGE_TBM_SURFACE = 7,
-    STORAGE_MAX = STORAGE_TBM_SURFACE,
-#else
-    STORAGE_MAX = STORAGE_GPU_MEMORY_BUFFER,
+    STORAGE_TBM_SURFACE = 6,
+#endif
+#if defined(TIZEN_VIDEO_HOLE)
+    // Indicates protected media that needs to be directly rendered to hw. It
+    // is, in principle, platform independent, see http://crbug.com/323157 and
+    // https://groups.google.com/a/google.com/d/topic/chrome-gpu/eIM1RwarUmk/discussion
+    STORAGE_HOLE = 7,
 #endif
+    STORAGE_GPU_MEMORY_BUFFER = 8,
+    STORAGE_MAX = STORAGE_GPU_MEMORY_BUFFER,
   };
 
   // CB to be called on the mailbox backing this frame and its GpuMemoryBuffers
@@ -390,6 +394,11 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
   static scoped_refptr<VideoFrame> CreateTransparentFrame(
       const gfx::Size& size);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  // Allocates a hole frame.
+  static scoped_refptr<VideoFrame> CreateHoleFrame(const gfx::Size& size);
+#endif
+
   static size_t NumPlanes(VideoPixelFormat format);
 
   // Returns the required allocation size for a (tightly packed) frame of the
index 62f8d17..227f9d1 100644 (file)
@@ -453,6 +453,12 @@ void PipelineController::FireOnTrackChangeCompleteForTesting(State set_to) {
   OnTrackChangeComplete();
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void PipelineController::SetMediaGeometry(gfx::RectF rect_f) {
+  pipeline_->SetMediaGeometry(rect_f);
+}
+#endif
+
 void PipelineController::OnTrackChangeComplete() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
index 4eff4f7..fb6cde0 100644 (file)
@@ -154,6 +154,10 @@ class MEDIA_EXPORT PipelineController {
   // OnceCallback, and doesn't play nicely with gmock.
   void FireOnTrackChangeCompleteForTesting(State set_to);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetMediaGeometry(gfx::RectF rect_f);
+#endif
+
  private:
   // Attempts to make progress from the current state to the target state.
   void Dispatch();
index c529abc..b81b11e 100644 (file)
@@ -224,6 +224,18 @@ base::TimeDelta MojoRenderer::GetMediaTime() {
   return media_time_interpolator_.GetInterpolatedTime();
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void MojoRenderer::SetVideoHole(bool is_video_hole) {
+  if (remote_renderer_.is_bound())
+    remote_renderer_->SetVideoHole(is_video_hole);
+}
+
+void MojoRenderer::SetMediaGeometry(const gfx::RectF& rect) {
+  if (remote_renderer_.is_bound())
+    remote_renderer_->SetMediaGeometry(rect);
+}
+#endif
+
 void MojoRenderer::OnTimeUpdate(base::TimeDelta time,
                                 base::TimeDelta max_time,
                                 base::TimeTicks capture_time) {
index 3e98c19..acde794 100644 (file)
@@ -67,6 +67,11 @@ class MojoRenderer : public Renderer, public mojom::RendererClient {
   void SetVolume(float volume) override;
   base::TimeDelta GetMediaTime() override;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) override;
+  void SetMediaGeometry(const gfx::RectF& rect) override;
+#endif
+
  private:
   // mojom::RendererClient implementation, dispatched on the |task_runner_|.
   void OnTimeUpdate(base::TimeDelta time,
index 3fd355d..f3eea40 100644 (file)
@@ -46,6 +46,16 @@ void MojoRendererWrapper::SetLatencyHint(
   mojo_renderer_->SetLatencyHint(latency_hint);
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void MojoRendererWrapper::SetVideoHole(bool is_video_hole) {
+  mojo_renderer_->SetVideoHole(is_video_hole);
+}
+
+void MojoRendererWrapper::SetMediaGeometry(const gfx::RectF& rect) {
+  mojo_renderer_->SetMediaGeometry(rect);
+}
+#endif
+
 base::TimeDelta MojoRendererWrapper::GetMediaTime() {
   return mojo_renderer_->GetMediaTime();
 }
index 743cd3f..938b5d1 100644 (file)
@@ -36,6 +36,12 @@ class MojoRendererWrapper : public Renderer {
   void StartPlayingFrom(base::TimeDelta time) override;
   void SetPlaybackRate(double playback_rate) override;
   void SetVolume(float volume) override;
+
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) override;
+  void SetMediaGeometry(const gfx::RectF& rect) override;
+#endif
+
   base::TimeDelta GetMediaTime() override;
 
  private:
index 0783af8..a52d07f 100644 (file)
@@ -124,6 +124,10 @@ mojom("mojom") {
     enabled_features += [ "tizen_multimedia" ]
   }
 
+  if (tizen_video_hole) {
+    enabled_features += [ "tizen_video_hole" ]
+  }
+
   shared_typemaps = [
     {
       types = [
index 9077053..cd20071 100644 (file)
@@ -51,6 +51,12 @@ interface Renderer {
   // Attaches the CDM associated with `cdm_id` to the renderer service,
   // executing the callback with whether the CDM was successfully attached.
   SetCdm(mojo_base.mojom.UnguessableToken? cdm_id) => (bool success);
+
+  [EnableIf=tizen_video_hole]
+  SetVideoHole(bool is_video_hole);
+
+  [EnableIf=tizen_video_hole]
+  SetMediaGeometry(gfx.mojom.RectF rect);
 };
 
 // A Mojo equivalent of media::RendererClient. See media/mojo/README.md
index 1697c7b..cdd5afc 100644 (file)
@@ -151,6 +151,16 @@ void MojoRendererService::SetCdm(
                                    weak_this_, std::move(callback)));
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void MojoRendererService::SetVideoHole(bool is_video_hole) {
+  renderer_->SetVideoHole(is_video_hole);
+}
+
+void MojoRendererService::SetMediaGeometry(const gfx::RectF& rect) {
+  renderer_->SetMediaGeometry(rect);
+}
+#endif
+
 void MojoRendererService::OnError(PipelineStatus error) {
   DVLOG(1) << __func__ << "(" << error << ")";
   state_ = STATE_ERROR;
index 295eebd..f78b31a 100644 (file)
@@ -72,6 +72,11 @@ class MEDIA_MOJO_EXPORT MojoRendererService final : public mojom::Renderer,
   void SetCdm(const absl::optional<base::UnguessableToken>& cdm_id,
               SetCdmCallback callback) final;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) final;
+  void SetMediaGeometry(const gfx::RectF& rect) final;
+#endif
+
  private:
   enum State {
     STATE_UNINITIALIZED,
index 9b419ca..ec296e6 100644 (file)
 #include "ui/gl/gl_enums.h"
 #include "ui/gl/trace_util.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "components/viz/common/quads/solid_color_draw_quad.h"
+#endif
+
 namespace media {
 namespace {
 
@@ -708,6 +712,20 @@ void VideoResourceUpdater::AppendQuads(
 
       break;
     }
+#if defined(TIZEN_VIDEO_HOLE)
+    case VideoFrameResourceType::HOLE: {
+      DCHECK_EQ(frame_resources_.size(), 0u);
+      auto* solid_color_draw_quad =
+          render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
+
+      // Create a solid color quad with transparent black and force no
+      // blending / no anti-aliasing.
+      solid_color_draw_quad->SetAll(shared_quad_state, quad_rect,
+                                    visible_quad_rect, false,
+                                    SkColors::kTransparent, true);
+      break;
+    }
+#endif
     case VideoFrameResourceType::NONE:
       NOTIMPLEMENTED();
       break;
@@ -717,6 +735,14 @@ void VideoResourceUpdater::AppendQuads(
 VideoFrameExternalResources
 VideoResourceUpdater::CreateExternalResourcesFromVideoFrame(
     scoped_refptr<VideoFrame> video_frame) {
+#if defined(TIZEN_VIDEO_HOLE)
+  if (video_frame->storage_type() == media::VideoFrame::STORAGE_HOLE) {
+    VideoFrameExternalResources external_resources;
+    external_resources.type = VideoFrameResourceType::HOLE;
+    return external_resources;
+  }
+#endif
+
   if (video_frame->format() == PIXEL_FORMAT_UNKNOWN)
     return VideoFrameExternalResources();
   DCHECK(video_frame->HasTextures() || video_frame->IsMappable());
index e3a0783..9ffac77 100644 (file)
@@ -54,6 +54,11 @@ enum class VideoFrameResourceType {
   RGB,
   RGBA_PREMULTIPLIED,
   RGBA,
+#if defined(TIZEN_VIDEO_HOLE)
+  // TODO(danakj): Implement this with a solid color layer instead of a video
+  // frame and video layer.
+  HOLE,
+#endif
   STREAM_TEXTURE,
   // The VideoFrame is merely a hint to compositor that a hole must be made
   // transparent so the video underlay will be visible.
index e492fa3..2b11003 100644 (file)
@@ -151,6 +151,9 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
   out->cookie_enabled = data.cookie_enabled();
   out->accelerated_video_decode_enabled =
       data.accelerated_video_decode_enabled();
+#if defined(TIZEN_VIDEO_HOLE)
+  out->video_hole_enabled = data.video_hole_enabled();
+#endif
   out->user_gesture_required_for_presentation =
       data.user_gesture_required_for_presentation();
   out->text_tracks_enabled = data.text_tracks_enabled();
index 1ce751e..52d345f 100644 (file)
@@ -170,6 +170,10 @@ struct BLINK_COMMON_EXPORT WebPreferences {
   // Defaults to false.
   bool accelerated_video_decode_enabled;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool video_hole_enabled = false;
+#endif
+
   blink::mojom::ImageAnimationPolicy animation_policy =
       blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAllowed;
 
index 5c90c53..ff8609a 100644 (file)
@@ -443,6 +443,12 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
     return r.accelerated_video_decode_enabled;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  static bool video_hole_enabled(const blink::web_pref::WebPreferences& r) {
+    return r.video_hole_enabled;
+  }
+#endif
+
   static blink::mojom::ImageAnimationPolicy animation_policy(
       const blink::web_pref::WebPreferences& r) {
     return r.animation_policy;
index 01be4fe..e038259 100644 (file)
@@ -338,6 +338,9 @@ mojom("mojom_platform") {
   if (use_efl) {
     enabled_features += [ "is_efl" ]
   }
+  if (tizen_video_hole) {
+    enabled_features += [ "tizen_video_hole" ]
+  }
 
   shared_cpp_typemaps = [
     {
index bb78cf4..e0f87f5 100644 (file)
@@ -220,6 +220,9 @@ struct WebPreferences {
   // Defaults to false.
   bool accelerated_video_decode_enabled;
 
+  [EnableIf=tizen_video_hole]
+  bool video_hole_enabled;
+
   ImageAnimationPolicy animation_policy;
 
   bool user_gesture_required_for_presentation;
index 17dfb14..46ca55c 100644 (file)
@@ -129,6 +129,9 @@ interface Widget {
   [EnableIf=is_efl]
   PrintToPdf(uint32 width, uint32 height, mojo_base.mojom.FilePath filename);
 
+  [EnableIf=tizen_video_hole]
+  SetVideoHoleForRender(bool enable);
+
   // Informs the widget that it was hidden. This allows it to reduce its
   // resource utilization, and will cancel any pending
   // RecordContentToVisibleTimeRequest that was set with WasShown or
index 6c2a31f..0ed1483 100644 (file)
@@ -175,6 +175,12 @@ class BLINK_PLATFORM_EXPORT VideoFrameCompositor
     submitter_ = std::move(submitter);
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetDrawableContentRectChangedCallback(
+      cc::DrawableContentRectChangedCallback cb) override;
+  void OnDrawableContentRectChanged(const gfx::Rect&) override;
+#endif
+
  private:
   // TracingCategory name for |auto_open_close_|.
   static constexpr const char kTracingCategory[] = "media,rail";
@@ -230,6 +236,10 @@ class BLINK_PLATFORM_EXPORT VideoFrameCompositor
   // Can only be called from the compositor thread.
   base::TimeDelta GetLastIntervalWithoutLock();
 
+#if defined(TIZEN_VIDEO_HOLE)
+  cc::DrawableContentRectChangedCallback drawable_content_rect_changed_cb_;
+#endif
+
   // This will run tasks on the compositor thread. If
   // kEnableSurfaceLayerForVideo is enabled, it will instead run tasks on the
   // media thread.
index bd5247c..05e0d6f 100644 (file)
@@ -92,6 +92,9 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerBuilder {
       mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
       CreateSurfaceLayerBridgeCB create_bridge_callback,
       scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+#if defined(TIZEN_VIDEO_HOLE)
+      bool is_video_hole,
+#endif
       bool use_surface_layer_for_video,
       bool is_background_suspend_enabled,
       bool is_background_video_playback_enabled,
index 0e49c67..617094f 100644 (file)
@@ -290,6 +290,9 @@ class WebSettings {
   virtual void SetAccessibilityEnabled(bool) = 0;
   virtual bool GetAccessibilityEnabled() = 0;
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetVideoHoleEnabled(bool) = 0;
+#endif
 
  protected:
   ~WebSettings() = default;
index ed6c3a0..91135d7 100644 (file)
@@ -469,6 +469,13 @@ class BLINK_EXPORT WebView {
   // Returns whether this WebView represents a fenced frame root or not.
   virtual bool IsFencedFrameRoot() const = 0;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  // Video hole support ---------------------------------------------------
+  virtual void SetVideoHoleForRender(bool enable) = 0;
+  virtual bool IsVideoHoleForRender() const = 0;
+  virtual void SetVideoHoleDisabledForOES(bool enabled) = 0;
+#endif
+
   // Misc -------------------------------------------------------------
 
   // Returns the number of live WebView instances in this process.
index 1f5a363..7ff759c 100644 (file)
@@ -807,4 +807,9 @@ bool WebSettingsImpl::GetAccessibilityEnabled() {
 }
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+void WebSettingsImpl::SetVideoHoleEnabled(bool enabled) {
+  settings_->SetVideoHoleEnabled(enabled);
+}
+#endif
 }  // namespace blink
index dc092d8..f316fa7 100644 (file)
@@ -236,6 +236,9 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
   void SetAccessibilityEnabled(bool) override;
   bool GetAccessibilityEnabled() override;
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHoleEnabled(bool) override;
+#endif
 
   bool RenderVSyncNotificationEnabled() const {
     return render_v_sync_notification_enabled_;
index 643e14b..ab133fb 100644 (file)
@@ -1832,6 +1832,10 @@ void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
   settings->SetTouchDragEndContextMenu(prefs.touch_dragend_context_menu);
   settings->SetWebXRImmersiveArAllowed(prefs.webxr_immersive_ar_allowed);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  settings->SetVideoHoleEnabled(prefs.video_hole_enabled);
+#endif
+
 #if BUILDFLAG(IS_MAC)
   web_view_impl->SetMaximumLegibleScale(
       prefs.default_maximum_page_scale_factor);
@@ -4019,4 +4023,20 @@ void WebViewImpl::ScrollFocusedNodeIntoView() {
 }
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+void WebViewImpl::SetVideoHoleForRender(bool enable) {
+  web_pref::WebPreferences pref = GetWebPreferences();
+  pref.video_hole_enabled = enable;
+  SetWebPreferences(pref);
+}
+
+bool WebViewImpl::IsVideoHoleForRender() const {
+  return GetPage()->GetSettings().GetVideoHoleEnabled() &&
+         !is_videoHole_disabled_for_oes_;
+}
+
+void WebViewImpl::SetVideoHoleDisabledForOES(bool disabled) {
+  is_videoHole_disabled_for_oes_ = disabled;
+}
+#endif
 }  // namespace blink
index 887ef26..5c3d4a2 100644 (file)
@@ -518,9 +518,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
 
   gfx::Vector2dF ElasticOverscroll() const { return elastic_overscroll_; }
 
-  class ChromeClient& GetChromeClient() const {
-    return *chrome_client_.Get();
-  }
+  class ChromeClient& GetChromeClient() const { return *chrome_client_.Get(); }
 
   // Allows main frame updates to occur if they were previously blocked. They
   // are blocked during loading a navigation, to allow Blink to proceed without
@@ -610,6 +608,12 @@ class CORE_EXPORT WebViewImpl final : public WebView,
   // words, after the frame has painted something.
   void DidFirstVisuallyNonEmptyPaint();
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHoleForRender(bool enable) override;
+  bool IsVideoHoleForRender() const override;
+  void SetVideoHoleDisabledForOES(bool disabled) override;
+#endif
+
  private:
   FRIEND_TEST_ALL_PREFIXES(WebFrameTest, DivScrollIntoEditableTest);
   FRIEND_TEST_ALL_PREFIXES(WebFrameTest,
@@ -887,6 +891,10 @@ class CORE_EXPORT WebViewImpl final : public WebView,
 
   gfx::Vector2dF elastic_overscroll_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool is_videoHole_disabled_for_oes_;
+#endif
+
   // If true, we send IPC messages when |preferred_size_| changes.
   bool send_preferred_size_changes_ = false;
 
index a80dcbe..0025005 100644 (file)
       initial: true,
       type: "bool",
     },
+    {
+      name: "videoHoleEnabled",
+      initial: false,
+      type: "bool"
+    },
   ],
 }
index 8e54d84..fe072e5 100644 (file)
@@ -4207,6 +4207,14 @@ void WebFrameWidgetImpl::SetMaxRefreshRate(uint32_t max_refresh_rate) {
 }
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+void WebFrameWidgetImpl::SetVideoHoleForRender(bool enable) {
+  WebView* view = View();
+  if (view)
+    view->SetVideoHoleForRender(enable);
+}
+#endif
+
 void WebFrameWidgetImpl::OrientationChanged() {
   local_root_->SendOrientationChangeEvent();
 }
index f15ee24..af3dca2 100644 (file)
@@ -717,6 +717,10 @@ class CORE_EXPORT WebFrameWidgetImpl
                   uint32_t height,
                   const base::FilePath& filename) override;
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHoleForRender(bool enable) override;
+#endif
+
   void OrientationChanged() override;
   void DidUpdateSurfaceAndScreen(
       const display::ScreenInfos& previous_original_screen_infos) override;
index 0fcb111..bee1063 100644 (file)
@@ -568,6 +568,10 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
 
   virtual void PasswordFieldReset(HTMLInputElement& element) {}
 
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetVideoHoleDisabledForOES(bool disabled) const {}
+#endif
+
  protected:
   ChromeClient() = default;
 
index a824973..0841a93 100644 (file)
@@ -48,6 +48,12 @@ class MediaStreamDescriptor;
 class WebMediaPlayerMS;
 struct WebMediaPlayerMSCompositorTraits;
 
+#if defined(TIZEN_VIDEO_HOLE)
+using DrawableContentRectChangedCallback =
+    base::RepeatingCallback<void(gfx::Rect, bool)>;
+using VideoVisibilityChangedCallback = base::RepeatingCallback<void(bool)>;
+#endif
+
 // This class is designed to handle the work load on compositor thread for
 // WebMediaPlayerMS. It will be instantiated on the main thread, but destroyed
 // on the thread holding the last reference.
@@ -146,6 +152,14 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
   // Gets metadata which is available after kReadyStateHaveMetadata state.
   Metadata GetMetadata();
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetDrawableContentRectChangedCallback(
+      DrawableContentRectChangedCallback cb) override {}
+
+  // Notifies the client of video plane geometry to be use.
+  void OnDrawableContentRectChanged(const gfx::Rect&) override {}
+#endif
+
  private:
   friend class WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor,
                                          WebMediaPlayerMSCompositorTraits>;
index fdbf31d..d008071 100644 (file)
@@ -477,4 +477,16 @@ void VideoFrameCompositor::OnContextLost() {
   SetCurrentFrame_Locked(std::move(black_frame), tick_clock_->NowTicks());
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void VideoFrameCompositor::SetDrawableContentRectChangedCallback(
+    cc::DrawableContentRectChangedCallback cb) {
+  drawable_content_rect_changed_cb_ = std::move(cb);
+}
+
+void VideoFrameCompositor::OnDrawableContentRectChanged(const gfx::Rect& rect) {
+  if (!drawable_content_rect_changed_cb_.is_null())
+    drawable_content_rect_changed_cb_.Run(rect, true);
+}
+#endif
+
 }  // namespace blink
index 9b3cd2e..bab6de1 100644 (file)
@@ -55,6 +55,9 @@ WebMediaPlayer* WebMediaPlayerBuilder::Build(
     mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
     CreateSurfaceLayerBridgeCB create_bridge_callback,
     scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool is_video_hole,
+#endif
     bool use_surface_layer,
     bool is_background_suspend_enabled,
     bool is_background_video_playback_enabled,
@@ -72,7 +75,11 @@ WebMediaPlayer* WebMediaPlayerBuilder::Build(
       std::move(request_routing_token_cb), std::move(media_observer),
       enable_instant_source_buffer_gc, embedded_media_experience_enabled,
       std::move(metrics_provider), std::move(create_bridge_callback),
-      std::move(raster_context_provider), use_surface_layer,
+      std::move(raster_context_provider),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole,
+#endif
+      use_surface_layer,
       is_background_suspend_enabled, is_background_video_playback_enabled,
       is_background_video_track_optimization_supported,
       std::move(demuxer_override), std::move(remote_interfaces));
index f31d3a4..8808a01 100644 (file)
 #include "media/base/android/media_codec_util.h"
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+// NSW : Is this necessary?
+namespace {
+const base::TimeDelta kLayerBoundUpdateInterval = base::Milliseconds(50);
+}  // namespace
+#endif
+
 namespace blink {
 namespace {
 
@@ -414,6 +421,9 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
     mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
     CreateSurfaceLayerBridgeCB create_bridge_callback,
     scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+#if defined(TIZEN_VIDEO_HOLE)
+    bool is_video_hole,
+#endif
     bool use_surface_layer,
     bool is_background_suspend_enabled,
     bool is_background_video_playback_enabled,
@@ -456,6 +466,9 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
           base::BindRepeating(&WebMediaPlayerImpl::GetCurrentTimeInternal,
                               base::Unretained(this))),
       will_play_helper_(nullptr),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole_(is_video_hole),
+#endif
       demuxer_override_(std::move(demuxer_override)) {
   DVLOG(1) << __func__;
   DCHECK(adjust_allocated_memory_cb_);
@@ -489,6 +502,9 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
       media_task_runner_, main_task_runner_,
       base::BindRepeating(&WebMediaPlayerImpl::CreateRenderer,
                           base::Unretained(this)),
+#if defined(TIZEN_VIDEO_HOLE)
+      is_video_hole_,
+#endif
       media_log_.get());
 
   pipeline_controller_ = std::make_unique<media::PipelineController>(
@@ -564,6 +580,18 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
   // it's not interested in recording these events.
   playback_events_recorder_.reset_on_disconnect();
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_) {
+    vfc_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &VideoFrameCompositor::SetDrawableContentRectChangedCallback,
+            base::Unretained(compositor_.get()),
+            media::BindToCurrentLoop(base::BindRepeating(
+                &WebMediaPlayerImpl::OnDrawableContentRectChanged,
+                weak_this_))));
+  }
+#endif
 #if BUILDFLAG(IS_ANDROID)
   renderer_factory_selector_->SetRemotePlayStateChangeCB(
       media::BindToCurrentLoop(base::BindRepeating(
@@ -2461,6 +2489,13 @@ void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
 
   RecordVideoNaturalSize(rotated_size);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (ShouldUseVideoHole()) {
+    CreateVideoHoleFrame();
+    StartLayerBoundUpdateTimer();
+  }
+#endif
+
   gfx::Size old_size = pipeline_metadata_.natural_size;
   if (rotated_size == old_size)
     return;
@@ -2542,6 +2577,13 @@ void WebMediaPlayerImpl::OnVideoConfigChange(
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (ShouldUseVideoHole()) {
+    CreateVideoHoleFrame();
+    StartLayerBoundUpdateTimer();
+  }
+#endif
+
   const bool codec_change =
       pipeline_metadata_.video_decoder_config.codec() != config.codec();
   const bool codec_profile_change =
@@ -2917,6 +2959,11 @@ std::unique_ptr<media::Renderer> WebMediaPlayerImpl::CreateRenderer(
   media_metrics_provider_->SetRendererType(renderer_type_);
   media_log_->SetProperty<MediaLogProperty::kRendererName>(renderer_type_);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (ShouldUseVideoHole())
+    StartLayerBoundUpdateTimer();
+#endif
+
   return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer(
       media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
       compositor_.get(), std::move(request_overlay_info_cb),
@@ -4118,4 +4165,74 @@ bool WebMediaPlayerImpl::PassedTimingAllowOriginCheck() const {
   return true;
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+bool WebMediaPlayerImpl::ShouldUseVideoHole() const {
+  if (HasVideo() && is_video_hole_)
+    return true;
+  return false;
+}
+
+void WebMediaPlayerImpl::CreateVideoHoleFrame() {
+  gfx::Size size(pipeline_metadata_.natural_size.width(),
+                 pipeline_metadata_.natural_size.height());
+
+  scoped_refptr<media::VideoFrame> video_frame =
+      media::VideoFrame::CreateHoleFrame(size);
+  if (video_frame)
+    compositor_->PaintSingleFrame(video_frame);
+}
+
+void WebMediaPlayerImpl::OnDrawableContentRectChanged(gfx::Rect rect,
+                                                      bool is_video) {
+  gfx::RectF rect_f = static_cast<gfx::RectF>(rect);
+  LOG(INFO) << __func__ << " : " << rect_f.ToString();
+  if (rect_f != last_computed_rect_)
+    pipeline_controller_->SetMediaGeometry(rect_f);
+
+  last_computed_rect_ = rect_f;
+}
+
+bool WebMediaPlayerImpl::UpdateBoundaryRectangle() {
+  if (!video_layer_)
+    return false;
+
+  // Compute the geometry of video frame layer.
+  cc::Layer* layer = video_layer_.get();
+  if (!layer->layer_tree_host())
+    return false;
+
+  gfx::Rect layer_screen_space_rect = cc::MathUtil::MapEnclosingClippedRect(
+      layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds()));
+  gfx::RectF rect = gfx::RectF(layer_screen_space_rect);
+  // Return false when the geometry hasn't been changed from the last time.
+  // if (last_computed_rect_ == rect)
+  //   return false;
+
+  // Store the changed geometry information when it is actually changed.
+  last_computed_rect_ = rect;
+  return true;
+}
+
+void WebMediaPlayerImpl::StartLayerBoundUpdateTimer() {
+  if (layer_bound_update_timer_.IsRunning())
+    return;
+
+  LOG(INFO) << __func__;
+  layer_bound_update_timer_.Start(
+      FROM_HERE, kLayerBoundUpdateInterval, this,
+      &WebMediaPlayerImpl::OnLayerBoundUpdateTimerFired);
+}
+
+void WebMediaPlayerImpl::StopLayerBoundUpdateTimer() {
+  if (layer_bound_update_timer_.IsRunning())
+    layer_bound_update_timer_.Stop();
+}
+
+void WebMediaPlayerImpl::OnLayerBoundUpdateTimerFired() {
+  LOG(INFO) << __func__;
+  if (UpdateBoundaryRectangle())
+    pipeline_controller_->SetMediaGeometry(last_computed_rect_);
+  StopLayerBoundUpdateTimer();
+}
+#endif
 }  // namespace blink
index 31b94dd..218cb25 100644 (file)
@@ -139,6 +139,9 @@ class PLATFORM_EXPORT WebMediaPlayerImpl
       mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
       CreateSurfaceLayerBridgeCB create_bridge_callback,
       scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+#if defined(TIZEN_VIDEO_HOLE)
+      bool is_video_hole,
+#endif
       bool use_surface_layer,
       bool is_background_suspend_enabled,
       bool is_background_video_play_enabled,
@@ -668,6 +671,16 @@ class PLATFORM_EXPORT WebMediaPlayerImpl
   // Returns true if the video frame from this player are being captured.
   bool IsVideoBeingCaptured() const;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool ShouldUseVideoHole() const;
+  void CreateVideoHoleFrame();
+  void OnDrawableContentRectChanged(gfx::Rect rect, bool is_video);
+  bool UpdateBoundaryRectangle();
+  void StartLayerBoundUpdateTimer();
+  void StopLayerBoundUpdateTimer();
+  void OnLayerBoundUpdateTimerFired();
+#endif
+
   // Report UMAs when this object instance is destroyed.
   void ReportSessionUMAs() const;
 
@@ -1068,6 +1081,12 @@ class PLATFORM_EXPORT WebMediaPlayerImpl
 
   LearningExperimentHelper will_play_helper_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool is_video_hole_;
+  gfx::RectF last_computed_rect_;
+  base::RepeatingTimer layer_bound_update_timer_;
+#endif
+
   // Stores the optional override Demuxer until it is used in DoLoad().
   std::unique_ptr<media::Demuxer> demuxer_override_;
 
index e345298..4f07693 100644 (file)
@@ -500,6 +500,12 @@ void WidgetBase::PrintToPdf(uint32_t width,
 }
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+void WidgetBase::SetVideoHoleForRender(bool enable) {
+  client_->SetVideoHoleForRender(enable);
+}
+#endif
+
 void WidgetBase::WasHidden() {
   // A provisional frame widget will never be hidden since that would require it
   // to be shown first. A frame must be attached to the frame tree before
index faec533..43344d4 100644 (file)
@@ -148,6 +148,9 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
                   uint32_t height,
                   const base::FilePath& filename) override;
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHoleForRender(bool enable) override;
+#endif
   void WasHidden() override;
   void WasShown(bool was_evicted,
                 mojom::blink::RecordContentToVisibleTimeRequestPtr
index 608f7cd..d34b06f 100644 (file)
@@ -180,6 +180,9 @@ class WidgetBaseClient {
                           uint32_t height,
                           const base::FilePath& filename) {}
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetVideoHoleForRender(bool enable) {}
+#endif
 
   // Convert screen coordinates to device emulated coordinates (scaled
   // coordinates when devtools is used). This occurs for popups where their
index 92914cb..66cc744 100644 (file)
@@ -42,6 +42,9 @@ config("tizen_feature_flags") {
     if (tizen_web_speech_recognition) {
       defines += [ "TIZEN_WEB_SPEECH_RECOGNITION" ]
     }
+    if (tizen_video_hole) {
+      defines += [ "TIZEN_VIDEO_HOLE" ]
+    }
 
     # TODO: There are X11 dependencies in following condition.
     #       The files need to be implemented based on Wayland.
index 8854b6a..9b971e9 100644 (file)
@@ -49,6 +49,7 @@ declare_args() {
   tizen_multimedia_support = false
   tizen_multimedia = false
   tizen_tbm_support = false
+  tizen_video_hole = false
   tizen_audio_io = false
   tizen_web_speech_recognition = false
 
index 078276d..531f7f2 100755 (executable)
@@ -224,6 +224,7 @@ add_tizen_flags() {
                              tizen_audio_io=true
                              tizen_web_speech_recognition=true
                              tizen_tbm_support=true
+                             tizen_video_hole=true
                             "
 }
 
index e5d1313..19667a5 100644 (file)
 #include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_tizen.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#endif
+
 #if defined(TIZEN_TBM_SUPPORT)
 namespace media {
 void DestroyMediaPacket(void* media_packet, int player_id) {
@@ -43,6 +47,7 @@ void DestroyMediaPacket(void* media_packet, int player_id) {
 }
 }  // namespace media
 #endif
+
 namespace content {
 
 class TizenRendererImpl::RendererClientInternal final
@@ -150,6 +155,9 @@ TizenRendererImpl::TizenRendererImpl(
       render_process_id_(process_id),
       routing_id_(routing_id),
       volume_(kDefaultVolume),
+#if defined(TIZEN_VIDEO_HOLE)
+      web_contents_(web_contents),
+#endif
       renderer_extension_receiver_(this,
                                    std::move(renderer_extension_receiver)) {
   DCHECK_EQ(WebContents::FromRenderFrameHost(
@@ -339,6 +347,51 @@ void TizenRendererImpl::Seek(base::TimeDelta time) {
   GetPlayer()->Seek(time);
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void TizenRendererImpl::SetVideoHole(bool is_video_hole) {
+  if (is_video_hole_ == is_video_hole)
+    return;
+
+  is_video_hole_ = is_video_hole;
+  SetPlayerVideoHole();
+}
+
+void TizenRendererImpl::SetPlayerVideoHole() {
+  if (GetPlayer())
+    GetPlayer()->SetVideoHole(is_video_hole_);
+}
+
+void TizenRendererImpl::SetMediaGeometry(const gfx::RectF& rect) {
+  if (video_rect_ == rect)
+    return;
+
+  video_rect_ = rect;
+  SetPlayerMediaGeometry();
+}
+
+void TizenRendererImpl::SetPlayerMediaGeometry() {
+  if (GetPlayer())
+    GetPlayer()->SetMediaGeometry(GetViewportRect(), video_rect_);
+}
+
+gfx::Rect TizenRendererImpl::GetViewportRect() const {
+  if (!web_contents_)
+    return gfx::Rect();
+
+  if (RenderWidgetHostViewAura* rwhv = static_cast<RenderWidgetHostViewAura*>(
+          web_contents_->GetRenderWidgetHostView())) {
+    if (rwhv->offscreen_helper()) {
+      // offscreen rendering mode
+      return rwhv->offscreen_helper()->GetViewBoundsInPix();
+    } else {
+      // onscreen rendering mode
+      return rwhv->window()->bounds();
+    }
+  }
+  return gfx::Rect();
+}
+#endif
+
 void TizenRendererImpl::StartPlayingFrom(base::TimeDelta time) {
   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
             << " time : " << time.InMicroseconds();
@@ -348,7 +401,13 @@ void TizenRendererImpl::StartPlayingFrom(base::TimeDelta time) {
                time.InMicroseconds());
 
   if (!GetPlayer()->IsInitialized())
-    GetPlayer()->Initialize(sink_);
+#if defined(TIZEN_VIDEO_HOLE)
+    if (is_video_hole_) {
+      SetPlayerVideoHole();
+      SetPlayerMediaGeometry();
+    }
+#endif
+  GetPlayer()->Initialize(sink_);
 
   if (!GetPlayer()->IsPrepared()) {
     SetStreamInfo();
index fbb96a8..3e03aae 100644 (file)
@@ -91,6 +91,13 @@ class CONTENT_EXPORT TizenRendererImpl
   void OnDurationChange(base::TimeDelta duration);
   void OnBufferUpdate(base::TimeDelta time);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) final;
+  void SetMediaGeometry(const gfx::RectF& rect) final;
+
+  gfx::Rect GetViewportRect() const;
+#endif
+
   void OnNewFrameAvailable(uint32_t playerId,
                            base::UnsafeSharedMemoryRegion frame,
                            uint32_t size,
@@ -121,6 +128,10 @@ class CONTENT_EXPORT TizenRendererImpl
 
   void SetStreamInfo();
   void SetPlayerVolume();
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetPlayerVideoHole();
+  void SetPlayerMediaGeometry();
+#endif
   void OnRendererEnded();
   void OnError(media::PipelineStatus error);
   void OnStatisticsUpdate(const media::PipelineStatistics& stats);
@@ -181,6 +192,12 @@ class CONTENT_EXPORT TizenRendererImpl
   // Indicates if a serious error has been encountered by the |media_player_|.
   bool has_error_ = false;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  WebContents* web_contents_;
+  bool is_video_hole_ = false;
+  gfx::RectF video_rect_;
+#endif
+
   base::WeakPtrFactory<TizenRendererImpl> weak_factory_{this};
 };
 
index 0ae0b6c..9cc558b 100644 (file)
@@ -59,6 +59,17 @@ void MediaPlayerRendererClient::Initialize(
                      weak_factory_.GetWeakPtr()));
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void MediaPlayerRendererClient::SetVideoHole(bool is_video_hole) {
+  is_video_hole_ = is_video_hole;
+  MojoRendererWrapper::SetVideoHole(is_video_hole);
+}
+
+void MediaPlayerRendererClient::SetMediaGeometry(const gfx::RectF& rect) {
+  MojoRendererWrapper::SetMediaGeometry(rect);
+}
+#endif
+
 void MediaPlayerRendererClient::OnRemoteRendererInitialized(
     media::PipelineStatus status) {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
index f601a44..e2933d0 100644 (file)
@@ -61,6 +61,11 @@ class CONTENT_EXPORT MediaPlayerRendererClient
                   media::RendererClient* client,
                   media::PipelineStatusCallback init_cb) override;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) override;
+  void SetMediaGeometry(const gfx::RectF& rect) override;
+#endif
+
   // media::mojom::MediaPlayerRendererClientExtension implementation
   void OnDurationChange(base::TimeDelta duration) override;
   void OnVideoSizeChange(const gfx::Size& size) override;
@@ -85,6 +90,10 @@ class CONTENT_EXPORT MediaPlayerRendererClient
  private:
   void OnRemoteRendererInitialized(media::PipelineStatus status);
 
+#if defined(TIZEN_MULTIMEDIA)
+  bool is_video_hole_ = false;
+#endif
+
   // The underlying type should always be a MediaUrlDemuxer, but we only use
   // methods from the MediaResource interface.
   media::MediaResource* media_resource_;
index f2ea9ab..3d3a2b3 100644 (file)
 #include "base/time/time.h"
 #include "media/base/efl/media_player_util_efl.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "ui/gfx/geometry/rect_f.h"
+#endif
+
 typedef struct media_packet_s* media_packet_h;
 
 namespace content {
@@ -76,6 +80,12 @@ class MEDIA_EXPORT MediaPlayerEfl {
   virtual void Resume() { suspended_ = false; }
   virtual void Suspend() { suspended_ = true; }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  virtual void SetVideoHole(bool is_video_hole) = 0;
+  virtual void SetMediaGeometry(const gfx::Rect& viewport_rect,
+                                const gfx::RectF& rect) = 0;
+#endif
+
  protected:
   explicit MediaPlayerEfl(int player_id, MediaPlayerManager* manager);
 
index c693f64..6da6d56 100644 (file)
 #include "third_party/libyuv/include/libyuv/planar_functions.h"
 #include "ui/gfx/geometry/size.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h"
+#include "tizen_src/chromium_impl/media/filters/esplusplayer_util.h"
+#endif
+
 namespace {
 
 // Update duration every 100ms.
@@ -162,12 +167,25 @@ void MediaPlayerBridgeCapi::Prepare(CompleteCB cb) {
       PLAYER_ERROR_NONE)
     LOG(ERROR) << "Unable to set streaming user agent.";
 
-  ret = player_set_media_packet_video_frame_decoded_cb(
-      player_, MediaPacketDecodedCb, this);
-  if (ret != PLAYER_ERROR_NONE) {
-    OnHandlePlayerError(ret, FROM_HERE);
-    RunCompleteCB(false, FROM_HERE);
-    return;
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_) {
+    ret = player_set_display(player_, PLAYER_DISPLAY_TYPE_OVERLAY,
+                             video_plane_controller_->GetVideoPlaneHandle());
+    if (ret != PLAYER_ERROR_NONE) {
+      OnHandlePlayerError(ret, FROM_HERE);
+      RunCompleteCB(false, FROM_HERE);
+      return;
+    }
+  } else
+#endif
+  {
+    ret = player_set_media_packet_video_frame_decoded_cb(
+        player_, MediaPacketDecodedCb, this);
+    if (ret != PLAYER_ERROR_NONE) {
+      OnHandlePlayerError(ret, FROM_HERE);
+      RunCompleteCB(false, FROM_HERE);
+      return;
+    }
   }
 
   player_set_completed_cb(player_, PlaybackCompleteCb, this);
@@ -194,6 +212,19 @@ void MediaPlayerBridgeCapi::OnMediaError(MediaError error_type) {
 }
 
 void MediaPlayerBridgeCapi::Initialize() {
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_) {
+    if (!video_plane_controller_)
+      return;
+
+    int ret = video_plane_controller_->Initialize();
+    if (ret != PLAYER_ERROR_NONE) {
+      OnHandlePlayerError(ret, FROM_HERE);
+      return;
+    }
+  }
+#endif
+
   Prepare(base::BindOnce(&MediaPlayerBridgeCapi::OnInitComplete,
                          weak_factory_.GetWeakPtr()));
 }
@@ -281,6 +312,14 @@ void MediaPlayerBridgeCapi::Play() {
     return;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (!delayed_rect_.IsEmpty() && !delayed_viewport_rect_.IsEmpty()) {
+    SetMediaGeometry(delayed_viewport_rect_, delayed_rect_);
+    delayed_viewport_rect_ = gfx::Rect();
+    delayed_rect_ = gfx::RectF();
+  }
+#endif
+
   WakeUpDisplayAndAcquireDisplayLock();
 
   StartCurrentTimeUpdateTimer();
@@ -384,6 +423,32 @@ void MediaPlayerBridgeCapi::SetVolume(double volume) {
   volume_ = volume;
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void MediaPlayerBridgeCapi::SetVideoHole(bool is_video_hole) {
+  LOG(INFO) << __func__ << " is_video_hole : " << is_video_hole;
+  is_video_hole_ = is_video_hole;
+  if (is_video_hole_ && player_ && !video_plane_controller_) {
+    video_plane_controller_.reset(new VideoPlaneControllerCapi(player_));
+  }
+}
+
+void MediaPlayerBridgeCapi::SetMediaGeometry(const gfx::Rect& viewport_rect,
+                                             const gfx::RectF& rect) {
+  if (!is_video_hole_)
+    return;
+
+  if (GetPlayerState() < PLAYER_STATE_PLAYING) {
+    delayed_viewport_rect_ = viewport_rect;
+    delayed_rect_ = rect;
+    return;
+  }
+
+  LOG(INFO) << __func__ << " viewport_rect: " << viewport_rect.ToString()
+            << " rect : " << rect.ToString();
+  video_plane_controller_->SetMediaGeometry(viewport_rect, rect);
+}
+#endif
+
 void MediaPlayerBridgeCapi::UpdateMediaType() {
   int sample_rate = 0;
   int channel = 0;
@@ -542,6 +607,11 @@ void MediaPlayerBridgeCapi::PlayerPrepared() {
     return;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_)
+    video_plane_controller_->ApplyDeferredVideoRectIfNeeded();
+#endif
+
   UpdateMediaType();
   if (media_type_ == 0) {
     RunCompleteCB(true, FROM_HERE);
index dd55516..396abe9 100644 (file)
 #include "media/base/ranges.h"
 #include "media/base/video_frame.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h"
+#include "ui/gfx/geometry/rect_f.h"
+#endif
+
 namespace media {
 
 class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerEfl {
@@ -41,6 +46,12 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerEfl {
   void SetVolume(double volume) override;
   double GetCurrentTime() override;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) override;
+  void SetMediaGeometry(const gfx::Rect& viewport_rect,
+                        const gfx::RectF& rect) override;
+#endif
+
   void ExecuteDelayedPlayerState();
 
   void OnPlaybackCompleteUpdate();
@@ -109,6 +120,13 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerEfl {
 
   int media_type_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool is_video_hole_ = false;
+  gfx::Rect delayed_viewport_rect_;
+  gfx::RectF delayed_rect_;
+  std::unique_ptr<VideoPlaneController> video_plane_controller_;
+#endif
+
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<MediaPlayerBridgeCapi> weak_factory_;
 };
diff --git a/tizen_src/chromium_impl/media/base/tizen/video_plane_controller.cc b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller.cc
new file mode 100644 (file)
index 0000000..8fc2e15
--- /dev/null
@@ -0,0 +1,163 @@
+// Copyright 2016 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/tizen/video_plane_controller.h"
+
+#if defined(OS_TIZEN_TV_PRODUCT)
+#include "ui/display/device_display_info_efl.h"
+#endif
+
+namespace media {
+
+void* VideoPlaneController::main_window_handle_ = nullptr;
+VideoPlaneController::RenderingMode VideoPlaneController::rendering_mode_ =
+    VideoPlaneController::RenderingMode::OFFSCREEN;
+
+VideoPlaneController::VideoPlaneController() : should_crop_video_(false) {}
+
+VideoPlaneController::~VideoPlaneController() {}
+
+void* VideoPlaneController::GetVideoPlaneHandle() {
+  if (!main_window_handle_)
+    LOG(ERROR) << "failed: main window is null!";
+
+  return main_window_handle_;
+}
+
+gfx::RectF VideoPlaneController::SetCropRatio(
+    const gfx::Rect& viewport_rect,
+    const gfx::RectF& video_rect,
+    const absl::optional<gfx::RectF>& visible_cropratio) {
+  gfx::RectF view_rect =
+      gfx::RectF(viewport_rect.x(), viewport_rect.y(), viewport_rect.width(),
+                 viewport_rect.height());
+
+  // Offset the position of the video to fit the screen.
+  // Because of the player(MM) use the based on the
+  // screen(EFL window) coordinates, the offset this.
+  gfx::RectF screen_video_rect = video_rect;
+  screen_video_rect.Offset(view_rect.x(), view_rect.y());
+
+  gfx::RectF visible_rect = screen_video_rect;
+  visible_rect.Intersect(view_rect);
+
+  int ret = PLAYER_ERROR_NONE;
+
+  if (visible_rect.size() == screen_video_rect.size() ||
+      visible_rect.IsEmpty()) {
+    if (should_crop_video_ || (visible_cropratio != gfx::RectF{0, 0, 1, 1})) {
+      ret = PlayerSetCropRatio(
+          visible_cropratio.value_or(gfx::RectF(0, 0, 1, 1)));
+      if (ret != PLAYER_ERROR_NONE)
+        return gfx::RectF();
+    }
+    should_crop_video_ = false;
+
+    if (visible_rect.IsEmpty())
+      return gfx::RectF(view_rect.x(), view_rect.y(), 1, 1);
+    return screen_video_rect;
+  }
+
+  gfx::RectF cropratio_rect = screen_video_rect;
+  cropratio_rect.set_x(screen_video_rect.x() < visible_rect.x()
+                           ? abs(screen_video_rect.x() - visible_rect.x()) /
+                                 screen_video_rect.width()
+                           : 0.0);
+
+  cropratio_rect.set_width(
+      screen_video_rect.width() > visible_rect.width()
+          ? 1.0 - abs(screen_video_rect.width() - visible_rect.width()) /
+                      screen_video_rect.width()
+          : 1.0);
+
+  cropratio_rect.set_y(screen_video_rect.y() < visible_rect.y()
+                           ? abs(screen_video_rect.y() - visible_rect.y()) /
+                                 screen_video_rect.height()
+                           : 0.0);
+
+  cropratio_rect.set_height(
+      screen_video_rect.height() > visible_rect.height()
+          ? 1.0 - abs(screen_video_rect.height() - visible_rect.height()) /
+                      screen_video_rect.height()
+          : 1.0);
+
+  if (visible_cropratio.has_value())
+    cropratio_rect.Intersect(visible_cropratio.value());
+  ret = PlayerSetCropRatio(cropratio_rect);
+  if (ret != PLAYER_ERROR_NONE)
+    return gfx::RectF();
+
+  should_crop_video_ = true;
+
+  return visible_rect;
+}
+
+void VideoPlaneController::SetDeferredVideoRect(
+    const gfx::Rect& viewport_rect,
+    const gfx::RectF& rect,
+    const absl::optional<gfx::RectF>& visible_crop_ratio) {
+  deferred_viewport_rect_ = viewport_rect;
+  deferred_video_rect_ = rect;
+  deferred_visible_crop_ratio_ = visible_crop_ratio;
+}
+
+void VideoPlaneController::ApplyDeferredVideoRectIfNeeded() {
+  if (!deferred_video_rect_.IsEmpty() ||
+      deferred_visible_crop_ratio_.has_value()) {
+    SetMediaGeometry(deferred_viewport_rect_, deferred_video_rect_,
+                     deferred_visible_crop_ratio_, GetVideoRotation());
+    deferred_video_rect_ = gfx::RectF();
+    deferred_visible_crop_ratio_ = gfx::RectF();
+  }
+}
+
+int VideoPlaneController::SetMediaGeometry(
+    const gfx::Rect& viewport_rect,
+    const gfx::RectF& rect,
+    const absl::optional<gfx::RectF>& visible_ratio,
+    int rotation) {
+  LOG(INFO) << "VideoPlaneController::SetMediaGeometry, viewport_rect: "
+            << viewport_rect.ToString() << " rect: " << rect.ToString()
+            << " visible_ratio: "
+            << visible_ratio.value_or(gfx::RectF(0, 0, 1, 1)).ToString()
+            << " rotation: " << rotation;
+
+  video_rotation_ = rotation;
+  SetDisplayRotation();
+
+  if (rect.IsEmpty()) {
+    LOG(INFO) << "skip: rect is empty!";
+    return PLAYER_ERROR_NONE;
+  }
+
+  current_viewport_rect_ = viewport_rect;
+  current_rect_ = rect;
+  current_visible_ratio_ = visible_ratio;
+
+  if (!IsAvailableSetMediaGeometry()) {
+    LOG(INFO) << "store the video rect because of player was not ready.";
+    SetDeferredVideoRect(viewport_rect, rect, visible_ratio);
+    return PLAYER_ERROR_NONE;
+  }
+
+  LOG(INFO) << "Video_geometry (" << rect.ToString() << ")";
+
+  gfx::RectF display_rect = SetCropRatio(viewport_rect, rect, visible_ratio);
+
+  if (display_rect.IsEmpty()) {
+    LOG(INFO) << "skip: crop rect is empty!";
+    return PLAYER_ERROR_NONE;
+  }
+
+  LOG(INFO) << "Display_video_geometry(" << display_rect.ToString() << ")";
+
+  return SetVideoRect(display_rect);
+}
+
+void VideoPlaneController::ResetMediaGeometry() {
+  SetMediaGeometry(current_viewport_rect_, current_rect_,
+                   current_visible_ratio_, video_rotation_);
+}
+
+}  // namespace media
diff --git a/tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h
new file mode 100644 (file)
index 0000000..e96b1bd
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2016 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_H_
+#define MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_H_
+
+#include "base/logging.h"
+#include "media/base/media_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace media {
+
+class MediaPlayerESPlusPlayer;
+
+class MEDIA_EXPORT VideoPlaneController {
+ public:
+  enum class RenderingMode { OFFSCREEN, ONSCREEN };
+  enum PlayerError { PLAYER_ERROR_NONE, PLAYER_ERROR_INVALID_OPERATION };
+
+  static void SetSharedVideoWindowHandle(void* handle,
+                                         RenderingMode rendering_mode) {
+    main_window_handle_ = handle;
+    rendering_mode_ = rendering_mode;
+  }
+  static RenderingMode rendering_mode() { return rendering_mode_; }
+
+  VideoPlaneController();
+  virtual ~VideoPlaneController();
+
+  virtual int Initialize() = 0;
+  void* GetVideoPlaneHandle();
+  int SetMediaGeometry(
+      const gfx::Rect& viewport_rect,
+      const gfx::RectF& rect,
+      const absl::optional<gfx::RectF>& visible_cropratio = absl::nullopt,
+      int rotation = 0);
+
+  void ApplyDeferredVideoRectIfNeeded();
+
+  void ResetMediaGeometry();
+  virtual void SetDisplayRotation(int rotation_degree) = 0;
+  virtual void SetDisplayRotation() = 0;
+
+ protected:
+  int GetVideoRotation() const { return video_rotation_; }
+
+ private:
+  static void* main_window_handle_;
+  static RenderingMode rendering_mode_;
+
+  gfx::RectF SetCropRatio(const gfx::Rect&,
+                          const gfx::RectF&,
+                          const absl::optional<gfx::RectF>& visible_crop_ratio);
+
+  // If player_prepare_async is not complete, store the video rect.
+  void SetDeferredVideoRect(const gfx::Rect&,
+                            const gfx::RectF&,
+                            const absl::optional<gfx::RectF>&);
+
+  virtual int SetVideoRect(const gfx::RectF&) = 0;
+  virtual int PlayerSetCropRatio(const gfx::RectF& rect) = 0;
+  virtual bool IsAvailableSetMediaGeometry() = 0;
+
+  bool should_crop_video_;
+  gfx::Rect deferred_viewport_rect_{};
+  gfx::RectF deferred_video_rect_{};
+  absl::optional<gfx::RectF> deferred_visible_crop_ratio_{};
+  gfx::Rect current_viewport_rect_;
+  gfx::RectF current_rect_;
+  absl::optional<gfx::RectF> current_visible_ratio_;
+  int video_rotation_{0};
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_H_
diff --git a/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.cc b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.cc
new file mode 100644 (file)
index 0000000..ec0a699
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright 2016 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/tizen/video_plane_controller_capi.h"
+
+#include <Evas.h>
+
+#include "base/logging.h"
+#include "media/base/efl/media_player_util_efl.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+
+#if defined(OS_TIZEN_TV_PRODUCT)
+#include <player_product.h>
+#endif
+
+namespace media {
+
+VideoPlaneControllerCapi::VideoPlaneControllerCapi(player_h player)
+    : player_handle_(player) {}
+
+VideoPlaneControllerCapi::~VideoPlaneControllerCapi() {}
+
+int VideoPlaneControllerCapi::Initialize() {
+  int ret = PLAYER_ERROR_NONE;
+#if defined(OS_TIZEN_TV_PRODUCT)
+  ret = player_set_display_mode(player_handle_, PLAYER_DISPLAY_MODE_DST_ROI);
+
+  if (ret != PLAYER_ERROR_NONE)
+    return ret;
+
+  // init video size
+  gfx::RectF init_rect(0.0f, 0.0f, 1.0f, 1.0f);
+  ret = SetVideoRect(init_rect);
+#endif
+
+  return ret;
+}
+
+int VideoPlaneControllerCapi::SetVideoRect(const gfx::RectF& rect) {
+  int ret = PLAYER_ERROR_NONE;
+#if defined(OS_TIZEN_TV_PRODUCT)
+  ret = player_set_display_roi_area(player_handle_, rect.x(), rect.y(),
+                                    rect.width(), rect.height());
+#endif
+  return ret;
+}
+
+int VideoPlaneControllerCapi::PlayerSetCropRatio(const gfx::RectF& rect) {
+  int ret = PLAYER_ERROR_NONE;
+#if defined(OS_TIZEN_TV_PRODUCT)
+  LOG(INFO) << "crop_ratio : (" << rect.x() << ", " << rect.y() << ", "
+            << rect.width() << ", " << rect.height() << ")";
+
+  ret = player_set_crop_ratio(player_handle_, rect.x(), rect.y(), rect.width(),
+                              rect.height());
+#endif
+  return ret;
+}
+
+player_state_e VideoPlaneControllerCapi::GetPlayerState() {
+  player_state_e state = PLAYER_STATE_NONE;
+  player_get_state(player_handle_, &state);
+  return state;
+}
+
+bool VideoPlaneControllerCapi::IsAvailableSetMediaGeometry() {
+  return (GetPlayerState() >= PLAYER_STATE_READY);
+}
+
+void VideoPlaneControllerCapi::SetDisplayRotation(int rotation_degree) {
+  player_display_rotation_e screen_rotation =
+      ConvertToPlayerDisplayRotation(rotation_degree);
+  player_display_rotation_e rotation = PLAYER_DISPLAY_ROTATION_NONE;
+  int ret = player_get_display_rotation(player_handle_, &rotation);
+  if (ret == PLAYER_ERROR_NONE && screen_rotation != rotation) {
+    LOG(INFO) << "video should rotate angle : " << screen_rotation;
+    ret = player_set_display_rotation(player_handle_, screen_rotation);
+    if (ret != PLAYER_ERROR_NONE) {
+      LOG(ERROR) << "Cannot set display rotation : "
+                 << GetErrorString(static_cast<player_error_e>(ret));
+    }
+  }
+}
+
+void VideoPlaneControllerCapi::SetDisplayRotation() {
+  int rotation =
+      display::Screen::GetScreen()->GetPrimaryDisplay().RotationAsDegree();
+  SetDisplayRotation(rotation);
+}
+
+player_display_rotation_e
+VideoPlaneControllerCapi::ConvertToPlayerDisplayRotation(int rotation) {
+  switch (rotation) {
+#if defined(OS_TIZEN_TV_PRODUCT)
+    case 90:
+      return PLAYER_DISPLAY_ROTATION_270;
+    case 180:
+      return PLAYER_DISPLAY_ROTATION_180;
+    case 270:
+      return PLAYER_DISPLAY_ROTATION_90;
+#else
+    case 90:
+      return PLAYER_DISPLAY_ROTATION_90;
+    case 180:
+      return PLAYER_DISPLAY_ROTATION_180;
+    case 270:
+      return PLAYER_DISPLAY_ROTATION_270;
+#endif
+    default:
+      return PLAYER_DISPLAY_ROTATION_NONE;
+  }
+}
+
+}  // namespace media
diff --git a/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h
new file mode 100644 (file)
index 0000000..fbc46a3
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_CAPI_H_
+#define MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_CAPI_H_
+
+#include <player.h>
+
+#include "media/base/tizen/video_plane_controller.h"
+
+namespace media {
+
+class MEDIA_EXPORT VideoPlaneControllerCapi : public VideoPlaneController {
+ public:
+  VideoPlaneControllerCapi(player_h player);
+
+  ~VideoPlaneControllerCapi() override;
+
+  int Initialize() override;
+  void SetDisplayRotation(int) override;
+  void SetDisplayRotation() override;
+
+ private:
+  player_state_e GetPlayerState();
+  int SetVideoRect(const gfx::RectF&) override;
+  int PlayerSetCropRatio(const gfx::RectF& rect) override;
+  bool IsAvailableSetMediaGeometry() override;
+
+  player_display_rotation_e ConvertToPlayerDisplayRotation(int rotation);
+
+  player_h player_handle_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_CAPI_H_
diff --git a/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.cc b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.cc
new file mode 100644 (file)
index 0000000..f6ce55f
--- /dev/null
@@ -0,0 +1,97 @@
+// Copyright 2019 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/tizen/video_plane_controller_esplusplayer.h"
+
+#include <Evas.h>
+#include <drm.h>
+#include <esplusplayer_capi.h>
+#include <esplusplayer_internal.h>
+
+#include "base/logging.h"
+#include "tizen_src/chromium_impl/media/filters/esplusplayer_util.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+
+namespace media {
+
+VideoPlaneControllerESPlusPlayer::VideoPlaneControllerESPlusPlayer(
+    void* esplayer_handle)
+    : player_handle_(esplayer_handle) {}
+
+VideoPlaneControllerESPlusPlayer::~VideoPlaneControllerESPlusPlayer() {}
+
+int VideoPlaneControllerESPlusPlayer::Initialize() {
+  int player_error = esplusplayer_set_display_mode(
+      player_handle_, ESPLUSPLAYER_DISPLAY_MODE_DST_ROI);
+  if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+    LOG(ERROR) << "esplusplayer_set_display_mode failed! error code "
+               << player_error;
+
+    return player_error;
+  }
+
+  // init video size
+  gfx::RectF init_rect(0.0f, 0.0f, 1.0f, 1.0f);
+  return SetVideoRect(init_rect);
+}
+
+int VideoPlaneControllerESPlusPlayer::SetVideoRect(const gfx::RectF& rect) {
+  LOG(INFO) << __func__ << " rect:" << rect.ToString();
+  int player_error = esplusplayer_set_display_roi(
+      player_handle_, rect.x(), rect.y(), rect.width(), rect.height());
+  if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+    LOG(ERROR) << "esplusplayer_set_display_roi failed! error code "
+               << player_error;
+  }
+  return player_error;
+}
+
+int VideoPlaneControllerESPlusPlayer::PlayerSetCropRatio(
+    const gfx::RectF& rect) {
+  LOG(INFO) << "crop_ratio : (" << rect.x() << ", " << rect.y() << ", "
+            << rect.width() << ", " << rect.height() << ")";
+
+  int player_error = esplusplayer_set_video_roi(
+      player_handle_, rect.x(), rect.y(), rect.width(), rect.height());
+  if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+    LOG(ERROR) << "esplusplayer_set_display_roi failed! error code "
+               << player_error;
+  }
+  return player_error;
+}
+
+esplusplayer_state VideoPlaneControllerESPlusPlayer::GetPlayerState() {
+  return esplusplayer_get_state(player_handle_);
+}
+
+bool VideoPlaneControllerESPlusPlayer::IsAvailableSetMediaGeometry() {
+  return (GetPlayerState() >= ESPLUSPLAYER_STATE_READY);
+}
+
+void VideoPlaneControllerESPlusPlayer::SetDisplayRotation(int rotation_degree) {
+  esplusplayer_display_rotation_type screen_rotation =
+      ConvertToESPlusPlayerDisplayRotation(rotation_degree);
+
+  esplusplayer_display_rotation_type rotation;
+  int player_error =
+      esplusplayer_get_display_rotation(player_handle_, &rotation);
+  if (player_error == ESPLUSPLAYER_ERROR_TYPE_NONE &&
+      screen_rotation != rotation) {
+    LOG(INFO) << "video should rotate angle : " << screen_rotation;
+
+    player_error =
+        esplusplayer_set_display_rotation(player_handle_, screen_rotation);
+    if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+      LOG(ERROR) << "Cannot set display rotation. error code " << player_error;
+    }
+  }
+}
+
+void VideoPlaneControllerESPlusPlayer::SetDisplayRotation() {
+  int display_rotation =
+      display::Screen::GetScreen()->GetPrimaryDisplay().RotationAsDegree();
+  SetDisplayRotation((display_rotation + GetVideoRotation()) % 360);
+}
+}  // namespace media
diff --git a/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h
new file mode 100644 (file)
index 0000000..e141abc
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2019 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_ESPLUSPLAYER_H_
+#define MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_ESPLUSPLAYER_H_
+
+#include <esplusplayer_capi/esplusplayer_capi.h>
+#include <esplusplayer_capi/esplusplayer_internal.h>
+
+#include "media/base/tizen/video_plane_controller.h"
+
+namespace media {
+
+class MEDIA_EXPORT VideoPlaneControllerESPlusPlayer
+    : public VideoPlaneController {
+ public:
+  VideoPlaneControllerESPlusPlayer(void* esplayer_handle);
+
+  ~VideoPlaneControllerESPlusPlayer() override;
+
+  int Initialize() override;
+  void SetDisplayRotation(int) override;
+  void SetDisplayRotation() override;
+
+ private:
+  esplusplayer_state GetPlayerState();
+  int SetVideoRect(const gfx::RectF&) override;
+  int PlayerSetCropRatio(const gfx::RectF& rect) override;
+  bool IsAvailableSetMediaGeometry() override;
+
+  esplusplayer_handle player_handle_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_TIZEN_VIDEO_PLANE_CONTROLLER_ESPLUSPLAYER_H_
index 531e06f..c36a37c 100644 (file)
@@ -176,7 +176,8 @@ PipelineStatus GetPipelineError(const esplusplayer_error_type error) {
   return PIPELINE_ERROR_DECODE;
 }
 
-gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type) {
+gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type,
+                                bool is_video_hole) {
   switch (mime_type) {
     case ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1:
       return {k8KVideoMaxWidth, k8KVideoMaxHeight};
@@ -186,11 +187,28 @@ gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type) {
     case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
       return {k8KVideoMaxWidth, k8KVideoMaxHeight};
     case ESPLUSPLAYER_VIDEO_MIME_TYPE_H264:
-      return {kFHDVideoMaxWidth, kFHDVideoMaxHeight};
+      if (is_video_hole)
+        return {k4KVideoMaxWidth, k4KVideoMaxHeight};
+      else
+        return {kFHDVideoMaxWidth, kFHDVideoMaxHeight};
     default:
       // for all kind of codecs.
       return {kFHDVideoMaxWidth, kFHDVideoMaxHeight};
   }
 }
 
+esplusplayer_display_rotation_type ConvertToESPlusPlayerDisplayRotation(
+    int rotation) {
+  switch (rotation) {
+    case 90:
+      return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_270;
+    case 180:
+      return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_180;
+    case 270:
+      return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_90;
+    default:
+      return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_NONE;
+  }
+}
+
 }  // namespace media
index aba62d7..f610363 100644 (file)
@@ -14,7 +14,6 @@
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
-
 const int kElementryStreamCount = 2;  // Audio, Video only.
 
 const int kVideoFramerateDen = 100;
@@ -45,7 +44,11 @@ esplusplayer_stream_type GetESPlusPlayerStreamType(DemuxerStream::Type type);
 
 PipelineStatus GetPipelineError(const esplusplayer_error_type error);
 
-gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type);
+gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type,
+                                bool is_video_hole);
+
+esplusplayer_display_rotation_type ConvertToESPlusPlayerDisplayRotation(
+    int rotation);
 
 }  // namespace media
 
index 45e9b99..a4aa284 100644 (file)
@@ -218,13 +218,13 @@ void MediaPlayerBridgeCapiAdapter::OnNewFrameAvailable(
 
 #if defined(TIZEN_VIDEO_HOLE)
 void MediaPlayerBridgeCapiAdapter::SetVideoHole(bool is_video_hole) {
-  NOTIMPLEMENTED();
+  media_player_->SetVideoHole(is_video_hole);
 }
 
 void MediaPlayerBridgeCapiAdapter::SetMediaGeometry(
     const gfx::Rect& viewport_rect,
     const gfx::RectF& rect) {
-  NOTIMPLEMENTED();
+  media_player_->SetMediaGeometry(viewport_rect, rect);
 }
 #endif
 
index 077a93d..c2084bb 100644 (file)
 #include "third_party/libyuv/include/libyuv/convert.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include <Ecore_Wl2.h>
+#include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h"
+#endif
+
 namespace media {
 using player_buffer_size_t = unsigned long long;
 
@@ -154,6 +159,14 @@ bool MediaPlayerESPlusPlayer::CreatePlayer() {
 
   buffer_observer_.reset(BufferObserver::CreateBufferObserver());
 
+#if defined(TIZEN_VIDEO_HOLE)
+  LOG(INFO) << __func__ << " is_video_hole_: " << is_video_hole_;
+  if (is_video_hole_) {
+    video_plane_controller_.reset(
+        new VideoPlaneControllerESPlusPlayer(esplayer_));
+  }
+#endif
+
   return true;
 }
 
@@ -191,6 +204,10 @@ void MediaPlayerESPlusPlayer::Initialize(VideoRendererSink* sink) {
 
   esplusplayer_decoded_video_frame_buffer_type video_frame_buffer_type =
       ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_COPY;
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_)
+    video_frame_buffer_type = ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_NONE;
+#endif
 
   error = esplusplayer_set_video_frame_buffer_type(esplayer_,
                                                    video_frame_buffer_type);
@@ -244,6 +261,41 @@ void MediaPlayerESPlusPlayer::Prepare() {
     return;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_ && video_plane_controller_) {
+    if (video_plane_controller_->Initialize() != TIZEN_ERROR_NONE) {
+      LOG(ERROR) << "video_plane_controller init error";
+      return;
+    }
+    LOG(INFO) << __func__ << " set ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY";
+    int player_error = ESPLUSPLAYER_ERROR_TYPE_NONE;
+    if (video_plane_controller_->rendering_mode() ==
+        VideoPlaneController::RenderingMode::OFFSCREEN) {
+      player_error = esplusplayer_set_display(
+          esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
+          video_plane_controller_->GetVideoPlaneHandle());
+    } else {
+      int wl_w, wl_h, wl_x, wl_y;
+      ecore_wl2_window_geometry_get(
+          static_cast<Ecore_Wl2_Window*>(
+              video_plane_controller_->GetVideoPlaneHandle()),
+          &wl_x, &wl_y, &wl_w, &wl_h);
+
+      player_error = esplusplayer_set_ecore_display(
+          esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
+          static_cast<Ecore_Wl2_Window*>(
+              video_plane_controller_->GetVideoPlaneHandle()),
+          wl_x, wl_y, wl_w, wl_h);
+    }
+    if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+      LOG(ERROR) << "player_error #"
+                 << esplusplayer_get_error_string(
+                        static_cast<esplusplayer_error_type>(player_error));
+      return;
+    }
+  }
+#endif
+
   int error = esplusplayer_prepare_async(esplayer_);
   if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
     LOG(ERROR) << "player prepare failed! error #"
@@ -614,7 +666,8 @@ void MediaPlayerESPlusPlayer::InitializeStreamConfig(DemuxerStream::Type type) {
     } else {
       video_stream_info.codec_data = NULL;
     }
-    auto max_resolution = GetMaxCodecResolution(video_stream_info.mime_type);
+    auto max_resolution =
+        GetMaxCodecResolution(video_stream_info.mime_type, is_video_hole_);
 
     video_stream_info.max_width = max_resolution.width();
     video_stream_info.max_height = max_resolution.height();
@@ -881,6 +934,11 @@ void MediaPlayerESPlusPlayer::OnPrepareComplete(bool result) {
             << " pending_seek_ : " << pending_seek_
             << " pending_seek_position_ : " << pending_seek_position_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (is_video_hole_)
+    video_plane_controller_->ResetMediaGeometry();
+#endif
+
   is_prepared_ = true;
   if (pending_seek_) {
     Seek(pending_seek_position_);
@@ -1190,4 +1248,29 @@ void MediaPlayerESPlusPlayer::SetFrameAvailableCallback(
   data_cb_ = datacb;
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void MediaPlayerESPlusPlayer::SetVideoHole(bool is_video_hole) {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
+            << " is_video_hole : " << is_video_hole;
+  is_video_hole_ = is_video_hole;
+  if (is_video_hole_ && esplayer_ && !video_plane_controller_) {
+    LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
+              << " pended set video_plane_controller";
+    video_plane_controller_.reset(
+        new VideoPlaneControllerESPlusPlayer(esplayer_));
+  }
+}
+
+void MediaPlayerESPlusPlayer::SetMediaGeometry(const gfx::Rect& viewport_rect,
+                                               const gfx::RectF& rect) {
+  if (!is_video_hole_)
+    return;
+
+  LOG(INFO) << __func__ << " viewport_rect: " << viewport_rect.ToString()
+            << " rect : " << rect.ToString();
+  video_plane_controller_->SetMediaGeometry(viewport_rect, rect);
+}
+
+#endif
+
 }  // namespace media
index 3992847..72e0f6d 100644 (file)
 #include "tizen_src/chromium_impl/media/filters/esplusplayer_util.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_tizen.h"
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h"
+#include "ui/gfx/geometry/rect_f.h"
+#endif
+
 namespace media {
 
 class DemuxerStream;
 class RendererClient;
+class VideoPlaneController;
 
 using Queue = base::circular_deque<scoped_refptr<DecoderBuffer>>;
 
@@ -70,6 +76,11 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
   base::TimeDelta GetCurrentTime() override;
 
   void SetFrameAvailableCallback(const DataRequestCB& datacb) override;
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHole(bool is_video_hole) override;
+  void SetMediaGeometry(const gfx::Rect& viewport_rect,
+                        const gfx::RectF& rect) override;
+#endif
 
 #if defined(TIZEN_TBM_SUPPORT)
   void DestroyMediaPacket(void* media_packet) override;
@@ -166,6 +177,12 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
 
   bool should_set_playback_rate_ = false;
 
+  bool is_video_hole_ = false;
+#if defined(TIZEN_VIDEO_HOLE)
+  gfx::Rect viewport_rect_;
+  std::unique_ptr<VideoPlaneController> video_plane_controller_;
+#endif
+
   base::OnceClosure flush_cb_;
 
   int player_id_ = 0;
index 7edc247..8227060 100644 (file)
@@ -20,12 +20,12 @@ if (use_ozone) {
 if (tizen_multimedia_support) {
   external_media_efl_deps += [
     "//tizen_src/build:capi-media-audio-io",
-    "//tizen_src/build:libcapi-media-audio-io",
     "//tizen_src/build:capi-media-camera",
-    "//tizen_src/build:libcapi-media-camera",
     "//tizen_src/build:capi-media-player",
-    "//tizen_src/build:libcapi-media-player",
     "//tizen_src/build:ecore",
+    "//tizen_src/build:libcapi-media-audio-io",
+    "//tizen_src/build:libcapi-media-camera",
+    "//tizen_src/build:libcapi-media-player",
     "//tizen_src/build:libecore",
     "//tizen_src/build:mm_player",
   ]
@@ -96,6 +96,13 @@ if (tizen_multimedia) {
     "//tizen_src/chromium_impl/media:media_efl_config",
   ]
 
+  if (use_wayland) {
+    external_media_video_decode_config += [
+      "//tizen_src/build:ecore-wayland",
+      "//tizen_src/build:libecore-wayland",
+    ]
+  }
+
   external_media_video_decode_sources += [
     "//tizen_src/chromium_impl/media/filters/esplusplayer_buffer_observer.h",
     "//tizen_src/chromium_impl/media/filters/esplusplayer_buffer_observer_impl.cc",
@@ -128,6 +135,17 @@ if (tizen_multimedia) {
     "//tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.cc",
     "//tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h",
   ]
+
+  if (tizen_video_hole) {
+    external_media_video_decode_sources += [
+      "//tizen_src/chromium_impl/media/base/tizen/video_plane_controller.cc",
+      "//tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h",
+      "//tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.cc",
+      "//tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h",
+      "//tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.cc",
+      "//tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h",
+    ]
+  }
 }
 
 if (tizen_audio_io) {
index 3b357f1..4b94f31 100644 (file)
 #include <cursor_module.h>
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+#include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h"
+#endif
+
 namespace ui {
 
 #if BUILDFLAG(IS_TIZEN_TV)
@@ -49,6 +53,11 @@ EflWindow::~EflWindow() {
 #endif
   if (ee_)
     ecore_evas_free(ee_);
+
+#if defined(TIZEN_VIDEO_HOLE)
+  media::VideoPlaneController::SetSharedVideoWindowHandle(
+      nullptr, media::VideoPlaneController::RenderingMode::ONSCREEN);
+#endif
 }
 
 void EflWindow::Show(bool inactive) {
@@ -276,6 +285,12 @@ void EflWindow::Initialize(const PlatformWindowInitProperties& properties) {
     return;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  // Hand a window handle to enable video hole in OnscreenRendering mode.
+  media::VideoPlaneController::SetSharedVideoWindowHandle(
+      ww, media::VideoPlaneController::RenderingMode::ONSCREEN);
+#endif
+
   void* egl_window = ecore_wl2_egl_window_native_get(wl2_egl_window_);
   if (!egl_window) {
     LOG(ERROR) << "Failed to get native egl window";
index 2c57cee..0d397e1 100644 (file)
@@ -214,6 +214,10 @@ IPC_MESSAGE_ROUTED2(EwkHostMsg_WebAppCapableGet,
                     bool, /* capable */
                     int /* calback id */)
 
+#if defined(TIZEN_VIDEO_HOLE)
+IPC_MESSAGE_ROUTED1(EwkViewMsg_SetVideoHole, bool /* Enable */)
+#endif
+
 IPC_SYNC_MESSAGE_CONTROL1_1(EwkHostMsg_DecideNavigationPolicy,
                             NavigationPolicyParams,
                             bool /*handled*/)
index 10b9ff8..81d92fe 100644 (file)
@@ -1697,6 +1697,13 @@ void EWebView::RenderViewReady() {
         base::BindRepeating(&EWebView::OnFocusOut, base::Unretained(this)));
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (rwhva() && pending_video_hole_setting_) {
+    rwhva()->host()->SetVideoHoleForRender(pending_video_hole_setting_);
+    pending_video_hole_setting_ = false;
+  }
+#endif
+
   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
 
   SendDelayedMessages(render_view_host);
@@ -2631,6 +2638,18 @@ void EWebView::UrlRequestSet(
   web_contents_->GetController().LoadURLWithParams(params);
 }
 
+#if defined(TIZEN_VIDEO_HOLE)
+void EWebView::SetVideoHoleSupport(bool enable) {
+  if (!web_contents_->GetPrimaryMainFrame() ||
+      !web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() || !rwhva()) {
+    pending_video_hole_setting_ = enable;
+    return;
+  }
+
+  rwhva()->host()->SetVideoHoleForRender(enable);
+}
+#endif
+
 bool EWebView::HandleShow() {
   if (!native_view_)
     return false;
@@ -2651,6 +2670,12 @@ bool EWebView::HandleMove(int x, int y) {
   if (!native_view_)
     return false;
   evas_object_move(native_view_, x, y);
+
+#if defined(TIZEN_VIDEO_HOLE) && !defined(EWK_BRINGUP)
+  if (rwhva())
+    rwhva()->offscreen_helper()->DidMoveWebView();
+#endif
+
   return true;
 }
 
index 0fd0d14..bcf8a89 100644 (file)
@@ -619,6 +619,10 @@ class EWebView {
                                                   int64_t current_quota);
   void ExceededIndexedDatabaseQuotaReply(bool allow);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetVideoHoleSupport(bool enable);
+#endif
+
   /// ---- Event handling
   bool HandleShow();
   bool HandleHide();
@@ -867,6 +871,9 @@ class EWebView {
   std::unique_ptr<EWebAccessibility> eweb_accessibility_;
   bool lazy_initialize_atk_ = false;
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+  bool pending_video_hole_setting_ = false;
+#endif
 };
 
 const unsigned int g_default_tilt_motion_sensitivity = 3;
index 482c88e..de2255c 100644 (file)
@@ -53,6 +53,9 @@
 #if defined(TIZEN_WEB_SPEECH_RECOGNITION)
 #include "content/browser/speech/tts_platform_impl_tizen.h"
 #endif
+#if defined(TIZEN_VIDEO_HOLE)
+#include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h"
+#endif
 
 static Eina_Bool _ewk_view_default_user_media_permission(
     Evas_Object*, Ewk_User_Media_Permission_Request*, void*);
@@ -1419,7 +1422,17 @@ void ewk_view_clear_all_tiles_resources(Evas_Object* ewkView) {
 
 Eina_Bool ewk_view_set_support_video_hole(Evas_Object* ewkView, Evas_Object* window, Eina_Bool enable, Eina_Bool isVideoWindow) {
   LOG_EWK_API_MOCKUP();
-  return false;
+#if defined(TIZEN_VIDEO_HOLE)
+  EWK_VIEW_IMPL_GET_OR_RETURN(ewkView, impl, EINA_FALSE);
+  impl->SetVideoHoleSupport(enable);
+  media::VideoPlaneController::SetSharedVideoWindowHandle(
+      window,
+      static_cast<media::VideoPlaneController::RenderingMode>(isVideoWindow));
+  return EINA_TRUE;
+#else
+  LOG_EWK_API_MOCKUP("Video Hole feature is not enabled");
+  return EINA_FALSE;
+#endif
 }
 
 void ewk_view_widget_pepper_extension_callback_set(Evas_Object* ewk_view, Generic_Sync_Call_Callback cb, void* user_data) {
index d637a51..77e8c36 100644 (file)
@@ -752,6 +752,28 @@ EXPORT_API void ewk_view_request_manifest(Evas_Object* o, Ewk_View_Request_Manif
 * @}
 */
 
+#if defined(TIZEN_VIDEO_HOLE)
+/**
+ * @brief Sets the support of video hole and video window, Use H/W overlay for
+ * performance of video output
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] o the view object
+ * @param[in] o the top-level window object
+ * @param[in] enable EINA_TRUE to set on support the video hole,
+ *            EINA_FALSE otherwise
+ * @param[in] enable EINA_TRUE to set on the video window of video hole,
+ *            EINA_FALSE to set on the video windowless of video hole
+ *
+ * @return return @c EINA_TRUE on success or @c EINA_FALSE on failure
+ */
+EXPORT_API Eina_Bool ewk_view_set_support_video_hole(Evas_Object* ewkView,
+                                                     Evas_Object* window,
+                                                     Eina_Bool enable,
+                                                     Eina_Bool isVideoWindow);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index b19985e..8a8cb87 100644 (file)
@@ -74,6 +74,9 @@ Browser::Browser(bool desktop,
       tracing_enabled_(false),
       user_agent_(ua),
       tizen_version_(tizen_version),
+#if defined(TIZEN_VIDEO_HOLE)
+      video_hole_(false),
+#endif
 #if BUILDFLAG(IS_TIZEN)
       haptic_timer_id_(nullptr),
       haptic_handle_(nullptr),
index 4247e72..45eeda8 100644 (file)
@@ -51,6 +51,11 @@ class Browser {
   void OnWindowLoadStarted(Window::IdType id);
   void OnWindowLoadFinished(Window::IdType id);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  void SetEnableVideoHole(bool enable) { video_hole_ = enable; }
+  bool IsVideoHoleEnabled() const { return video_hole_; }
+#endif
+
   void Exit() const;
   void SetDefaultZoomFactor(double zoom);
   double DefaultZoomFactor();
@@ -91,6 +96,9 @@ class Browser {
   std::string user_agent_;
   std::string tizen_version_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool video_hole_;
+#endif
 #if BUILDFLAG(IS_TIZEN)
   Ecore_Timer* haptic_timer_id_;
   haptic_device_h haptic_handle_;
index 0c598c6..9ac8c55 100644 (file)
@@ -43,6 +43,10 @@ int desktop_mode = 0;
 int desktop_mode = 1;
 #endif
 
+#if defined(TIZEN_VIDEO_HOLE)
+int video_hw_overlay = 0;
+#endif
+
 struct AppData {
   AppData() : browser(nullptr), ewk_initialized(false) { }
 
@@ -58,6 +62,9 @@ void show_help_and_exit(const char* app_name) {
   printf("  -n, --no-color   Don't use colors in application logs\n");
   printf("  -d, --desktop    Run application UI in desktop mode\n");
   printf("  -m, --mobile     Run application UI in mobile mode\n");
+#if defined(TIZEN_VIDEO_HOLE)
+  printf("  -o, --overlay   Enable the H/W overlay of video\n");
+#endif
   printf("  -u, --user-agent Set user agent string\n");
   printf("  -l, --gui-level  Run application different GUI elements\n");
   printf("        0 - no GUI\n");
@@ -110,10 +117,17 @@ void parse_options(int argc, char** argv, AppData* data) {
         {"zoom", required_argument, 0, 'z'},
         {"help", no_argument, &show_help, 1},
         {"tizen-version", required_argument, 0, 't'},
+#if defined(TIZEN_VIDEO_HOLE)
+        {"overlay", no_argument, &video_hw_overlay, 1},
+#endif
         {0, 0, 0, 0}};
 
     int option_index = 0;
+#if defined(TIZEN_VIDEO_HOLE)
+    c = getopt_long(argc, argv, "vndmhou:l:z:t:", long_options, &option_index);
+#else
     c = getopt_long(argc, argv, "vndmhu:l:z:t:", long_options, &option_index);
+#endif
 
     if (c == -1)
       break;
@@ -148,6 +162,11 @@ void parse_options(int argc, char** argv, AppData* data) {
     case 't':
         tizen_version = optarg;
         break;
+#if defined(TIZEN_VIDEO_HOLE)
+    case 'o':
+        video_hw_overlay = 1;
+        break;
+#endif
     default:
       // Ignore EFL or chromium specific options,
       // ewk_set_arguments should handle them
@@ -178,6 +197,12 @@ static bool app_create(void* data) {
       new Browser(desktop_mode, gui_level, user_agent, tizen_version);
   if (zoom_factor > 0)
     app_data->browser->SetDefaultZoomFactor(zoom_factor);
+
+#if defined(TIZEN_VIDEO_HOLE)
+  if (video_hw_overlay)
+    app_data->browser->SetEnableVideoHole(true);
+#endif
+
   std::vector<std::string>::iterator it = app_data->urls.begin();
   for (;it != app_data->urls.end(); ++it)
     app_data->browser->CreateWindow().LoadURL(*it);
index 6dae22b..56ad89b 100644 (file)
@@ -103,6 +103,11 @@ Window::Window(Browser& browser, int width, int height, bool incognito)
   else
     web_view_ = ewk_view_add(evas);
 
+#if defined(TIZEN_VIDEO_HOLE)
+  if (browser.IsVideoHoleEnabled())
+    ewk_view_set_support_video_hole(web_view_, window_, EINA_TRUE, EINA_FALSE);
+#endif
+
   evas_object_resize(web_view_, width, height);
   elm_object_part_content_set(web_view_elm_host_, "overlay", web_view_);