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

Unified Diff: media/remoting/remoting_renderer_controller.cc

Issue 2643253003: Media Remoting Clean-up: Less-redundant naming, style consistency, etc. (Closed)
Patch Set: Addressed 1st-round comments. UserExperienceController->RendererController 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 side-by-side diff with in-line comments
Download patch
Index: media/remoting/remoting_renderer_controller.cc
diff --git a/media/remoting/remoting_renderer_controller.cc b/media/remoting/remoting_renderer_controller.cc
deleted file mode 100644
index 515e08298ccd8e502f3be587800605d144722036..0000000000000000000000000000000000000000
--- a/media/remoting/remoting_renderer_controller.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/remoting/remoting_renderer_controller.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/threading/thread_checker.h"
-#include "base/time/time.h"
-#include "media/remoting/remoting_cdm_context.h"
-
-namespace media {
-
-RemotingRendererController::RemotingRendererController(
- scoped_refptr<RemotingSourceImpl> remoting_source)
- : remoting_source_(remoting_source), weak_factory_(this) {
- remoting_source_->AddClient(this);
-}
-
-RemotingRendererController::~RemotingRendererController() {
- DCHECK(thread_checker_.CalledOnValidThread());
- metrics_recorder_.WillStopSession(remoting::MEDIA_ELEMENT_DESTROYED);
- remoting_source_->RemoveClient(this);
-}
-
-void RemotingRendererController::OnStarted(bool success) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (success) {
- VLOG(1) << "Remoting started successively.";
- if (remote_rendering_started_) {
- metrics_recorder_.DidStartSession();
- DCHECK(!switch_renderer_cb_.is_null());
- switch_renderer_cb_.Run();
- } else {
- remoting_source_->StopRemoting(this);
- }
- } else {
- VLOG(1) << "Failed to start remoting.";
- remote_rendering_started_ = false;
- metrics_recorder_.WillStopSession(remoting::START_RACE);
- }
-}
-
-void RemotingRendererController::OnSessionStateChanged() {
- DCHECK(thread_checker_.CalledOnValidThread());
- UpdateFromSessionState(remoting::SINK_AVAILABLE, remoting::ROUTE_TERMINATED);
-}
-
-void RemotingRendererController::UpdateFromSessionState(
- remoting::StartTrigger start_trigger,
- remoting::StopTrigger stop_trigger) {
- VLOG(1) << "UpdateFromSessionState: " << remoting_source_->state();
- if (!sink_available_changed_cb_.is_null())
- sink_available_changed_cb_.Run(IsRemoteSinkAvailable());
-
- UpdateInterstitial(base::nullopt);
- UpdateAndMaybeSwitch(start_trigger, stop_trigger);
-}
-
-bool RemotingRendererController::IsRemoteSinkAvailable() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- switch (remoting_source_->state()) {
- case SESSION_CAN_START:
- case SESSION_STARTING:
- case SESSION_STARTED:
- return true;
- case SESSION_UNAVAILABLE:
- case SESSION_STOPPING:
- case SESSION_PERMANENTLY_STOPPED:
- return false;
- }
-
- return false; // To suppress compile warning.
-}
-
-void RemotingRendererController::OnEnteredFullscreen() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- is_fullscreen_ = true;
- // See notes in OnBecameDominantVisibleContent() for why this is forced:
- is_dominant_content_ = true;
- UpdateAndMaybeSwitch(remoting::ENTERED_FULLSCREEN,
- remoting::UNKNOWN_STOP_TRIGGER);
-}
-
-void RemotingRendererController::OnExitedFullscreen() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- is_fullscreen_ = false;
- // See notes in OnBecameDominantVisibleContent() for why this is forced:
- is_dominant_content_ = false;
- UpdateAndMaybeSwitch(remoting::UNKNOWN_START_TRIGGER,
- remoting::EXITED_FULLSCREEN);
-}
-
-void RemotingRendererController::OnBecameDominantVisibleContent(
- bool is_dominant) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Two scenarios where "dominance" status mixes with fullscreen transitions:
- //
- // 1. Just before/after entering fullscreen, the element will, of course,
- // become the dominant on-screen content via automatic page layout.
- // 2. Just before/after exiting fullscreen, the element may or may not
- // shrink in size enough to become non-dominant. However, exiting
- // fullscreen was caused by a user action that explicitly indicates a
- // desire to exit remoting, so even if the element is still dominant,
- // remoting should be shut down.
- //
- // Thus, to achieve the desired behaviors, |is_dominant_content_| is force-set
- // in OnEnteredFullscreen() and OnExitedFullscreen(), and changes to it here
- // are ignored while in fullscreen.
- if (is_fullscreen_)
- return;
-
- is_dominant_content_ = is_dominant;
- UpdateAndMaybeSwitch(remoting::BECAME_DOMINANT_CONTENT,
- remoting::BECAME_AUXILIARY_CONTENT);
-}
-
-void RemotingRendererController::OnSetCdm(CdmContext* cdm_context) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- auto* remoting_cdm_context = RemotingCdmContext::From(cdm_context);
- if (!remoting_cdm_context)
- return;
-
- remoting_source_->RemoveClient(this);
- remoting_source_ = remoting_cdm_context->GetRemotingSource();
- remoting_source_->AddClient(this);
- UpdateFromSessionState(remoting::CDM_READY, remoting::DECRYPTION_ERROR);
-}
-
-void RemotingRendererController::OnRemotePlaybackDisabled(bool disabled) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- is_remote_playback_disabled_ = disabled;
- metrics_recorder_.OnRemotePlaybackDisabled(disabled);
- UpdateAndMaybeSwitch(remoting::ENABLED_BY_PAGE, remoting::DISABLED_BY_PAGE);
-}
-
-void RemotingRendererController::OnSetPoster(const GURL& poster_url) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (poster_url != poster_url_) {
- poster_url_ = poster_url;
- if (poster_url_.is_empty())
- UpdateInterstitial(SkBitmap());
- else
- DownloadPosterImage();
- }
-}
-
-void RemotingRendererController::SetSwitchRendererCallback(
- const base::Closure& cb) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!cb.is_null());
-
- switch_renderer_cb_ = cb;
- // Note: Not calling UpdateAndMaybeSwitch() here since this method should be
- // called during the initialization phase of this RemotingRendererController;
- // and definitely before a whole lot of other things that are needed to
- // trigger a switch.
-}
-
-void RemotingRendererController::SetRemoteSinkAvailableChangedCallback(
- const base::Callback<void(bool)>& cb) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- sink_available_changed_cb_ = cb;
- if (!sink_available_changed_cb_.is_null())
- sink_available_changed_cb_.Run(IsRemoteSinkAvailable());
-}
-
-base::WeakPtr<remoting::RpcBroker> RemotingRendererController::GetRpcBroker()
- const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- return remoting_source_->GetRpcBroker()->GetWeakPtr();
-}
-
-void RemotingRendererController::StartDataPipe(
- std::unique_ptr<mojo::DataPipe> audio_data_pipe,
- std::unique_ptr<mojo::DataPipe> video_data_pipe,
- const RemotingSourceImpl::DataPipeStartCallback& done_callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- remoting_source_->StartDataPipe(std::move(audio_data_pipe),
- std::move(video_data_pipe), done_callback);
-}
-
-void RemotingRendererController::OnMetadataChanged(
- const PipelineMetadata& metadata) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- const gfx::Size old_size = pipeline_metadata_.natural_size;
- const bool was_audio_codec_supported = has_audio() && IsAudioCodecSupported();
- const bool was_video_codec_supported = has_video() && IsVideoCodecSupported();
- pipeline_metadata_ = metadata;
- const bool is_audio_codec_supported = has_audio() && IsAudioCodecSupported();
- const bool is_video_codec_supported = has_video() && IsVideoCodecSupported();
- metrics_recorder_.OnPipelineMetadataChanged(metadata);
-
- is_encrypted_ = false;
- if (has_video())
- is_encrypted_ |= metadata.video_decoder_config.is_encrypted();
- if (has_audio())
- is_encrypted_ |= metadata.audio_decoder_config.is_encrypted();
-
- if (pipeline_metadata_.natural_size != old_size)
- UpdateInterstitial(base::nullopt);
-
- remoting::StartTrigger start_trigger = remoting::UNKNOWN_START_TRIGGER;
- if (!was_audio_codec_supported && is_audio_codec_supported)
- start_trigger = remoting::SUPPORTED_AUDIO_CODEC;
- if (!was_video_codec_supported && is_video_codec_supported) {
- start_trigger = start_trigger == remoting::SUPPORTED_AUDIO_CODEC
- ? remoting::SUPPORTED_AUDIO_AND_VIDEO_CODECS
- : remoting::SUPPORTED_VIDEO_CODEC;
- }
- remoting::StopTrigger stop_trigger = remoting::UNKNOWN_STOP_TRIGGER;
- if (was_audio_codec_supported && !is_audio_codec_supported)
- stop_trigger = remoting::UNSUPPORTED_AUDIO_CODEC;
- if (was_video_codec_supported && !is_video_codec_supported) {
- stop_trigger = stop_trigger == remoting::UNSUPPORTED_AUDIO_CODEC
- ? remoting::UNSUPPORTED_AUDIO_AND_VIDEO_CODECS
- : remoting::UNSUPPORTED_VIDEO_CODEC;
- }
- UpdateAndMaybeSwitch(start_trigger, stop_trigger);
-}
-
-bool RemotingRendererController::IsVideoCodecSupported() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(has_video());
-
- switch (pipeline_metadata_.video_decoder_config.codec()) {
- case VideoCodec::kCodecH264:
- case VideoCodec::kCodecVP8:
- return true;
- default:
- VLOG(2) << "Remoting does not support video codec: "
- << pipeline_metadata_.video_decoder_config.codec();
- return false;
- }
-}
-
-bool RemotingRendererController::IsAudioCodecSupported() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(has_audio());
-
- switch (pipeline_metadata_.audio_decoder_config.codec()) {
- case AudioCodec::kCodecAAC:
- case AudioCodec::kCodecMP3:
- case AudioCodec::kCodecPCM:
- case AudioCodec::kCodecVorbis:
- case AudioCodec::kCodecFLAC:
- case AudioCodec::kCodecAMR_NB:
- case AudioCodec::kCodecAMR_WB:
- case AudioCodec::kCodecPCM_MULAW:
- case AudioCodec::kCodecGSM_MS:
- case AudioCodec::kCodecPCM_S16BE:
- case AudioCodec::kCodecPCM_S24BE:
- case AudioCodec::kCodecOpus:
- case AudioCodec::kCodecEAC3:
- case AudioCodec::kCodecPCM_ALAW:
- case AudioCodec::kCodecALAC:
- case AudioCodec::kCodecAC3:
- return true;
- default:
- VLOG(2) << "Remoting does not support audio codec: "
- << pipeline_metadata_.audio_decoder_config.codec();
- return false;
- }
-}
-
-void RemotingRendererController::OnPlaying() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- is_paused_ = false;
- UpdateAndMaybeSwitch(remoting::PLAY_COMMAND, remoting::UNKNOWN_STOP_TRIGGER);
-}
-
-void RemotingRendererController::OnPaused() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- is_paused_ = true;
-}
-
-bool RemotingRendererController::ShouldBeRemoting() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (switch_renderer_cb_.is_null()) {
- DCHECK(!remote_rendering_started_);
- return false; // No way to switch to a RemotingRenderImpl.
- }
-
- const RemotingSessionState state = remoting_source_->state();
- if (is_encrypted_) {
- // Due to technical limitations when playing encrypted content, once a
- // remoting session has been started, always return true here to indicate
- // that the RemotingRendererImpl should be used. In the stopped states,
- // RemotingRendererImpl will display an interstitial to notify the user that
- // local rendering cannot be resumed.
- //
- // TODO(miu): Revisit this once more of the encrypted-remoting impl is
- // in-place. For example, this will prevent metrics from recording session
- // stop reasons.
- return state == RemotingSessionState::SESSION_STARTED ||
- state == RemotingSessionState::SESSION_STOPPING ||
- state == RemotingSessionState::SESSION_PERMANENTLY_STOPPED;
- }
-
- if (encountered_renderer_fatal_error_)
- return false;
-
- switch (state) {
- case SESSION_UNAVAILABLE:
- return false; // Cannot remote media without a remote sink.
- case SESSION_CAN_START:
- case SESSION_STARTING:
- case SESSION_STARTED:
- break; // Media remoting is possible, assuming other requirments are met.
- case SESSION_STOPPING:
- case SESSION_PERMANENTLY_STOPPED:
- return false; // Use local rendering after stopping remoting.
- }
-
- switch (remoting_source_->sink_capabilities()) {
- case mojom::RemotingSinkCapabilities::NONE:
- return false;
- case mojom::RemotingSinkCapabilities::RENDERING_ONLY:
- case mojom::RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING:
- break; // The sink is capable of remote rendering.
- }
-
- if ((!has_audio() && !has_video()) ||
- (has_video() && !IsVideoCodecSupported()) ||
- (has_audio() && !IsAudioCodecSupported())) {
- return false;
- }
-
- if (is_remote_playback_disabled_)
- return false;
-
- // Normally, entering fullscreen or being the dominant visible content is the
- // signal that starts remote rendering. However, current technical limitations
- // require encrypted content be remoted without waiting for a user signal.
- return is_fullscreen_ || is_dominant_content_;
-}
-
-void RemotingRendererController::UpdateAndMaybeSwitch(
- remoting::StartTrigger start_trigger,
- remoting::StopTrigger stop_trigger) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- bool should_be_remoting = ShouldBeRemoting();
-
- if (remote_rendering_started_ == should_be_remoting)
- return;
-
- // Only switch to remoting when media is playing. Since the renderer is
- // created when video starts loading/playing, receiver will display a black
- // screen before video starts playing if switching to remoting when paused.
- // Thus, the user experience is improved by not starting remoting until
- // playback resumes.
- if (should_be_remoting && is_paused_)
- return;
-
- // Switch between local renderer and remoting renderer.
- remote_rendering_started_ = should_be_remoting;
-
- if (remote_rendering_started_) {
- DCHECK(!switch_renderer_cb_.is_null());
- if (remoting_source_->state() ==
- RemotingSessionState::SESSION_PERMANENTLY_STOPPED) {
- switch_renderer_cb_.Run();
- return;
- }
- DCHECK_NE(start_trigger, remoting::UNKNOWN_START_TRIGGER);
- metrics_recorder_.WillStartSession(start_trigger);
- // |switch_renderer_cb_.Run()| will be called after remoting is started
- // successfully.
- remoting_source_->StartRemoting(this);
- } else {
- // For encrypted content, it's only valid to switch to remoting renderer,
- // and never back to the local renderer. The RemotingCdmController will
- // force-stop the session when remoting has ended; so no need to call
- // StopRemoting() from here.
- DCHECK(!is_encrypted_);
- DCHECK_NE(stop_trigger, remoting::UNKNOWN_STOP_TRIGGER);
- metrics_recorder_.WillStopSession(stop_trigger);
- switch_renderer_cb_.Run();
- remoting_source_->StopRemoting(this);
- }
-}
-
-void RemotingRendererController::SetShowInterstitialCallback(
- const ShowInterstitialCallback& cb) {
- DCHECK(thread_checker_.CalledOnValidThread());
- show_interstitial_cb_ = cb;
- UpdateInterstitial(SkBitmap());
- if (!poster_url_.is_empty())
- DownloadPosterImage();
-}
-
-void RemotingRendererController::SetDownloadPosterCallback(
- const DownloadPosterCallback& cb) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(download_poster_cb_.is_null());
- download_poster_cb_ = cb;
- if (!poster_url_.is_empty())
- DownloadPosterImage();
-}
-
-void RemotingRendererController::UpdateInterstitial(
- const base::Optional<SkBitmap>& image) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (show_interstitial_cb_.is_null() ||
- pipeline_metadata_.natural_size.IsEmpty())
- return;
-
- RemotingInterstitialType type = RemotingInterstitialType::BETWEEN_SESSIONS;
- switch (remoting_source_->state()) {
- case SESSION_STARTED:
- type = RemotingInterstitialType::IN_SESSION;
- break;
- case SESSION_PERMANENTLY_STOPPED:
- type = RemotingInterstitialType::ENCRYPTED_MEDIA_FATAL_ERROR;
- break;
- case SESSION_UNAVAILABLE:
- case SESSION_CAN_START:
- case SESSION_STARTING:
- case SESSION_STOPPING:
- break;
- }
-
- show_interstitial_cb_.Run(image, pipeline_metadata_.natural_size, type);
-}
-
-void RemotingRendererController::DownloadPosterImage() {
- if (download_poster_cb_.is_null() || show_interstitial_cb_.is_null())
- return;
- DCHECK(!poster_url_.is_empty());
-
- const base::TimeTicks download_start_time = base::TimeTicks::Now();
- download_poster_cb_.Run(
- poster_url_,
- base::Bind(&RemotingRendererController::OnPosterImageDownloaded,
- weak_factory_.GetWeakPtr(), poster_url_, download_start_time));
-}
-
-void RemotingRendererController::OnPosterImageDownloaded(
- const GURL& download_url,
- base::TimeTicks download_start_time,
- const SkBitmap& image) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- metrics_recorder_.OnPosterImageDownloaded(
- base::TimeTicks::Now() - download_start_time, !image.drawsNothing());
- if (download_url != poster_url_)
- return; // The poster image URL has changed during the download.
- UpdateInterstitial(image);
-}
-
-void RemotingRendererController::OnRendererFatalError(
- remoting::StopTrigger stop_trigger) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Do not act on errors caused by things like Mojo pipes being closed during
- // shutdown.
- if (!remote_rendering_started_)
- return;
-
- encountered_renderer_fatal_error_ = true;
- UpdateAndMaybeSwitch(remoting::UNKNOWN_START_TRIGGER, stop_trigger);
-}
-
-} // namespace media

Powered by Google App Engine
This is Rietveld 408576698