From b2076c3c7344c34058bff4153cf359725a247333 Mon Sep 17 00:00:00 2001 From: Bo-Rong Chen Date: Mon, 21 Oct 2024 10:25:08 -0700 Subject: [PATCH] [Android] Support SbPlayer via video hole frame The CL was originally uploaded at https://chromium-review.googlesource.com/c/chromium/src/+/5806680. Replace the video hole draw quad manually in viz. This supports SbPlayer video rendering via punch hole display. b/352389546 --- .github/CODEOWNERS | 1 + .pre-commit-config.yaml | 1 + .../java/dev/cobalt/coat/CobaltActivity.java | 2 + components/viz/service/BUILD.gn | 14 ++ .../display/overlay_processor_android.cc | 17 ++ .../overlay_strategy_underlay_starboard.cc | 196 ++++++++++++++++++ .../overlay_strategy_underlay_starboard.h | 81 ++++++++ media/starboard/sbplayer_bridge.cc | 18 +- media/starboard/starboard_renderer.cc | 18 +- media/starboard/starboard_renderer.h | 12 +- .../platform/media/web_media_player_impl.cc | 3 +- 11 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 components/viz/service/display/starboard/overlay_strategy_underlay_starboard.cc create mode 100644 components/viz/service/display/starboard/overlay_strategy_underlay_starboard.h diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 88c4a79e218f..149f40dda00f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,3 +3,4 @@ /cobalt/ # no owners /media/starboard/ # no owners /starboard/ # no owners +/components/viz/service/display/starboard/ # no owners diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 25e244a7aa5e..d6a6000e5700 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,7 @@ files: | cobalt/| media/starboard/| starboard/| + components/viz/service/display/starboard/| .pre-commit-config.yaml| .pylintrc| docker-compose.yaml diff --git a/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java b/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java index 70e55cef175e..9d9b6e86f3ae 100644 --- a/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java +++ b/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java @@ -185,6 +185,8 @@ private void finishInitialization(Bundle savedInstanceState) { && savedInstanceState.containsKey(ACTIVE_SHELL_URL_KEY)) { shellUrl = savedInstanceState.getString(ACTIVE_SHELL_URL_KEY); } + // Set to overlay video mode. + mShellManager.getContentViewRenderView().setOverlayVideoMode(true); mShellManager.launchShell(shellUrl); toggleFullscreenMode(true); diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index f2fe76f53dac..98af361dce88 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn @@ -11,6 +11,10 @@ import("//media/gpu/args.gni") import("//skia/features.gni") import("//testing/libfuzzer/fuzzer_test.gni") +if (is_cobalt) { + import("//starboard/build/buildflags.gni") +} + config("viz_service_implementation") { } @@ -341,6 +345,16 @@ viz_component("service") { ] } + if (is_cobalt && use_starboard_media) { + sources += [ + "display/starboard/overlay_strategy_underlay_starboard.cc", + "display/starboard/overlay_strategy_underlay_starboard.h", + ] + deps += [ + "//starboard/build:starboard_buildflags", + ] + } + if (enable_cast_overlay_strategy) { sources += [ "display/overlay_strategy_underlay_cast.cc", diff --git a/components/viz/service/display/overlay_processor_android.cc b/components/viz/service/display/overlay_processor_android.cc index d9f15236b968..385ae40c15ef 100644 --- a/components/viz/service/display/overlay_processor_android.cc +++ b/components/viz/service/display/overlay_processor_android.cc @@ -17,6 +17,14 @@ #include "gpu/command_buffer/service/scheduler_sequence.h" #include "ui/gfx/geometry/rect_conversions.h" +// For BUILDFLAG(USE_STARBOARD_MEDIA) +#if BUILDFLAG(IS_COBALT) +#include "starboard/build/starboard_buildflags.h" +#if BUILDFLAG(USE_STARBOARD_MEDIA) +#include "components/viz/service/display/starboard/overlay_strategy_underlay_starboard.h" +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) +#endif // BUILDFLAG(IS_COBALT) + namespace viz { OverlayProcessorAndroid::OverlayProcessorAndroid( DisplayCompositorMemoryAndTaskController* display_controller) @@ -55,8 +63,17 @@ OverlayProcessorAndroid::OverlayProcessorAndroid( // the underlying overlay is opaque anyway; the candidate is referring to // a dummy resource that has no relation to what the overlay contains. // https://crbug.com/842931 . +#if BUILDFLAG(IS_COBALT) +#if BUILDFLAG(USE_STARBOARD_MEDIA) + strategies_.push_back(std::make_unique(this)); +#else // BUILDFLAG(USE_STARBOARD_MEDIA) + strategies_.push_back(std::make_unique( + this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates)); +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) +#else // BUILDFLAG(IS_COBALT) strategies_.push_back(std::make_unique( this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates)); +#endif // BUILDFLAG(IS_COBALT) overlay_candidates_.clear(); } diff --git a/components/viz/service/display/starboard/overlay_strategy_underlay_starboard.cc b/components/viz/service/display/starboard/overlay_strategy_underlay_starboard.cc new file mode 100644 index 000000000000..19cfeba6867d --- /dev/null +++ b/components/viz/service/display/starboard/overlay_strategy_underlay_starboard.cc @@ -0,0 +1,196 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "components/viz/service/display/starboard/overlay_strategy_underlay_starboard.h" + +#include +#include + +#include "base/containers/adapters.h" +#include "base/logging.h" +#include "components/viz/common/quads/draw_quad.h" +#include "components/viz/common/quads/solid_color_draw_quad.h" +#include "components/viz/common/quads/video_hole_draw_quad.h" +#include "components/viz/service/display/overlay_candidate_factory.h" +#include "ui/gfx/geometry/rect_conversions.h" + +namespace viz { + +OverlayStrategyUnderlayStarboard::OverlayStrategyUnderlayStarboard( + OverlayProcessorUsingStrategy* capability_checker) + : OverlayStrategyUnderlay(capability_checker) {} + +OverlayStrategyUnderlayStarboard::~OverlayStrategyUnderlayStarboard() {} + +void OverlayStrategyUnderlayStarboard::Propose( + const SkM44& output_color_matrix, + const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters, + const OverlayProcessorInterface::FilterOperationsMap& + render_pass_backdrop_filters, + DisplayResourceProvider* resource_provider, + AggregatedRenderPassList* render_pass_list, + SurfaceDamageRectList* surface_damage_rect_list, + const PrimaryPlane* primary_plane, + std::vector* candidates, + std::vector* content_bounds) { + auto* render_pass = render_pass_list->back().get(); + QuadList& quad_list = render_pass->quad_list; + OverlayCandidate candidate; + auto overlay_iter = quad_list.end(); + OverlayCandidateFactory candidate_factory = OverlayCandidateFactory( + render_pass, resource_provider, surface_damage_rect_list, + &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane), + &render_pass_filters); + + // Original code did reverse iteration. + // Here we do forward but find the last one. which should be the same thing. + for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { + if (OverlayCandidate::IsInvisibleQuad(*it)) { + continue; + } + + // Look for quads that are overlayable and require an overlay. Chromecast + // only supports a video underlay so this can't promote all quads that are + // overlayable, it needs to ensure that the quad requires overlays since + // that quad is side-channeled through a secure path into an overlay + // sitting underneath the primary plane. This is only looking at where the + // quad is supposed to be to replace it with a transparent quad to allow + // the underlay to be visible. + // VIDEO_HOLE implies it requires overlay. + if (it->material == DrawQuad::Material::kVideoHole && + candidate_factory.FromDrawQuad(*it, candidate) == + OverlayCandidate::CandidateStatus::kSuccess) { + overlay_iter = it; + } + } + + if (overlay_iter != quad_list.end()) { + candidates->emplace_back(overlay_iter, candidate, this); + } +} + +bool OverlayStrategyUnderlayStarboard::Attempt( + const SkM44& output_color_matrix, + const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters, + const OverlayProcessorInterface::FilterOperationsMap& + render_pass_backdrop_filters, + DisplayResourceProvider* resource_provider, + AggregatedRenderPassList* render_pass_list, + SurfaceDamageRectList* surface_damage_rect_list, + const PrimaryPlane* primary_plane, + OverlayCandidateList* candidate_list, + std::vector* content_bounds, + const OverlayProposedCandidate& proposed_candidate) { + // Before we attempt an overlay strategy, the candidate list should be empty. + DCHECK(candidate_list->empty()); + auto* render_pass = render_pass_list->back().get(); + QuadList& quad_list = render_pass->quad_list; + bool found_underlay = false; + gfx::Rect content_rect; + OverlayCandidateFactory candidate_factory = OverlayCandidateFactory( + render_pass, resource_provider, surface_damage_rect_list, + &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane), + &render_pass_filters); + + for (const auto* quad : base::Reversed(quad_list)) { + if (OverlayCandidate::IsInvisibleQuad(quad)) { + continue; + } + + const auto& transform = quad->shared_quad_state->quad_to_target_transform; + gfx::Rect quad_rect = transform.MapRect(quad->rect); + + bool is_underlay = false; + if (!found_underlay) { + OverlayCandidate candidate; + // Look for quads that are overlayable and require an overlay. Chromecast + // only supports a video underlay so this can't promote all quads that are + // overlayable, it needs to ensure that the quad requires overlays since + // that quad is side-channeled through a secure path into an overlay + // sitting underneath the primary plane. This is only looking at where the + // quad is supposed to be to replace it with a transparent quad to allow + // the underlay to be visible. + // VIDEO_HOLE implies it requires overlay. + is_underlay = quad->material == DrawQuad::Material::kVideoHole && + candidate_factory.FromDrawQuad(quad, candidate) == + OverlayCandidate::CandidateStatus::kSuccess; + found_underlay = is_underlay; + } + + if (!found_underlay && quad->material == DrawQuad::Material::kSolidColor) { + const SolidColorDrawQuad* solid = SolidColorDrawQuad::MaterialCast(quad); + if (solid->color == SkColors::kBlack) { + continue; + } + } + + if (is_underlay) { + content_rect.Subtract(quad_rect); + } else { + content_rect.Union(quad_rect); + } + } + + if (is_using_overlay_ != found_underlay) { + is_using_overlay_ = found_underlay; + LOG(INFO) << (found_underlay ? "Overlay activated" : "Overlay deactivated"); + } + + if (found_underlay) { + for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { + OverlayCandidate candidate; + if (it->material != DrawQuad::Material::kVideoHole || + candidate_factory.FromDrawQuad(*it, candidate) != + OverlayCandidate::CandidateStatus::kSuccess) { + continue; + } + + OverlayProposedCandidate proposed_to_commit(it, candidate, this); + CommitCandidate(proposed_to_commit, render_pass); + + break; + } + } + + DCHECK(content_bounds && content_bounds->empty()); + if (found_underlay) { + content_bounds->push_back(content_rect); + } + return found_underlay; +} + +void OverlayStrategyUnderlayStarboard::CommitCandidate( + const OverlayProposedCandidate& proposed_candidate, + AggregatedRenderPass* render_pass) { + if (proposed_candidate.candidate.has_mask_filter) { + render_pass->ReplaceExistingQuadWithSolidColor( + proposed_candidate.quad_iter, SkColors::kBlack, SkBlendMode::kDstOut); + } else { + render_pass->ReplaceExistingQuadWithSolidColor(proposed_candidate.quad_iter, + SkColors::kTransparent, + SkBlendMode::kSrcOver); + } +} + +// Turn on blending for the output surface plane so the underlay could show +// through. +void OverlayStrategyUnderlayStarboard::AdjustOutputSurfaceOverlay( + OverlayProcessorInterface::OutputSurfaceOverlayPlane* + output_surface_plane) { + if (output_surface_plane) { + output_surface_plane->enable_blending = true; + } +} + +} // namespace viz diff --git a/components/viz/service/display/starboard/overlay_strategy_underlay_starboard.h b/components/viz/service/display/starboard/overlay_strategy_underlay_starboard.h new file mode 100644 index 000000000000..247f34ff2329 --- /dev/null +++ b/components/viz/service/display/starboard/overlay_strategy_underlay_starboard.h @@ -0,0 +1,81 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_STARBOARD_OVERLAY_STRATEGY_UNDERLAY_STARBOARD_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_STARBOARD_OVERLAY_STRATEGY_UNDERLAY_STARBOARD_H_ + +#include +#include + +#include "components/viz/service/display/overlay_strategy_underlay.h" +#include "components/viz/service/viz_service_export.h" + +namespace viz { + +// The underlay strategy looks for a video hole quad, where the underlay +// video can be displayed directly. This is similar to the underlay +// strategy for Cast. +class VIZ_SERVICE_EXPORT OverlayStrategyUnderlayStarboard + : public OverlayStrategyUnderlay { + public: + explicit OverlayStrategyUnderlayStarboard( + OverlayProcessorUsingStrategy* capability_checker); + + OverlayStrategyUnderlayStarboard(const OverlayStrategyUnderlayStarboard&) = + delete; + OverlayStrategyUnderlayStarboard& operator=( + const OverlayStrategyUnderlayStarboard&) = delete; + + ~OverlayStrategyUnderlayStarboard() override; + + void Propose( + const SkM44& output_color_matrix, + const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters, + const OverlayProcessorInterface::FilterOperationsMap& + render_pass_backdrop_filters, + DisplayResourceProvider* resource_provider, + AggregatedRenderPassList* render_pass_list, + SurfaceDamageRectList* surface_damage_rect_list, + const PrimaryPlane* primary_plane, + std::vector* candidates, + std::vector* content_bounds) override; + + bool Attempt( + const SkM44& output_color_matrix, + const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters, + const OverlayProcessorInterface::FilterOperationsMap& + render_pass_backdrop_filters, + DisplayResourceProvider* resource_provider, + AggregatedRenderPassList* render_pass_list, + SurfaceDamageRectList* surface_damage_rect_list, + const PrimaryPlane* primary_plane, + OverlayCandidateList* candidates, + std::vector* content_bounds, + const OverlayProposedCandidate& proposed_candidate) override; + + void CommitCandidate(const OverlayProposedCandidate& proposed_candidate, + AggregatedRenderPass* render_pass) override; + + void AdjustOutputSurfaceOverlay( + OverlayProcessorInterface::OutputSurfaceOverlayPlane* + output_surface_plane) override; + + private: + // Keep track if an overlay is being used on the previous frame. + bool is_using_overlay_ = false; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_STARBOARD_OVERLAY_STRATEGY_UNDERLAY_STARBOARD_H_ diff --git a/media/starboard/sbplayer_bridge.cc b/media/starboard/sbplayer_bridge.cc index eac083a91651..e3d166f411c8 100644 --- a/media/starboard/sbplayer_bridge.cc +++ b/media/starboard/sbplayer_bridge.cc @@ -173,7 +173,8 @@ SbPlayerBridge::SbPlayerBridge( pipeline_identifier_(pipeline_identifier), is_url_based_(true) { DCHECK(host_); - DCHECK(set_bounds_helper_); + // TODO(b/352389546): set bounds via video_painter.cc + // DCHECK(set_bounds_helper_); output_mode_ = ComputeSbUrlPlayerOutputMode(default_output_mode); @@ -243,7 +244,8 @@ SbPlayerBridge::SbPlayerBridge( #endif // COBALT_MEDIA_ENABLE_DECODE_TARGET_PROVIDER DCHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); DCHECK(host_); - DCHECK(set_bounds_helper_); + // TODO(b/352389546): set bounds via video_painter.cc + // DCHECK(set_bounds_helper_); #if COBALT_MEDIA_ENABLE_DECODE_TARGET_PROVIDER DCHECK(decode_target_provider_); #endif // COBALT_MEDIA_ENABLE_DECODE_TARGET_PROVIDER @@ -277,7 +279,8 @@ SbPlayerBridge::~SbPlayerBridge() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); callback_helper_->ResetPlayer(); - set_bounds_helper_->SetPlayerBridge(NULL); + // TODO(b/352389546): set bounds via video_painter.cc + // set_bounds_helper_->SetPlayerBridge(NULL); #if COBALT_MEDIA_ENABLE_DECODE_TARGET_PROVIDER decode_target_provider_->SetOutputMode( @@ -588,7 +591,8 @@ void SbPlayerBridge::Suspend() { sbplayer_interface_->SetPlaybackRate(player_, 0.0); - set_bounds_helper_->SetPlayerBridge(NULL); + // TODO(b/352389546): set bounds via video_painter.cc + // set_bounds_helper_->SetPlayerBridge(NULL); base::AutoLock auto_lock(lock_); GetInfo_Locked(&cached_video_frames_decoded_, &cached_video_frames_dropped_, @@ -720,7 +724,8 @@ void SbPlayerBridge::CreateUrlPlayer(const std::string& url) { decode_target_provider_->SetOutputMode( ToVideoFrameProviderOutputMode(output_mode_)); - set_bounds_helper_->SetPlayerBridge(this); + // TODO(b/352389546): set bounds via video_painter.cc + // set_bounds_helper_->SetPlayerBridge(this); base::AutoLock auto_lock(lock_); UpdateBounds_Locked(); @@ -821,7 +826,8 @@ void SbPlayerBridge::CreatePlayer() { decode_target_provider_->SetOutputMode( ToVideoFrameProviderOutputMode(output_mode_)); #endif // COBALT_MEDIA_ENABLE_DECODE_TARGET_PROVIDER - set_bounds_helper_->SetPlayerBridge(this); + // TODO(b/352389546): set bounds via video_painter.cc + // set_bounds_helper_->SetPlayerBridge(this); base::AutoLock auto_lock(lock_); UpdateBounds_Locked(); diff --git a/media/starboard/starboard_renderer.cc b/media/starboard/starboard_renderer.cc index d07f6ae7c5fc..129edfab638f 100644 --- a/media/starboard/starboard_renderer.cc +++ b/media/starboard/starboard_renderer.cc @@ -16,6 +16,8 @@ #include "base/logging.h" #include "base/trace_event/trace_event.h" +#include "media/base/video_renderer_sink.h" +#include "media/renderers/video_overlay_factory.h" #include "starboard/common/media.h" namespace media { @@ -54,10 +56,12 @@ bool HasRemoteAudioOutputs( } // namespace StarboardRenderer::StarboardRenderer( - const scoped_refptr& task_runner) - : task_runner_(task_runner) { + const scoped_refptr& task_runner, + VideoRendererSink* video_renderer_sink) + : task_runner_(task_runner), video_renderer_sink_(video_renderer_sink) { DCHECK(task_runner_); LOG(INFO) << "StarboardRenderer constructed."; + video_overlay_factory_ = std::make_unique(); } StarboardRenderer::~StarboardRenderer() { @@ -420,6 +424,11 @@ void StarboardRenderer::UpdateDecoderConfig(DemuxerStream* stream) { content_size_change_cb_.Run(); } #endif // 0 + if (video_overlay_factory_) { + video_renderer_sink_->PaintSingleFrame( + video_overlay_factory_->CreateFrame( + stream->video_decoder_config().visible_rect().size())); + } } } @@ -472,6 +481,11 @@ void StarboardRenderer::OnDemuxerStreamRead( // TODO(b/375275033): Refine calling to OnVideoNaturalSizeChange(). client_->OnVideoNaturalSizeChange( stream->video_decoder_config().visible_rect().size()); + if (video_overlay_factory_) { + video_renderer_sink_->PaintSingleFrame( + video_overlay_factory_->CreateFrame( + stream->video_decoder_config().visible_rect().size())); + } } UpdateDecoderConfig(stream); stream->Read(1, base::BindOnce(&StarboardRenderer::OnDemuxerStreamRead, diff --git a/media/starboard/starboard_renderer.h b/media/starboard/starboard_renderer.h index ac964723b28d..8217a2829261 100644 --- a/media/starboard/starboard_renderer.h +++ b/media/starboard/starboard_renderer.h @@ -35,13 +35,17 @@ namespace media { +class VideoRendererSink; +class VideoOverlayFactory; + // SbPlayer based Renderer implementation, the entry point for all video // playbacks on Starboard platforms. class MEDIA_EXPORT StarboardRenderer final : public Renderer, private SbPlayerBridge::Host { public: explicit StarboardRenderer( - const scoped_refptr& task_runner); + const scoped_refptr& task_runner, + VideoRendererSink* video_renderer_sink); ~StarboardRenderer() final; @@ -103,6 +107,8 @@ class MEDIA_EXPORT StarboardRenderer final : public Renderer, scoped_refptr task_runner_; + const raw_ptr video_renderer_sink_; + raw_ptr audio_stream_ = nullptr; raw_ptr video_stream_ = nullptr; // TODO(b/375273774): Consider calling `void OnWaiting(WaitingReason reason)` @@ -112,6 +118,10 @@ class MEDIA_EXPORT StarboardRenderer final : public Renderer, // on `client_`? raw_ptr client_ = nullptr; + // Overlay factory used to create overlays for video frames rendered + // by the remote renderer. + std::unique_ptr video_overlay_factory_; + DefaultSbPlayerInterface sbplayer_interface_; // TODO(b/326652276): Support audio write duration. const base::TimeDelta audio_write_duration_local_ = base::Milliseconds(500); 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 60901ee9a794..9841be4ba8ff 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 @@ -2812,7 +2812,8 @@ std::unique_ptr WebMediaPlayerImpl::CreateRenderer( // `media_task_runner_` is always true, use an if statement to avoid // potential build warning on unreachable code. if (media_task_runner_) { - return std::make_unique(media_task_runner_); + return std::make_unique(media_task_runner_, + compositor_.get()); } #endif // BUILDFLAG(USE_STARBOARD_MEDIA) #endif // BUILDFLAG(IS_COBALT)