[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / media_foundation_renderer_wrapper.cc
1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/mojo/services/media_foundation_renderer_wrapper.h"
6
7 #include "base/functional/callback_helpers.h"
8 #include "base/task/sequenced_task_runner.h"
9 #include "media/base/win/mf_helpers.h"
10 #include "media/mojo/mojom/renderer_extensions.mojom.h"
11 #include "media/mojo/services/media_foundation_gpu_info_monitor.h"
12 #include "media/mojo/services/mojo_media_log.h"
13 #include "mojo/public/cpp/bindings/callback_helpers.h"
14 #include "mojo/public/cpp/system/platform_handle.h"
15
16 namespace media {
17
18 namespace {
19
20 bool HasAudio(MediaResource* media_resource) {
21   DCHECK(media_resource->GetType() == MediaResource::Type::kStream);
22
23   const auto media_streams = media_resource->GetAllStreams();
24   for (const media::DemuxerStream* stream : media_streams) {
25     if (stream->type() == media::DemuxerStream::Type::AUDIO)
26       return true;
27   }
28
29   return false;
30 }
31
32 LUID ChromeLuidToLuid(const CHROME_LUID& chrome_luid) {
33   LUID luid;
34   luid.LowPart = chrome_luid.LowPart;
35   luid.HighPart = chrome_luid.HighPart;
36   return luid;
37 }
38
39 }  // namespace
40
41 MediaFoundationRendererWrapper::MediaFoundationRendererWrapper(
42     scoped_refptr<base::SequencedTaskRunner> task_runner,
43     mojom::FrameInterfaceFactory* frame_interfaces,
44     mojo::PendingRemote<mojom::MediaLog> media_log_remote,
45     mojo::PendingReceiver<RendererExtension> renderer_extension_receiver,
46     mojo::PendingRemote<ClientExtension> client_extension_remote)
47     : frame_interfaces_(frame_interfaces),
48       renderer_extension_receiver_(this,
49                                    std::move(renderer_extension_receiver)),
50       client_extension_remote_(std::move(client_extension_remote), task_runner),
51       site_mute_observer_(this) {
52   DVLOG_FUNC(1);
53   DCHECK(frame_interfaces_);
54
55   renderer_ = std::make_unique<MediaFoundationRenderer>(
56       std::move(task_runner),
57       std::make_unique<MojoMediaLog>(std::move(media_log_remote), task_runner),
58       ChromeLuidToLuid(
59           MediaFoundationGpuInfoMonitor::GetInstance()->gpu_luid()));
60
61   luid_update_subscription_ =
62       MediaFoundationGpuInfoMonitor::GetInstance()->AddLuidObserver(
63           base::BindRepeating(&MediaFoundationRendererWrapper::OnGpuLuidChange,
64                               weak_factory_.GetWeakPtr()));
65 }
66
67 MediaFoundationRendererWrapper::~MediaFoundationRendererWrapper() {
68   DVLOG_FUNC(1);
69   if (!dcomp_surface_token_.is_empty())
70     dcomp_surface_registry_->UnregisterDCOMPSurfaceHandle(dcomp_surface_token_);
71 }
72
73 void MediaFoundationRendererWrapper::Initialize(
74     MediaResource* media_resource,
75     RendererClient* client,
76     PipelineStatusCallback init_cb) {
77   if (HasAudio(media_resource)) {
78     frame_interfaces_->RegisterMuteStateObserver(
79         site_mute_observer_.BindNewPipeAndPassRemote());
80   }
81
82   renderer_->SetFrameReturnCallbacks(
83       base::BindRepeating(
84           &MediaFoundationRendererWrapper::OnFrameGeneratedByMediaFoundation,
85           weak_factory_.GetWeakPtr()),
86       base::BindRepeating(
87           &MediaFoundationRendererWrapper::OnFramePoolInitialized,
88           weak_factory_.GetWeakPtr()));
89
90   renderer_->Initialize(media_resource, client, std::move(init_cb));
91 }
92
93 void MediaFoundationRendererWrapper::SetCdm(CdmContext* cdm_context,
94                                             CdmAttachedCB cdm_attached_cb) {
95   renderer_->SetCdm(cdm_context, std::move(cdm_attached_cb));
96 }
97
98 void MediaFoundationRendererWrapper::SetLatencyHint(
99     absl::optional<base::TimeDelta> latency_hint) {
100   renderer_->SetLatencyHint(latency_hint);
101 }
102
103 void MediaFoundationRendererWrapper::Flush(base::OnceClosure flush_cb) {
104   renderer_->Flush(std::move(flush_cb));
105 }
106
107 void MediaFoundationRendererWrapper::StartPlayingFrom(base::TimeDelta time) {
108   renderer_->StartPlayingFrom(time);
109 }
110
111 void MediaFoundationRendererWrapper::SetPlaybackRate(double playback_rate) {
112   renderer_->SetPlaybackRate(playback_rate);
113 }
114
115 void MediaFoundationRendererWrapper::SetVolume(float volume) {
116   volume_ = volume;
117   renderer_->SetVolume(muted_ ? 0 : volume_);
118 }
119
120 base::TimeDelta MediaFoundationRendererWrapper::GetMediaTime() {
121   return renderer_->GetMediaTime();
122 }
123
124 RendererType MediaFoundationRendererWrapper::GetRendererType() {
125   return RendererType::kMediaFoundation;
126 }
127
128 void MediaFoundationRendererWrapper::GetDCOMPSurface(
129     GetDCOMPSurfaceCallback callback) {
130   if (has_get_dcomp_surface_called_) {
131     renderer_extension_receiver_.ReportBadMessage(
132         "GetDCOMPSurface should only be called once!");
133     return;
134   }
135
136   has_get_dcomp_surface_called_ = true;
137   renderer_->GetDCompSurface(
138       base::BindOnce(&MediaFoundationRendererWrapper::OnReceiveDCOMPSurface,
139                      weak_factory_.GetWeakPtr(), std::move(callback)));
140 }
141
142 void MediaFoundationRendererWrapper::SetVideoStreamEnabled(bool enabled) {
143   renderer_->SetVideoStreamEnabled(enabled);
144 }
145
146 void MediaFoundationRendererWrapper::SetOutputRect(
147     const gfx::Rect& output_rect,
148     SetOutputRectCallback callback) {
149   renderer_->SetOutputRect(output_rect, std::move(callback));
150 }
151
152 void MediaFoundationRendererWrapper::OnMuteStateChange(bool muted) {
153   DVLOG_FUNC(2) << ": muted=" << muted;
154
155   if (muted == muted_)
156     return;
157
158   muted_ = muted;
159   renderer_->SetVolume(muted_ ? 0 : volume_);
160 }
161
162 void MediaFoundationRendererWrapper::OnGpuLuidChange(
163     const CHROME_LUID& adapter_luid) {
164   renderer_->SetGpuProcessAdapterLuid(ChromeLuidToLuid(adapter_luid));
165 }
166
167 void MediaFoundationRendererWrapper::OnReceiveDCOMPSurface(
168     GetDCOMPSurfaceCallback callback,
169     base::win::ScopedHandle handle,
170     const std::string& error) {
171   if (!handle.IsValid()) {
172     std::move(callback).Run(absl::nullopt, "invalid handle: " + error);
173     return;
174   }
175
176   if (!dcomp_surface_registry_) {
177     frame_interfaces_->CreateDCOMPSurfaceRegistry(
178         dcomp_surface_registry_.BindNewPipeAndPassReceiver());
179   }
180
181   auto register_cb = base::BindOnce(
182       &MediaFoundationRendererWrapper::OnDCOMPSurfaceHandleRegistered,
183       weak_factory_.GetWeakPtr(), std::move(callback));
184
185   dcomp_surface_registry_->RegisterDCOMPSurfaceHandle(
186       mojo::PlatformHandle(std::move(handle)),
187       mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(register_cb),
188                                                   absl::nullopt));
189 }
190
191 void MediaFoundationRendererWrapper::OnDCOMPSurfaceHandleRegistered(
192     GetDCOMPSurfaceCallback callback,
193     const absl::optional<base::UnguessableToken>& token) {
194   std::string error;
195   if (token) {
196     DCHECK(dcomp_surface_token_.is_empty());
197     dcomp_surface_token_ = token.value();
198   } else {
199     error = "dcomp surface handle registration failed";
200   }
201
202   std::move(callback).Run(token, error);
203 }
204
205 void MediaFoundationRendererWrapper::OnFramePoolInitialized(
206     std::vector<MediaFoundationFrameInfo> frame_textures,
207     const gfx::Size& texture_size) {
208   auto pool_params = media::mojom::FramePoolInitializationParameters::New();
209   for (auto& texture : frame_textures) {
210     auto frame_info = media::mojom::FrameTextureInfo::New();
211     gfx::GpuMemoryBufferHandle gpu_handle;
212
213     gpu_handle.dxgi_handle = std::move(texture.dxgi_handle);
214     gpu_handle.dxgi_token = gfx::DXGIHandleToken();
215     gpu_handle.type = gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE;
216
217     frame_info->token = texture.token;
218     frame_info->texture_handle = std::move(gpu_handle);
219     pool_params->frame_textures.emplace_back(std::move(frame_info));
220   }
221
222   pool_params->texture_size = texture_size;
223   client_extension_remote_->InitializeFramePool(std::move(pool_params));
224 }
225
226 void MediaFoundationRendererWrapper::OnFrameGeneratedByMediaFoundation(
227     const base::UnguessableToken& frame_token,
228     const gfx::Size& frame_size,
229     base::TimeDelta frame_timestamp) {
230   client_extension_remote_->OnFrameAvailable(frame_token, frame_size,
231                                              frame_timestamp);
232 }
233
234 void MediaFoundationRendererWrapper::NotifyFrameReleased(
235     const base::UnguessableToken& frame_token) {
236   renderer_->NotifyFrameReleased(frame_token);
237 }
238
239 void MediaFoundationRendererWrapper::RequestNextFrame() {
240   renderer_->RequestNextFrame();
241 }
242
243 void MediaFoundationRendererWrapper::SetMediaFoundationRenderingMode(
244     MediaFoundationRenderingMode mode) {
245   renderer_->SetMediaFoundationRenderingMode(mode);
246 }
247 }  // namespace media