blob: 9ee4acf279be35b1e2bc75a73dd82dd78d7b0d5a [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/cval_stats.h"
#include <numeric>
namespace cobalt {
namespace media {
CValContainer::CValContainer(std::string name,
int max_samples_before_calculation)
: cval_name_{name},
max_samples_before_calculation_{max_samples_before_calculation},
latest_{"Media." + name + ".Latest", 0, "Latest sample in microseconds."},
average_{"Media." + name + ".Average", 0,
"Average sample in microseconds."},
maximum_{"Media." + name + ".Maximum", 0,
"Maximum sample in microseconds."},
median_{"Media." + name + ".Median", 0, "Median sample in microseconds."},
minimum_{"Media." + name + ".Minimum", 0,
"Minimum sample in microseconds."} {}
void CValContainer::UpdateCVal(SbTime event_timing) {
latest_ = event_timing;
accumulated_sample_count_++;
if (!first_sample_added_) {
minimum_ = event_timing;
maximum_ = event_timing;
first_sample_added_ = true;
}
samples_[sample_write_index_] = event_timing;
sample_write_index_ = (sample_write_index_ + 1) % kMaxSamples;
if (accumulated_sample_count_ % max_samples_before_calculation_ == 0) {
std::vector<SbTime> copy;
int copy_size = std::min(accumulated_sample_count_, kMaxSamples);
copy.reserve(copy_size);
copy.assign(samples_, samples_ + copy_size);
std::sort(copy.begin(), copy.end());
if (copy.size() % 2 == 0) {
median_ = (copy[copy.size() / 2 - 1] + copy[copy.size() / 2]) / 2;
} else {
median_ = copy[copy.size() / 2];
}
minimum_ = std::min(minimum_.value(), copy[0]);
maximum_ = std::max(maximum_.value(), copy[copy.size() - 1]);
auto local_average = std::accumulate(copy.begin(), copy.end(), 0);
average_ += (local_average - average_.value()) / accumulated_sample_count_;
}
}
CValStats::CValStats() {
cval_containers_.emplace(
std::piecewise_construct,
std::forward_as_tuple(MediaTiming::SbPlayerCreate),
std::forward_as_tuple("SbPlayerCreateTime",
kMediaDefaultMaxSamplesBeforeCalculation));
cval_containers_.emplace(
std::piecewise_construct,
std::forward_as_tuple(MediaTiming::SbPlayerDestroy),
std::forward_as_tuple("SbPlayerDestructionTime",
kMediaDefaultMaxSamplesBeforeCalculation));
cval_containers_.emplace(
std::piecewise_construct,
std::forward_as_tuple(MediaTiming::SbPlayerWriteSamples),
std::forward_as_tuple("SbPlayerWriteSamplesTime",
kMediaHighFrequencyMaxSamplesBeforeCalculation));
}
void CValStats::StartTimer(MediaTiming event_type,
std::string pipeline_identifier) {
if (!enabled_) return;
running_timers_[std::make_pair(event_type, pipeline_identifier)] =
SbTimeGetMonotonicNow();
}
void CValStats::StopTimer(MediaTiming event_type,
std::string pipeline_identifier) {
if (!enabled_) return;
auto key = std::make_pair(event_type, pipeline_identifier);
DCHECK(running_timers_.find(key) != running_timers_.end());
SbTime time_taken = SbTimeGetMonotonicNow() - running_timers_[key];
auto cval_container = cval_containers_.find(event_type);
if (cval_container != cval_containers_.end()) {
cval_container->second.UpdateCVal(time_taken);
}
}
// for testing only
size_t CValStats::GetBufferIndexForTest() {
DCHECK(cval_containers_.size() > 0);
auto cval_container = cval_containers_.find(MediaTiming::SbPlayerCreate);
if (cval_container != cval_containers_.end()) {
return cval_container->second.GetSampleIndex();
}
return 0;
}
// for testing only
size_t CValStats::GetBufferSampleSizeForTest() {
DCHECK(cval_containers_.size() > 0);
auto cval_container = cval_containers_.find(MediaTiming::SbPlayerCreate);
if (cval_container != cval_containers_.end()) {
return cval_container->second.GetNumberSamples();
}
return 0;
}
} // namespace media
} // namespace cobalt