blob: eaa6459c2f528990470ab7f10b3590947d8081c4 [file] [log] [blame]
// Copyright 2023 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/media/base/metrics_provider.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
namespace cobalt {
namespace media {
using starboard::ScopedLock;
MediaMetricsProvider::~MediaMetricsProvider() { ReportPipelineUMA(); }
void MediaMetricsProvider::OnError(const ::media::PipelineStatus status) {
ScopedLock scoped_lock(mutex_);
uma_info_.last_pipeline_status = status;
}
void MediaMetricsProvider::SetHasAudio(AudioCodec audio_codec) {
ScopedLock scoped_lock(mutex_);
uma_info_.audio_codec = audio_codec;
uma_info_.has_audio = true;
}
void MediaMetricsProvider::SetHasVideo(VideoCodec video_codec) {
ScopedLock scoped_lock(mutex_);
uma_info_.video_codec = video_codec;
uma_info_.has_video = true;
}
void MediaMetricsProvider::SetHasPlayed() {
ScopedLock scoped_lock(mutex_);
uma_info_.has_ever_played = true;
}
void MediaMetricsProvider::SetHaveEnough() {
ScopedLock scoped_lock(mutex_);
uma_info_.has_reached_have_enough = true;
}
void MediaMetricsProvider::SetIsEME() {
ScopedLock scoped_lock(mutex_);
uma_info_.is_eme = true;
}
void MediaMetricsProvider::ReportPipelineUMA() {
ScopedLock scoped_lock(mutex_);
if (uma_info_.has_video && uma_info_.has_audio) {
base::UmaHistogramExactLinear(GetUMANameForAVStream(uma_info_),
uma_info_.last_pipeline_status,
PipelineStatus::PIPELINE_STATUS_MAX + 1);
} else if (uma_info_.has_audio) {
base::UmaHistogramExactLinear("Cobalt.Media.PipelineStatus.AudioOnly",
uma_info_.last_pipeline_status,
PipelineStatus::PIPELINE_STATUS_MAX + 1);
} else if (uma_info_.has_video) {
base::UmaHistogramExactLinear("Cobalt.Media.PipelineStatus.VideoOnly",
uma_info_.last_pipeline_status,
PipelineStatus::PIPELINE_STATUS_MAX + 1);
} else {
// Note: This metric can be recorded as a result of normal operation with
// Media Source Extensions. If a site creates a MediaSource object but never
// creates a source buffer or appends data, PIPELINE_OK will be recorded.
base::UmaHistogramExactLinear("Cobalt.Media.PipelineStatus.Unsupported",
uma_info_.last_pipeline_status,
PipelineStatus::PIPELINE_STATUS_MAX + 1);
}
// Report whether this player ever saw a playback event. Used to measure the
// effectiveness of efforts to reduce loaded-but-never-used players.
if (uma_info_.has_reached_have_enough)
base::UmaHistogramBoolean("Cobalt.Media.HasEverPlayed",
uma_info_.has_ever_played);
}
std::string MediaMetricsProvider::GetUMANameForAVStream(
const PipelineInfo& player_info) const {
constexpr char kPipelineUmaPrefix[] =
"Cobalt.Media.PipelineStatus.AudioVideo.";
std::string uma_name = kPipelineUmaPrefix;
if (player_info.video_codec == VideoCodec::kVP9)
uma_name += "VP9";
else if (player_info.video_codec == VideoCodec::kH264)
uma_name += "H264";
else if (player_info.video_codec == VideoCodec::kAV1)
uma_name += "AV1";
else
uma_name += "Other";
return uma_name;
}
void MediaMetricsProvider::StartTrackingAction(MediaAction action) {
DCHECK(!IsActionCurrentlyTracked(action));
ScopedLock scoped_lock(mutex_);
tracked_actions_start_times_[action] = clock_->NowTicks();
}
void MediaMetricsProvider::EndTrackingAction(MediaAction action) {
DCHECK(IsActionCurrentlyTracked(action));
ScopedLock scoped_lock(mutex_);
auto duration = clock_->NowTicks() - tracked_actions_start_times_[action];
ReportActionLatencyUMA(action, duration);
tracked_actions_start_times_.erase(action);
}
bool MediaMetricsProvider::IsActionCurrentlyTracked(MediaAction action) {
ScopedLock scoped_lock(mutex_);
return tracked_actions_start_times_.find(action) !=
tracked_actions_start_times_.end();
}
void MediaMetricsProvider::ReportActionLatencyUMA(
MediaAction action, const base::TimeDelta& action_duration) {
switch (action) {
case MediaAction::WEBMEDIAPLAYER_SEEK:
UMA_HISTOGRAM_TIMES("Cobalt.Media.WebMediaPlayer.Seek.Timing",
action_duration);
break;
case MediaAction::SBPLAYER_CREATE:
UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
"Cobalt.Media.SbPlayer.Create.Timing", action_duration,
base::TimeDelta::FromMicroseconds(100),
base::TimeDelta::FromMicroseconds(1500), 50);
break;
case MediaAction::SBPLAYER_CREATE_URL_PLAYER:
UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
"Cobalt.Media.SbPlayer.CreateUrlPlayer.Timing", action_duration,
base::TimeDelta::FromMicroseconds(100),
base::TimeDelta::FromMicroseconds(1500), 50);
break;
case MediaAction::SBPLAYER_DESTROY:
UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
"Cobalt.Media.SbPlayer.Destroy.Timing", action_duration,
base::TimeDelta::FromMicroseconds(500),
base::TimeDelta::FromMicroseconds(40000), 50);
break;
case MediaAction::UNKNOWN_ACTION:
default:
break;
}
}
} // namespace media
} // namespace cobalt