Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: media/remoting/remote_renderer_impl.cc

Issue 2631993002: Media Remoting: UMAs to track session events and measurements. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698