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

Unified Diff: media/remoting/remoting_renderer_controller.cc

Issue 2631993002: Media Remoting: UMAs to track session events and measurements. (Closed)
Patch Set: REBASE before commit 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
« no previous file with comments | « media/remoting/remoting_renderer_controller.h ('k') | media/remoting/remoting_source_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/remoting/remoting_renderer_controller.cc
diff --git a/media/remoting/remoting_renderer_controller.cc b/media/remoting/remoting_renderer_controller.cc
index ab938b98a7b9f08c3e7a9cdb6da2fa791824643e..515e08298ccd8e502f3be587800605d144722036 100644
--- a/media/remoting/remoting_renderer_controller.cc
+++ b/media/remoting/remoting_renderer_controller.cc
@@ -7,6 +7,7 @@
#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 {
@@ -19,6 +20,7 @@ RemotingRendererController::RemotingRendererController(
RemotingRendererController::~RemotingRendererController() {
DCHECK(thread_checker_.CalledOnValidThread());
+ metrics_recorder_.WillStopSession(remoting::MEDIA_ELEMENT_DESTROYED);
remoting_source_->RemoveClient(this);
}
@@ -28,6 +30,7 @@ void RemotingRendererController::OnStarted(bool success) {
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 {
@@ -36,18 +39,24 @@ void RemotingRendererController::OnStarted(bool success) {
} 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);
+}
- VLOG(1) << "OnSessionStateChanged: " << remoting_source_->state();
+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();
+ UpdateAndMaybeSwitch(start_trigger, stop_trigger);
}
bool RemotingRendererController::IsRemoteSinkAvailable() {
@@ -71,21 +80,45 @@ void RemotingRendererController::OnEnteredFullscreen() {
DCHECK(thread_checker_.CalledOnValidThread());
is_fullscreen_ = true;
- UpdateAndMaybeSwitch();
+ // 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;
- UpdateAndMaybeSwitch();
+ // 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();
+ UpdateAndMaybeSwitch(remoting::BECAME_DOMINANT_CONTENT,
+ remoting::BECAME_AUXILIARY_CONTENT);
}
void RemotingRendererController::OnSetCdm(CdmContext* cdm_context) {
@@ -97,15 +130,16 @@ void RemotingRendererController::OnSetCdm(CdmContext* cdm_context) {
remoting_source_->RemoveClient(this);
remoting_source_ = remoting_cdm_context->GetRemotingSource();
- remoting_source_->AddClient(this); // Calls OnSessionStateChanged().
- UpdateAndMaybeSwitch();
+ 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;
- UpdateAndMaybeSwitch();
+ metrics_recorder_.OnRemotePlaybackDisabled(disabled);
+ UpdateAndMaybeSwitch(remoting::ENABLED_BY_PAGE, remoting::DISABLED_BY_PAGE);
}
void RemotingRendererController::OnSetPoster(const GURL& poster_url) {
@@ -126,7 +160,10 @@ void RemotingRendererController::SetSwitchRendererCallback(
DCHECK(!cb.is_null());
switch_renderer_cb_ = cb;
- UpdateAndMaybeSwitch();
+ // 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(
@@ -160,7 +197,12 @@ void RemotingRendererController::OnMetadataChanged(
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())
@@ -171,7 +213,23 @@ void RemotingRendererController::OnMetadataChanged(
if (pipeline_metadata_.natural_size != old_size)
UpdateInterstitial(base::nullopt);
- UpdateAndMaybeSwitch();
+ 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() {
@@ -222,7 +280,7 @@ void RemotingRendererController::OnPlaying() {
DCHECK(thread_checker_.CalledOnValidThread());
is_paused_ = false;
- UpdateAndMaybeSwitch();
+ UpdateAndMaybeSwitch(remoting::PLAY_COMMAND, remoting::UNKNOWN_STOP_TRIGGER);
}
void RemotingRendererController::OnPaused() {
@@ -246,12 +304,16 @@ bool RemotingRendererController::ShouldBeRemoting() {
// 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 (irregular_playback_detected_)
+ if (encountered_renderer_fatal_error_)
return false;
switch (state) {
@@ -289,7 +351,9 @@ bool RemotingRendererController::ShouldBeRemoting() {
return is_fullscreen_ || is_dominant_content_;
}
-void RemotingRendererController::UpdateAndMaybeSwitch() {
+void RemotingRendererController::UpdateAndMaybeSwitch(
+ remoting::StartTrigger start_trigger,
+ remoting::StopTrigger stop_trigger) {
DCHECK(thread_checker_.CalledOnValidThread());
bool should_be_remoting = ShouldBeRemoting();
@@ -300,7 +364,8 @@ void RemotingRendererController::UpdateAndMaybeSwitch() {
// 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.
- // Keep mirroring the video in this case is good for the user experience.
+ // Thus, the user experience is improved by not starting remoting until
+ // playback resumes.
if (should_be_remoting && is_paused_)
return;
@@ -314,6 +379,8 @@ void RemotingRendererController::UpdateAndMaybeSwitch() {
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);
@@ -323,6 +390,8 @@ void RemotingRendererController::UpdateAndMaybeSwitch() {
// 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);
}
@@ -376,29 +445,37 @@ void RemotingRendererController::DownloadPosterImage() {
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_));
+ 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::OnIrregularPlaybackDetected() {
+void RemotingRendererController::OnRendererFatalError(
+ remoting::StopTrigger stop_trigger) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (irregular_playback_detected_)
+ // Do not act on errors caused by things like Mojo pipes being closed during
+ // shutdown.
+ if (!remote_rendering_started_)
return;
- irregular_playback_detected_ = true;
- UpdateAndMaybeSwitch();
+
+ encountered_renderer_fatal_error_ = true;
+ UpdateAndMaybeSwitch(remoting::UNKNOWN_START_TRIGGER, stop_trigger);
}
} // namespace media
« no previous file with comments | « media/remoting/remoting_renderer_controller.h ('k') | media/remoting/remoting_source_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698