| 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 |