Index: webrtc/video/video_quality_test.cc |
diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc |
index 6818a5cad6b390d28b6ab3d963c7b5f538458972..1d4b6583f7d499c2233f00a98016ee30a5e98238 100644 |
--- a/webrtc/video/video_quality_test.cc |
+++ b/webrtc/video/video_quality_test.cc |
@@ -57,6 +57,8 @@ constexpr char kSyncGroup[] = "av_sync"; |
constexpr int kOpusMinBitrateBps = 6000; |
constexpr int kOpusBitrateFbBps = 32000; |
constexpr int kFramesSentInQuickTest = 1; |
+constexpr uint32_t kThumbnailSendSsrcStart = 0xE0000; |
+constexpr uint32_t kThumbnailRtxSsrcStart = 0xF0000; |
struct VoiceEngineState { |
VoiceEngineState() |
@@ -1030,7 +1032,8 @@ VideoQualityTest::Params::Params() |
analyzer({"", 0.0, 0.0, 0, "", ""}), |
pipe(), |
logs(false), |
- ss({std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()}) {} |
+ ss({std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()}), |
+ num_thumbnails(0) {} |
VideoQualityTest::Params::~Params() = default; |
@@ -1098,6 +1101,13 @@ void VideoQualityTest::CheckParams() { |
} else if (params_.video.codec == "VP9") { |
RTC_CHECK_EQ(params_.ss.streams.size(), 1); |
} |
+ RTC_CHECK_GE(params_.num_thumbnails, 0); |
+ if (params_.num_thumbnails > 0) { |
+ RTC_CHECK_EQ(params_.ss.num_spatial_layers, 1); |
+ RTC_CHECK_EQ(params_.ss.streams.size(), 3); |
+ RTC_CHECK_EQ(params_.video.num_temporal_layers, 3); |
+ RTC_CHECK_EQ(params_.video.codec, "VP8"); |
+ } |
} |
// Static. |
@@ -1138,8 +1148,25 @@ VideoStream VideoQualityTest::DefaultVideoStream(const Params& params) { |
stream.target_bitrate_bps = params.video.target_bitrate_bps; |
stream.max_bitrate_bps = params.video.max_bitrate_bps; |
stream.max_qp = 52; |
- if (params.video.num_temporal_layers == 2) |
+ if (params.video.num_temporal_layers == 2) { |
stream.temporal_layer_thresholds_bps.push_back(stream.target_bitrate_bps); |
+ } else if (params.video.num_temporal_layers == 3) { |
+ stream.temporal_layer_thresholds_bps.push_back(stream.max_bitrate_bps / 4); |
+ stream.temporal_layer_thresholds_bps.push_back(stream.target_bitrate_bps); |
+ } |
+ return stream; |
+} |
+ |
+// Static. |
+VideoStream VideoQualityTest::DefaultThumbnailStream() { |
+ VideoStream stream; |
+ stream.width = 320; |
+ stream.height = 180; |
+ stream.max_framerate = 7; |
+ stream.min_bitrate_bps = 7500; |
+ stream.target_bitrate_bps = 37500; |
+ stream.max_bitrate_bps = 50000; |
+ stream.max_qp = 52; |
return stream; |
} |
@@ -1317,6 +1344,67 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, |
} |
} |
+void VideoQualityTest::SetupThumbnails(Transport* send_transport, |
+ Transport* recv_transport) { |
+ size_t num_video_streams = params_.ss.streams.size(); |
+ for (int i = 0; i < params_.num_thumbnails; ++i) { |
+ thumbnail_encoders_.emplace_back(VP8Encoder::Create()); |
+ |
+ VideoSendStream::Config thumbnail_send_config(send_transport); |
+ thumbnail_send_config.rtp.ssrcs.push_back(kThumbnailSendSsrcStart + i); |
+ thumbnail_send_config.encoder_settings.encoder = |
+ thumbnail_encoders_.back().get(); |
+ thumbnail_send_config.encoder_settings.payload_name = params_.video.codec; |
+ thumbnail_send_config.encoder_settings.payload_type = kPayloadTypeVP8; |
+ thumbnail_send_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; |
+ thumbnail_send_config.rtp.rtx.payload_type = kSendRtxPayloadType; |
+ thumbnail_send_config.rtp.rtx.ssrcs.push_back(kThumbnailRtxSsrcStart + i); |
+ thumbnail_send_config.rtp.extensions.clear(); |
+ if (params_.call.send_side_bwe) { |
+ thumbnail_send_config.rtp.extensions.push_back( |
+ RtpExtension(RtpExtension::kTransportSequenceNumberUri, |
+ test::kTransportSequenceNumberExtensionId)); |
+ } else { |
+ thumbnail_send_config.rtp.extensions.push_back(RtpExtension( |
+ RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId)); |
+ } |
+ |
+ VideoEncoderConfig thumbnail_encoder_config; |
+ thumbnail_encoder_config.min_transmit_bitrate_bps = 7500; |
+ thumbnail_send_config.suspend_below_min_bitrate = |
+ params_.video.suspend_below_min_bitrate; |
+ thumbnail_encoder_config.number_of_streams = 1; |
+ thumbnail_encoder_config.max_bitrate_bps = 50000; |
+ thumbnail_encoder_config.video_stream_factory = |
+ new rtc::RefCountedObject<VideoStreamFactory>( |
+ std::vector<webrtc::VideoStream>{DefaultThumbnailStream()}); |
+ thumbnail_encoder_config.spatial_layers = params_.ss.spatial_layers; |
+ |
+ thumbnail_encoder_configs_.push_back(thumbnail_encoder_config.Copy()); |
+ thumbnail_send_configs_.push_back(thumbnail_send_config.Copy()); |
+ |
+ CreateMatchingVideoReceiveConfigs(thumbnail_send_configs_[i], |
+ recv_transport); |
+ RTC_CHECK(video_receive_configs_.size() == num_video_streams + i + 1); |
+ video_receive_configs_[num_video_streams + i].rtp.nack.rtp_history_ms = |
+ kNackRtpHistoryMs; |
+ video_receive_configs_[num_video_streams + i].rtp.rtx_ssrc = |
+ kThumbnailRtxSsrcStart + i; |
+ video_receive_configs_[num_video_streams + i] |
+ .rtp.rtx_payload_types[kPayloadTypeVP8] = kSendRtxPayloadType; |
+ video_receive_configs_[num_video_streams + i].rtp.transport_cc = |
+ params_.call.send_side_bwe; |
+ video_receive_configs_[num_video_streams + i].rtp.remb = |
+ !params_.call.send_side_bwe; |
+ } |
+ |
+ for (size_t i = 0; i < thumbnail_send_configs_.size(); ++i) { |
+ thumbnail_send_streams_.push_back(sender_call_->CreateVideoSendStream( |
+ thumbnail_send_configs_[i].Copy(), |
+ thumbnail_encoder_configs_[i].Copy())); |
+ } |
+} |
+ |
void VideoQualityTest::SetupScreenshareOrSVC() { |
if (params_.screenshare.enabled) { |
// Fill out codec settings. |
@@ -1386,6 +1474,15 @@ void VideoQualityTest::SetupScreenshareOrSVC() { |
} |
} |
+void VideoQualityTest::SetupThumbnailCapturers(size_t num_thumbnail_streams) { |
+ VideoStream thumbnail = DefaultThumbnailStream(); |
+ for (size_t i = 0; i < num_thumbnail_streams; ++i) { |
+ thumbnail_capturers_.emplace_back(test::FrameGeneratorCapturer::Create( |
+ static_cast<int>(thumbnail.width), static_cast<int>(thumbnail.height), |
+ thumbnail.max_framerate, clock_)); |
+ } |
+} |
+ |
void VideoQualityTest::CreateCapturer() { |
if (params_.screenshare.enabled) { |
test::FrameGeneratorCapturer* frame_generator_capturer = |
@@ -1447,17 +1544,11 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) { |
if (graph_title.empty()) |
graph_title = VideoQualityTest::GenerateGraphTitle(); |
- // In the case of different resolutions, the functions calculating PSNR and |
- // SSIM return -1.0, instead of a positive value as usual. VideoAnalyzer |
- // aborts if the average psnr/ssim are below the given threshold, which is |
- // 0.0 by default. Setting the thresholds to -1.1 prevents the unnecessary |
- // abort. |
VideoStream& selected_stream = params_.ss.streams[params_.ss.selected_stream]; |
bool is_quick_test_enabled = field_trial::IsEnabled("WebRTC-QuickPerfTest"); |
VideoAnalyzer analyzer( |
&send_transport, params_.analyzer.test_label, |
- |
params_.analyzer.avg_psnr_threshold, params_.analyzer.avg_ssim_threshold, |
is_quick_test_enabled |
? kFramesSentInQuickTest |
@@ -1473,6 +1564,7 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) { |
recv_transport.SetReceiver(sender_call_->Receiver()); |
SetupVideo(&analyzer, &recv_transport); |
+ SetupThumbnails(&analyzer, &recv_transport); |
video_receive_configs_[params_.ss.selected_stream].renderer = &analyzer; |
video_send_config_.pre_encode_callback = analyzer.pre_encode_proxy(); |
RTC_DCHECK(!video_send_config_.post_encode_callback); |
@@ -1489,33 +1581,56 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) { |
video_send_stream_->SetSource(analyzer.OutputInterface(), |
degradation_preference_); |
+ SetupThumbnailCapturers(params_.num_thumbnails); |
+ for (size_t i = 0; i < thumbnail_send_streams_.size(); ++i) |
sprang_webrtc
2017/03/06 12:27:23
nit: {} for multi-line statements
ilnik
2017/03/06 12:37:51
Done.
|
+ thumbnail_send_streams_[i]->SetSource(thumbnail_capturers_[i].get(), |
+ degradation_preference_); |
+ |
CreateCapturer(); |
+ |
rtc::VideoSinkWants wants; |
video_capturer_->AddOrUpdateSink(analyzer.InputInterface(), wants); |
StartEncodedFrameLogs(video_send_stream_); |
StartEncodedFrameLogs(video_receive_streams_[0]); |
video_send_stream_->Start(); |
+ for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_) |
+ thumbnail_send_stream->Start(); |
for (VideoReceiveStream* receive_stream : video_receive_streams_) |
receive_stream->Start(); |
for (FlexfecReceiveStream* receive_stream : flexfec_receive_streams_) |
receive_stream->Start(); |
+ |
analyzer.StartMeasuringCpuProcessTime(); |
+ |
video_capturer_->Start(); |
+ for (std::unique_ptr<test::VideoCapturer>& video_caputurer : |
+ thumbnail_capturers_) { |
+ video_caputurer->Start(); |
+ } |
analyzer.Wait(); |
send_transport.StopSending(); |
recv_transport.StopSending(); |
+ for (std::unique_ptr<test::VideoCapturer>& video_caputurer : |
+ thumbnail_capturers_) |
+ video_caputurer->Stop(); |
video_capturer_->Stop(); |
for (FlexfecReceiveStream* receive_stream : flexfec_receive_streams_) |
receive_stream->Stop(); |
for (VideoReceiveStream* receive_stream : video_receive_streams_) |
receive_stream->Stop(); |
+ for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_) |
+ thumbnail_send_stream->Stop(); |
video_send_stream_->Stop(); |
DestroyStreams(); |
+ // thumbnails are not managed by CallTest. We need to destroy them manually. |
sprang_webrtc
2017/03/06 12:27:23
nit: capital T
ilnik
2017/03/06 12:37:51
Done.
|
+ for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_) |
+ sender_call_->DestroyVideoSendStream(thumbnail_send_stream); |
+ thumbnail_send_streams_.clear(); |
if (graph_data_output_file) |
fclose(graph_data_output_file); |