[M120 Migration][MM][WebRTC] Base implementation for webrtc video hole stream
[platform/framework/web/chromium-efl.git] / components / cast_streaming / renderer / control / playback_command_forwarding_renderer.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 "components/cast_streaming/renderer/control/playback_command_forwarding_renderer.h"
6
7 #include "base/memory/raw_ptr.h"
8 #include "base/notreached.h"
9 #include "base/task/bind_post_task.h"
10 #include "base/task/sequenced_task_runner.h"
11
12 namespace cast_streaming {
13 namespace {
14
15 constexpr base::TimeDelta kTimeUpdateInterval = base::Milliseconds(250);
16
17 }  // namespace
18
19 // Class responsible for receiving Renderer commands from a remote source and
20 // forwarding them to |owning_renderer| unchanged. This class exists only to
21 // avoid intersection of media::Renderer and media::mojom::Renderer methods in
22 // PlaybackCommandForwardingRenderer.
23 //
24 // NOTE: This class CANNOT be declared in an unnamed namespace or the friend
25 // declaration in PlaybackCommandForwardingRenderer will no longer function.
26 class RendererCommandForwarder : public media::mojom::Renderer {
27  public:
28   // |owning_renderer| is expected to outlive this class.
29   RendererCommandForwarder(
30       PlaybackCommandForwardingRenderer* owning_renderer,
31       mojo::PendingReceiver<media::mojom::Renderer> playback_controller,
32       scoped_refptr<base::SequencedTaskRunner> task_runner)
33       : owning_renderer_(owning_renderer),
34         playback_controller_(this, std::move(playback_controller)) {
35     DCHECK(owning_renderer_);
36
37     playback_controller_.set_disconnect_handler(base::BindPostTask(
38         std::move(task_runner),
39         base::BindOnce(&PlaybackCommandForwardingRenderer::OnMojoDisconnect,
40                        owning_renderer_->weak_factory_.GetWeakPtr())));
41   }
42
43   ~RendererCommandForwarder() override = default;
44
45   // media::mojom::Renderer overrides.
46 #if defined(TIZEN_MULTIMEDIA)
47   void EnableLowLatencyMode() override {}
48   void SetHardwareResource(
49       media::mojom::HardwareResourceConfig config,
50       media::mojom::Renderer::SetHardwareResourceCallback) override {}
51   void RequestVideoDecodedBuffer(
52       media::mojom::Renderer::RequestVideoDecodedBufferCallback cb) override {}
53 #endif
54   void Initialize(
55       ::mojo::PendingAssociatedRemote<media::mojom::RendererClient> client,
56       absl::optional<
57           std::vector<::mojo::PendingRemote<::media::mojom::DemuxerStream>>>
58           streams,
59       media::mojom::MediaUrlParamsPtr media_url_params,
60       InitializeCallback callback) override {
61     owning_renderer_->MojoRendererInitialize(
62         std::move(client), std::move(streams), std::move(media_url_params),
63         std::move(callback));
64   }
65
66   void StartPlayingFrom(::base::TimeDelta time) override {
67     owning_renderer_->MojoRendererStartPlayingFrom(std::move(time));
68   }
69
70   void SetPlaybackRate(double playback_rate) override {
71     owning_renderer_->MojoRendererSetPlaybackRate(playback_rate);
72   }
73
74   void Flush(FlushCallback callback) override {
75     owning_renderer_->MojoRendererFlush(std::move(callback));
76   }
77
78   void SetVolume(float volume) override {
79     owning_renderer_->MojoRendererSetVolume(volume);
80   }
81
82   void SetCdm(const absl::optional<::base::UnguessableToken>& cdm_id,
83               SetCdmCallback callback) override {
84     owning_renderer_->MojoRendererSetCdm(cdm_id, std::move(callback));
85   }
86
87 #if BUILDFLAG(IS_TIZEN_TV)
88   void SetActiveTextTrack(int, bool) override {}
89   void SetActiveAudioTrack(int) override {}
90   void SetActiveVideoTrack(int) override {}
91   void SetPreferTextLanguage(const std::string&) override {}
92 #endif
93
94  private:
95   const raw_ptr<PlaybackCommandForwardingRenderer, ExperimentalRenderer>
96       owning_renderer_;
97   mojo::Receiver<media::mojom::Renderer> playback_controller_;
98 };
99
100 PlaybackCommandForwardingRenderer::PlaybackCommandForwardingRenderer(
101     std::unique_ptr<media::Renderer> renderer,
102     scoped_refptr<base::SequencedTaskRunner> task_runner,
103     mojo::PendingReceiver<media::mojom::Renderer> pending_renderer_controls)
104     : real_renderer_(std::move(renderer)),
105       pending_renderer_controls_(std::move(pending_renderer_controls)),
106       task_runner_(std::move(task_runner)),
107       weak_factory_(this) {
108   DCHECK(real_renderer_);
109   DCHECK(pending_renderer_controls_);
110   InitializeSendTimestampUpdateCaller();
111 }
112
113 PlaybackCommandForwardingRenderer::~PlaybackCommandForwardingRenderer() =
114     default;
115
116 void PlaybackCommandForwardingRenderer::Initialize(
117     media::MediaResource* media_resource,
118     media::RendererClient* client,
119     media::PipelineStatusCallback init_cb) {
120   DCHECK(!init_cb_);
121
122   upstream_renderer_client_ = client;
123   init_cb_ = std::move(init_cb);
124   real_renderer_->Initialize(
125       media_resource, this,
126       base::BindPostTask(
127           task_runner_, base::BindOnce(&PlaybackCommandForwardingRenderer::
128                                            OnRealRendererInitializationComplete,
129                                        weak_factory_.GetWeakPtr())));
130 }
131
132 void PlaybackCommandForwardingRenderer::SetCdm(media::CdmContext* cdm_context,
133                                                CdmAttachedCB cdm_attached_cb) {
134   // CDM should not be set for current mirroring use cases.
135   NOTREACHED();
136 }
137
138 void PlaybackCommandForwardingRenderer::SetLatencyHint(
139     absl::optional<base::TimeDelta> latency_hint) {
140   // Not relevant for current mirroring use cases.
141 }
142
143 void PlaybackCommandForwardingRenderer::Flush(base::OnceClosure flush_cb) {}
144
145 void PlaybackCommandForwardingRenderer::StartPlayingFrom(base::TimeDelta time) {
146   DCHECK(task_runner_->RunsTasksInCurrentSequence());
147 }
148
149 void PlaybackCommandForwardingRenderer::SetPlaybackRate(double playback_rate) {
150   DCHECK(task_runner_->RunsTasksInCurrentSequence());
151 }
152
153 void PlaybackCommandForwardingRenderer::SetVolume(float volume) {}
154
155 base::TimeDelta PlaybackCommandForwardingRenderer::GetMediaTime() {
156   return real_renderer_ ? real_renderer_->GetMediaTime() : base::TimeDelta();
157 }
158
159 media::RendererType PlaybackCommandForwardingRenderer::GetRendererType() {
160   return media::RendererType::kCastStreaming;
161 }
162
163 void PlaybackCommandForwardingRenderer::OnRealRendererInitializationComplete(
164     media::PipelineStatus status) {
165   DCHECK(init_cb_);
166   DCHECK(!playback_controller_);
167
168   playback_controller_ = std::make_unique<RendererCommandForwarder>(
169       this, std::move(pending_renderer_controls_), task_runner_);
170
171   std::move(init_cb_).Run(status);
172 }
173
174 // NOTE: The mojo pipe CANNOT be bound to task runner |task_runner_| - this will
175 // result in runtime errors on the release branch due to an outdated mojo
176 // implementation. Calls must instead be bounced to the correct task runner in
177 // each receiver method.
178 // TODO(b/205307190): Bind the mojo pipe to the task runner directly.
179 void PlaybackCommandForwardingRenderer::MojoRendererInitialize(
180     ::mojo::PendingAssociatedRemote<media::mojom::RendererClient> client,
181     absl::optional<
182         std::vector<::mojo::PendingRemote<::media::mojom::DemuxerStream>>>
183         streams,
184     media::mojom::MediaUrlParamsPtr media_url_params,
185     media::mojom::Renderer::InitializeCallback callback) {
186   DCHECK(!media_url_params);
187   DCHECK(client);
188
189   // NOTE: To maintain existing functionality, and ensure mirroring continues
190   // working as currently written with or without this Renderer, the mirroring
191   // data stream is provided through the standard Initialize() call, not passed
192   // over the mojo pipe here
193   DCHECK(!streams || streams.value().empty());
194
195   if (!task_runner_->RunsTasksInCurrentSequence()) {
196     task_runner_->PostTask(
197         FROM_HERE,
198         base::BindOnce(
199             &PlaybackCommandForwardingRenderer::MojoRendererInitialize,
200             weak_factory_.GetWeakPtr(), std::move(client), std::move(streams),
201             std::move(media_url_params), std::move(callback)));
202     return;
203   }
204
205   remote_renderer_client_.Bind(std::move(client));
206
207   // |playback_controller_| which forwards the call here is only set following
208   // the completion of real_renderer_->Initialize().
209   std::move(callback).Run(true);
210 }
211
212 void PlaybackCommandForwardingRenderer::MojoRendererFlush(
213     media::mojom::Renderer::FlushCallback callback) {
214   if (!task_runner_->RunsTasksInCurrentSequence()) {
215     task_runner_->PostTask(
216         FROM_HERE,
217         base::BindOnce(&PlaybackCommandForwardingRenderer::MojoRendererFlush,
218                        weak_factory_.GetWeakPtr(), std::move(callback)));
219     return;
220   }
221
222   real_renderer_->Flush(std::move(callback));
223 }
224
225 void PlaybackCommandForwardingRenderer::MojoRendererStartPlayingFrom(
226     ::base::TimeDelta time) {
227   if (!task_runner_->RunsTasksInCurrentSequence()) {
228     task_runner_->PostTask(
229         FROM_HERE,
230         base::BindOnce(
231             &PlaybackCommandForwardingRenderer::MojoRendererStartPlayingFrom,
232             weak_factory_.GetWeakPtr(), time));
233     return;
234   }
235
236   real_renderer_->StartPlayingFrom(time);
237 }
238
239 void PlaybackCommandForwardingRenderer::MojoRendererSetPlaybackRate(
240     double playback_rate) {
241   if (!task_runner_->RunsTasksInCurrentSequence()) {
242     task_runner_->PostTask(
243         FROM_HERE,
244         base::BindOnce(
245             &PlaybackCommandForwardingRenderer::MojoRendererSetPlaybackRate,
246             weak_factory_.GetWeakPtr(), playback_rate));
247     return;
248   }
249
250   real_renderer_->SetPlaybackRate(playback_rate);
251 }
252
253 void PlaybackCommandForwardingRenderer::MojoRendererSetVolume(float volume) {
254   if (!task_runner_->RunsTasksInCurrentSequence()) {
255     task_runner_->PostTask(
256         FROM_HERE,
257         base::BindOnce(
258             &PlaybackCommandForwardingRenderer::MojoRendererSetVolume,
259             weak_factory_.GetWeakPtr(), volume));
260     return;
261   }
262
263   real_renderer_->SetVolume(volume);
264 }
265
266 void PlaybackCommandForwardingRenderer::MojoRendererSetCdm(
267     const absl::optional<::base::UnguessableToken>& cdm_id,
268     media::mojom::Renderer::SetCdmCallback callback) {
269   NOTREACHED() << "Use of a CDM is not supported by the remoting protocol.";
270 }
271
272 void PlaybackCommandForwardingRenderer::OnError(media::PipelineStatus status) {
273   if (remote_renderer_client_) {
274     remote_renderer_client_->OnError(status);
275   }
276   if (upstream_renderer_client_) {
277     upstream_renderer_client_->OnError(status);
278   }
279 }
280
281 void PlaybackCommandForwardingRenderer::OnFallback(
282     media::PipelineStatus status) {}
283
284 void PlaybackCommandForwardingRenderer::OnEnded() {
285   DCHECK(task_runner_->RunsTasksInCurrentSequence());
286
287   if (remote_renderer_client_) {
288     remote_renderer_client_->OnEnded();
289   }
290   if (upstream_renderer_client_) {
291     upstream_renderer_client_->OnEnded();
292   }
293 }
294
295 void PlaybackCommandForwardingRenderer::OnStatisticsUpdate(
296     const media::PipelineStatistics& stats) {
297   DCHECK(task_runner_->RunsTasksInCurrentSequence());
298
299   if (remote_renderer_client_) {
300     remote_renderer_client_->OnStatisticsUpdate(stats);
301   }
302   if (upstream_renderer_client_) {
303     upstream_renderer_client_->OnStatisticsUpdate(stats);
304   }
305 }
306
307 void PlaybackCommandForwardingRenderer::OnBufferingStateChange(
308     media::BufferingState state,
309     media::BufferingStateChangeReason reason) {
310   DCHECK(task_runner_->RunsTasksInCurrentSequence());
311
312   if (remote_renderer_client_) {
313     remote_renderer_client_->OnBufferingStateChange(state, reason);
314   }
315   if (upstream_renderer_client_) {
316     upstream_renderer_client_->OnBufferingStateChange(state, reason);
317   }
318 }
319
320 void PlaybackCommandForwardingRenderer::OnWaiting(media::WaitingReason reason) {
321   DCHECK(task_runner_->RunsTasksInCurrentSequence());
322
323   if (remote_renderer_client_) {
324     remote_renderer_client_->OnWaiting(reason);
325   }
326   if (upstream_renderer_client_) {
327     upstream_renderer_client_->OnWaiting(reason);
328   }
329 }
330
331 void PlaybackCommandForwardingRenderer::OnAudioConfigChange(
332     const media::AudioDecoderConfig& config) {
333   DCHECK(task_runner_->RunsTasksInCurrentSequence());
334
335   if (remote_renderer_client_) {
336     remote_renderer_client_->OnAudioConfigChange(config);
337   }
338   if (upstream_renderer_client_) {
339     upstream_renderer_client_->OnAudioConfigChange(config);
340   }
341 }
342
343 void PlaybackCommandForwardingRenderer::OnVideoConfigChange(
344     const media::VideoDecoderConfig& config) {
345   DCHECK(task_runner_->RunsTasksInCurrentSequence());
346
347   if (remote_renderer_client_) {
348     remote_renderer_client_->OnVideoConfigChange(config);
349   }
350   if (upstream_renderer_client_) {
351     upstream_renderer_client_->OnVideoConfigChange(config);
352   }
353 }
354
355 void PlaybackCommandForwardingRenderer::OnVideoNaturalSizeChange(
356     const gfx::Size& size) {
357   DCHECK(task_runner_->RunsTasksInCurrentSequence());
358
359   if (remote_renderer_client_) {
360     remote_renderer_client_->OnVideoNaturalSizeChange(size);
361   }
362   if (upstream_renderer_client_) {
363     upstream_renderer_client_->OnVideoNaturalSizeChange(size);
364   }
365 }
366
367 void PlaybackCommandForwardingRenderer::OnVideoOpacityChange(bool opaque) {
368   DCHECK(task_runner_->RunsTasksInCurrentSequence());
369
370   if (remote_renderer_client_) {
371     remote_renderer_client_->OnVideoOpacityChange(opaque);
372   }
373   if (upstream_renderer_client_) {
374     upstream_renderer_client_->OnVideoOpacityChange(opaque);
375   }
376 }
377
378 void PlaybackCommandForwardingRenderer::OnVideoFrameRateChange(
379     absl::optional<int> fps) {
380   DCHECK(task_runner_->RunsTasksInCurrentSequence());
381
382   // media::mojom::RendererClient does not support this call.
383   if (upstream_renderer_client_) {
384     upstream_renderer_client_->OnVideoFrameRateChange(std::move(fps));
385   }
386 }
387
388 void PlaybackCommandForwardingRenderer::SendTimestampUpdate() {
389   DCHECK(task_runner_->RunsTasksInCurrentSequence());
390
391   if (!remote_renderer_client_) {
392     return;
393   }
394
395   // Because |remote_renderer_client_| isn't set until |real_renderer_| is
396   // initialized, this call is well defined.
397   base::TimeDelta media_time = real_renderer_->GetMediaTime();
398   remote_renderer_client_->OnTimeUpdate(media_time, media_time,
399                                         base::TimeTicks::Now());
400 }
401
402 void PlaybackCommandForwardingRenderer::InitializeSendTimestampUpdateCaller() {
403   if (!task_runner_->RunsTasksInCurrentSequence()) {
404     task_runner_->PostTask(
405         FROM_HERE, base::BindOnce(&PlaybackCommandForwardingRenderer::
406                                       InitializeSendTimestampUpdateCaller,
407                                   weak_factory_.GetWeakPtr()));
408     return;
409   }
410
411   send_timestamp_update_caller_.Start(
412       FROM_HERE, kTimeUpdateInterval,
413       base::BindPostTask(
414           task_runner_,
415           base::BindRepeating(
416               &PlaybackCommandForwardingRenderer::SendTimestampUpdate,
417               weak_factory_.GetWeakPtr())));
418 }
419
420 void PlaybackCommandForwardingRenderer::OnMojoDisconnect() {
421   DCHECK(task_runner_->RunsTasksInCurrentSequence());
422
423   OnError(media::PIPELINE_ERROR_DISCONNECTED);
424   real_renderer_.reset();
425 }
426
427 }  // namespace cast_streaming