From: Venugopal S M Date: Thu, 19 Jan 2023 13:45:46 +0000 (+0530) Subject: [M108 Migration] Enable video hole feature X-Git-Tag: submit/tizen/20230227.160252~68 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c65a73d10638773d9a7406b4f24f978a8c368ee3;p=platform%2Fframework%2Fweb%2Fchromium-efl.git [M108 Migration] Enable video hole feature - 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 --- diff --git a/cc/layers/video_frame_provider.h b/cc/layers/video_frame_provider.h index f1f6f8388047..777655d84ce2 100644 --- a/cc/layers/video_frame_provider.h +++ b/cc/layers/video_frame_provider.h @@ -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; +#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() {} }; diff --git a/cc/layers/video_frame_provider_client_impl.cc b/cc/layers/video_frame_provider_client_impl.cc index 1b10337ce13f..d9c5e9643ba5 100644 --- a/cc/layers/video_frame_provider_client_impl.cc +++ b/cc/layers/video_frame_provider_client_impl.cc @@ -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(); diff --git a/cc/layers/video_frame_provider_client_impl.h b/cc/layers/video_frame_provider_client_impl.h index e07ada90d58d..b30c35e3f7b8 100644 --- a/cc/layers/video_frame_provider_client_impl.h +++ b/cc/layers/video_frame_provider_client_impl.h @@ -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_; } diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 96080d78ca65..0d829c1b3843 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc @@ -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) { diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h index 99c89dc8ef34..9b1fa014a391 100644 --- a/cc/layers/video_layer_impl.h +++ b/cc/layers/video_layer_impl.h @@ -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 provider_client_impl_; diff --git a/components/cast_streaming/renderer/playback_command_forwarding_renderer.cc b/components/cast_streaming/renderer/playback_command_forwarding_renderer.cc index b276199faf5e..c364dfd88816 100644 --- a/components/cast_streaming/renderer/playback_command_forwarding_renderer.cc +++ b/components/cast_streaming/renderer/playback_command_forwarding_renderer.cc @@ -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 playback_controller_; diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 438113068ac6..2dcf3378e56c 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -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(); diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index fc9598a4d048..3e509d37a97f 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -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_; } diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc index 7848a794929e..b949d092338d 100644 --- a/content/renderer/media/media_factory.cc +++ b/content/renderer/media/media_factory.cc @@ -376,6 +376,9 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer( const cc::LayerTreeSettings& settings, scoped_refptr main_thread_compositor_task_runner, +#if defined(TIZEN_VIDEO_HOLE) + bool is_video_hole, +#endif scoped_refptr 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, diff --git a/content/renderer/media/media_factory.h b/content/renderer/media/media_factory.h index ff560afa084d..cacc42e9195f 100644 --- a/content/renderer/media/media_factory.h +++ b/content/renderer/media/media_factory.h @@ -106,6 +106,9 @@ class MediaFactory { const cc::LayerTreeSettings& settings, scoped_refptr main_thread_compositor_task_runner, +#if defined(TIZEN_VIDEO_HOLE) + bool is_video_hole, +#endif scoped_refptr compositor_worker_task_runner); // Provides an EncryptedMediaClient to connect blink's EME layer to media's diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index b5b806f59ebf..3593383e8620 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -3236,10 +3236,19 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer( const blink::WebString& sink_id, const cc::LayerTreeSettings& settings, scoped_refptr 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)); } diff --git a/media/base/pipeline.h b/media/base/pipeline.h index d97fb4abab3f..83a965e45bb9 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -24,6 +24,10 @@ #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; 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 diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 30159d79bdba..eef4c7b1970b 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -63,6 +63,9 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost, public: RendererWrapper(scoped_refptr media_task_runner, scoped_refptr 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& 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 media_task_runner, scoped_refptr 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 media_task_runner, scoped_refptr 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( - 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; diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 04d1fa616794..d6bfd5de8eaa 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -86,6 +86,9 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline { PipelineImpl(scoped_refptr media_task_runner, scoped_refptr 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& enabled_track_ids, diff --git a/media/base/renderer.h b/media/base/renderer.h index 8fdc6080c142..9b1d7f51f939 100644 --- a/media/base/renderer.h +++ b/media/base/renderer.h @@ -14,6 +14,10 @@ #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; diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index ef1213f5e5f2..fd0dd6965b9d 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc @@ -89,6 +89,10 @@ std::string VideoFrame::StorageTypeToString( #if defined(TIZEN_TBM_SUPPORT) 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::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::CreateHoleFrame( + const gfx::Size& natural_size) { + auto layout = VideoFrameLayout::Create(PIXEL_FORMAT_UNKNOWN, natural_size); + scoped_refptr 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); diff --git a/media/base/video_frame.h b/media/base/video_frame.h index ffeb81e954db..b856464c24bf 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h @@ -108,13 +108,17 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { // 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 { static scoped_refptr CreateTransparentFrame( const gfx::Size& size); +#if defined(TIZEN_VIDEO_HOLE) + // Allocates a hole frame. + static scoped_refptr CreateHoleFrame(const gfx::Size& size); +#endif + static size_t NumPlanes(VideoPixelFormat format); // Returns the required allocation size for a (tightly packed) frame of the diff --git a/media/filters/pipeline_controller.cc b/media/filters/pipeline_controller.cc index 62f8d171fd59..227f9d17fd3e 100644 --- a/media/filters/pipeline_controller.cc +++ b/media/filters/pipeline_controller.cc @@ -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()); diff --git a/media/filters/pipeline_controller.h b/media/filters/pipeline_controller.h index 4eff4f79b3e4..fb6cde0ef744 100644 --- a/media/filters/pipeline_controller.h +++ b/media/filters/pipeline_controller.h @@ -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(); diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc index c529abc382bf..b81b11ec984f 100644 --- a/media/mojo/clients/mojo_renderer.cc +++ b/media/mojo/clients/mojo_renderer.cc @@ -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) { diff --git a/media/mojo/clients/mojo_renderer.h b/media/mojo/clients/mojo_renderer.h index 3e98c1963a1f..acde794709ac 100644 --- a/media/mojo/clients/mojo_renderer.h +++ b/media/mojo/clients/mojo_renderer.h @@ -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, diff --git a/media/mojo/clients/mojo_renderer_wrapper.cc b/media/mojo/clients/mojo_renderer_wrapper.cc index 3fd355d6678d..f3eea4080711 100644 --- a/media/mojo/clients/mojo_renderer_wrapper.cc +++ b/media/mojo/clients/mojo_renderer_wrapper.cc @@ -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(); } diff --git a/media/mojo/clients/mojo_renderer_wrapper.h b/media/mojo/clients/mojo_renderer_wrapper.h index 743cd3fd2c29..938b5d1af917 100644 --- a/media/mojo/clients/mojo_renderer_wrapper.h +++ b/media/mojo/clients/mojo_renderer_wrapper.h @@ -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: diff --git a/media/mojo/mojom/BUILD.gn b/media/mojo/mojom/BUILD.gn index 0783af8c2ff3..a52d07f36ff6 100644 --- a/media/mojo/mojom/BUILD.gn +++ b/media/mojo/mojom/BUILD.gn @@ -124,6 +124,10 @@ mojom("mojom") { enabled_features += [ "tizen_multimedia" ] } + if (tizen_video_hole) { + enabled_features += [ "tizen_video_hole" ] + } + shared_typemaps = [ { types = [ diff --git a/media/mojo/mojom/renderer.mojom b/media/mojo/mojom/renderer.mojom index 9077053c69d6..cd2007142b92 100644 --- a/media/mojo/mojom/renderer.mojom +++ b/media/mojo/mojom/renderer.mojom @@ -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 diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 1697c7b6bff9..cdd5afc7ce49 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc @@ -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; diff --git a/media/mojo/services/mojo_renderer_service.h b/media/mojo/services/mojo_renderer_service.h index 295eebdefcf2..f78b31a1d79b 100644 --- a/media/mojo/services/mojo_renderer_service.h +++ b/media/mojo/services/mojo_renderer_service.h @@ -72,6 +72,11 @@ class MEDIA_MOJO_EXPORT MojoRendererService final : public mojom::Renderer, void SetCdm(const absl::optional& 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, diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index 9b419ca9032f..ec296e6bb326 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc @@ -56,6 +56,10 @@ #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(); + + // 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 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()); diff --git a/media/renderers/video_resource_updater.h b/media/renderers/video_resource_updater.h index e3a0783fd7d7..9ffac77d8064 100644 --- a/media/renderers/video_resource_updater.h +++ b/media/renderers/video_resource_updater.h @@ -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. diff --git a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc index e492fa3c4d6a..2b1100331399 100644 --- a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc +++ b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc @@ -151,6 +151,9 @@ bool StructTraitscookie_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(); diff --git a/third_party/blink/public/common/web_preferences/web_preferences.h b/third_party/blink/public/common/web_preferences/web_preferences.h index 1ce751e19f61..52d345f497fb 100644 --- a/third_party/blink/public/common/web_preferences/web_preferences.h +++ b/third_party/blink/public/common/web_preferences/web_preferences.h @@ -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; diff --git a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h index 5c90c533c571..ff8609a8aaac 100644 --- a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h +++ b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h @@ -443,6 +443,12 @@ struct BLINK_COMMON_EXPORT StructTraits metrics_provider, CreateSurfaceLayerBridgeCB create_bridge_callback, scoped_refptr 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, diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h index 0e49c6715088..617094f17110 100644 --- a/third_party/blink/public/web/web_settings.h +++ b/third_party/blink/public/web/web_settings.h @@ -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; diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index ed6c3a07e22a..91135d75b2c4 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h @@ -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. diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc index 1f5a3633c5ec..7ff759cb2191 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.cc +++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc @@ -807,4 +807,9 @@ bool WebSettingsImpl::GetAccessibilityEnabled() { } #endif +#if defined(TIZEN_VIDEO_HOLE) +void WebSettingsImpl::SetVideoHoleEnabled(bool enabled) { + settings_->SetVideoHoleEnabled(enabled); +} +#endif } // namespace blink diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h index dc092d8c5019..f316fa71d996 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.h +++ b/third_party/blink/renderer/core/exported/web_settings_impl.h @@ -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_; diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 643e14bc956b..ab133fb82f11 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc @@ -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 diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 887ef2659902..5c3d4a215531 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h @@ -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; diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 index a80dcbeb76f4..0025005d169c 100644 --- a/third_party/blink/renderer/core/frame/settings.json5 +++ b/third_party/blink/renderer/core/frame/settings.json5 @@ -1055,5 +1055,10 @@ initial: true, type: "bool", }, + { + name: "videoHoleEnabled", + initial: false, + type: "bool" + }, ], } diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 8e54d84538d0..fe072e5c7952 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc @@ -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(); } diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index f15ee2412b93..af3dca28f942 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h @@ -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; diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h index 0fcb11187381..bee106344a78 100644 --- a/third_party/blink/renderer/core/page/chrome_client.h +++ b/third_party/blink/renderer/core/page/chrome_client.h @@ -568,6 +568,10 @@ class CORE_EXPORT ChromeClient : public GarbageCollected { virtual void PasswordFieldReset(HTMLInputElement& element) {} +#if defined(TIZEN_VIDEO_HOLE) + virtual void SetVideoHoleDisabledForOES(bool disabled) const {} +#endif + protected: ChromeClient() = default; diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h index a82497399be7..0841a93710e3 100644 --- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h +++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h @@ -48,6 +48,12 @@ class MediaStreamDescriptor; class WebMediaPlayerMS; struct WebMediaPlayerMSCompositorTraits; +#if defined(TIZEN_VIDEO_HOLE) +using DrawableContentRectChangedCallback = + base::RepeatingCallback; +using VideoVisibilityChangedCallback = base::RepeatingCallback; +#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; diff --git a/third_party/blink/renderer/platform/media/video_frame_compositor.cc b/third_party/blink/renderer/platform/media/video_frame_compositor.cc index fdbf31de93b2..d00807168bc6 100644 --- a/third_party/blink/renderer/platform/media/video_frame_compositor.cc +++ b/third_party/blink/renderer/platform/media/video_frame_compositor.cc @@ -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 diff --git a/third_party/blink/renderer/platform/media/web_media_player_builder.cc b/third_party/blink/renderer/platform/media/web_media_player_builder.cc index 9b3cd2eeca0e..bab6de115107 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_builder.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_builder.cc @@ -55,6 +55,9 @@ WebMediaPlayer* WebMediaPlayerBuilder::Build( mojo::PendingRemote metrics_provider, CreateSurfaceLayerBridgeCB create_bridge_callback, scoped_refptr 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)); diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/third_party/blink/renderer/platform/media/web_media_player_impl.cc index f31d3a4dc941..8808a019539a 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.cc @@ -101,6 +101,13 @@ #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 metrics_provider, CreateSurfaceLayerBridgeCB create_bridge_callback, scoped_refptr 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( @@ -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 WebMediaPlayerImpl::CreateRenderer( media_metrics_provider_->SetRendererType(renderer_type_); media_log_->SetProperty(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 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(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 diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.h b/third_party/blink/renderer/platform/media/web_media_player_impl.h index 31b94dd93e07..218cb25b87ec 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.h +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.h @@ -139,6 +139,9 @@ class PLATFORM_EXPORT WebMediaPlayerImpl mojo::PendingRemote metrics_provider, CreateSurfaceLayerBridgeCB create_bridge_callback, scoped_refptr 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 demuxer_override_; diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index e345298ed2d2..4f076937da24 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc @@ -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 diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h index faec533ac5c2..43344d42a4b2 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.h +++ b/third_party/blink/renderer/platform/widget/widget_base.h @@ -147,6 +147,9 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget, void PrintToPdf(uint32_t width, 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, diff --git a/third_party/blink/renderer/platform/widget/widget_base_client.h b/third_party/blink/renderer/platform/widget/widget_base_client.h index 608f7cd635a2..d34b06f3f8a1 100644 --- a/third_party/blink/renderer/platform/widget/widget_base_client.h +++ b/third_party/blink/renderer/platform/widget/widget_base_client.h @@ -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 diff --git a/tizen_src/build/config/BUILD.gn b/tizen_src/build/config/BUILD.gn index 92914cb3dffe..66cc744b59ba 100644 --- a/tizen_src/build/config/BUILD.gn +++ b/tizen_src/build/config/BUILD.gn @@ -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. diff --git a/tizen_src/build/config/tizen_features.gni b/tizen_src/build/config/tizen_features.gni index 8854b6a73a86..9b971e9741ed 100644 --- a/tizen_src/build/config/tizen_features.gni +++ b/tizen_src/build/config/tizen_features.gni @@ -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 diff --git a/tizen_src/build/gn_chromiumefl.sh b/tizen_src/build/gn_chromiumefl.sh index 078276da3627..531f7f21b614 100755 --- a/tizen_src/build/gn_chromiumefl.sh +++ b/tizen_src/build/gn_chromiumefl.sh @@ -224,6 +224,7 @@ add_tizen_flags() { tizen_audio_io=true tizen_web_speech_recognition=true tizen_tbm_support=true + tizen_video_hole=true " } diff --git a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc index e5d13132c00b..19667a543e40 100644 --- a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc +++ b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc @@ -28,6 +28,10 @@ #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( + 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(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(); diff --git a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h index fbb96a8cd49f..3e03aae4851b 100644 --- a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h +++ b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h @@ -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 weak_factory_{this}; }; diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc index 0ae0b6cad392..9cc558b8df82 100644 --- a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc +++ b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc @@ -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()); diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h index f601a44f2f21..e2933d07896d 100644 --- a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h +++ b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h @@ -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_; diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_efl.h b/tizen_src/chromium_impl/media/base/efl/media_player_efl.h index f2ea9abf4e85..3d3a2b3b0f5f 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_player_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/media_player_efl.h @@ -11,6 +11,10 @@ #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); diff --git a/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.cc b/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.cc index c693f64b397d..6da6d565539d 100644 --- a/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.cc +++ b/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.cc @@ -15,6 +15,11 @@ #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); diff --git a/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h b/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h index dd5551658f93..396abe9d9660 100644 --- a/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h +++ b/tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h @@ -15,6 +15,11 @@ #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 video_plane_controller_; +#endif + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory 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 index 000000000000..8fc2e152ef66 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller.cc @@ -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& 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& 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& 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 index 000000000000..e96b1bd318e0 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller.h @@ -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& 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& 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&); + + 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 deferred_visible_crop_ratio_{}; + gfx::Rect current_viewport_rect_; + gfx::RectF current_rect_; + absl::optional 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 index 000000000000..ec0a699f7583 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.cc @@ -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 + +#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 +#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(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 index 000000000000..fbc46a3a2181 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h @@ -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 + +#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 index 000000000000..f6ce55ffa2e0 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.cc @@ -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 +#include +#include +#include + +#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 index 000000000000..e141abce68e7 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h @@ -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 +#include + +#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_ diff --git a/tizen_src/chromium_impl/media/filters/esplusplayer_util.cc b/tizen_src/chromium_impl/media/filters/esplusplayer_util.cc index 531e06f55449..c36a37cf9695 100644 --- a/tizen_src/chromium_impl/media/filters/esplusplayer_util.cc +++ b/tizen_src/chromium_impl/media/filters/esplusplayer_util.cc @@ -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 diff --git a/tizen_src/chromium_impl/media/filters/esplusplayer_util.h b/tizen_src/chromium_impl/media/filters/esplusplayer_util.h index aba62d79a30c..f610363fa9b7 100644 --- a/tizen_src/chromium_impl/media/filters/esplusplayer_util.h +++ b/tizen_src/chromium_impl/media/filters/esplusplayer_util.h @@ -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 diff --git a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc index 45e9b99c609b..a4aa284d9364 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc +++ b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc @@ -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 diff --git a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc index 077a93d2d6e8..c2084bb25354 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc +++ b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc @@ -16,6 +16,11 @@ #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 +#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( + 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( + 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(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(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(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 diff --git a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h index 39928471b4cc..72e0f6ddc2d1 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h +++ b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h @@ -19,10 +19,16 @@ #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>; @@ -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 video_plane_controller_; +#endif + base::OnceClosure flush_cb_; int player_id_ = 0; diff --git a/tizen_src/chromium_impl/media/media_efl.gni b/tizen_src/chromium_impl/media/media_efl.gni index 7edc247d097e..8227060422a9 100644 --- a/tizen_src/chromium_impl/media/media_efl.gni +++ b/tizen_src/chromium_impl/media/media_efl.gni @@ -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) { diff --git a/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_window.cc b/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_window.cc index 3b357f1460f4..4b94f3105698 100644 --- a/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_window.cc +++ b/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_window.cc @@ -21,6 +21,10 @@ #include #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"; diff --git a/tizen_src/ewk/efl_integration/common/render_messages_ewk.h b/tizen_src/ewk/efl_integration/common/render_messages_ewk.h index 2c57ceecccf2..0d397e1eb6da 100644 --- a/tizen_src/ewk/efl_integration/common/render_messages_ewk.h +++ b/tizen_src/ewk/efl_integration/common/render_messages_ewk.h @@ -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*/) diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 10b9ff83e074..81d92fe9c2b9 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -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; } diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 0fd0d140b64d..bcf8a891fa79 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -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 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; diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 482c88e83ca9..de2255ca6783 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -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(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) { diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.h b/tizen_src/ewk/efl_integration/public/ewk_view.h index d637a51173ea..77e8c36cd4e0 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.h +++ b/tizen_src/ewk/efl_integration/public/ewk_view.h @@ -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 diff --git a/tizen_src/ewk/ubrowser/browser.cc b/tizen_src/ewk/ubrowser/browser.cc index b19985e90e6e..8a8cb87c44d4 100644 --- a/tizen_src/ewk/ubrowser/browser.cc +++ b/tizen_src/ewk/ubrowser/browser.cc @@ -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), diff --git a/tizen_src/ewk/ubrowser/browser.h b/tizen_src/ewk/ubrowser/browser.h index 4247e722b8b0..45eeda8ecca4 100644 --- a/tizen_src/ewk/ubrowser/browser.h +++ b/tizen_src/ewk/ubrowser/browser.h @@ -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_; diff --git a/tizen_src/ewk/ubrowser/main.cc b/tizen_src/ewk/ubrowser/main.cc index 0c598c6aac2d..9ac8c550d374 100644 --- a/tizen_src/ewk/ubrowser/main.cc +++ b/tizen_src/ewk/ubrowser/main.cc @@ -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::iterator it = app_data->urls.begin(); for (;it != app_data->urls.end(); ++it) app_data->browser->CreateWindow().LoadURL(*it); diff --git a/tizen_src/ewk/ubrowser/window.cc b/tizen_src/ewk/ubrowser/window.cc index 6dae22b4684f..56ad89b79068 100644 --- a/tizen_src/ewk/ubrowser/window.cc +++ b/tizen_src/ewk/ubrowser/window.cc @@ -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_);