Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / media / remoting / renderer_controller.h
1 // Copyright 2016 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 #ifndef MEDIA_REMOTING_RENDERER_CONTROLLER_H_
6 #define MEDIA_REMOTING_RENDERER_CONTROLLER_H_
7
8 #include <memory>
9
10 #include "base/functional/callback.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/threading/thread_checker.h"
14 #include "base/timer/timer.h"
15 #include "build/build_config.h"
16 #include "build/buildflag.h"
17 #include "media/base/media_observer.h"
18 #include "media/media_buildflags.h"
19 #include "media/mojo/mojom/remoting.mojom.h"
20 #include "media/mojo/mojom/remoting_common.mojom.h"
21 #include "media/remoting/metrics.h"
22 #include "mojo/public/cpp/bindings/pending_receiver.h"
23 #include "mojo/public/cpp/bindings/pending_remote.h"
24 #include "mojo/public/cpp/bindings/receiver.h"
25 #include "mojo/public/cpp/bindings/remote.h"
26
27 #if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC)
28 #include "third_party/openscreen/src/cast/streaming/rpc_messenger.h"  // nogncheck
29 #include "third_party/openscreen/src/util/weak_ptr.h"  // nogncheck
30 #endif
31
32 namespace base {
33 class TickClock;
34 }
35
36 namespace media {
37
38 namespace remoting {
39
40 // This class monitors player events as a MediaObserver and may trigger the
41 // switch of the media renderer between local playback and remoting.
42 class RendererController final : public mojom::RemotingSource,
43                                  public MediaObserver {
44  public:
45   RendererController(
46       mojo::PendingReceiver<mojom::RemotingSource> source_receiver,
47       mojo::PendingRemote<mojom::Remoter> remoter);
48
49   RendererController(const RendererController&) = delete;
50   RendererController& operator=(const RendererController&) = delete;
51
52   ~RendererController() override;
53
54   // mojom::RemotingSource implementations.
55   void OnSinkAvailable(mojom::RemotingSinkMetadataPtr metadata) override;
56   void OnSinkGone() override;
57   void OnStarted() override;
58   void OnStartFailed(mojom::RemotingStartFailReason reason) override;
59   void OnMessageFromSink(const std::vector<uint8_t>& message) override;
60   void OnStopped(mojom::RemotingStopReason reason) override;
61
62   // MediaObserver implementation.
63   void OnBecameDominantVisibleContent(bool is_dominant) override;
64   void OnMetadataChanged(const PipelineMetadata& metadata) override;
65   void OnRemotePlaybackDisabled(bool disabled) override;
66   void OnMediaRemotingRequested() override;
67   void OnPlaying() override;
68   void OnPaused() override;
69   void OnFrozen() override;
70   void OnDataSourceInitialized(const GURL& url_after_redirects) override;
71   void OnHlsManifestDetected() override;
72   void SetClient(MediaObserverClient* client) override;
73
74   base::WeakPtr<RendererController> GetWeakPtr() {
75     return weak_factory_.GetWeakPtr();
76   }
77
78   // Used by AdaptiveRendererFactory to query whether to create a Media
79   // Remoting Renderer.
80   bool remote_rendering_started() const {
81     DCHECK(thread_checker_.CalledOnValidThread());
82     return remote_rendering_started_;
83   }
84
85   using DataPipeStartCallback = base::OnceCallback<void(
86       mojo::PendingRemote<mojom::RemotingDataStreamSender> audio,
87       mojo::PendingRemote<mojom::RemotingDataStreamSender> video,
88       mojo::ScopedDataPipeProducerHandle audio_handle,
89       mojo::ScopedDataPipeProducerHandle video_handle)>;
90   // Creates up to two data pipes with a byte capacity of |data_pipe_capacity|:
91   // one for audio if |audio| is true and one for |video| if video is true. The
92   // controller then starts processing the consumer ends of the data pipes,
93   // with the producer ends supplied to the |done_callback|.
94   void StartDataPipe(uint32_t data_pipe_capacity,
95                      bool audio,
96                      bool video,
97                      DataPipeStartCallback done_callback);
98
99 #if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC)
100   openscreen::WeakPtr<openscreen::cast::RpcMessenger> GetRpcMessenger();
101 #endif
102
103   // Called by CourierRenderer when it encountered a fatal error. This will
104   // cause remoting to shut down. Media remoting might be re-tried after the
105   // media element stops and re-starts being the dominant visible content in the
106   // tab.
107   void OnRendererFatalError(StopTrigger stop_trigger);
108
109  private:
110   friend class RendererControllerTest;
111
112   bool has_audio() const {
113     return pipeline_metadata_.has_audio &&
114            pipeline_metadata_.audio_decoder_config.IsValidConfig();
115   }
116
117   bool has_video() const {
118     return pipeline_metadata_.has_video &&
119            pipeline_metadata_.video_decoder_config.IsValidConfig();
120   }
121
122   // Called when the session availability state may have changed. Each call to
123   // this method could cause a remoting session to be started or stopped; and if
124   // that happens, the |start_trigger| or |stop_trigger| must be the reason.
125   void UpdateFromSessionState(StartTrigger start_trigger,
126                               StopTrigger stop_trigger);
127
128   bool IsVideoCodecSupported() const;
129   bool IsAudioCodecSupported() const;
130   bool IsAudioOrVideoSupported() const;
131
132   // Returns |kCompatible| if all of the technical requirements for the media
133   // pipeline and remote rendering are being met, and the first detected
134   // reason if incompatible. This does not include environmental conditions,
135   // such as the content being dominant in the viewport, available network
136   // bandwidth, etc.
137   RemotingCompatibility GetVideoCompatibility() const;
138   RemotingCompatibility GetAudioCompatibility() const;
139   RemotingCompatibility GetCompatibility() const;
140
141   // Determines whether to enter or leave Remoting mode and switches if
142   // necessary. Each call to this method could cause a remoting session to be
143   // started or stopped; and if that happens, the |start_trigger| or
144   // |stop_trigger| must be the reason.
145   void UpdateAndMaybeSwitch(StartTrigger start_trigger,
146                             StopTrigger stop_trigger);
147
148   // Activates or deactivates the remote playback monitoring based on whether
149   // the element is compatible with Remote Playback API.
150   void UpdateRemotePlaybackAvailabilityMonitoringState();
151
152   // Queries on remoting sink capabilities.
153   bool HasVideoCapability(mojom::RemotingSinkVideoCapability capability) const;
154   bool HasAudioCapability(mojom::RemotingSinkAudioCapability capability) const;
155   bool HasFeatureCapability(mojom::RemotingSinkFeature capability) const;
156   bool SinkSupportsRemoting() const;
157   bool ShouldBeRemoting();
158
159   // Start `pixel_rate_timer_` to calculate pixel rate.
160   void MaybeStartCalculatePixelRateTimer();
161   void DoCalculatePixelRate(int decoded_frame_count_before_delay,
162                             base::TimeTicks delayed_start_time);
163   PixelRateSupport GetPixelRateSupport() const;
164
165   // Callback from RpcMessenger when sending message to remote sink.
166   void SendMessageToSink(std::vector<uint8_t> message);
167
168 #if BUILDFLAG(IS_ANDROID)
169   bool IsAudioRemotePlaybackSupported() const;
170   bool IsVideoRemotePlaybackSupported() const;
171   bool IsRemotePlaybackSupported() const;
172 #endif  // BUILDFLAG(IS_ANDROID)
173
174 #if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC)
175   // Handles dispatching of incoming and outgoing RPC messages.
176   openscreen::cast::RpcMessenger rpc_messenger_;
177 #endif
178
179   const mojo::Receiver<mojom::RemotingSource> receiver_;
180   const mojo::Remote<mojom::Remoter> remoter_;
181
182   // When the sink is available for remoting, this describes its metadata. When
183   // not available, this is empty. Updated by OnSinkAvailable/Gone().
184   mojom::RemotingSinkMetadataPtr sink_metadata_;
185
186   // Indicates whether remoting is started.
187   bool remote_rendering_started_ = false;
188
189   // Indicates whether remote playback is currently disabled. This starts out as
190   // true, and should be updated at least once via a call to
191   // OnRemotePlaybackDisabled() at some point in the future. A web page
192   // typically sets/removes the disableRemotePlayback attribute on a
193   // HTMLMediaElement to disable/enable remoting of its content. Please see the
194   // Remote Playback API spec for more details:
195   // https://w3c.github.io/remote-playback
196   bool is_remote_playback_disabled_ = true;
197
198   // Indicates whether video is the dominant visible content in the tab.
199   bool is_dominant_content_ = false;
200
201   // Indicates whether video is paused.
202   bool is_paused_ = true;
203
204   // Indicates whether OnRendererFatalError() has been called. This indicates
205   // one of several possible problems: 1) An environmental problem such as
206   // out-of-memory, insufficient network bandwidth, etc. 2) The receiver may
207   // have been unable to play-out the content correctly (e.g., not capable of a
208   // high frame rate at a high resolution). 3) An implementation bug. In any
209   // case, once a renderer encounters a fatal error, remoting will be shut down.
210   // The value gets reset after the media element stops being the dominant
211   // visible content in the tab.
212   bool encountered_renderer_fatal_error_ = false;
213
214   // This is used to check all the methods are called on the current thread in
215   // debug builds.
216   base::ThreadChecker thread_checker_;
217
218   // Current pipeline metadata.
219   PipelineMetadata pipeline_metadata_;
220
221   // Current data source information.
222   GURL url_after_redirects_;
223
224   bool is_hls_ = false;
225
226   // True if the browser has requested to start remoting without fullscreening
227   // the media content. The value is reset to False when it switches back to
228   // local rendering.
229   bool is_media_remoting_requested_ = false;
230
231   // Records session events of interest.
232   SessionMetricsRecorder metrics_recorder_;
233
234   // Not owned by this class. Can only be set once by calling SetClient().
235   raw_ptr<MediaObserverClient> client_ = nullptr;
236
237   // This timer is used to calculate the media content's pixel rate. The timer
238   // is stopped when the media playback is paused or when the media metadata
239   // changed.
240   base::OneShotTimer pixel_rate_timer_;
241
242   // Current pixel rate. Its value is reset to 0 when
243   // pipeline_metadata_.natural_size changes.
244   double pixels_per_second_ = 0;
245
246   raw_ptr<const base::TickClock> clock_;
247
248   base::WeakPtrFactory<RendererController> weak_factory_{this};
249 };
250
251 }  // namespace remoting
252 }  // namespace media
253
254 #endif  // MEDIA_REMOTING_RENDERER_CONTROLLER_H_