Skip to content

Commit

Permalink
[android] Measuring CPU usage
Browse files Browse the repository at this point in the history
Add measuring the CPU usage for testing the performance.

b/322869860
  • Loading branch information
borongc committed Jan 30, 2024
1 parent 40d4816 commit 38009f8
Show file tree
Hide file tree
Showing 12 changed files with 600 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cobalt/media/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ component("media") {
"base/sbplayer_bridge.h",
"base/sbplayer_interface.cc",
"base/sbplayer_interface.h",
"base/sbplayer_perf.cc",
"base/sbplayer_perf.h",
"base/sbplayer_pipeline.cc",
"base/sbplayer_pipeline.h",
"base/sbplayer_set_bounds_helper.cc",
Expand Down
38 changes: 38 additions & 0 deletions cobalt/media/base/sbplayer_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "starboard/common/player.h"
#include "starboard/common/string.h"
#include "starboard/configuration.h"
#include "starboard/extension/player_perf.h"
#include "starboard/extension/player_set_max_video_input_size.h"
#include "starboard/memory.h"
#include "starboard/once.h"
Expand All @@ -45,6 +46,8 @@ using base::TimeDelta;
using starboard::FormatString;
using starboard::GetPlayerOutputModeName;

constexpr bool kForceCPUUtilizationMeasure = true;

class StatisticsWrapper {
public:
static StatisticsWrapper* GetInstance();
Expand Down Expand Up @@ -251,6 +254,7 @@ SbPlayerBridge::SbPlayerBridge(
decode_target_provider_(decode_target_provider),
max_video_capabilities_(max_video_capabilities),
max_video_input_size_(max_video_input_size),
perf_thread_("cpu_utilization_perf"),
cval_stats_(&interface->cval_stats_),
pipeline_identifier_(pipeline_identifier)
#if SB_HAS(PLAYER_WITH_URL)
Expand All @@ -274,6 +278,16 @@ SbPlayerBridge::SbPlayerBridge(
UpdateVideoConfig(video_config, video_mime_type);
}

const StarboardExtensionPlayerPerfApi* player_perf_extension =
static_cast<const StarboardExtensionPlayerPerfApi*>(
SbSystemGetExtension(kStarboardExtensionPlayerPerfName));
if (kForceCPUUtilizationMeasure && player_perf_extension &&
strcmp(player_perf_extension->name, kStarboardExtensionPlayerPerfName) ==
0 &&
player_perf_extension->version >= 1) {
perf_thread_.Start();
}

output_mode_ = ComputeSbPlayerOutputMode(default_output_mode);

CreatePlayer();
Expand All @@ -289,6 +303,19 @@ SbPlayerBridge::SbPlayerBridge(
SbPlayerBridge::~SbPlayerBridge() {
DCHECK(task_runner_->BelongsToCurrentThread());

const StarboardExtensionPlayerPerfApi* player_perf_extension =
static_cast<const StarboardExtensionPlayerPerfApi*>(
SbSystemGetExtension(kStarboardExtensionPlayerPerfName));
if (kForceCPUUtilizationMeasure && player_perf_extension &&
strcmp(player_perf_extension->name, kStarboardExtensionPlayerPerfName) ==
0 &&
player_perf_extension->version >= 1) {
if (sbplayer_perf_) {
sbplayer_perf_->Stop();
}
perf_thread_.Stop();
}

callback_helper_->ResetPlayer();
set_bounds_helper_->SetPlayerBridge(NULL);

Expand Down Expand Up @@ -794,6 +821,17 @@ void SbPlayerBridge::CreatePlayer() {
&SbPlayerBridge::DecoderStatusCB, &SbPlayerBridge::PlayerStatusCB,
&SbPlayerBridge::PlayerErrorCB, this,
get_decode_target_graphics_context_provider_func_.Run());
const StarboardExtensionPlayerPerfApi* player_perf_extension =
static_cast<const StarboardExtensionPlayerPerfApi*>(
SbSystemGetExtension(kStarboardExtensionPlayerPerfName));
if (kForceCPUUtilizationMeasure && player_perf_extension &&
strcmp(player_perf_extension->name, kStarboardExtensionPlayerPerfName) ==
0 &&
player_perf_extension->version >= 1) {
sbplayer_perf_ = new SbPlayerPerf(sbplayer_interface_, player_,
perf_thread_.task_runner());
sbplayer_perf_->Start();
}
cval_stats_->StopTimer(MediaTiming::SbPlayerCreate, pipeline_identifier_);

is_creating_player_ = false;
Expand Down
4 changes: 4 additions & 0 deletions cobalt/media/base/sbplayer_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "cobalt/media/base/decode_target_provider.h"
#include "cobalt/media/base/decoder_buffer_cache.h"
#include "cobalt/media/base/sbplayer_interface.h"
#include "cobalt/media/base/sbplayer_perf.h"
#include "cobalt/media/base/sbplayer_set_bounds_helper.h"
#include "starboard/media.h"
#include "starboard/player.h"
Expand Down Expand Up @@ -325,6 +326,9 @@ class SbPlayerBridge {
bool pending_audio_eos_buffer_ = false;
bool pending_video_eos_buffer_ = false;

base::Thread perf_thread_;
SbPlayerPerf* sbplayer_perf_;

CValStats* cval_stats_;
std::string pipeline_identifier_;
};
Expand Down
142 changes: 142 additions & 0 deletions cobalt/media/base/sbplayer_perf.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright 2024 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/sbplayer_perf.h"

#include "base/bind.h"
#include "base/logging.h"
#include "cobalt/base/statistics.h"
#include "starboard/extension/player_perf.h"
#include "starboard/once.h"
#include "starboard/player.h"
#include "starboard/system.h"

namespace cobalt {
namespace media {

namespace {

const int64_t kMaxMeasurementSamples = 256;

class StatisticsWrapper {
public:
static StatisticsWrapper* GetInstance();
base::Statistics<double, int, 1024> cpu_usage{"Media.CPUUsage"};
};

} // namespace

SB_ONCE_INITIALIZE_FUNCTION(StatisticsWrapper, StatisticsWrapper::GetInstance);

void SbPlayerPerf::Start() {
task_runner_->PostTask(
FROM_HERE, base::Bind(&SbPlayerPerf::StartTask, base::Unretained(this)));
}

void SbPlayerPerf::StartTask() {
DCHECK(task_runner_->BelongsToCurrentThread());
timer_.Start(FROM_HERE, base::Seconds(1), this,
&SbPlayerPerf::GetPlatformIndependentCPUUsage);
}

void SbPlayerPerf::Stop() {
task_runner_->PostTask(
FROM_HERE, base::Bind(&SbPlayerPerf::StopTask, base::Unretained(this)));
}

void SbPlayerPerf::StopTask() {
DCHECK(task_runner_->BelongsToCurrentThread());
timer_.Stop();
}

void SbPlayerPerf::GetPlatformIndependentCPUUsage() {
DCHECK(task_runner_->BelongsToCurrentThread());

const StarboardExtensionPlayerPerfApi* player_perf_extension =
static_cast<const StarboardExtensionPlayerPerfApi*>(
SbSystemGetExtension(kStarboardExtensionPlayerPerfName));
if (player_perf_extension &&
strcmp(player_perf_extension->name, kStarboardExtensionPlayerPerfName) ==
0 &&
player_perf_extension->version >= 1) {
double cpu_usage_perf =
player_perf_extension->GetPlatformIndependentCPUUsage();
if (cpu_usage_perf == 0.0 && data_count_ == 0) {
// The first sample is 0, so skip it
return;
}
StatisticsWrapper::GetInstance()->cpu_usage.AddSample(cpu_usage_perf, 1);
data_count_ += 1;
if (data_count_ == kMaxMeasurementSamples) {
#if SB_API_VERSION >= 15
SbPlayerInfo info;
#else // SB_API_VERSION >= 15
SbPlayerInfo2 info;
#endif // SB_API_VERSION >= 15
interface_->GetInfo(player_, &info);
double dropped_frame_percentage =
100.0 * static_cast<double>(info.dropped_video_frames) /
static_cast<double>(info.total_video_frames);
LOG(ERROR) << "Brown Brand/model_name: " << sb_system_property_brand_name_
<< " " << sb_system_property_model_name_
<< ", platform_name: " << sb_system_property_platform_name_
<< ", num_of_processors: " << sb_number_of_processors_
<< ", dropped_frames(%): " << dropped_frame_percentage
<< "%, dropped_frames: " << info.dropped_video_frames
<< ", total_frames: " << info.total_video_frames
<< ", audio_underrun_count: "
<< player_perf_extension->GetAudioUnderrunCount()
<< ", CPU usage statistics(%): min: "
<< StatisticsWrapper::GetInstance()->cpu_usage.min()
<< "%, median: "
<< StatisticsWrapper::GetInstance()->cpu_usage.GetMedian()
<< "%, average: "
<< StatisticsWrapper::GetInstance()->cpu_usage.average()
<< "%, max: "
<< StatisticsWrapper::GetInstance()->cpu_usage.max() << "%";
}
}
}

std::string SbPlayerPerf::GetSbSystemProperty(SbSystemPropertyId property_id) {
char property[1024] = {0};
std::string result = "";
if (!SbSystemGetProperty(property_id, property,
SB_ARRAY_SIZE_INT(property))) {
DLOG(FATAL) << "Failed to get kSbSystemPropertyPlatformName.";
return result;
}
result = property;
return result;
}

SbPlayerPerf::SbPlayerPerf(
SbPlayerInterface* interface, SbPlayer player,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
: task_runner_(task_runner),
data_count_(0),
interface_(interface),
player_(player),
sb_number_of_processors_(SbSystemGetNumberOfProcessors()),
sb_system_property_brand_name_(
GetSbSystemProperty(kSbSystemPropertyBrandName)),
sb_system_property_model_name_(
GetSbSystemProperty(kSbSystemPropertyModelName)),
sb_system_property_platform_name_(
GetSbSystemProperty(kSbSystemPropertyPlatformName)) {}

SbPlayerPerf::~SbPlayerPerf() {}

} // namespace media
} // namespace cobalt
70 changes: 70 additions & 0 deletions cobalt/media/base/sbplayer_perf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2024 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.

#ifndef COBALT_MEDIA_BASE_SBPLAYER_PERF_H_
#define COBALT_MEDIA_BASE_SBPLAYER_PERF_H_

#include <string>
#include <vector>

#include "base/memory/ref_counted.h"
#include "base/task_runner.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "cobalt/media/base/sbplayer_interface.h"
#include "starboard/common/system_property.h"
#include "starboard/types.h"

namespace cobalt {
namespace media {

class SbPlayerPerf {
public:
// Constructs a measure pipeline that will execute on |task_runner|.
explicit SbPlayerPerf(
SbPlayerInterface* interface, SbPlayer player,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
~SbPlayerPerf();

void Start();
void StartTask();
void Stop();
void StopTask();

private:
// Refer base/process/process_metrics.h for GetPlatformIndependentCPUUsage()
void GetPlatformIndependentCPUUsage();
std::string GetSbSystemProperty(SbSystemPropertyId property_id);

// Message loop used to execute pipeline tasks. It is thread-safe.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::RepeatingTimer timer_;

SbPlayerInterface* interface_;
SbPlayer player_;

// TODO(borongchen): ensure when to log CPU statistics, as each video segment
// will Play() once
int data_count_;
std::string sb_system_property_brand_name_;
std::string sb_system_property_model_name_;
std::string sb_system_property_platform_name_;
int sb_number_of_processors_;
};

} // namespace media
} // namespace cobalt

#endif // COBALT_MEDIA_BASE_SBPLAYER_PERF_H_
2 changes: 2 additions & 0 deletions starboard/android/shared/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ static_library("starboard_platform") {
"player_create.cc",
"player_destroy.cc",
"player_get_preferred_output_mode.cc",
"player_perf.cc",
"player_perf.h",
"player_set_bounds.cc",
"player_set_max_video_input_size.cc",
"player_set_max_video_input_size.h",
Expand Down
3 changes: 3 additions & 0 deletions starboard/android/shared/audio_track_audio_sink_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <vector>

#include "starboard/android/shared/media_capabilities_cache.h"
#include "starboard/android/shared/player_perf.h"
#include "starboard/common/string.h"
#include "starboard/common/time.h"
#include "starboard/shared/starboard/media/media_util.h"
Expand Down Expand Up @@ -160,6 +161,8 @@ AudioTrackAudioSink::AudioTrackAudioSink(
return;
}

SetAudioTrackBridge(&bridge_);

audio_out_thread_ = SbThreadCreate(
0, kSbThreadPriorityRealTime, kSbThreadNoAffinity, true,
"audio_track_audio_out", &AudioTrackAudioSink::ThreadEntryPoint, this);
Expand Down
Loading

0 comments on commit 38009f8

Please sign in to comment.