| Index: webrtc/video/video_quality_test.cc
|
| diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc
|
| index 7cc71dcf0e114c728359dec6e12b734f49bfef6d..48347d7b4e0691a57b634a4afc6e3637c4b9b6c9 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;
|
| }
|
|
|
| @@ -1327,6 +1354,92 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
|
| }
|
| }
|
|
|
| +void VideoQualityTest::SetupThumbnails(Transport* send_transport,
|
| + Transport* recv_transport) {
|
| + for (int i = 0; i < params_.num_thumbnails; ++i) {
|
| + thumbnail_encoders_.emplace_back(VP8Encoder::Create());
|
| +
|
| + // Thumbnails will be send in the other way: from receiver_call to
|
| + // sender_call.
|
| + VideoSendStream::Config thumbnail_send_config(recv_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;
|
| +
|
| + VideoReceiveStream::Config thumbnail_receive_config(send_transport);
|
| + thumbnail_receive_config.rtp.remb = false;
|
| + thumbnail_receive_config.rtp.transport_cc = true;
|
| + thumbnail_receive_config.rtp.local_ssrc = kReceiverLocalVideoSsrc;
|
| + for (const RtpExtension& extension : thumbnail_send_config.rtp.extensions)
|
| + thumbnail_receive_config.rtp.extensions.push_back(extension);
|
| + thumbnail_receive_config.renderer = &fake_renderer_;
|
| +
|
| + VideoReceiveStream::Decoder decoder =
|
| + test::CreateMatchingDecoder(thumbnail_send_config.encoder_settings);
|
| + allocated_decoders_.push_back(
|
| + std::unique_ptr<VideoDecoder>(decoder.decoder));
|
| + thumbnail_receive_config.decoders.clear();
|
| + thumbnail_receive_config.decoders.push_back(decoder);
|
| + thumbnail_receive_config.rtp.remote_ssrc =
|
| + thumbnail_send_config.rtp.ssrcs[0];
|
| +
|
| + thumbnail_receive_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
|
| + thumbnail_receive_config.rtp.rtx_ssrc = kThumbnailRtxSsrcStart + i;
|
| + thumbnail_receive_config.rtp.rtx_payload_types[kPayloadTypeVP8] =
|
| + kSendRtxPayloadType;
|
| + thumbnail_receive_config.rtp.transport_cc = params_.call.send_side_bwe;
|
| + thumbnail_receive_config.rtp.remb = !params_.call.send_side_bwe;
|
| +
|
| + thumbnail_encoder_configs_.push_back(thumbnail_encoder_config.Copy());
|
| + thumbnail_send_configs_.push_back(thumbnail_send_config.Copy());
|
| + thumbnail_receive_configs_.push_back(thumbnail_receive_config.Copy());
|
| + }
|
| +
|
| + for (int i = 0; i < params_.num_thumbnails; ++i) {
|
| + thumbnail_send_streams_.push_back(receiver_call_->CreateVideoSendStream(
|
| + thumbnail_send_configs_[i].Copy(),
|
| + thumbnail_encoder_configs_[i].Copy()));
|
| + thumbnail_receive_streams_.push_back(sender_call_->CreateVideoReceiveStream(
|
| + thumbnail_receive_configs_[i].Copy()));
|
| + }
|
| +}
|
| +
|
| +void VideoQualityTest::DestroyThumbnailStreams() {
|
| + for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_)
|
| + receiver_call_->DestroyVideoSendStream(thumbnail_send_stream);
|
| + thumbnail_send_streams_.clear();
|
| + for (VideoReceiveStream* thumbnail_receive_stream :
|
| + thumbnail_receive_streams_)
|
| + sender_call_->DestroyVideoReceiveStream(thumbnail_receive_stream);
|
| + thumbnail_send_streams_.clear();
|
| + thumbnail_receive_streams_.clear();
|
| +}
|
| +
|
| void VideoQualityTest::SetupScreenshareOrSVC() {
|
| if (params_.screenshare.enabled) {
|
| // Fill out codec settings.
|
| @@ -1396,6 +1509,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 =
|
| @@ -1457,17 +1579,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
|
| @@ -1483,6 +1599,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);
|
| @@ -1499,33 +1616,60 @@ 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) {
|
| + 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();
|
| + for (VideoReceiveStream* thumbnail_receive_stream :
|
| + thumbnail_receive_streams_)
|
| + thumbnail_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 (VideoReceiveStream* thumbnail_receive_stream :
|
| + thumbnail_receive_streams_)
|
| + thumbnail_receive_stream->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();
|
| + DestroyThumbnailStreams();
|
|
|
| if (graph_data_output_file)
|
| fclose(graph_data_output_file);
|
|
|