Reland "Fix threading model of video quality test with audio enabled"

This is a reland of f537da6c194d2c021709a255563c27b261e92488

Original change's description:
> Fix threading model of video quality test with audio enabled
> 
> Bug: None
> Change-Id: Ifb7fc57df54ec4d0a6f8c7f0504f3c06de6ac756
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130514
> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
> Commit-Queue: Artem Titov <titovartem@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27413}

Bug: None
Change-Id: I4fb793a5a5f636103159ed537847d6f2deb60108
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132797
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27621}
This commit is contained in:
Artem Titov
2019-04-02 13:46:53 +02:00
committed by Commit Bot
parent 6796ec2289
commit ff7730d2ba
3 changed files with 92 additions and 80 deletions

View File

@ -49,21 +49,23 @@ bool IsFlexfec(int payload_type) {
} }
} // namespace } // namespace
VideoAnalyzer::VideoAnalyzer(test::LayerFilteringTransport* transport, VideoAnalyzer::VideoAnalyzer(
const std::string& test_label, test::LayerFilteringTransport* transport,
double avg_psnr_threshold, const std::string& test_label,
double avg_ssim_threshold, double avg_psnr_threshold,
int duration_frames, double avg_ssim_threshold,
FILE* graph_data_output_file, int duration_frames,
const std::string& graph_title, FILE* graph_data_output_file,
uint32_t ssrc_to_analyze, const std::string& graph_title,
uint32_t rtx_ssrc_to_analyze, uint32_t ssrc_to_analyze,
size_t selected_stream, uint32_t rtx_ssrc_to_analyze,
int selected_sl, size_t selected_stream,
int selected_tl, int selected_sl,
bool is_quick_test_enabled, int selected_tl,
Clock* clock, bool is_quick_test_enabled,
std::string rtp_dump_name) Clock* clock,
std::string rtp_dump_name,
test::SingleThreadedTaskQueueForTesting* task_queue)
: transport_(transport), : transport_(transport),
receiver_(nullptr), receiver_(nullptr),
call_(nullptr), call_(nullptr),
@ -99,10 +101,10 @@ VideoAnalyzer::VideoAnalyzer(test::LayerFilteringTransport* transport,
avg_psnr_threshold_(avg_psnr_threshold), avg_psnr_threshold_(avg_psnr_threshold),
avg_ssim_threshold_(avg_ssim_threshold), avg_ssim_threshold_(avg_ssim_threshold),
is_quick_test_enabled_(is_quick_test_enabled), is_quick_test_enabled_(is_quick_test_enabled),
stats_polling_thread_(&PollStatsThread, this, "StatsPoller"),
done_(true, false), done_(true, false),
clock_(clock), clock_(clock),
start_ms_(clock->TimeInMilliseconds()) { start_ms_(clock->TimeInMilliseconds()),
task_queue_(task_queue) {
// Create thread pool for CPU-expensive PSNR/SSIM calculations. // Create thread pool for CPU-expensive PSNR/SSIM calculations.
// Try to use about as many threads as cores, but leave kMinCoresLeft alone, // Try to use about as many threads as cores, but leave kMinCoresLeft alone,
@ -336,7 +338,12 @@ void VideoAnalyzer::Wait() {
// at time-out check if frames_processed is going up. If so, give it more // at time-out check if frames_processed is going up. If so, give it more
// time, otherwise fail. Hopefully this will reduce test flakiness. // time, otherwise fail. Hopefully this will reduce test flakiness.
stats_polling_thread_.Start(); {
rtc::CritScope lock(&comparison_lock_);
stop_stats_poller_ = false;
stats_polling_task_id_ = task_queue_->PostDelayedTask(
[this]() { PollStats(); }, kSendStatsPollingIntervalMs);
}
int last_frames_processed = -1; int last_frames_processed = -1;
int last_frames_captured = -1; int last_frames_captured = -1;
@ -381,11 +388,15 @@ void VideoAnalyzer::Wait() {
if (iteration > 0) if (iteration > 0)
printf("- Farewell, sweet Concorde!\n"); printf("- Farewell, sweet Concorde!\n");
{
rtc::CritScope lock(&comparison_lock_);
stop_stats_poller_ = true;
task_queue_->CancelTask(stats_polling_task_id_);
}
PrintResults(); PrintResults();
if (graph_data_output_file_) if (graph_data_output_file_)
PrintSamplesToFile(); PrintSamplesToFile();
stats_polling_thread_.Stop();
} }
void VideoAnalyzer::StartMeasuringCpuProcessTime() { void VideoAnalyzer::StartMeasuringCpuProcessTime() {
@ -456,57 +467,56 @@ bool VideoAnalyzer::IsInSelectedSpatialAndTemporalLayer(
} }
} }
void VideoAnalyzer::PollStatsThread(void* obj) {
static_cast<VideoAnalyzer*>(obj)->PollStats();
}
void VideoAnalyzer::PollStats() { void VideoAnalyzer::PollStats() {
while (!done_.Wait(kSendStatsPollingIntervalMs)) { rtc::CritScope crit(&comparison_lock_);
rtc::CritScope crit(&comparison_lock_); if (stop_stats_poller_) {
return;
Call::Stats call_stats = call_->GetStats();
send_bandwidth_bps_.AddSample(call_stats.send_bandwidth_bps);
VideoSendStream::Stats send_stats = send_stream_->GetStats();
// It's not certain that we yet have estimates for any of these stats.
// Check that they are positive before mixing them in.
if (send_stats.encode_frame_rate > 0)
encode_frame_rate_.AddSample(send_stats.encode_frame_rate);
if (send_stats.avg_encode_time_ms > 0)
encode_time_ms_.AddSample(send_stats.avg_encode_time_ms);
if (send_stats.encode_usage_percent > 0)
encode_usage_percent_.AddSample(send_stats.encode_usage_percent);
if (send_stats.media_bitrate_bps > 0)
media_bitrate_bps_.AddSample(send_stats.media_bitrate_bps);
size_t fec_bytes = 0;
for (const auto& kv : send_stats.substreams) {
fec_bytes += kv.second.rtp_stats.fec.payload_bytes +
kv.second.rtp_stats.fec.padding_bytes;
}
fec_bitrate_bps_.AddSample((fec_bytes - last_fec_bytes_) * 8);
last_fec_bytes_ = fec_bytes;
if (receive_stream_ != nullptr) {
VideoReceiveStream::Stats receive_stats = receive_stream_->GetStats();
if (receive_stats.decode_ms > 0)
decode_time_ms_.AddSample(receive_stats.decode_ms);
if (receive_stats.max_decode_ms > 0)
decode_time_max_ms_.AddSample(receive_stats.max_decode_ms);
if (receive_stats.width > 0 && receive_stats.height > 0) {
pixels_.AddSample(receive_stats.width * receive_stats.height);
}
}
if (audio_receive_stream_ != nullptr) {
AudioReceiveStream::Stats receive_stats =
audio_receive_stream_->GetStats();
audio_expand_rate_.AddSample(receive_stats.expand_rate);
audio_accelerate_rate_.AddSample(receive_stats.accelerate_rate);
audio_jitter_buffer_ms_.AddSample(receive_stats.jitter_buffer_ms);
}
memory_usage_.AddSample(rtc::GetProcessResidentSizeBytes());
} }
Call::Stats call_stats = call_->GetStats();
send_bandwidth_bps_.AddSample(call_stats.send_bandwidth_bps);
VideoSendStream::Stats send_stats = send_stream_->GetStats();
// It's not certain that we yet have estimates for any of these stats.
// Check that they are positive before mixing them in.
if (send_stats.encode_frame_rate > 0)
encode_frame_rate_.AddSample(send_stats.encode_frame_rate);
if (send_stats.avg_encode_time_ms > 0)
encode_time_ms_.AddSample(send_stats.avg_encode_time_ms);
if (send_stats.encode_usage_percent > 0)
encode_usage_percent_.AddSample(send_stats.encode_usage_percent);
if (send_stats.media_bitrate_bps > 0)
media_bitrate_bps_.AddSample(send_stats.media_bitrate_bps);
size_t fec_bytes = 0;
for (const auto& kv : send_stats.substreams) {
fec_bytes += kv.second.rtp_stats.fec.payload_bytes +
kv.second.rtp_stats.fec.padding_bytes;
}
fec_bitrate_bps_.AddSample((fec_bytes - last_fec_bytes_) * 8);
last_fec_bytes_ = fec_bytes;
if (receive_stream_ != nullptr) {
VideoReceiveStream::Stats receive_stats = receive_stream_->GetStats();
if (receive_stats.decode_ms > 0)
decode_time_ms_.AddSample(receive_stats.decode_ms);
if (receive_stats.max_decode_ms > 0)
decode_time_max_ms_.AddSample(receive_stats.max_decode_ms);
if (receive_stats.width > 0 && receive_stats.height > 0) {
pixels_.AddSample(receive_stats.width * receive_stats.height);
}
}
if (audio_receive_stream_ != nullptr) {
AudioReceiveStream::Stats receive_stats = audio_receive_stream_->GetStats();
audio_expand_rate_.AddSample(receive_stats.expand_rate);
audio_accelerate_rate_.AddSample(receive_stats.accelerate_rate);
audio_jitter_buffer_ms_.AddSample(receive_stats.jitter_buffer_ms);
}
memory_usage_.AddSample(rtc::GetProcessResidentSizeBytes());
stats_polling_task_id_ = task_queue_->PostDelayedTask(
[this]() { PollStats(); }, kSendStatsPollingIntervalMs);
} }
bool VideoAnalyzer::FrameComparisonThread(void* obj) { bool VideoAnalyzer::FrameComparisonThread(void* obj) {

View File

@ -44,7 +44,8 @@ class VideoAnalyzer : public PacketReceiver,
int selected_tl, int selected_tl,
bool is_quick_test_enabled, bool is_quick_test_enabled,
Clock* clock, Clock* clock,
std::string rtp_dump_name); std::string rtp_dump_name,
test::SingleThreadedTaskQueueForTesting* task_queue);
~VideoAnalyzer(); ~VideoAnalyzer();
virtual void SetReceiver(PacketReceiver* receiver); virtual void SetReceiver(PacketReceiver* receiver);
@ -178,7 +179,6 @@ class VideoAnalyzer : public PacketReceiver,
int64_t render_time_ms) int64_t render_time_ms)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
static void PollStatsThread(void* obj);
void PollStats(); void PollStats();
static bool FrameComparisonThread(void* obj); static bool FrameComparisonThread(void* obj);
bool CompareFrames(); bool CompareFrames();
@ -273,14 +273,17 @@ class VideoAnalyzer : public PacketReceiver,
bool is_quick_test_enabled_; bool is_quick_test_enabled_;
std::vector<rtc::PlatformThread*> comparison_thread_pool_; std::vector<rtc::PlatformThread*> comparison_thread_pool_;
rtc::PlatformThread stats_polling_thread_;
rtc::Event comparison_available_event_; rtc::Event comparison_available_event_;
std::deque<FrameComparison> comparisons_ RTC_GUARDED_BY(comparison_lock_); std::deque<FrameComparison> comparisons_ RTC_GUARDED_BY(comparison_lock_);
rtc::Event done_; rtc::Event done_;
test::SingleThreadedTaskQueueForTesting::TaskId stats_polling_task_id_
RTC_GUARDED_BY(comparison_lock_);
bool stop_stats_poller_ RTC_GUARDED_BY(comparison_lock_);
std::unique_ptr<test::RtpFileWriter> rtp_file_writer_; std::unique_ptr<test::RtpFileWriter> rtp_file_writer_;
Clock* const clock_; Clock* const clock_;
const int64_t start_ms_; const int64_t start_ms_;
test::SingleThreadedTaskQueueForTesting* task_queue_;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -1203,13 +1203,11 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
recv_event_log_ = RtcEventLog::CreateNull(); recv_event_log_ = RtcEventLog::CreateNull();
} }
Call::Config send_call_config(send_event_log_.get()); task_queue_.SendTask([this, &params, &send_transport, &recv_transport]() {
Call::Config recv_call_config(recv_event_log_.get()); Call::Config send_call_config(send_event_log_.get());
send_call_config.bitrate_config = params.call.call_bitrate_config; Call::Config recv_call_config(recv_event_log_.get());
recv_call_config.bitrate_config = params.call.call_bitrate_config; send_call_config.bitrate_config = params.call.call_bitrate_config;
recv_call_config.bitrate_config = params.call.call_bitrate_config;
task_queue_.SendTask([this, &send_call_config, &recv_call_config,
&send_transport, &recv_transport]() {
if (params_.audio.enabled) if (params_.audio.enabled)
InitializeAudioDevice(&send_call_config, &recv_call_config, InitializeAudioDevice(&send_call_config, &recv_call_config,
params_.audio.use_real_adm); params_.audio.use_real_adm);
@ -1234,7 +1232,8 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
kSendRtxSsrcs[params_.ss[0].selected_stream], kSendRtxSsrcs[params_.ss[0].selected_stream],
static_cast<size_t>(params_.ss[0].selected_stream), static_cast<size_t>(params_.ss[0].selected_stream),
params.ss[0].selected_sl, params_.video[0].selected_tl, params.ss[0].selected_sl, params_.video[0].selected_tl,
is_quick_test_enabled, clock_, params_.logging.rtp_dump_name); is_quick_test_enabled, clock_, params_.logging.rtp_dump_name,
&task_queue_);
task_queue_.SendTask([&]() { task_queue_.SendTask([&]() {
analyzer_->SetCall(sender_call_.get()); analyzer_->SetCall(sender_call_.get());