blob: 00832cac653ef3b299213ba531dd3fc951249dc1 [file] [log] [blame]
// Copyright 2020 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/playback_statistics.h"
#include "starboard/atomic.h"
#include "starboard/common/format_string.h"
namespace cobalt {
namespace media {
namespace {
volatile SbAtomic32 s_max_active_instances = 0;
volatile SbAtomic32 s_active_instances = 0;
volatile SbAtomic32 s_av1_played = 0;
volatile SbAtomic32 s_h264_played = 0;
volatile SbAtomic32 s_hevc_played = 0;
volatile SbAtomic32 s_vp9_played = 0;
volatile SbAtomic32 s_min_video_width = 999999;
volatile SbAtomic32 s_min_video_height = 999999;
volatile SbAtomic32 s_max_video_width = 0;
volatile SbAtomic32 s_max_video_height = 0;
volatile SbAtomic32 s_last_working_codec = kUnknownVideoCodec;
int RoundValues(SbAtomic32 value) {
if (value < 10) {
return value;
}
if (value < 100) {
return value / 10 * 10;
}
return value / 100 * 100;
}
void UpdateMaxValue(SbAtomic32 new_value, volatile SbAtomic32* max) {
SB_DCHECK(max);
for (;;) {
auto current_max_value = SbAtomicNoBarrier_Load(max);
if (new_value <= current_max_value) {
return;
}
if (SbAtomicAcquire_CompareAndSwap(max, current_max_value, new_value) ==
current_max_value) {
return;
}
}
}
void UpdateMinValue(SbAtomic32 new_value, volatile SbAtomic32* min) {
SB_DCHECK(min);
for (;;) {
auto current_min_value = SbAtomicNoBarrier_Load(min);
if (new_value >= current_min_value) {
return;
}
if (SbAtomicAcquire_CompareAndSwap(min, current_min_value, new_value) ==
current_min_value) {
return;
}
}
}
} // namespace
PlaybackStatistics::Record::Record(const VideoDecoderConfig& video_config) {
SbAtomicNoBarrier_Increment(&s_active_instances, 1);
UpdateMaxValue(s_active_instances, &s_max_active_instances);
if (video_config.codec() == kCodecAV1) {
SbAtomicBarrier_Increment(&s_av1_played, 1);
} else if (video_config.codec() == kCodecH264) {
SbAtomicBarrier_Increment(&s_h264_played, 1);
} else if (video_config.codec() == kCodecHEVC) {
SbAtomicBarrier_Increment(&s_hevc_played, 1);
} else if (video_config.codec() == kCodecVP9) {
SbAtomicBarrier_Increment(&s_vp9_played, 1);
} else {
SB_NOTREACHED();
}
OnConfigChange(video_config);
}
PlaybackStatistics::Record::~Record() {
SbAtomicNoBarrier_Increment(&s_active_instances, -1);
}
void PlaybackStatistics::Record::OnPresenting(
const VideoDecoderConfig& video_config) {
SbAtomicNoBarrier_Store(&s_last_working_codec, video_config.codec());
}
void PlaybackStatistics::Record::OnConfigChange(
const VideoDecoderConfig& video_config) {
auto width = static_cast<SbAtomic32>(video_config.natural_size().width());
auto height = static_cast<SbAtomic32>(video_config.natural_size().height());
UpdateMinValue(width, &s_min_video_width);
UpdateMaxValue(width, &s_max_video_width);
UpdateMinValue(height, &s_min_video_height);
UpdateMaxValue(height, &s_max_video_height);
LOG(INFO) << "Playback statistics on config change: "
<< PlaybackStatistics::GetStatistics(video_config);
}
// static
std::string PlaybackStatistics::GetStatistics(
const VideoDecoderConfig& current_video_config) {
return starboard::FormatString(
"current_codec: %s, drm: %s, width: %d, height: %d,"
" active_players (max): %d (%d), av1: ~%d, h264: ~%d, hevc: ~%d,"
" vp9: ~%d, min_width: %d, min_height: %d, max_width: %d, max_height: %d,"
" last_working_codec: %s",
GetCodecName(current_video_config.codec()).c_str(),
(current_video_config.is_encrypted() ? "Y" : "N"),
static_cast<int>(current_video_config.natural_size().width()),
static_cast<int>(current_video_config.natural_size().height()),
SbAtomicNoBarrier_Load(&s_active_instances),
SbAtomicNoBarrier_Load(&s_max_active_instances),
RoundValues(SbAtomicNoBarrier_Load(&s_av1_played)),
RoundValues(SbAtomicNoBarrier_Load(&s_h264_played)),
RoundValues(SbAtomicNoBarrier_Load(&s_hevc_played)),
RoundValues(SbAtomicNoBarrier_Load(&s_vp9_played)),
SbAtomicNoBarrier_Load(&s_min_video_width),
SbAtomicNoBarrier_Load(&s_min_video_height),
SbAtomicNoBarrier_Load(&s_max_video_width),
SbAtomicNoBarrier_Load(&s_max_video_height),
GetCodecName(static_cast<VideoCodec>(
SbAtomicNoBarrier_Load(&s_last_working_codec)))
.c_str());
}
} // namespace media
} // namespace cobalt