Chromium Code Reviews| 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/renderer_controller.h" | 5 #include "media/remoting/renderer_controller.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/threading/thread_checker.h" | 9 #include "base/threading/thread_checker.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 DCHECK(thread_checker_.CalledOnValidThread()); | 48 DCHECK(thread_checker_.CalledOnValidThread()); |
| 49 UpdateFromSessionState(SINK_AVAILABLE, ROUTE_TERMINATED); | 49 UpdateFromSessionState(SINK_AVAILABLE, ROUTE_TERMINATED); |
| 50 } | 50 } |
| 51 | 51 |
| 52 void RendererController::UpdateFromSessionState(StartTrigger start_trigger, | 52 void RendererController::UpdateFromSessionState(StartTrigger start_trigger, |
| 53 StopTrigger stop_trigger) { | 53 StopTrigger stop_trigger) { |
| 54 VLOG(1) << "UpdateFromSessionState: " << session_->state(); | 54 VLOG(1) << "UpdateFromSessionState: " << session_->state(); |
| 55 if (client_) | 55 if (client_) |
| 56 client_->ActivateViewportIntersectionMonitoring(IsRemoteSinkAvailable()); | 56 client_->ActivateViewportIntersectionMonitoring(IsRemoteSinkAvailable()); |
| 57 | 57 |
| 58 UpdateInterstitial(base::nullopt); | |
| 59 UpdateAndMaybeSwitch(start_trigger, stop_trigger); | 58 UpdateAndMaybeSwitch(start_trigger, stop_trigger); |
| 60 } | 59 } |
| 61 | 60 |
| 62 bool RendererController::IsRemoteSinkAvailable() { | 61 bool RendererController::IsRemoteSinkAvailable() { |
| 63 DCHECK(thread_checker_.CalledOnValidThread()); | 62 DCHECK(thread_checker_.CalledOnValidThread()); |
| 64 | 63 |
| 65 switch (session_->state()) { | 64 switch (session_->state()) { |
| 66 case SharedSession::SESSION_CAN_START: | 65 case SharedSession::SESSION_CAN_START: |
| 67 case SharedSession::SESSION_STARTING: | 66 case SharedSession::SESSION_STARTING: |
| 68 case SharedSession::SESSION_STARTED: | 67 case SharedSession::SESSION_STARTED: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 } | 131 } |
| 133 | 132 |
| 134 void RendererController::OnRemotePlaybackDisabled(bool disabled) { | 133 void RendererController::OnRemotePlaybackDisabled(bool disabled) { |
| 135 DCHECK(thread_checker_.CalledOnValidThread()); | 134 DCHECK(thread_checker_.CalledOnValidThread()); |
| 136 | 135 |
| 137 is_remote_playback_disabled_ = disabled; | 136 is_remote_playback_disabled_ = disabled; |
| 138 metrics_recorder_.OnRemotePlaybackDisabled(disabled); | 137 metrics_recorder_.OnRemotePlaybackDisabled(disabled); |
| 139 UpdateAndMaybeSwitch(ENABLED_BY_PAGE, DISABLED_BY_PAGE); | 138 UpdateAndMaybeSwitch(ENABLED_BY_PAGE, DISABLED_BY_PAGE); |
| 140 } | 139 } |
| 141 | 140 |
| 142 void RendererController::OnSetPoster(const GURL& poster_url) { | |
| 143 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 144 | |
| 145 if (poster_url != poster_url_) { | |
| 146 poster_url_ = poster_url; | |
| 147 if (poster_url_.is_empty()) | |
| 148 UpdateInterstitial(SkBitmap()); | |
| 149 else | |
| 150 DownloadPosterImage(); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 base::WeakPtr<RpcBroker> RendererController::GetRpcBroker() const { | 141 base::WeakPtr<RpcBroker> RendererController::GetRpcBroker() const { |
| 155 DCHECK(thread_checker_.CalledOnValidThread()); | 142 DCHECK(thread_checker_.CalledOnValidThread()); |
| 156 | 143 |
| 157 return session_->rpc_broker()->GetWeakPtr(); | 144 return session_->rpc_broker()->GetWeakPtr(); |
| 158 } | 145 } |
| 159 | 146 |
| 160 void RendererController::StartDataPipe( | 147 void RendererController::StartDataPipe( |
| 161 std::unique_ptr<mojo::DataPipe> audio_data_pipe, | 148 std::unique_ptr<mojo::DataPipe> audio_data_pipe, |
| 162 std::unique_ptr<mojo::DataPipe> video_data_pipe, | 149 std::unique_ptr<mojo::DataPipe> video_data_pipe, |
| 163 const SharedSession::DataPipeStartCallback& done_callback) { | 150 const SharedSession::DataPipeStartCallback& done_callback) { |
| 164 DCHECK(thread_checker_.CalledOnValidThread()); | 151 DCHECK(thread_checker_.CalledOnValidThread()); |
| 165 | 152 |
| 166 session_->StartDataPipe(std::move(audio_data_pipe), | 153 session_->StartDataPipe(std::move(audio_data_pipe), |
| 167 std::move(video_data_pipe), done_callback); | 154 std::move(video_data_pipe), done_callback); |
| 168 } | 155 } |
| 169 | 156 |
| 170 void RendererController::OnMetadataChanged(const PipelineMetadata& metadata) { | 157 void RendererController::OnMetadataChanged(const PipelineMetadata& metadata) { |
| 171 DCHECK(thread_checker_.CalledOnValidThread()); | 158 DCHECK(thread_checker_.CalledOnValidThread()); |
| 172 | 159 |
| 173 const gfx::Size old_size = pipeline_metadata_.natural_size; | |
| 174 const bool was_audio_codec_supported = has_audio() && IsAudioCodecSupported(); | 160 const bool was_audio_codec_supported = has_audio() && IsAudioCodecSupported(); |
| 175 const bool was_video_codec_supported = has_video() && IsVideoCodecSupported(); | 161 const bool was_video_codec_supported = has_video() && IsVideoCodecSupported(); |
| 176 pipeline_metadata_ = metadata; | 162 pipeline_metadata_ = metadata; |
| 177 const bool is_audio_codec_supported = has_audio() && IsAudioCodecSupported(); | 163 const bool is_audio_codec_supported = has_audio() && IsAudioCodecSupported(); |
| 178 const bool is_video_codec_supported = has_video() && IsVideoCodecSupported(); | 164 const bool is_video_codec_supported = has_video() && IsVideoCodecSupported(); |
| 179 metrics_recorder_.OnPipelineMetadataChanged(metadata); | 165 metrics_recorder_.OnPipelineMetadataChanged(metadata); |
| 180 | 166 |
| 181 is_encrypted_ = false; | 167 is_encrypted_ = false; |
| 182 if (has_video()) | 168 if (has_video()) |
| 183 is_encrypted_ |= metadata.video_decoder_config.is_encrypted(); | 169 is_encrypted_ |= metadata.video_decoder_config.is_encrypted(); |
| 184 if (has_audio()) | 170 if (has_audio()) |
| 185 is_encrypted_ |= metadata.audio_decoder_config.is_encrypted(); | 171 is_encrypted_ |= metadata.audio_decoder_config.is_encrypted(); |
| 186 | 172 |
| 187 if (pipeline_metadata_.natural_size != old_size) | |
| 188 UpdateInterstitial(base::nullopt); | |
| 189 | |
| 190 StartTrigger start_trigger = UNKNOWN_START_TRIGGER; | 173 StartTrigger start_trigger = UNKNOWN_START_TRIGGER; |
| 191 if (!was_audio_codec_supported && is_audio_codec_supported) | 174 if (!was_audio_codec_supported && is_audio_codec_supported) |
| 192 start_trigger = SUPPORTED_AUDIO_CODEC; | 175 start_trigger = SUPPORTED_AUDIO_CODEC; |
| 193 if (!was_video_codec_supported && is_video_codec_supported) { | 176 if (!was_video_codec_supported && is_video_codec_supported) { |
| 194 start_trigger = start_trigger == SUPPORTED_AUDIO_CODEC | 177 start_trigger = start_trigger == SUPPORTED_AUDIO_CODEC |
| 195 ? SUPPORTED_AUDIO_AND_VIDEO_CODECS | 178 ? SUPPORTED_AUDIO_AND_VIDEO_CODECS |
| 196 : SUPPORTED_VIDEO_CODEC; | 179 : SUPPORTED_VIDEO_CODEC; |
| 197 } | 180 } |
| 198 StopTrigger stop_trigger = UNKNOWN_STOP_TRIGGER; | 181 StopTrigger stop_trigger = UNKNOWN_STOP_TRIGGER; |
| 199 if (was_audio_codec_supported && !is_audio_codec_supported) | 182 if (was_audio_codec_supported && !is_audio_codec_supported) |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 if (!client_) { | 252 if (!client_) { |
| 270 DCHECK(!remote_rendering_started_); | 253 DCHECK(!remote_rendering_started_); |
| 271 return false; // No way to switch to the remoting renderer. | 254 return false; // No way to switch to the remoting renderer. |
| 272 } | 255 } |
| 273 | 256 |
| 274 const SharedSession::SessionState state = session_->state(); | 257 const SharedSession::SessionState state = session_->state(); |
| 275 if (is_encrypted_) { | 258 if (is_encrypted_) { |
| 276 // Due to technical limitations when playing encrypted content, once a | 259 // Due to technical limitations when playing encrypted content, once a |
| 277 // remoting session has been started, always return true here to indicate | 260 // remoting session has been started, always return true here to indicate |
| 278 // that the CourierRenderer should continue to be used. In the stopped | 261 // that the CourierRenderer should continue to be used. In the stopped |
| 279 // states, CourierRenderer will display an interstitial to notify the user | 262 // states, an interstitial will be shown to notify the user that local |
|
miu
2017/04/13 02:15:10
I'm wondering if we need this last sentence anymor
xjz
2017/04/13 23:48:36
Done.
| |
| 280 // that local rendering cannot be resumed. | 263 // rendering cannot be resumed. |
| 281 // | 264 // |
| 282 // TODO(miu): Revisit this once more of the encrypted-remoting impl is | 265 // TODO(miu): Revisit this once more of the encrypted-remoting impl is |
| 283 // in-place. For example, this will prevent metrics from recording session | 266 // in-place. For example, this will prevent metrics from recording session |
| 284 // stop reasons. | 267 // stop reasons. |
| 285 return state == SharedSession::SESSION_STARTED || | 268 return state == SharedSession::SESSION_STARTED || |
| 286 state == SharedSession::SESSION_STOPPING || | 269 state == SharedSession::SESSION_STOPPING || |
| 287 state == SharedSession::SESSION_PERMANENTLY_STOPPED; | 270 state == SharedSession::SESSION_PERMANENTLY_STOPPED; |
| 288 } | 271 } |
| 289 | 272 |
| 290 if (encountered_renderer_fatal_error_) | 273 if (encountered_renderer_fatal_error_) |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 // started successfully. | 340 // started successfully. |
| 358 session_->StartRemoting(this); | 341 session_->StartRemoting(this); |
| 359 } else { | 342 } else { |
| 360 // For encrypted content, it's only valid to switch to remoting renderer, | 343 // For encrypted content, it's only valid to switch to remoting renderer, |
| 361 // and never back to the local renderer. The RemotingCdmController will | 344 // and never back to the local renderer. The RemotingCdmController will |
| 362 // force-stop the session when remoting has ended; so no need to call | 345 // force-stop the session when remoting has ended; so no need to call |
| 363 // StopRemoting() from here. | 346 // StopRemoting() from here. |
| 364 DCHECK(!is_encrypted_); | 347 DCHECK(!is_encrypted_); |
| 365 DCHECK_NE(stop_trigger, UNKNOWN_STOP_TRIGGER); | 348 DCHECK_NE(stop_trigger, UNKNOWN_STOP_TRIGGER); |
| 366 metrics_recorder_.WillStopSession(stop_trigger); | 349 metrics_recorder_.WillStopSession(stop_trigger); |
| 367 // Update the interstitial one last time before switching back to the local | |
| 368 // Renderer. | |
| 369 UpdateInterstitial(base::nullopt); | |
| 370 client_->SwitchRenderer(false); | 350 client_->SwitchRenderer(false); |
| 371 session_->StopRemoting(this); | 351 session_->StopRemoting(this); |
| 372 } | 352 } |
| 373 } | 353 } |
| 374 | 354 |
| 375 void RendererController::SetShowInterstitialCallback( | |
| 376 const ShowInterstitialCallback& cb) { | |
| 377 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 378 show_interstitial_cb_ = cb; | |
| 379 UpdateInterstitial(SkBitmap()); | |
| 380 if (!poster_url_.is_empty()) | |
| 381 DownloadPosterImage(); | |
| 382 } | |
| 383 | |
| 384 void RendererController::SetDownloadPosterCallback( | |
| 385 const DownloadPosterCallback& cb) { | |
| 386 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 387 DCHECK(download_poster_cb_.is_null()); | |
| 388 download_poster_cb_ = cb; | |
| 389 if (!poster_url_.is_empty()) | |
| 390 DownloadPosterImage(); | |
| 391 } | |
| 392 | |
| 393 void RendererController::UpdateInterstitial( | |
| 394 const base::Optional<SkBitmap>& image) { | |
| 395 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 396 if (show_interstitial_cb_.is_null()) | |
| 397 return; | |
| 398 | |
| 399 InterstitialType type = InterstitialType::BETWEEN_SESSIONS; | |
| 400 switch (remote_rendering_started_ ? session_->state() | |
| 401 : SharedSession::SESSION_STOPPING) { | |
| 402 case SharedSession::SESSION_STARTED: | |
| 403 type = InterstitialType::IN_SESSION; | |
| 404 break; | |
| 405 case SharedSession::SESSION_PERMANENTLY_STOPPED: | |
| 406 type = InterstitialType::ENCRYPTED_MEDIA_FATAL_ERROR; | |
| 407 break; | |
| 408 case SharedSession::SESSION_UNAVAILABLE: | |
| 409 case SharedSession::SESSION_CAN_START: | |
| 410 case SharedSession::SESSION_STARTING: | |
| 411 case SharedSession::SESSION_STOPPING: | |
| 412 break; | |
| 413 } | |
| 414 | |
| 415 bool needs_update = false; | |
| 416 if (image.has_value()) { | |
| 417 interstitial_background_ = image.value(); | |
| 418 needs_update = true; | |
| 419 } | |
| 420 if (interstitial_natural_size_ != pipeline_metadata_.natural_size) { | |
| 421 interstitial_natural_size_ = pipeline_metadata_.natural_size; | |
| 422 needs_update = true; | |
| 423 } | |
| 424 if (interstitial_type_ != type) { | |
| 425 interstitial_type_ = type; | |
| 426 needs_update = true; | |
| 427 } | |
| 428 if (!needs_update) | |
| 429 return; | |
| 430 | |
| 431 show_interstitial_cb_.Run(interstitial_background_, | |
| 432 interstitial_natural_size_, interstitial_type_); | |
| 433 } | |
| 434 | |
| 435 void RendererController::DownloadPosterImage() { | |
| 436 if (download_poster_cb_.is_null() || show_interstitial_cb_.is_null()) | |
| 437 return; | |
| 438 DCHECK(!poster_url_.is_empty()); | |
| 439 | |
| 440 const base::TimeTicks download_start_time = base::TimeTicks::Now(); | |
| 441 download_poster_cb_.Run( | |
| 442 poster_url_, | |
| 443 base::Bind(&RendererController::OnPosterImageDownloaded, | |
| 444 weak_factory_.GetWeakPtr(), poster_url_, download_start_time)); | |
| 445 } | |
| 446 | |
| 447 void RendererController::OnPosterImageDownloaded( | |
| 448 const GURL& download_url, | |
| 449 base::TimeTicks download_start_time, | |
| 450 const SkBitmap& image) { | |
| 451 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 452 | |
| 453 metrics_recorder_.OnPosterImageDownloaded( | |
| 454 base::TimeTicks::Now() - download_start_time, !image.drawsNothing()); | |
| 455 if (download_url != poster_url_) | |
| 456 return; // The poster image URL has changed during the download. | |
| 457 UpdateInterstitial(image); | |
| 458 } | |
| 459 | |
| 460 void RendererController::OnRendererFatalError(StopTrigger stop_trigger) { | 355 void RendererController::OnRendererFatalError(StopTrigger stop_trigger) { |
| 461 DCHECK(thread_checker_.CalledOnValidThread()); | 356 DCHECK(thread_checker_.CalledOnValidThread()); |
| 462 | 357 |
| 463 // Do not act on errors caused by things like Mojo pipes being closed during | 358 // Do not act on errors caused by things like Mojo pipes being closed during |
| 464 // shutdown. | 359 // shutdown. |
| 465 if (!remote_rendering_started_) | 360 if (!remote_rendering_started_) |
| 466 return; | 361 return; |
| 467 | 362 |
| 468 encountered_renderer_fatal_error_ = true; | 363 encountered_renderer_fatal_error_ = true; |
| 469 UpdateAndMaybeSwitch(UNKNOWN_START_TRIGGER, stop_trigger); | 364 UpdateAndMaybeSwitch(UNKNOWN_START_TRIGGER, stop_trigger); |
| 470 } | 365 } |
| 471 | 366 |
| 472 void RendererController::SetClient(MediaObserverClient* client) { | 367 void RendererController::SetClient(MediaObserverClient* client) { |
| 473 DCHECK(thread_checker_.CalledOnValidThread()); | 368 DCHECK(thread_checker_.CalledOnValidThread()); |
| 474 DCHECK(client); | 369 DCHECK(client); |
| 475 DCHECK(!client_); | 370 DCHECK(!client_); |
| 476 | 371 |
| 477 client_ = client; | 372 client_ = client; |
| 478 client_->ActivateViewportIntersectionMonitoring(IsRemoteSinkAvailable()); | 373 client_->ActivateViewportIntersectionMonitoring(IsRemoteSinkAvailable()); |
| 479 } | 374 } |
| 480 | 375 |
| 481 } // namespace remoting | 376 } // namespace remoting |
| 482 } // namespace media | 377 } // namespace media |
| OLD | NEW |