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.
5 #ifndef MEDIA_REMOTING_COURIER_RENDERER_H_
6 #define MEDIA_REMOTING_COURIER_RENDERER_H_
12 #include "base/containers/circular_deque.h"
13 #include "base/functional/callback.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/synchronization/lock.h"
18 #include "base/task/sequenced_task_runner.h"
19 #include "base/task/single_thread_task_runner.h"
20 #include "base/time/time.h"
21 #include "base/timer/timer.h"
22 #include "media/base/pipeline_status.h"
23 #include "media/base/renderer.h"
24 #include "media/mojo/mojom/remoting.mojom.h"
25 #include "media/remoting/metrics.h"
26 #include "mojo/public/cpp/bindings/pending_remote.h"
27 #include "mojo/public/cpp/system/data_pipe.h"
28 #include "third_party/abseil-cpp/absl/types/optional.h"
29 #include "third_party/openscreen/src/cast/streaming/remoting.pb.h"
30 #include "third_party/openscreen/src/cast/streaming/rpc_messenger.h"
31 #include "third_party/openscreen/src/util/weak_ptr.h"
36 class VideoRendererSink;
40 class DemuxerStreamAdapter;
41 class RendererController;
43 // A media::Renderer implementation that proxies all operations to a remote
44 // renderer via RPCs. The CourierRenderer is instantiated by
45 // AdaptiveRendererFactory when media remoting is meant to take place.
46 class CourierRenderer final : public Renderer {
48 // The whole class except for constructor and GetMediaTime() runs on
49 // |media_task_runner|. The constructor and GetMediaTime() run on render main
51 CourierRenderer(scoped_refptr<base::SequencedTaskRunner> media_task_runner,
52 const base::WeakPtr<RendererController>& controller,
53 VideoRendererSink* video_renderer_sink);
55 CourierRenderer(const CourierRenderer&) = delete;
56 CourierRenderer& operator=(const CourierRenderer&) = delete;
58 ~CourierRenderer() final;
61 // Callback when attempting to establish data pipe. The function is set to
62 // static in order to post task to media thread in order to avoid threading
64 static void OnDataPipeCreatedOnMainThread(
65 scoped_refptr<base::SequencedTaskRunner> media_task_runner,
66 base::WeakPtr<CourierRenderer> self,
67 openscreen::WeakPtr<openscreen::cast::RpcMessenger> rpc_messenger,
68 mojo::PendingRemote<mojom::RemotingDataStreamSender> audio,
69 mojo::PendingRemote<mojom::RemotingDataStreamSender> video,
70 mojo::ScopedDataPipeProducerHandle audio_handle,
71 mojo::ScopedDataPipeProducerHandle video_handle);
73 // Callback function when RPC message is received. The function is set to
74 // static in order to post task to media thread in order to avoid threading
76 static void OnMessageReceivedOnMainThread(
77 scoped_refptr<base::SequencedTaskRunner> media_task_runner,
78 base::WeakPtr<CourierRenderer> self,
79 std::unique_ptr<openscreen::cast::RpcMessage> message);
82 // media::Renderer implementation.
83 void Initialize(MediaResource* media_resource,
84 RendererClient* client,
85 PipelineStatusCallback init_cb) final;
86 void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint) final;
87 void Flush(base::OnceClosure flush_cb) final;
88 void StartPlayingFrom(base::TimeDelta time) final;
89 void SetPlaybackRate(double playback_rate) final;
90 void SetVolume(float volume) final;
91 base::TimeDelta GetMediaTime() final;
92 RendererType GetRendererType() final;
95 friend class CourierRendererTest;
107 // Callback when attempting to establish data pipe. Runs on media thread only.
108 void OnDataPipeCreated(
109 mojo::PendingRemote<mojom::RemotingDataStreamSender> audio,
110 mojo::PendingRemote<mojom::RemotingDataStreamSender> video,
111 mojo::ScopedDataPipeProducerHandle audio_handle,
112 mojo::ScopedDataPipeProducerHandle video_handle,
113 int audio_rpc_handle,
114 int video_rpc_handle);
116 // Callback function when RPC message is received. Runs on media thread only.
117 void OnReceivedRpc(std::unique_ptr<openscreen::cast::RpcMessage> message);
119 // Function to post task to main thread in order to send RPC message.
120 void SendRpcToRemote(std::unique_ptr<openscreen::cast::RpcMessage> message);
122 // Functions when RPC message is received.
123 void AcquireRendererDone(
124 std::unique_ptr<openscreen::cast::RpcMessage> message);
125 void InitializeCallback(
126 std::unique_ptr<openscreen::cast::RpcMessage> message);
127 void FlushUntilCallback();
128 void OnTimeUpdate(std::unique_ptr<openscreen::cast::RpcMessage> message);
129 void OnBufferingStateChange(
130 std::unique_ptr<openscreen::cast::RpcMessage> message);
131 void OnAudioConfigChange(
132 std::unique_ptr<openscreen::cast::RpcMessage> message);
133 void OnVideoConfigChange(
134 std::unique_ptr<openscreen::cast::RpcMessage> message);
135 void OnVideoNaturalSizeChange(
136 std::unique_ptr<openscreen::cast::RpcMessage> message);
137 void OnVideoOpacityChange(
138 std::unique_ptr<openscreen::cast::RpcMessage> message);
139 void OnStatisticsUpdate(
140 std::unique_ptr<openscreen::cast::RpcMessage> message);
142 // Called when |current_media_time_| is updated.
143 void OnMediaTimeUpdated();
145 // Called to update the |video_stats_queue_|.
146 void UpdateVideoStatsQueue(int video_frames_decoded,
147 int video_frames_dropped);
149 // Called to clear all recent measurements history and schedule resuming after
150 // a stabilization period elapses.
151 void ResetMeasurements();
153 // Called when a fatal runtime error occurs. |stop_trigger| is the error code
154 // handed to the RendererController.
155 void OnFatalError(StopTrigger stop_trigger);
157 // Called periodically to measure the data flows from the
158 // DemuxerStreamAdapters and record this information in the metrics.
159 void MeasureAndRecordDataRates();
161 // Helper to check whether is waiting for data from the Demuxers while
162 // receiver is waiting for buffering. If yes, remoting will be continued even
163 // though the playback might be delayed or paused.
164 bool IsWaitingForDataFromDemuxers() const;
166 // Helpers to register/deregister the renderer with the RPC messenger. These
167 // must be called on the media thread to dereference the weak pointer to
168 // this, which if contains a valid RPC messenger pointer will result in a
169 // jump to the main thread.
170 void RegisterForRpcMessaging();
171 void DeregisterFromRpcMessaging();
174 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
175 const scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
177 // Current renderer playback time information.
178 base::TimeDelta current_media_time_;
179 base::TimeDelta current_max_time_;
180 // Both |current_media_time_| and |current_max_time_| should be protected by
181 // lock because it can be accessed from both media and render main thread.
182 base::Lock time_lock_;
184 raw_ptr<MediaResource> media_resource_;
185 raw_ptr<RendererClient> client_;
186 std::unique_ptr<DemuxerStreamAdapter> audio_demuxer_stream_adapter_;
187 std::unique_ptr<DemuxerStreamAdapter> video_demuxer_stream_adapter_;
189 // Component to establish mojo remoting service on browser process.
190 const base::WeakPtr<RendererController> controller_;
192 // Broker class to process incoming and outgoing RPC messages.
193 // Only accessed on |main_task_runner_|. NOTE: the messenger is wrapped
194 // in an |openscreen::WeakPtr| instead of |base|'s implementation due to
195 // it being defined in the third_party/openscreen repository.
196 const openscreen::WeakPtr<openscreen::cast::RpcMessenger> rpc_messenger_;
198 // RPC handle value for CourierRenderer component.
199 const int rpc_handle_;
201 // RPC handle value for render on receiver endpoint.
202 int remote_renderer_handle_;
205 PipelineStatusCallback init_workflow_done_callback_;
206 base::OnceClosure flush_cb_;
208 const raw_ptr<VideoRendererSink>
209 video_renderer_sink_; // Outlives this class.
211 // Current playback rate.
212 double playback_rate_ = 0;
215 float volume_ = 1.0f;
217 // Ignores updates until this time.
218 base::TimeTicks ignore_updates_until_time_;
220 // Indicates whether stats has been updated.
221 bool stats_updated_ = false;
223 // Stores all |current_media_time_| and the local time when updated in the
224 // moving time window. This is used to check whether the playback duration
225 // matches the update duration in the window.
226 base::circular_deque<std::pair<base::TimeTicks, base::TimeDelta>>
229 // Stores all updates on the number of video frames decoded/dropped, and the
230 // local time when updated in the moving time window. This is used to check
231 // whether too many video frames were dropped.
232 base::circular_deque<std::tuple<base::TimeTicks, int, int>>
235 // The total number of frames decoded/dropped in the time window.
236 int sum_video_frames_decoded_ = 0;
237 int sum_video_frames_dropped_ = 0;
239 // Records the number of consecutive times that remoting playback was delayed.
240 int times_playback_delayed_ = 0;
242 // Records events and measurements of interest.
243 RendererMetricsRecorder metrics_recorder_;
245 raw_ptr<const base::TickClock> clock_;
247 // A timer that polls the DemuxerStreamAdapters periodically to measure
248 // the data flow rates for metrics.
249 base::RepeatingTimer data_flow_poll_timer_;
251 // Indicates whether is waiting for data from the Demuxers while receiver
252 // reported buffer underflow.
253 bool receiver_is_blocked_on_local_demuxers_ = true;
255 base::WeakPtrFactory<CourierRenderer> weak_factory_{this};
258 } // namespace remoting
261 #endif // MEDIA_REMOTING_COURIER_RENDERER_H_