Add cpu measurements to VideoProcessorIntegrationTest.

Remove unused method ExcludeFrameTypesToStr.

Bug: webrtc:6634
Change-Id: I2816466ed428b8ce13f3073ca496c2891d5d6368
Reviewed-on: https://webrtc-review.googlesource.com/9400
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20350}
This commit is contained in:
Åsa Persson
2017-10-19 12:14:09 +02:00
committed by Commit Bot
parent ea7a3f8225
commit 7173cf20cc
7 changed files with 71 additions and 28 deletions

View File

@ -446,6 +446,7 @@ if (rtc_include_tests) {
"../../common_video", "../../common_video",
"../../media:rtc_audio_video", "../../media:rtc_audio_video",
"../../rtc_base:rtc_base_approved", "../../rtc_base:rtc_base_approved",
"../../rtc_base:rtc_base_tests_utils",
"../../system_wrappers", "../../system_wrappers",
"../../test:field_trial", "../../test:field_trial",
"../../test:test_support", "../../test:test_support",

View File

@ -36,6 +36,7 @@ DENOISING = ('Denoising', 'denoising')
RESILIENCE = ('Resilience', 'resilience') RESILIENCE = ('Resilience', 'resilience')
ERROR_CONCEALMENT = ('Error concealment', 'error concealment') ERROR_CONCEALMENT = ('Error concealment', 'error concealment')
QP = ('Average QP', 'avg QP') QP = ('Average QP', 'avg QP')
CPU_USAGE = ('CPU usage %', 'CPU usage (%)')
PSNR = ('PSNR avg', 'PSNR (dB)') PSNR = ('PSNR avg', 'PSNR (dB)')
SSIM = ('SSIM avg', 'SSIM') SSIM = ('SSIM avg', 'SSIM')
ENC_BITRATE = ('Encoded bitrate', 'encoded bitrate (kbps)') ENC_BITRATE = ('Encoded bitrate', 'encoded bitrate (kbps)')
@ -93,6 +94,7 @@ RESULTS = [
ENCODE_TIME_AVG, ENCODE_TIME_AVG,
DECODE_TIME_AVG, DECODE_TIME_AVG,
QP, QP,
CPU_USAGE,
AVG_KEY_FRAME_SIZE, AVG_KEY_FRAME_SIZE,
AVG_NON_KEY_FRAME_SIZE, AVG_NON_KEY_FRAME_SIZE,
] ]

View File

@ -14,9 +14,7 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <memory>
#include <utility> #include <utility>
#include <vector>
#include "api/video/i420_buffer.h" #include "api/video/i420_buffer.h"
#include "common_types.h" // NOLINT(build/include) #include "common_types.h" // NOLINT(build/include)
@ -137,16 +135,8 @@ int GetElapsedTimeMicroseconds(int64_t start_ns, int64_t stop_ns) {
} // namespace } // namespace
const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { int TestConfig::NumberOfCores() const {
switch (e) { return use_single_core ? 1 : CpuInfo::DetectNumberOfCores();
case kExcludeOnlyFirstKeyFrame:
return "ExcludeOnlyFirstKeyFrame";
case kExcludeAllKeyFrames:
return "ExcludeAllKeyFrames";
default:
RTC_NOTREACHED();
return "Unknown";
}
} }
VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder, VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder,
@ -201,8 +191,7 @@ void VideoProcessor::Init() {
<< "Failed to register decode complete callback"; << "Failed to register decode complete callback";
// Initialize the encoder and decoder. // Initialize the encoder and decoder.
uint32_t num_cores = int num_cores = config_.NumberOfCores();
config_.use_single_core ? 1 : CpuInfo::DetectNumberOfCores();
RTC_CHECK_EQ( RTC_CHECK_EQ(
encoder_->InitEncode(&config_.codec_settings, num_cores, encoder_->InitEncode(&config_.codec_settings, num_cores,
config_.networking_config.max_payload_size_in_bytes), config_.networking_config.max_payload_size_in_bytes),

View File

@ -49,11 +49,11 @@ enum ExcludeFrameTypes {
kExcludeAllKeyFrames kExcludeAllKeyFrames
}; };
// Returns a string representation of the enum value.
const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e);
// Test configuration for a test run. // Test configuration for a test run.
struct TestConfig { struct TestConfig {
// Returns the number of cores to use.
int NumberOfCores() const;
// Plain name of YUV file to process without file extension. // Plain name of YUV file to process without file extension.
std::string filename; std::string filename;
@ -82,6 +82,10 @@ struct TestConfig {
// If set to false, the maximum number of available cores will be used. // If set to false, the maximum number of available cores will be used.
bool use_single_core = false; bool use_single_core = false;
// Should cpu usage be measured?
// If set to true, the encoding will run in real-time.
bool measure_cpu = false;
// If > 0: forces the encoder to create a keyframe every Nth frame. // If > 0: forces the encoder to create a keyframe every Nth frame.
// Note that the encoder may create a keyframe in other locations in addition // Note that the encoder may create a keyframe in other locations in addition
// to this setting. Forcing key frames may also affect encoder planning // to this setting. Forcing key frames may also affect encoder planning
@ -89,9 +93,7 @@ struct TestConfig {
// produce an expensive key frame. // produce an expensive key frame.
int keyframe_interval = 0; int keyframe_interval = 0;
// The codec settings to use for the test (target bitrate, video size, // Codec settings to use.
// framerate and so on). This struct should be filled in using the
// VideoCodingModule::Codec() method.
webrtc::VideoCodec codec_settings; webrtc::VideoCodec codec_settings;
// If printing of information to stdout shall be performed during processing. // If printing of information to stdout shall be performed during processing.
@ -126,8 +128,7 @@ struct TestConfig {
// Video Engine, where signaling would request a retransmit of the lost packets, // Video Engine, where signaling would request a retransmit of the lost packets,
// since they're so important. // since they're so important.
// //
// Note this class is not thread safe in any way and is meant for simple testing // Note this class is not thread safe and is meant for simple testing purposes.
// purposes.
class VideoProcessor { class VideoProcessor {
public: public:
VideoProcessor(webrtc::VideoEncoder* encoder, VideoProcessor(webrtc::VideoEncoder* encoder,

View File

@ -29,6 +29,7 @@
#include "modules/video_coding/include/video_codec_interface.h" #include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/include/video_coding.h" #include "modules/video_coding/include/video_coding.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/cpu_time.h"
#include "rtc_base/event.h" #include "rtc_base/event.h"
#include "rtc_base/file.h" #include "rtc_base/file.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
@ -77,8 +78,52 @@ int NumberOfTemporalLayers(const VideoCodec& codec_settings) {
} }
} }
bool RunEncodeInRealTime(const TestConfig& config) {
if (config.measure_cpu) {
return true;
}
#if defined(WEBRTC_ANDROID)
// In order to not overwhelm the OpenMAX buffers in the Android MediaCodec.
return (config.hw_encoder || config.hw_decoder);
#else
return false;
#endif
}
} // namespace } // namespace
class VideoProcessorIntegrationTest::CpuProcessTime final {
public:
explicit CpuProcessTime(const TestConfig& config) : config_(config) {}
~CpuProcessTime() {}
void Start() {
if (config_.measure_cpu) {
cpu_time_ -= rtc::GetProcessCpuTimeNanos();
wallclock_time_ -= rtc::SystemTimeNanos();
}
}
void Stop() {
if (config_.measure_cpu) {
cpu_time_ += rtc::GetProcessCpuTimeNanos();
wallclock_time_ += rtc::SystemTimeNanos();
}
}
void Print() const {
if (config_.measure_cpu) {
printf("CPU usage %%: %f\n", GetUsagePercent() / config_.NumberOfCores());
}
}
private:
double GetUsagePercent() const {
return static_cast<double>(cpu_time_) / wallclock_time_ * 100.0;
}
const TestConfig config_;
int64_t cpu_time_ = 0;
int64_t wallclock_time_ = 0;
};
VideoProcessorIntegrationTest::VideoProcessorIntegrationTest() { VideoProcessorIntegrationTest::VideoProcessorIntegrationTest() {
#if defined(WEBRTC_ANDROID) #if defined(WEBRTC_ANDROID)
InitializeAndroidObjects(); InitializeAndroidObjects();
@ -158,20 +203,18 @@ void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify(
rate_profiles[rate_update_index].input_fps); rate_profiles[rate_update_index].input_fps);
}); });
cpu_process_time_->Start();
// Process all frames. // Process all frames.
int frame_number = 0; int frame_number = 0;
const int num_frames = config_.num_frames; const int num_frames = config_.num_frames;
RTC_DCHECK_GE(num_frames, 1); RTC_DCHECK_GE(num_frames, 1);
while (frame_number < num_frames) { while (frame_number < num_frames) {
// In order to not overwhelm the OpenMAX buffers in the Android if (RunEncodeInRealTime(config_)) {
// MediaCodec API, we roughly pace the frames here. The downside // Roughly pace the frames.
// of this is that the encode run will be done in real-time.
#if defined(WEBRTC_ANDROID)
if (config_.hw_encoder || config_.hw_decoder) {
SleepMs(rtc::kNumMillisecsPerSec / SleepMs(rtc::kNumMillisecsPerSec /
rate_profiles[rate_update_index].input_fps); rate_profiles[rate_update_index].input_fps);
} }
#endif
task_queue.PostTask([this] { processor_->ProcessFrame(); }); task_queue.PostTask([this] { processor_->ProcessFrame(); });
++frame_number; ++frame_number;
@ -193,6 +236,7 @@ void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify(
if (config_.hw_encoder || config_.hw_decoder) { if (config_.hw_encoder || config_.hw_decoder) {
SleepMs(1 * rtc::kNumMillisecsPerSec); SleepMs(1 * rtc::kNumMillisecsPerSec);
} }
cpu_process_time_->Stop();
ReleaseAndCloseObjects(&task_queue); ReleaseAndCloseObjects(&task_queue);
// Calculate and print rate control statistics. // Calculate and print rate control statistics.
@ -238,6 +282,7 @@ void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify(
// Calculate and print other statistics. // Calculate and print other statistics.
EXPECT_EQ(num_frames, static_cast<int>(stats_.size())); EXPECT_EQ(num_frames, static_cast<int>(stats_.size()));
stats_.PrintSummary(); stats_.PrintSummary();
cpu_process_time_->Print();
// Calculate and print image quality statistics. // Calculate and print image quality statistics.
// TODO(marpan): Should compute these quality metrics per SetRates update. // TODO(marpan): Should compute these quality metrics per SetRates update.
@ -382,6 +427,7 @@ void VideoProcessorIntegrationTest::SetUpAndInitObjects(
} }
} }
cpu_process_time_.reset(new CpuProcessTime(config_));
packet_manipulator_.reset(new PacketManipulatorImpl( packet_manipulator_.reset(new PacketManipulatorImpl(
&packet_reader_, config_.networking_config, config_.verbose)); &packet_reader_, config_.networking_config, config_.verbose));

View File

@ -115,6 +115,7 @@ class VideoProcessorIntegrationTest : public testing::Test {
TestConfig config_; TestConfig config_;
private: private:
class CpuProcessTime;
static const int kMaxNumTemporalLayers = 3; static const int kMaxNumTemporalLayers = 3;
struct TestResults { struct TestResults {
@ -195,6 +196,7 @@ class VideoProcessorIntegrationTest : public testing::Test {
std::unique_ptr<PacketManipulator> packet_manipulator_; std::unique_ptr<PacketManipulator> packet_manipulator_;
Stats stats_; Stats stats_;
std::unique_ptr<VideoProcessor> processor_; std::unique_ptr<VideoProcessor> processor_;
std::unique_ptr<CpuProcessTime> cpu_process_time_;
// Quantities updated for every encoded frame. // Quantities updated for every encoded frame.
TestResults actual_; TestResults actual_;

View File

@ -32,6 +32,7 @@ const bool kFrameDropperOn = false;
// Test settings. // Test settings.
const bool kUseSingleCore = false; const bool kUseSingleCore = false;
const bool kMeasureCpu = false;
const VisualizationParams kVisualizationParams = { const VisualizationParams kVisualizationParams = {
false, // save_encoded_ivf false, // save_encoded_ivf
false, // save_decoded_y4m false, // save_decoded_y4m
@ -62,6 +63,7 @@ class VideoProcessorIntegrationTestParameterized
config_.output_filename = config_.output_filename =
TempFilename(OutputPath(), "plot_videoprocessor_integrationtest"); TempFilename(OutputPath(), "plot_videoprocessor_integrationtest");
config_.use_single_core = kUseSingleCore; config_.use_single_core = kUseSingleCore;
config_.measure_cpu = kMeasureCpu;
config_.verbose = true; config_.verbose = true;
config_.hw_encoder = hw_codec_; config_.hw_encoder = hw_codec_;
config_.hw_decoder = hw_codec_; config_.hw_decoder = hw_codec_;