Skip to content

Commit

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

b/302715613
  • Loading branch information
borongc committed Jan 29, 2024
1 parent a184866 commit 6997d0a
Show file tree
Hide file tree
Showing 11 changed files with 556 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 @@ -66,6 +66,8 @@ component("media") {
"media_module.h",
"player/web_media_player_impl.cc",
"player/web_media_player_impl.h",
"player/web_media_player_perf.cc",
"player/web_media_player_perf.h",
"player/web_media_player_proxy.cc",
"player/web_media_player_proxy.h",
"progressive/avc_access_unit.cc",
Expand Down
43 changes: 43 additions & 0 deletions cobalt/media/player/web_media_player_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "cobalt/media/progressive/data_source_reader.h"
#include "cobalt/media/progressive/demuxer_extension_wrapper.h"
#include "cobalt/media/progressive/progressive_demuxer.h"
#include "starboard/extension/player_perf.h"
#include "starboard/system.h"
#include "starboard/types.h"
#include "third_party/chromium/media/base/bind_to_current_loop.h"
Expand Down Expand Up @@ -71,6 +72,8 @@ const char* kMediaEme = "Media.EME.";
// greater than or equal to duration() - kEndOfStreamEpsilonInSeconds".
const double kEndOfStreamEpsilonInSeconds = 2.0;

constexpr bool kForceCPUUtilizationMeasure = true;

DECLARE_INSTANCE_COUNTER(WebMediaPlayerImpl);

bool IsNearTheEndOfStream(const WebMediaPlayerImpl* wmpi, double position) {
Expand Down Expand Up @@ -116,6 +119,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
#endif // SB_API_VERSION >= 15
::media::MediaLog* const media_log)
: pipeline_thread_("media_pipeline"),
perf_thread_("cpu_utilization_perf"),
network_state_(WebMediaPlayer::kNetworkStateEmpty),
ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
main_loop_(base::MessageLoop::current()),
Expand Down Expand Up @@ -149,6 +153,17 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
#endif // SB_API_VERSION >= 15
media_log_, &media_metrics_provider_, decode_target_provider_.get());

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();
web_media_player_perf_ = new WebMediaPlayerPerf(perf_thread_.task_runner());

Check warning on line 164 in cobalt/media/player/web_media_player_impl.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_impl.cc#L156-L164

Added lines #L156 - L164 were not covered by tests
}

// Also we want to be notified of |main_loop_| destruction.
main_loop_->AddDestructionObserver(this);

Expand Down Expand Up @@ -180,6 +195,15 @@ WebMediaPlayerImpl::~WebMediaPlayerImpl() {
main_loop_->RemoveDestructionObserver(this);
}
pipeline_thread_.Stop();
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_.Stop();

Check warning on line 205 in cobalt/media/player/web_media_player_impl.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_impl.cc#L198-L205

Added lines #L198 - L205 were not covered by tests
}
}

namespace {
Expand Down Expand Up @@ -845,6 +869,15 @@ void WebMediaPlayerImpl::StartPipeline(::media::Demuxer* demuxer) {
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged),
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnContentSizeChanged),
GetClient()->MaxVideoCapabilities(), GetClient()->MaxVideoInputSize());
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) {
web_media_player_perf_->Start();

Check warning on line 879 in cobalt/media/player/web_media_player_impl.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_impl.cc#L872-L879

Added lines #L872 - L879 were not covered by tests
}
}

void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
Expand Down Expand Up @@ -903,6 +936,16 @@ void WebMediaPlayerImpl::Destroy() {
proxy_->AbortDataSource();
}

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) {
web_media_player_perf_->Stop();

Check warning on line 946 in cobalt/media/player/web_media_player_impl.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_impl.cc#L939-L946

Added lines #L939 - L946 were not covered by tests
}

// Make sure to kill the pipeline so there's no more media threads running.
// Note: stopping the pipeline might block for a long time.
base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
Expand Down
4 changes: 4 additions & 0 deletions cobalt/media/player/web_media_player_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "cobalt/media/base/sbplayer_interface.h"
#include "cobalt/media/player/web_media_player.h"
#include "cobalt/media/player/web_media_player_delegate.h"
#include "cobalt/media/player/web_media_player_perf.h"
#include "third_party/chromium/media/base/demuxer.h"
#include "third_party/chromium/media/base/eme_constants.h"
#include "third_party/chromium/media/base/media_log.h"
Expand Down Expand Up @@ -240,6 +241,7 @@ class WebMediaPlayerImpl : public WebMediaPlayer,
void OnContentSizeChanged();

base::Thread pipeline_thread_;
base::Thread perf_thread_;

// TODO(hclam): get rid of these members and read from the pipeline directly.
NetworkState network_state_;
Expand All @@ -251,6 +253,8 @@ class WebMediaPlayerImpl : public WebMediaPlayer,

scoped_refptr<Pipeline> pipeline_;

scoped_refptr<WebMediaPlayerPerf> web_media_player_perf_;

// The currently selected key system. Empty string means that no key system
// has been selected.
std::string current_key_system_;
Expand Down
124 changes: 124 additions & 0 deletions cobalt/media/player/web_media_player_perf.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// 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/player/web_media_player_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/system.h"

namespace cobalt {
namespace media {

namespace {

const int64_t kMaxSamples = 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 WebMediaPlayerPerf::Start() {
task_runner_->PostTask(FROM_HERE,
base::Bind(&WebMediaPlayerPerf::StartTask, this));

Check warning on line 43 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L41-L43

Added lines #L41 - L43 were not covered by tests
}

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

Check warning on line 49 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L46-L49

Added lines #L46 - L49 were not covered by tests
}

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

Check warning on line 54 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L52-L54

Added lines #L52 - L54 were not covered by tests
}

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

Check warning on line 59 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L57-L59

Added lines #L57 - L59 were not covered by tests
}

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

Check warning on line 63 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L62-L63

Added lines #L62 - L63 were not covered by tests

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) {
LOG(ERROR) << "Brown first sample, skip";
return;

Check warning on line 76 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L65-L76

Added lines #L65 - L76 were not covered by tests
}
StatisticsWrapper::GetInstance()->cpu_usage.AddSample(cpu_usage_perf, 1);
data_count_ += 1;
if (data_count_ == kMaxSamples) {
LOG(ERROR) << "Brown CPU usage statistics (%): brand name: "
<< sb_system_property_brand_name_
<< ", model name: " << sb_system_property_model_name_
<< ", platform name: " << sb_system_property_platform_name_
<< ", min: "
<< StatisticsWrapper::GetInstance()->cpu_usage.min()
<< "%, median: "
<< StatisticsWrapper::GetInstance()->cpu_usage.GetMedian()
<< "%, average: "
<< StatisticsWrapper::GetInstance()->cpu_usage.average()
<< "%, max: "
<< StatisticsWrapper::GetInstance()->cpu_usage.max() << "%";

Check warning on line 92 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L78-L92

Added lines #L78 - L92 were not covered by tests
}
}
}

std::string WebMediaPlayerPerf::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;

Check warning on line 104 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L98-L104

Added lines #L98 - L104 were not covered by tests
}
result = property;
return result;

Check warning on line 107 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L106-L107

Added lines #L106 - L107 were not covered by tests
}

WebMediaPlayerPerf::WebMediaPlayerPerf(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
: task_runner_(task_runner),
data_count_(0),
sb_system_property_brand_name_(
GetSbSystemProperty(kSbSystemPropertyBrandName)),
sb_system_property_model_name_(
GetSbSystemProperty(kSbSystemPropertyModelName)),
sb_system_property_platform_name_(
GetSbSystemProperty(kSbSystemPropertyPlatformName)) {}

Check warning on line 119 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L119

Added line #L119 was not covered by tests

WebMediaPlayerPerf::~WebMediaPlayerPerf() {}

Check warning on line 121 in cobalt/media/player/web_media_player_perf.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/player/web_media_player_perf.cc#L121

Added line #L121 was not covered by tests

} // namespace media
} // namespace cobalt
65 changes: 65 additions & 0 deletions cobalt/media/player/web_media_player_perf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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_PLAYER_WEB_MEDIA_PLAYER_PERF_H_
#define COBALT_MEDIA_PLAYER_WEB_MEDIA_PLAYER_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 "starboard/common/system_property.h"
#include "starboard/types.h"

namespace cobalt {
namespace media {

class WebMediaPlayerPerf
: public base::RefCountedThreadSafe<WebMediaPlayerPerf> {
public:
// Constructs a measure pipeline that will execute on |task_runner|.
WebMediaPlayerPerf(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
~WebMediaPlayerPerf();

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_;

// 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_;
};

} // namespace media
} // namespace cobalt

#endif // COBALT_MEDIA_PLAYER_WEB_MEDIA_PLAYER_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
Loading

0 comments on commit 6997d0a

Please sign in to comment.