OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/remoting/remote_renderer_impl.h" | 5 #include "media/remoting/remote_renderer_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> |
8 #include <utility> | 9 #include <utility> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
12 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
14 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/numerics/safe_math.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 17 #include "base/threading/thread_task_runner_handle.h" |
16 #include "base/time/time.h" | 18 #include "base/time/time.h" |
17 #include "media/base/bind_to_current_loop.h" | 19 #include "media/base/bind_to_current_loop.h" |
18 #include "media/base/demuxer_stream_provider.h" | 20 #include "media/base/demuxer_stream_provider.h" |
19 #include "media/remoting/remote_demuxer_stream_adapter.h" | 21 #include "media/remoting/remote_demuxer_stream_adapter.h" |
20 #include "media/remoting/remoting_renderer_controller.h" | 22 #include "media/remoting/remoting_renderer_controller.h" |
21 #include "media/remoting/rpc/proto_enum_utils.h" | 23 #include "media/remoting/rpc/proto_enum_utils.h" |
22 #include "media/remoting/rpc/proto_utils.h" | 24 #include "media/remoting/rpc/proto_utils.h" |
23 | 25 |
24 namespace { | 26 namespace { |
25 | 27 |
26 // The moving time window to track the media time and statistics updates. | 28 // The moving time window to track the media time and statistics updates. |
27 constexpr base::TimeDelta kTrackingWindow = base::TimeDelta::FromSeconds(3); | 29 constexpr base::TimeDelta kTrackingWindow = base::TimeDelta::FromSeconds(3); |
28 | 30 |
29 // The allowed delay for the remoting playback. When exceeds this limit, the | 31 // The allowed delay for the remoting playback. When exceeds this limit, the |
30 // user experience is likely poor and the controller is notified. | 32 // user experience is likely poor and the controller is notified. |
31 constexpr base::TimeDelta kMediaPlaybackDelayThreshold = | 33 constexpr base::TimeDelta kMediaPlaybackDelayThreshold = |
32 base::TimeDelta::FromMilliseconds(450); | 34 base::TimeDelta::FromMilliseconds(450); |
33 | 35 |
34 // The allowed percentage of the number of video frames dropped vs. the number | 36 // The allowed percentage of the number of video frames dropped vs. the number |
35 // of the video frames decoded. When exceeds this limit, the user experience is | 37 // of the video frames decoded. When exceeds this limit, the user experience is |
36 // likely poor and the controller is notified. | 38 // likely poor and the controller is notified. |
37 constexpr int kMaxNumVideoFramesDroppedPercentage = 3; | 39 constexpr int kMaxNumVideoFramesDroppedPercentage = 3; |
38 | 40 |
39 // The time period to allow receiver get stable after playback rate change or | 41 // The time period to allow receiver get stable after playback rate change or |
40 // Flush(). | 42 // Flush(). |
41 constexpr base::TimeDelta kStabilizationPeriod = | 43 constexpr base::TimeDelta kStabilizationPeriod = |
42 base::TimeDelta::FromSeconds(2); | 44 base::TimeDelta::FromSeconds(2); |
43 } | 45 |
| 46 // The amount of time between polling the DemuxerStreamAdapters to measure their |
| 47 // data flow rates for metrics. |
| 48 constexpr base::TimeDelta kDataFlowPollPeriod = |
| 49 base::TimeDelta::FromSeconds(10); |
| 50 |
| 51 } // namespace |
44 | 52 |
45 namespace media { | 53 namespace media { |
46 | 54 |
47 RemoteRendererImpl::RemoteRendererImpl( | 55 RemoteRendererImpl::RemoteRendererImpl( |
48 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, | 56 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, |
49 const base::WeakPtr<RemotingRendererController>& | 57 const base::WeakPtr<RemotingRendererController>& |
50 remoting_renderer_controller, | 58 remoting_renderer_controller, |
51 VideoRendererSink* video_renderer_sink) | 59 VideoRendererSink* video_renderer_sink) |
52 : state_(STATE_UNINITIALIZED), | 60 : state_(STATE_UNINITIALIZED), |
53 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 61 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 } | 103 } |
96 | 104 |
97 void RemoteRendererImpl::Initialize( | 105 void RemoteRendererImpl::Initialize( |
98 DemuxerStreamProvider* demuxer_stream_provider, | 106 DemuxerStreamProvider* demuxer_stream_provider, |
99 media::RendererClient* client, | 107 media::RendererClient* client, |
100 const PipelineStatusCB& init_cb) { | 108 const PipelineStatusCB& init_cb) { |
101 VLOG(2) << __func__; | 109 VLOG(2) << __func__; |
102 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 110 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
103 DCHECK(demuxer_stream_provider); | 111 DCHECK(demuxer_stream_provider); |
104 DCHECK(client); | 112 DCHECK(client); |
105 DCHECK(media_task_runner_->RunsTasksOnCurrentThread()); | 113 |
106 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 114 if (state_ != STATE_UNINITIALIZED) { |
| 115 media_task_runner_->PostTask( |
| 116 FROM_HERE, base::Bind(init_cb, PIPELINE_ERROR_INVALID_STATE)); |
| 117 return; |
| 118 } |
| 119 |
107 demuxer_stream_provider_ = demuxer_stream_provider; | 120 demuxer_stream_provider_ = demuxer_stream_provider; |
108 client_ = client; | 121 client_ = client; |
109 init_workflow_done_callback_ = init_cb; | 122 init_workflow_done_callback_ = init_cb; |
110 | 123 |
111 state_ = STATE_CREATE_PIPE; | 124 state_ = STATE_CREATE_PIPE; |
112 // Create audio mojo data pipe handles if audio is available. | 125 // Create audio mojo data pipe handles if audio is available. |
113 ::media::DemuxerStream* audio_demuxer_stream = | 126 ::media::DemuxerStream* audio_demuxer_stream = |
114 demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO); | 127 demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO); |
115 std::unique_ptr<mojo::DataPipe> audio_data_pipe; | 128 std::unique_ptr<mojo::DataPipe> audio_data_pipe; |
116 if (audio_demuxer_stream) { | 129 if (audio_demuxer_stream) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 } | 161 } |
149 } | 162 } |
150 | 163 |
151 void RemoteRendererImpl::Flush(const base::Closure& flush_cb) { | 164 void RemoteRendererImpl::Flush(const base::Closure& flush_cb) { |
152 VLOG(2) << __func__; | 165 VLOG(2) << __func__; |
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 166 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
154 DCHECK(flush_cb_.is_null()); | 167 DCHECK(flush_cb_.is_null()); |
155 | 168 |
156 if (state_ != STATE_PLAYING) { | 169 if (state_ != STATE_PLAYING) { |
157 DCHECK_EQ(state_, STATE_ERROR); | 170 DCHECK_EQ(state_, STATE_ERROR); |
| 171 // In the error state, this renderer will be shut down shortly. To prevent |
| 172 // breaking the pipeline impl, just run the done callback (interface |
| 173 // requirement). |
| 174 media_task_runner_->PostTask(FROM_HERE, flush_cb); |
158 return; | 175 return; |
159 } | 176 } |
160 | 177 |
161 state_ = STATE_FLUSHING; | 178 state_ = STATE_FLUSHING; |
162 base::Optional<uint32_t> flush_audio_count; | 179 base::Optional<uint32_t> flush_audio_count; |
163 if (audio_demuxer_stream_adapter_) | 180 if (audio_demuxer_stream_adapter_) |
164 flush_audio_count = audio_demuxer_stream_adapter_->SignalFlush(true); | 181 flush_audio_count = audio_demuxer_stream_adapter_->SignalFlush(true); |
165 base::Optional<uint32_t> flush_video_count; | 182 base::Optional<uint32_t> flush_video_count; |
166 if (video_demuxer_stream_adapter_) | 183 if (video_demuxer_stream_adapter_) |
167 flush_video_count = video_demuxer_stream_adapter_->SignalFlush(true); | 184 flush_video_count = video_demuxer_stream_adapter_->SignalFlush(true); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_STARTPLAYINGFROM); | 227 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_STARTPLAYINGFROM); |
211 rpc->set_integer64_value(time.InMicroseconds()); | 228 rpc->set_integer64_value(time.InMicroseconds()); |
212 VLOG(2) << __func__ << ": Sending RPC_R_STARTPLAYINGFROM to " << rpc->handle() | 229 VLOG(2) << __func__ << ": Sending RPC_R_STARTPLAYINGFROM to " << rpc->handle() |
213 << " with time_usec=" << rpc->integer64_value(); | 230 << " with time_usec=" << rpc->integer64_value(); |
214 SendRpcToRemote(std::move(rpc)); | 231 SendRpcToRemote(std::move(rpc)); |
215 | 232 |
216 { | 233 { |
217 base::AutoLock auto_lock(time_lock_); | 234 base::AutoLock auto_lock(time_lock_); |
218 current_media_time_ = time; | 235 current_media_time_ = time; |
219 } | 236 } |
220 ResetQueues(); | 237 ResetMeasurements(); |
221 } | 238 } |
222 | 239 |
223 void RemoteRendererImpl::SetPlaybackRate(double playback_rate) { | 240 void RemoteRendererImpl::SetPlaybackRate(double playback_rate) { |
224 VLOG(2) << __func__ << ": " << playback_rate; | 241 VLOG(2) << __func__ << ": " << playback_rate; |
225 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 242 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
226 | 243 |
227 if (state_ != STATE_PLAYING) | 244 if (state_ != STATE_FLUSHING && state_ != STATE_PLAYING) { |
| 245 DCHECK_EQ(state_, STATE_ERROR); |
228 return; | 246 return; |
| 247 } |
229 | 248 |
230 // Issues RPC_R_SETPLAYBACKRATE RPC message. | 249 // Issues RPC_R_SETPLAYBACKRATE RPC message. |
231 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); | 250 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); |
232 rpc->set_handle(remote_renderer_handle_); | 251 rpc->set_handle(remote_renderer_handle_); |
233 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_SETPLAYBACKRATE); | 252 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_SETPLAYBACKRATE); |
234 rpc->set_double_value(playback_rate); | 253 rpc->set_double_value(playback_rate); |
235 VLOG(2) << __func__ << ": Sending RPC_R_SETPLAYBACKRATE to " << rpc->handle() | 254 VLOG(2) << __func__ << ": Sending RPC_R_SETPLAYBACKRATE to " << rpc->handle() |
236 << " with rate=" << rpc->double_value(); | 255 << " with rate=" << rpc->double_value(); |
237 SendRpcToRemote(std::move(rpc)); | 256 SendRpcToRemote(std::move(rpc)); |
238 playback_rate_ = playback_rate; | 257 playback_rate_ = playback_rate; |
239 ResetQueues(); | 258 ResetMeasurements(); |
240 } | 259 } |
241 | 260 |
242 void RemoteRendererImpl::SetVolume(float volume) { | 261 void RemoteRendererImpl::SetVolume(float volume) { |
243 VLOG(2) << __func__ << ": " << volume; | 262 VLOG(2) << __func__ << ": " << volume; |
244 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 263 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
245 | 264 |
| 265 if (state_ != STATE_FLUSHING && state_ != STATE_PLAYING) { |
| 266 DCHECK_EQ(state_, STATE_ERROR); |
| 267 return; |
| 268 } |
| 269 |
246 // Issues RPC_R_SETVOLUME RPC message. | 270 // Issues RPC_R_SETVOLUME RPC message. |
247 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); | 271 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); |
248 rpc->set_handle(remote_renderer_handle_); | 272 rpc->set_handle(remote_renderer_handle_); |
249 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_SETVOLUME); | 273 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_SETVOLUME); |
250 rpc->set_double_value(volume); | 274 rpc->set_double_value(volume); |
251 VLOG(2) << __func__ << ": Sending RPC_R_SETVOLUME to " << rpc->handle() | 275 VLOG(2) << __func__ << ": Sending RPC_R_SETVOLUME to " << rpc->handle() |
252 << " with volume=" << rpc->double_value(); | 276 << " with volume=" << rpc->double_value(); |
253 SendRpcToRemote(std::move(rpc)); | 277 SendRpcToRemote(std::move(rpc)); |
254 } | 278 } |
255 | 279 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 void RemoteRendererImpl::OnDataPipeCreated( | 311 void RemoteRendererImpl::OnDataPipeCreated( |
288 mojom::RemotingDataStreamSenderPtrInfo audio, | 312 mojom::RemotingDataStreamSenderPtrInfo audio, |
289 mojom::RemotingDataStreamSenderPtrInfo video, | 313 mojom::RemotingDataStreamSenderPtrInfo video, |
290 mojo::ScopedDataPipeProducerHandle audio_handle, | 314 mojo::ScopedDataPipeProducerHandle audio_handle, |
291 mojo::ScopedDataPipeProducerHandle video_handle, | 315 mojo::ScopedDataPipeProducerHandle video_handle, |
292 int audio_rpc_handle, | 316 int audio_rpc_handle, |
293 int video_rpc_handle) { | 317 int video_rpc_handle) { |
294 VLOG(2) << __func__; | 318 VLOG(2) << __func__; |
295 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 319 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
296 DCHECK(!init_workflow_done_callback_.is_null()); | 320 DCHECK(!init_workflow_done_callback_.is_null()); |
| 321 |
| 322 if (state_ == STATE_ERROR) |
| 323 return; // Abort because something went wrong in the meantime. |
297 DCHECK_EQ(state_, STATE_CREATE_PIPE); | 324 DCHECK_EQ(state_, STATE_CREATE_PIPE); |
298 | 325 |
299 // Create audio demuxer stream adapter if audio is available. | 326 // Create audio demuxer stream adapter if audio is available. |
300 ::media::DemuxerStream* audio_demuxer_stream = | 327 ::media::DemuxerStream* audio_demuxer_stream = |
301 demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO); | 328 demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO); |
302 if (audio_demuxer_stream && audio.is_valid() && audio_handle.is_valid() && | 329 if (audio_demuxer_stream && audio.is_valid() && audio_handle.is_valid() && |
303 audio_rpc_handle != remoting::kInvalidHandle) { | 330 audio_rpc_handle != remoting::kInvalidHandle) { |
304 VLOG(2) << "Initialize audio"; | 331 VLOG(2) << "Initialize audio"; |
305 audio_demuxer_stream_adapter_.reset( | 332 audio_demuxer_stream_adapter_.reset( |
306 new remoting::RemoteDemuxerStreamAdapter( | 333 new remoting::RemoteDemuxerStreamAdapter( |
307 main_task_runner_, media_task_runner_, "audio", | 334 main_task_runner_, media_task_runner_, "audio", |
308 audio_demuxer_stream, rpc_broker_, audio_rpc_handle, | 335 audio_demuxer_stream, rpc_broker_, audio_rpc_handle, |
309 std::move(audio), std::move(audio_handle))); | 336 std::move(audio), std::move(audio_handle), |
| 337 base::Bind(&RemoteRendererImpl::OnFatalError, |
| 338 base::Unretained(this)))); |
310 } | 339 } |
311 | 340 |
312 // Create video demuxer stream adapter if video is available. | 341 // Create video demuxer stream adapter if video is available. |
313 ::media::DemuxerStream* video_demuxer_stream = | 342 ::media::DemuxerStream* video_demuxer_stream = |
314 demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO); | 343 demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO); |
315 if (video_demuxer_stream && video.is_valid() && video_handle.is_valid() && | 344 if (video_demuxer_stream && video.is_valid() && video_handle.is_valid() && |
316 video_rpc_handle != remoting::kInvalidHandle) { | 345 video_rpc_handle != remoting::kInvalidHandle) { |
317 VLOG(2) << "Initialize video"; | 346 VLOG(2) << "Initialize video"; |
318 video_demuxer_stream_adapter_.reset( | 347 video_demuxer_stream_adapter_.reset( |
319 new remoting::RemoteDemuxerStreamAdapter( | 348 new remoting::RemoteDemuxerStreamAdapter( |
320 main_task_runner_, media_task_runner_, "video", | 349 main_task_runner_, media_task_runner_, "video", |
321 video_demuxer_stream, rpc_broker_, video_rpc_handle, | 350 video_demuxer_stream, rpc_broker_, video_rpc_handle, |
322 std::move(video), std::move(video_handle))); | 351 std::move(video), std::move(video_handle), |
| 352 base::Bind(&RemoteRendererImpl::OnFatalError, |
| 353 base::Unretained(this)))); |
323 } | 354 } |
324 | 355 |
325 // Checks if data pipe is created successfully. | 356 // Checks if data pipe is created successfully. |
326 if (!audio_demuxer_stream_adapter_ && !video_demuxer_stream_adapter_) { | 357 if (!audio_demuxer_stream_adapter_ && !video_demuxer_stream_adapter_) { |
327 OnFatalError(PIPELINE_ERROR_ABORT); | 358 OnFatalError(remoting::DATA_PIPE_CREATE_ERROR); |
328 return; | 359 return; |
329 } | 360 } |
330 | 361 |
331 state_ = STATE_ACQUIRING; | 362 state_ = STATE_ACQUIRING; |
332 // Issues RPC_ACQUIRE_RENDERER RPC message. | 363 // Issues RPC_ACQUIRE_RENDERER RPC message. |
333 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); | 364 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); |
334 rpc->set_handle(remoting::kReceiverHandle); | 365 rpc->set_handle(remoting::kReceiverHandle); |
335 rpc->set_proc(remoting::pb::RpcMessage::RPC_ACQUIRE_RENDERER); | 366 rpc->set_proc(remoting::pb::RpcMessage::RPC_ACQUIRE_RENDERER); |
336 rpc->set_integer_value(rpc_handle_); | 367 rpc->set_integer_value(rpc_handle_); |
337 VLOG(2) << __func__ << ": Sending RPC_ACQUIRE_RENDERER to " << rpc->handle() | 368 VLOG(2) << __func__ << ": Sending RPC_ACQUIRE_RENDERER to " << rpc->handle() |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 break; | 402 break; |
372 case remoting::pb::RpcMessage::RPC_RC_ONBUFFERINGSTATECHANGE: | 403 case remoting::pb::RpcMessage::RPC_RC_ONBUFFERINGSTATECHANGE: |
373 OnBufferingStateChange(std::move(message)); | 404 OnBufferingStateChange(std::move(message)); |
374 break; | 405 break; |
375 case remoting::pb::RpcMessage::RPC_RC_ONENDED: | 406 case remoting::pb::RpcMessage::RPC_RC_ONENDED: |
376 VLOG(2) << __func__ << ": Received RPC_RC_ONENDED."; | 407 VLOG(2) << __func__ << ": Received RPC_RC_ONENDED."; |
377 client_->OnEnded(); | 408 client_->OnEnded(); |
378 break; | 409 break; |
379 case remoting::pb::RpcMessage::RPC_RC_ONERROR: | 410 case remoting::pb::RpcMessage::RPC_RC_ONERROR: |
380 VLOG(2) << __func__ << ": Received RPC_RC_ONERROR."; | 411 VLOG(2) << __func__ << ": Received RPC_RC_ONERROR."; |
381 OnFatalError(PIPELINE_ERROR_DECODE); | 412 OnFatalError(remoting::RECEIVER_PIPELINE_ERROR); |
382 break; | 413 break; |
383 case remoting::pb::RpcMessage::RPC_RC_ONVIDEONATURALSIZECHANGE: | 414 case remoting::pb::RpcMessage::RPC_RC_ONVIDEONATURALSIZECHANGE: |
384 OnVideoNaturalSizeChange(std::move(message)); | 415 OnVideoNaturalSizeChange(std::move(message)); |
385 break; | 416 break; |
386 case remoting::pb::RpcMessage::RPC_RC_ONVIDEOOPACITYCHANGE: | 417 case remoting::pb::RpcMessage::RPC_RC_ONVIDEOOPACITYCHANGE: |
387 OnVideoOpacityChange(std::move(message)); | 418 OnVideoOpacityChange(std::move(message)); |
388 break; | 419 break; |
389 case remoting::pb::RpcMessage::RPC_RC_ONSTATISTICSUPDATE: | 420 case remoting::pb::RpcMessage::RPC_RC_ONSTATISTICSUPDATE: |
390 OnStatisticsUpdate(std::move(message)); | 421 OnStatisticsUpdate(std::move(message)); |
391 break; | 422 break; |
(...skipping 16 matching lines...) Expand all Loading... |
408 DCHECK(main_task_runner_); | 439 DCHECK(main_task_runner_); |
409 main_task_runner_->PostTask( | 440 main_task_runner_->PostTask( |
410 FROM_HERE, base::Bind(&remoting::RpcBroker::SendMessageToRemote, | 441 FROM_HERE, base::Bind(&remoting::RpcBroker::SendMessageToRemote, |
411 rpc_broker_, base::Passed(&message))); | 442 rpc_broker_, base::Passed(&message))); |
412 } | 443 } |
413 | 444 |
414 void RemoteRendererImpl::AcquireRendererDone( | 445 void RemoteRendererImpl::AcquireRendererDone( |
415 std::unique_ptr<remoting::pb::RpcMessage> message) { | 446 std::unique_ptr<remoting::pb::RpcMessage> message) { |
416 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 447 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
417 DCHECK(message); | 448 DCHECK(message); |
418 DCHECK(!init_workflow_done_callback_.is_null()); | 449 |
419 if (state_ != STATE_ACQUIRING || init_workflow_done_callback_.is_null()) { | |
420 VLOG(1) << "Unexpected acquire renderer done RPC. Shutting down."; | |
421 OnFatalError(PIPELINE_ERROR_ABORT); | |
422 return; | |
423 } | |
424 remote_renderer_handle_ = message->integer_value(); | 450 remote_renderer_handle_ = message->integer_value(); |
425 VLOG(2) << __func__ | 451 VLOG(2) << __func__ |
426 << ": Received RPC_ACQUIRE_RENDERER_DONE with remote_renderer_handle=" | 452 << ": Received RPC_ACQUIRE_RENDERER_DONE with remote_renderer_handle=" |
427 << remote_renderer_handle_; | 453 << remote_renderer_handle_; |
| 454 |
| 455 if (state_ != STATE_ACQUIRING || init_workflow_done_callback_.is_null()) { |
| 456 LOG(WARNING) << "Unexpected acquire renderer done RPC."; |
| 457 OnFatalError(remoting::PEERS_OUT_OF_SYNC); |
| 458 return; |
| 459 } |
428 state_ = STATE_INITIALIZING; | 460 state_ = STATE_INITIALIZING; |
429 | 461 |
430 // Issues RPC_R_INITIALIZE RPC message to initialize renderer. | 462 // Issues RPC_R_INITIALIZE RPC message to initialize renderer. |
431 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); | 463 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); |
432 rpc->set_handle(remote_renderer_handle_); | 464 rpc->set_handle(remote_renderer_handle_); |
433 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_INITIALIZE); | 465 rpc->set_proc(remoting::pb::RpcMessage::RPC_R_INITIALIZE); |
434 remoting::pb::RendererInitialize* init = | 466 remoting::pb::RendererInitialize* init = |
435 rpc->mutable_renderer_initialize_rpc(); | 467 rpc->mutable_renderer_initialize_rpc(); |
436 init->set_client_handle(rpc_handle_); | 468 init->set_client_handle(rpc_handle_); |
437 init->set_audio_demuxer_handle( | 469 init->set_audio_demuxer_handle( |
(...skipping 10 matching lines...) Expand all Loading... |
448 << ", audio_demuxer_handle=" << init->audio_demuxer_handle() | 480 << ", audio_demuxer_handle=" << init->audio_demuxer_handle() |
449 << ", video_demuxer_handle=" << init->video_demuxer_handle() | 481 << ", video_demuxer_handle=" << init->video_demuxer_handle() |
450 << ", callback_handle=" << init->callback_handle(); | 482 << ", callback_handle=" << init->callback_handle(); |
451 SendRpcToRemote(std::move(rpc)); | 483 SendRpcToRemote(std::move(rpc)); |
452 } | 484 } |
453 | 485 |
454 void RemoteRendererImpl::InitializeCallback( | 486 void RemoteRendererImpl::InitializeCallback( |
455 std::unique_ptr<remoting::pb::RpcMessage> message) { | 487 std::unique_ptr<remoting::pb::RpcMessage> message) { |
456 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 488 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
457 DCHECK(message); | 489 DCHECK(message); |
458 DCHECK(!init_workflow_done_callback_.is_null()); | |
459 if (state_ != STATE_INITIALIZING || init_workflow_done_callback_.is_null()) { | |
460 VLOG(1) << "Unexpected initialize callback RPC. Shutting down."; | |
461 OnFatalError(PIPELINE_ERROR_ABORT); | |
462 return; | |
463 } | |
464 | 490 |
465 const bool success = message->boolean_value(); | 491 const bool success = message->boolean_value(); |
466 VLOG(2) << __func__ | 492 VLOG(2) << __func__ |
467 << ": Received RPC_R_INITIALIZE_CALLBACK with success=" << success; | 493 << ": Received RPC_R_INITIALIZE_CALLBACK with success=" << success; |
468 if (!success) { | 494 |
469 OnFatalError(PIPELINE_ERROR_ABORT); | 495 if (state_ != STATE_INITIALIZING || init_workflow_done_callback_.is_null()) { |
| 496 LOG(WARNING) << "Unexpected initialize callback RPC."; |
| 497 OnFatalError(remoting::PEERS_OUT_OF_SYNC); |
470 return; | 498 return; |
471 } | 499 } |
472 | 500 |
| 501 if (!success) { |
| 502 OnFatalError(remoting::RECEIVER_INITIALIZE_FAILED); |
| 503 return; |
| 504 } |
| 505 |
| 506 metrics_recorder_.OnRendererInitialized(); |
| 507 |
473 state_ = STATE_PLAYING; | 508 state_ = STATE_PLAYING; |
474 base::ResetAndReturn(&init_workflow_done_callback_).Run(::media::PIPELINE_OK); | 509 base::ResetAndReturn(&init_workflow_done_callback_).Run(::media::PIPELINE_OK); |
475 } | 510 } |
476 | 511 |
477 void RemoteRendererImpl::FlushUntilCallback() { | 512 void RemoteRendererImpl::FlushUntilCallback() { |
478 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 513 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 514 VLOG(2) << __func__ << ": Received RPC_R_FLUSHUNTIL_CALLBACK"; |
| 515 |
479 if (state_ != STATE_FLUSHING || flush_cb_.is_null()) { | 516 if (state_ != STATE_FLUSHING || flush_cb_.is_null()) { |
480 VLOG(1) << "Unexpected flushuntil callback RPC. Shutting down."; | 517 LOG(WARNING) << "Unexpected flushuntil callback RPC."; |
481 OnFatalError(PIPELINE_ERROR_ABORT); | 518 OnFatalError(remoting::PEERS_OUT_OF_SYNC); |
482 return; | 519 return; |
483 } | 520 } |
484 VLOG(2) << __func__ << ": Received RPC_R_FLUSHUNTIL_CALLBACK"; | 521 |
485 state_ = STATE_PLAYING; | 522 state_ = STATE_PLAYING; |
486 if (audio_demuxer_stream_adapter_) | 523 if (audio_demuxer_stream_adapter_) |
487 audio_demuxer_stream_adapter_->SignalFlush(false); | 524 audio_demuxer_stream_adapter_->SignalFlush(false); |
488 if (video_demuxer_stream_adapter_) | 525 if (video_demuxer_stream_adapter_) |
489 video_demuxer_stream_adapter_->SignalFlush(false); | 526 video_demuxer_stream_adapter_->SignalFlush(false); |
490 base::ResetAndReturn(&flush_cb_).Run(); | 527 base::ResetAndReturn(&flush_cb_).Run(); |
491 ResetQueues(); | 528 ResetMeasurements(); |
492 } | 529 } |
493 | 530 |
494 void RemoteRendererImpl::SetCdmCallback( | 531 void RemoteRendererImpl::SetCdmCallback( |
495 std::unique_ptr<remoting::pb::RpcMessage> message) { | 532 std::unique_ptr<remoting::pb::RpcMessage> message) { |
496 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 533 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
497 DCHECK(message); | 534 DCHECK(message); |
498 VLOG(2) << __func__ << ": Received RPC_R_SETCDM_CALLBACK with cdm_id=" | 535 VLOG(2) << __func__ << ": Received RPC_R_SETCDM_CALLBACK with cdm_id=" |
499 << message->renderer_set_cdm_rpc().cdm_id() << ", callback_handle=" | 536 << message->renderer_set_cdm_rpc().cdm_id() << ", callback_handle=" |
500 << message->renderer_set_cdm_rpc().callback_handle(); | 537 << message->renderer_set_cdm_rpc().callback_handle(); |
501 // TODO(erickung): add implementation once Remote CDM implementation is done. | 538 // TODO(erickung): add implementation once Remote CDM implementation is done. |
502 NOTIMPLEMENTED(); | 539 NOTIMPLEMENTED(); |
503 } | 540 } |
504 | 541 |
505 void RemoteRendererImpl::OnTimeUpdate( | 542 void RemoteRendererImpl::OnTimeUpdate( |
506 std::unique_ptr<remoting::pb::RpcMessage> message) { | 543 std::unique_ptr<remoting::pb::RpcMessage> message) { |
507 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 544 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
508 DCHECK(message); | 545 DCHECK(message); |
509 // Shutdown remoting session if receiving malformed RPC message. | 546 // Shutdown remoting session if receiving malformed RPC message. |
510 if (!message->has_rendererclient_ontimeupdate_rpc()) { | 547 if (!message->has_rendererclient_ontimeupdate_rpc()) { |
511 VLOG(1) << __func__ << " missing required RPC message"; | 548 VLOG(1) << __func__ << " missing required RPC message"; |
512 OnFatalError(PIPELINE_ERROR_ABORT); | 549 OnFatalError(remoting::RPC_INVALID); |
513 return; | 550 return; |
514 } | 551 } |
515 const int64_t time_usec = | 552 const int64_t time_usec = |
516 message->rendererclient_ontimeupdate_rpc().time_usec(); | 553 message->rendererclient_ontimeupdate_rpc().time_usec(); |
517 const int64_t max_time_usec = | 554 const int64_t max_time_usec = |
518 message->rendererclient_ontimeupdate_rpc().max_time_usec(); | 555 message->rendererclient_ontimeupdate_rpc().max_time_usec(); |
519 VLOG(2) << __func__ | 556 VLOG(2) << __func__ |
520 << ": Received RPC_RC_ONTIMEUPDATE with time_usec=" << time_usec | 557 << ": Received RPC_RC_ONTIMEUPDATE with time_usec=" << time_usec |
521 << ", max_time_usec=" << max_time_usec; | 558 << ", max_time_usec=" << max_time_usec; |
522 // Ignores invalid time, such as negative value, or time larger than max value | 559 // Ignores invalid time, such as negative value, or time larger than max value |
523 // (usually the time stamp that all streams are pushed into AV pipeline). | 560 // (usually the time stamp that all streams are pushed into AV pipeline). |
524 if (time_usec < 0 || max_time_usec < 0 || time_usec > max_time_usec) | 561 if (time_usec < 0 || max_time_usec < 0 || time_usec > max_time_usec) |
525 return; | 562 return; |
526 | 563 |
527 { | 564 { |
528 // Updates current time information. | 565 // Updates current time information. |
529 base::AutoLock auto_lock(time_lock_); | 566 base::AutoLock auto_lock(time_lock_); |
530 current_media_time_ = base::TimeDelta::FromMicroseconds(time_usec); | 567 current_media_time_ = base::TimeDelta::FromMicroseconds(time_usec); |
531 current_max_time_ = base::TimeDelta::FromMicroseconds(max_time_usec); | 568 current_max_time_ = base::TimeDelta::FromMicroseconds(max_time_usec); |
532 } | 569 } |
533 | 570 |
| 571 metrics_recorder_.OnEvidenceOfPlayoutAtReceiver(); |
534 OnMediaTimeUpdated(); | 572 OnMediaTimeUpdated(); |
535 } | 573 } |
536 | 574 |
537 void RemoteRendererImpl::OnBufferingStateChange( | 575 void RemoteRendererImpl::OnBufferingStateChange( |
538 std::unique_ptr<remoting::pb::RpcMessage> message) { | 576 std::unique_ptr<remoting::pb::RpcMessage> message) { |
539 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 577 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
540 DCHECK(message); | 578 DCHECK(message); |
541 if (!message->has_rendererclient_onbufferingstatechange_rpc()) { | 579 if (!message->has_rendererclient_onbufferingstatechange_rpc()) { |
542 VLOG(1) << __func__ << " missing required RPC message"; | 580 VLOG(1) << __func__ << " missing required RPC message"; |
543 OnFatalError(PIPELINE_ERROR_ABORT); | 581 OnFatalError(remoting::RPC_INVALID); |
544 return; | 582 return; |
545 } | 583 } |
546 VLOG(2) << __func__ << ": Received RPC_RC_ONBUFFERINGSTATECHANGE with state=" | 584 VLOG(2) << __func__ << ": Received RPC_RC_ONBUFFERINGSTATECHANGE with state=" |
547 << message->rendererclient_onbufferingstatechange_rpc().state(); | 585 << message->rendererclient_onbufferingstatechange_rpc().state(); |
548 base::Optional<::media::BufferingState> state = | 586 base::Optional<::media::BufferingState> state = |
549 remoting::ToMediaBufferingState( | 587 remoting::ToMediaBufferingState( |
550 message->rendererclient_onbufferingstatechange_rpc().state()); | 588 message->rendererclient_onbufferingstatechange_rpc().state()); |
551 if (!state.has_value()) | 589 if (!state.has_value()) |
552 return; | 590 return; |
553 client_->OnBufferingStateChange(state.value()); | 591 client_->OnBufferingStateChange(state.value()); |
554 } | 592 } |
555 | 593 |
556 void RemoteRendererImpl::OnVideoNaturalSizeChange( | 594 void RemoteRendererImpl::OnVideoNaturalSizeChange( |
557 std::unique_ptr<remoting::pb::RpcMessage> message) { | 595 std::unique_ptr<remoting::pb::RpcMessage> message) { |
558 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 596 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
559 DCHECK(message); | 597 DCHECK(message); |
560 // Shutdown remoting session if receiving malformed RPC message. | 598 // Shutdown remoting session if receiving malformed RPC message. |
561 if (!message->has_rendererclient_onvideonatualsizechange_rpc()) { | 599 if (!message->has_rendererclient_onvideonatualsizechange_rpc()) { |
562 VLOG(1) << __func__ << " missing required RPC message"; | 600 VLOG(1) << __func__ << " missing required RPC message"; |
563 OnFatalError(PIPELINE_ERROR_ABORT); | 601 OnFatalError(remoting::RPC_INVALID); |
564 return; | 602 return; |
565 } | 603 } |
566 const auto& size_change = | 604 const auto& size_change = |
567 message->rendererclient_onvideonatualsizechange_rpc(); | 605 message->rendererclient_onvideonatualsizechange_rpc(); |
568 VLOG(2) << __func__ << ": Received RPC_RC_ONVIDEONATURALSIZECHANGE with size=" | 606 VLOG(2) << __func__ << ": Received RPC_RC_ONVIDEONATURALSIZECHANGE with size=" |
569 << size_change.width() << 'x' << size_change.height(); | 607 << size_change.width() << 'x' << size_change.height(); |
570 if (size_change.width() <= 0 || size_change.height() <= 0) | 608 if (size_change.width() <= 0 || size_change.height() <= 0) |
571 return; | 609 return; |
572 client_->OnVideoNaturalSizeChange( | 610 client_->OnVideoNaturalSizeChange( |
573 gfx::Size(size_change.width(), size_change.height())); | 611 gfx::Size(size_change.width(), size_change.height())); |
574 } | 612 } |
575 | 613 |
576 void RemoteRendererImpl::OnVideoOpacityChange( | 614 void RemoteRendererImpl::OnVideoOpacityChange( |
577 std::unique_ptr<remoting::pb::RpcMessage> message) { | 615 std::unique_ptr<remoting::pb::RpcMessage> message) { |
578 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 616 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
579 DCHECK(message); | 617 DCHECK(message); |
580 const bool opaque = message->boolean_value(); | 618 const bool opaque = message->boolean_value(); |
581 VLOG(2) << __func__ | 619 VLOG(2) << __func__ |
582 << ": Received RPC_RC_ONVIDEOOPACITYCHANGE with opaque=" << opaque; | 620 << ": Received RPC_RC_ONVIDEOOPACITYCHANGE with opaque=" << opaque; |
583 client_->OnVideoOpacityChange(opaque); | 621 client_->OnVideoOpacityChange(opaque); |
584 } | 622 } |
585 | 623 |
586 void RemoteRendererImpl::OnStatisticsUpdate( | 624 void RemoteRendererImpl::OnStatisticsUpdate( |
587 std::unique_ptr<remoting::pb::RpcMessage> message) { | 625 std::unique_ptr<remoting::pb::RpcMessage> message) { |
588 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 626 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
589 DCHECK(message); | 627 DCHECK(message); |
590 // Shutdown remoting session if receiving malformed RPC message. | 628 // Shutdown remoting session if receiving malformed RPC message. |
591 if (!message->has_rendererclient_onstatisticsupdate_rpc()) { | 629 if (!message->has_rendererclient_onstatisticsupdate_rpc()) { |
592 VLOG(1) << __func__ << " missing required RPC message"; | 630 VLOG(1) << __func__ << " missing required RPC message"; |
593 OnFatalError(PIPELINE_ERROR_ABORT); | 631 OnFatalError(remoting::RPC_INVALID); |
594 return; | 632 return; |
595 } | 633 } |
596 const auto& rpc_message = message->rendererclient_onstatisticsupdate_rpc(); | 634 const auto& rpc_message = message->rendererclient_onstatisticsupdate_rpc(); |
597 ::media::PipelineStatistics stats; | 635 ::media::PipelineStatistics stats; |
598 // Note: Each |stats| value is a delta, not the aggregate amount. | 636 // Note: Each |stats| value is a delta, not the aggregate amount. |
599 stats.audio_bytes_decoded = rpc_message.audio_bytes_decoded(); | 637 stats.audio_bytes_decoded = rpc_message.audio_bytes_decoded(); |
600 stats.video_bytes_decoded = rpc_message.video_bytes_decoded(); | 638 stats.video_bytes_decoded = rpc_message.video_bytes_decoded(); |
601 stats.video_frames_decoded = rpc_message.video_frames_decoded(); | 639 stats.video_frames_decoded = rpc_message.video_frames_decoded(); |
602 stats.video_frames_dropped = rpc_message.video_frames_dropped(); | 640 stats.video_frames_dropped = rpc_message.video_frames_dropped(); |
603 stats.audio_memory_usage = rpc_message.audio_memory_usage(); | 641 stats.audio_memory_usage = rpc_message.audio_memory_usage(); |
604 stats.video_memory_usage = rpc_message.video_memory_usage(); | 642 stats.video_memory_usage = rpc_message.video_memory_usage(); |
605 VLOG(2) << __func__ | 643 VLOG(2) << __func__ |
606 << ": Received RPC_RC_ONSTATISTICSUPDATE with audio_bytes_decoded=" | 644 << ": Received RPC_RC_ONSTATISTICSUPDATE with audio_bytes_decoded=" |
607 << stats.audio_bytes_decoded | 645 << stats.audio_bytes_decoded |
608 << ", video_bytes_decoded=" << stats.video_bytes_decoded | 646 << ", video_bytes_decoded=" << stats.video_bytes_decoded |
609 << ", video_frames_decoded=" << stats.video_frames_decoded | 647 << ", video_frames_decoded=" << stats.video_frames_decoded |
610 << ", video_frames_dropped=" << stats.video_frames_dropped | 648 << ", video_frames_dropped=" << stats.video_frames_dropped |
611 << ", audio_memory_usage=" << stats.audio_memory_usage | 649 << ", audio_memory_usage=" << stats.audio_memory_usage |
612 << ", video_memory_usage=" << stats.video_memory_usage; | 650 << ", video_memory_usage=" << stats.video_memory_usage; |
613 | 651 |
| 652 if (stats.audio_bytes_decoded > 0 || stats.video_frames_decoded > 0 || |
| 653 stats.video_frames_dropped > 0) { |
| 654 metrics_recorder_.OnEvidenceOfPlayoutAtReceiver(); |
| 655 } |
614 UpdateVideoStatsQueue(stats.video_frames_decoded, stats.video_frames_dropped); | 656 UpdateVideoStatsQueue(stats.video_frames_decoded, stats.video_frames_dropped); |
615 client_->OnStatisticsUpdate(stats); | 657 client_->OnStatisticsUpdate(stats); |
616 } | 658 } |
617 | 659 |
618 void RemoteRendererImpl::OnDurationChange( | 660 void RemoteRendererImpl::OnDurationChange( |
619 std::unique_ptr<remoting::pb::RpcMessage> message) { | 661 std::unique_ptr<remoting::pb::RpcMessage> message) { |
620 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 662 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
621 DCHECK(message); | 663 DCHECK(message); |
622 VLOG(2) << __func__ << ": Received RPC_RC_ONDURATIONCHANGE with usec=" | 664 VLOG(2) << __func__ << ": Received RPC_RC_ONDURATIONCHANGE with usec=" |
623 << message->integer64_value(); | 665 << message->integer64_value(); |
624 if (message->integer64_value() < 0) | 666 if (message->integer64_value() < 0) |
625 return; | 667 return; |
626 client_->OnDurationChange( | 668 client_->OnDurationChange( |
627 base::TimeDelta::FromMicroseconds(message->integer64_value())); | 669 base::TimeDelta::FromMicroseconds(message->integer64_value())); |
628 } | 670 } |
629 | 671 |
630 void RemoteRendererImpl::OnFatalError(PipelineStatus error) { | 672 void RemoteRendererImpl::OnFatalError(remoting::StopTrigger stop_trigger) { |
631 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 673 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
632 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 674 DCHECK_NE(remoting::UNKNOWN_STOP_TRIGGER, stop_trigger); |
633 | 675 |
634 // An error has already been delivered. | 676 VLOG(2) << __func__ << " with StopTrigger " << stop_trigger; |
635 if (state_ == STATE_ERROR) | |
636 return; | |
637 | 677 |
638 VLOG(2) << __func__ << " with PipelineStatus error=" << error; | 678 // If this is the first error, notify the controller. It is expected the |
| 679 // controller will shut down this renderer shortly. |
| 680 if (state_ != STATE_ERROR) { |
| 681 state_ = STATE_ERROR; |
| 682 main_task_runner_->PostTask( |
| 683 FROM_HERE, base::Bind(&RemotingRendererController::OnRendererFatalError, |
| 684 remoting_renderer_controller_, stop_trigger)); |
| 685 } |
639 | 686 |
640 const State old_state = state_; | 687 data_flow_poll_timer_.Stop(); |
641 state_ = STATE_ERROR; | |
642 | 688 |
643 if (!init_workflow_done_callback_.is_null()) { | 689 if (!init_workflow_done_callback_.is_null()) { |
644 DCHECK(old_state == STATE_CREATE_PIPE || old_state == STATE_ACQUIRING || | 690 base::ResetAndReturn(&init_workflow_done_callback_) |
645 old_state == STATE_INITIALIZING); | 691 .Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
646 base::ResetAndReturn(&init_workflow_done_callback_).Run(error); | |
647 return; | 692 return; |
648 } | 693 } |
649 | 694 |
650 if (!flush_cb_.is_null()) | 695 if (!flush_cb_.is_null()) |
651 base::ResetAndReturn(&flush_cb_).Run(); | 696 base::ResetAndReturn(&flush_cb_).Run(); |
652 | |
653 // After OnError() returns, the pipeline may destroy |this|. | |
654 client_->OnError(error); | |
655 } | 697 } |
656 | 698 |
657 // static | 699 // static |
658 void RemoteRendererImpl::RequestUpdateInterstitialOnMainThread( | 700 void RemoteRendererImpl::RequestUpdateInterstitialOnMainThread( |
659 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, | 701 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, |
660 base::WeakPtr<RemoteRendererImpl> remote_renderer_impl, | 702 base::WeakPtr<RemoteRendererImpl> remote_renderer_impl, |
661 const base::Optional<SkBitmap>& background_image, | 703 const base::Optional<SkBitmap>& background_image, |
662 const gfx::Size& canvas_size, | 704 const gfx::Size& canvas_size, |
663 RemotingInterstitialType interstitial_type) { | 705 RemotingInterstitialType interstitial_type) { |
664 media_task_runner->PostTask( | 706 media_task_runner->PostTask( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 base::TimeDelta media_duration = | 740 base::TimeDelta media_duration = |
699 media_time_queue_.back().second - media_time_queue_.front().second; | 741 media_time_queue_.back().second - media_time_queue_.front().second; |
700 base::TimeDelta update_duration = | 742 base::TimeDelta update_duration = |
701 (media_time_queue_.back().first - media_time_queue_.front().first) * | 743 (media_time_queue_.back().first - media_time_queue_.front().first) * |
702 playback_rate_; | 744 playback_rate_; |
703 if ((media_duration - update_duration).magnitude() >= | 745 if ((media_duration - update_duration).magnitude() >= |
704 kMediaPlaybackDelayThreshold) { | 746 kMediaPlaybackDelayThreshold) { |
705 VLOG(1) << "Irregular playback detected: Media playback delayed." | 747 VLOG(1) << "Irregular playback detected: Media playback delayed." |
706 << " media_duration = " << media_duration | 748 << " media_duration = " << media_duration |
707 << " update_duration = " << update_duration; | 749 << " update_duration = " << update_duration; |
708 OnIrregularPlaybackDetected(); | 750 OnFatalError(remoting::PACING_TOO_SLOWLY); |
709 } | 751 } |
710 // Prune |media_time_queue_|. | 752 // Prune |media_time_queue_|. |
711 while (media_time_queue_.back().first - media_time_queue_.front().first >= | 753 while (media_time_queue_.back().first - media_time_queue_.front().first >= |
712 kTrackingWindow) | 754 kTrackingWindow) |
713 media_time_queue_.pop_front(); | 755 media_time_queue_.pop_front(); |
714 } | 756 } |
715 | 757 |
716 void RemoteRendererImpl::UpdateVideoStatsQueue(int video_frames_decoded, | 758 void RemoteRendererImpl::UpdateVideoStatsQueue(int video_frames_decoded, |
717 int video_frames_dropped) { | 759 int video_frames_dropped) { |
718 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 760 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
(...skipping 20 matching lines...) Expand all Loading... |
739 current_time - std::get<0>(video_stats_queue_.front()); | 781 current_time - std::get<0>(video_stats_queue_.front()); |
740 if (window_duration < kTrackingWindow) | 782 if (window_duration < kTrackingWindow) |
741 return; // Not enough data to make a reliable decision. | 783 return; // Not enough data to make a reliable decision. |
742 | 784 |
743 if (sum_video_frames_decoded_ && | 785 if (sum_video_frames_decoded_ && |
744 sum_video_frames_dropped_ * 100 > | 786 sum_video_frames_dropped_ * 100 > |
745 sum_video_frames_decoded_ * kMaxNumVideoFramesDroppedPercentage) { | 787 sum_video_frames_decoded_ * kMaxNumVideoFramesDroppedPercentage) { |
746 VLOG(1) << "Irregular playback detected: Too many video frames dropped." | 788 VLOG(1) << "Irregular playback detected: Too many video frames dropped." |
747 << " video_frames_decoded= " << sum_video_frames_decoded_ | 789 << " video_frames_decoded= " << sum_video_frames_decoded_ |
748 << " video_frames_dropped= " << sum_video_frames_dropped_; | 790 << " video_frames_dropped= " << sum_video_frames_dropped_; |
749 OnIrregularPlaybackDetected(); | 791 OnFatalError(remoting::FRAME_DROP_RATE_HIGH); |
750 } | 792 } |
751 // Prune |video_stats_queue_|. | 793 // Prune |video_stats_queue_|. |
752 while (std::get<0>(video_stats_queue_.back()) - | 794 while (std::get<0>(video_stats_queue_.back()) - |
753 std::get<0>(video_stats_queue_.front()) >= | 795 std::get<0>(video_stats_queue_.front()) >= |
754 kTrackingWindow) { | 796 kTrackingWindow) { |
755 sum_video_frames_decoded_ -= std::get<1>(video_stats_queue_.front()); | 797 sum_video_frames_decoded_ -= std::get<1>(video_stats_queue_.front()); |
756 sum_video_frames_dropped_ -= std::get<2>(video_stats_queue_.front()); | 798 sum_video_frames_dropped_ -= std::get<2>(video_stats_queue_.front()); |
757 video_stats_queue_.pop_front(); | 799 video_stats_queue_.pop_front(); |
758 } | 800 } |
759 } | 801 } |
760 | 802 |
761 void RemoteRendererImpl::ResetQueues() { | 803 void RemoteRendererImpl::ResetMeasurements() { |
762 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 804 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
763 media_time_queue_.clear(); | 805 media_time_queue_.clear(); |
764 video_stats_queue_.clear(); | 806 video_stats_queue_.clear(); |
765 sum_video_frames_dropped_ = 0; | 807 sum_video_frames_dropped_ = 0; |
766 sum_video_frames_decoded_ = 0; | 808 sum_video_frames_decoded_ = 0; |
767 stats_updated_ = false; | 809 stats_updated_ = false; |
768 ignore_updates_until_time_ = base::TimeTicks::Now() + kStabilizationPeriod; | 810 ignore_updates_until_time_ = base::TimeTicks::Now() + kStabilizationPeriod; |
| 811 |
| 812 if (state_ != STATE_ERROR && |
| 813 (audio_demuxer_stream_adapter_ || video_demuxer_stream_adapter_)) { |
| 814 data_flow_poll_timer_.Start(FROM_HERE, kDataFlowPollPeriod, this, |
| 815 &RemoteRendererImpl::MeasureAndRecordDataRates); |
| 816 } |
769 } | 817 } |
770 | 818 |
771 void RemoteRendererImpl::OnIrregularPlaybackDetected() { | 819 void RemoteRendererImpl::MeasureAndRecordDataRates() { |
772 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 820 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
773 main_task_runner_->PostTask( | 821 |
774 FROM_HERE, | 822 // Whenever media is first started or flushed/seeked, there is a "burst |
775 base::Bind(&RemotingRendererController::OnIrregularPlaybackDetected, | 823 // bufferring" period as the remote device rapidly fills its buffer before |
776 remoting_renderer_controller_)); | 824 // resuming playback. Since the goal here is to measure the sustained content |
| 825 // bitrates, ignore the byte counts the first time since the last |
| 826 // ResetMeasurements() call. |
| 827 const base::TimeTicks current_time = base::TimeTicks::Now(); |
| 828 if (current_time < ignore_updates_until_time_ + kDataFlowPollPeriod) { |
| 829 if (audio_demuxer_stream_adapter_) |
| 830 audio_demuxer_stream_adapter_->GetBytesWrittenAndReset(); |
| 831 if (video_demuxer_stream_adapter_) |
| 832 video_demuxer_stream_adapter_->GetBytesWrittenAndReset(); |
| 833 return; |
| 834 } |
| 835 |
| 836 const int kBytesPerKilobit = 1024 / 8; |
| 837 if (audio_demuxer_stream_adapter_) { |
| 838 const double kilobits_per_second = |
| 839 (audio_demuxer_stream_adapter_->GetBytesWrittenAndReset() / |
| 840 kDataFlowPollPeriod.InSecondsF()) / |
| 841 kBytesPerKilobit; |
| 842 DCHECK_GE(kilobits_per_second, 0); |
| 843 const base::CheckedNumeric<int> checked_kbps = kilobits_per_second; |
| 844 metrics_recorder_.OnAudioRateEstimate( |
| 845 checked_kbps.ValueOrDefault(std::numeric_limits<int>::max())); |
| 846 } |
| 847 if (video_demuxer_stream_adapter_) { |
| 848 const double kilobits_per_second = |
| 849 (video_demuxer_stream_adapter_->GetBytesWrittenAndReset() / |
| 850 kDataFlowPollPeriod.InSecondsF()) / |
| 851 kBytesPerKilobit; |
| 852 DCHECK_GE(kilobits_per_second, 0); |
| 853 const base::CheckedNumeric<int> checked_kbps = kilobits_per_second; |
| 854 metrics_recorder_.OnVideoRateEstimate( |
| 855 checked_kbps.ValueOrDefault(std::numeric_limits<int>::max())); |
| 856 } |
777 } | 857 } |
778 | 858 |
779 } // namespace media | 859 } // namespace media |
OLD | NEW |