summaryrefslogtreecommitdiff
path: root/chromium/third_party/webrtc/video/video_quality_test.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-31 16:33:43 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-06 16:33:22 +0000
commitda51f56cc21233c2d30f0fe0d171727c3102b2e0 (patch)
tree4e579ab70ce4b19bee7984237f3ce05a96d59d83 /chromium/third_party/webrtc/video/video_quality_test.cc
parentc8c2d1901aec01e934adf561a9fdf0cc776cdef8 (diff)
downloadqtwebengine-chromium-da51f56cc21233c2d30f0fe0d171727c3102b2e0.tar.gz
BASELINE: Update Chromium to 65.0.3525.40
Also imports missing submodules Change-Id: I36901b7c6a325cda3d2c10cedb2186c25af3b79b Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/third_party/webrtc/video/video_quality_test.cc')
-rw-r--r--chromium/third_party/webrtc/video/video_quality_test.cc1187
1 files changed, 607 insertions, 580 deletions
diff --git a/chromium/third_party/webrtc/video/video_quality_test.cc b/chromium/third_party/webrtc/video/video_quality_test.cc
index e40d2955f05..ec110ff694e 100644
--- a/chromium/third_party/webrtc/video/video_quality_test.cc
+++ b/chromium/third_party/webrtc/video/video_quality_test.cc
@@ -17,46 +17,30 @@
#include <string>
#include <vector>
-#include "api/optional.h"
-#include "call/call.h"
-#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
-#include "logging/rtc_event_log/rtc_event_log.h"
#include "media/engine/internalencoderfactory.h"
#include "media/engine/webrtcvideoengine.h"
#include "modules/audio_mixer/audio_mixer_impl.h"
-#include "modules/rtp_rtcp/include/rtp_header_parser.h"
#include "modules/rtp_rtcp/source/rtp_format.h"
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "modules/video_coding/codecs/h264/include/h264.h"
-#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp8/include/vp8_common_types.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
-#include "rtc_base/checks.h"
#include "rtc_base/cpu_time.h"
-#include "rtc_base/event.h"
#include "rtc_base/flags.h"
#include "rtc_base/format_macros.h"
-#include "rtc_base/logging.h"
#include "rtc_base/memory_usage.h"
#include "rtc_base/pathutils.h"
-#include "rtc_base/platform_file.h"
-#include "rtc_base/ptr_util.h"
-#include "rtc_base/timeutils.h"
#include "system_wrappers/include/cpu_info.h"
-#include "system_wrappers/include/field_trial.h"
-#include "test/gtest.h"
-#include "test/layer_filtering_transport.h"
+#include "test/rtp_file_writer.h"
#include "test/run_loop.h"
#include "test/statistics.h"
#include "test/testsupport/fileutils.h"
#include "test/testsupport/frame_writer.h"
+#include "test/testsupport/perf_test.h"
#include "test/testsupport/test_artifacts.h"
#include "test/vcm_capturer.h"
#include "test/video_renderer.h"
-#include "voice_engine/include/voe_base.h"
-
-#include "test/rtp_file_writer.h"
DEFINE_bool(save_worst_frame,
false,
@@ -77,48 +61,6 @@ constexpr uint32_t kThumbnailRtxSsrcStart = 0xF0000;
constexpr int kDefaultMaxQp = cricket::WebRtcVideoChannel::kDefaultQpMax;
-struct VoiceEngineState {
- VoiceEngineState()
- : voice_engine(nullptr),
- base(nullptr),
- send_channel_id(-1),
- receive_channel_id(-1) {}
-
- webrtc::VoiceEngine* voice_engine;
- webrtc::VoEBase* base;
- int send_channel_id;
- int receive_channel_id;
-};
-
-void CreateVoiceEngine(
- VoiceEngineState* voe,
- webrtc::AudioDeviceModule* adm,
- webrtc::AudioProcessing* apm,
- rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory) {
- voe->voice_engine = webrtc::VoiceEngine::Create();
- voe->base = webrtc::VoEBase::GetInterface(voe->voice_engine);
- EXPECT_EQ(0, adm->Init());
- EXPECT_EQ(0, voe->base->Init(adm, apm, decoder_factory));
- webrtc::VoEBase::ChannelConfig config;
- config.enable_voice_pacing = true;
- voe->send_channel_id = voe->base->CreateChannel(config);
- EXPECT_GE(voe->send_channel_id, 0);
- voe->receive_channel_id = voe->base->CreateChannel();
- EXPECT_GE(voe->receive_channel_id, 0);
-}
-
-void DestroyVoiceEngine(VoiceEngineState* voe) {
- voe->base->DeleteChannel(voe->send_channel_id);
- voe->send_channel_id = -1;
- voe->base->DeleteChannel(voe->receive_channel_id);
- voe->receive_channel_id = -1;
- voe->base->Release();
- voe->base = nullptr;
-
- webrtc::VoiceEngine::Delete(voe->voice_engine);
- voe->voice_engine = nullptr;
-}
-
class VideoStreamFactory
: public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
public:
@@ -134,6 +76,8 @@ class VideoStreamFactory
std::vector<webrtc::VideoStream> streams = streams_;
streams[streams_.size() - 1].height = height;
streams[streams_.size() - 1].width = width;
+
+ streams[0].bitrate_priority = encoder_config.bitrate_priority;
return streams;
}
@@ -280,25 +224,25 @@ class VideoAnalyzer : public PacketReceiver,
}
DeliveryStatus DeliverPacket(MediaType media_type,
- const uint8_t* packet,
- size_t length,
+ rtc::CopyOnWriteBuffer packet,
const PacketTime& packet_time) override {
// Ignore timestamps of RTCP packets. They're not synchronized with
// RTP packet timestamps and so they would confuse wrap_handler_.
- if (RtpHeaderParser::IsRtcp(packet, length)) {
- return receiver_->DeliverPacket(media_type, packet, length, packet_time);
+ if (RtpHeaderParser::IsRtcp(packet.cdata(), packet.size())) {
+ return receiver_->DeliverPacket(media_type, std::move(packet),
+ packet_time);
}
if (rtp_file_writer_) {
test::RtpPacket p;
- memcpy(p.data, packet, length);
- p.length = length;
- p.original_length = length;
+ memcpy(p.data, packet.cdata(), packet.size());
+ p.length = packet.size();
+ p.original_length = packet.size();
p.time_ms = clock_->TimeInMilliseconds() - start_ms_;
rtp_file_writer_->WritePacket(&p);
}
- RtpUtility::RtpHeaderParser parser(packet, length);
+ RtpUtility::RtpHeaderParser parser(packet.cdata(), packet.size());
RTPHeader header;
parser.Parse(&header);
if (!IsFlexfec(header.payloadType) &&
@@ -315,12 +259,7 @@ class VideoAnalyzer : public PacketReceiver,
Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
}
- return receiver_->DeliverPacket(media_type, packet, length, packet_time);
- }
-
- void MeasuredEncodeTiming(int64_t ntp_time_ms, int encode_time_ms) {
- rtc::CritScope crit(&comparison_lock_);
- samples_encode_time_ms_[ntp_time_ms] = encode_time_ms;
+ return receiver_->DeliverPacket(media_type, std::move(packet), packet_time);
}
void PreEncodeOnFrame(const VideoFrame& video_frame) {
@@ -331,8 +270,7 @@ class VideoAnalyzer : public PacketReceiver,
frames_.pop_front();
RTC_CHECK(!frames_.empty());
}
- first_encoded_timestamp_ =
- rtc::Optional<uint32_t>(video_frame.timestamp());
+ first_encoded_timestamp_ = video_frame.timestamp();
}
}
@@ -340,7 +278,7 @@ class VideoAnalyzer : public PacketReceiver,
rtc::CritScope lock(&crit_);
if (!first_sent_timestamp_ &&
encoded_frame.stream_id_ == selected_stream_) {
- first_sent_timestamp_ = rtc::Optional<uint32_t>(encoded_frame.timestamp_);
+ first_sent_timestamp_ = encoded_frame.timestamp_;
}
}
@@ -426,7 +364,7 @@ class VideoAnalyzer : public PacketReceiver,
AddFrameComparison(reference_frame, video_frame, false, render_time_ms);
- last_rendered_frame_ = rtc::Optional<VideoFrame>(video_frame);
+ last_rendered_frame_ = video_frame;
StopExcludingCpuThreadTime();
}
@@ -592,9 +530,6 @@ class VideoAnalyzer : public PacketReceiver,
public:
explicit OnEncodeTimingProxy(VideoAnalyzer* parent) : parent_(parent) {}
- void OnEncodeTiming(int64_t ntp_time_ms, int encode_time_ms) override {
- parent_->MeasuredEncodeTiming(ntp_time_ms, encode_time_ms);
- }
void EncodedFrameCallback(const EncodedFrame& frame) override {
parent_->PostEncodeFrameCallback(frame);
}
@@ -818,18 +753,18 @@ class VideoAnalyzer : public PacketReceiver,
PrintResult("send_bandwidth", send_bandwidth_bps_, " bps");
if (worst_frame_) {
- printf("RESULT min_psnr: %s = %lf dB\n", test_label_.c_str(),
- worst_frame_->psnr);
+ test::PrintResult("min_psnr", "", test_label_.c_str(), worst_frame_->psnr,
+ "dB", false);
}
if (receive_stream_ != nullptr) {
PrintResult("decode_time", decode_time_ms_, " ms");
}
- printf("RESULT dropped_frames: %s = %d frames\n", test_label_.c_str(),
- dropped_frames_);
- printf("RESULT cpu_usage: %s = %lf %%\n", test_label_.c_str(),
- GetCpuUsagePercent());
+ test::PrintResult("dropped_frames", "", test_label_.c_str(),
+ dropped_frames_, "frames", false);
+ test::PrintResult("cpu_usage", "", test_label_.c_str(),
+ GetCpuUsagePercent(), "%", false);
#if defined(WEBRTC_WIN)
// On Linux and Mac in Resident Set some unused pages may be counted.
@@ -918,12 +853,9 @@ class VideoAnalyzer : public PacketReceiver,
void PrintResult(const char* result_type,
test::Statistics stats,
const char* unit) {
- printf("RESULT %s: %s = {%f, %f}%s\n",
- result_type,
- test_label_.c_str(),
- stats.Mean(),
- stats.StandardDeviation(),
- unit);
+ test::PrintResultMeanAndError(result_type, "", test_label_.c_str(),
+ stats.Mean(), stats.StandardDeviation(), unit,
+ false);
}
void PrintSamplesToFile(void) {
@@ -946,27 +878,12 @@ class VideoAnalyzer : public PacketReceiver,
"psnr "
"ssim "
"encode_time_ms\n");
- int missing_encode_time_samples = 0;
for (const Sample& sample : samples_) {
- auto it = samples_encode_time_ms_.find(sample.input_time_ms);
- int encode_time_ms;
- if (it != samples_encode_time_ms_.end()) {
- encode_time_ms = it->second;
- } else {
- ++missing_encode_time_samples;
- encode_time_ms = -1;
- }
fprintf(out, "%d %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRIuS
- " %lf %lf %d\n",
+ " %lf %lf\n",
sample.dropped, sample.input_time_ms, sample.send_time_ms,
sample.recv_time_ms, sample.render_time_ms,
- sample.encoded_frame_size, sample.psnr, sample.ssim,
- encode_time_ms);
- }
- if (missing_encode_time_samples) {
- fprintf(stderr,
- "Warning: Missing encode_time_ms samples for %d frame(s).\n",
- missing_encode_time_samples);
+ sample.encoded_frame_size, sample.psnr, sample.ssim);
}
}
@@ -1061,8 +978,6 @@ class VideoAnalyzer : public PacketReceiver,
PreEncodeProxy pre_encode_proxy_;
OnEncodeTimingProxy encode_timing_proxy_;
std::vector<Sample> samples_ RTC_GUARDED_BY(comparison_lock_);
- std::map<int64_t, int> samples_encode_time_ms_
- RTC_GUARDED_BY(comparison_lock_);
test::Statistics sender_time_ RTC_GUARDED_BY(comparison_lock_);
test::Statistics receiver_time_ RTC_GUARDED_BY(comparison_lock_);
test::Statistics psnr_ RTC_GUARDED_BY(comparison_lock_);
@@ -1147,13 +1062,16 @@ VideoQualityTest::VideoQualityTest()
VideoQualityTest::Params::Params()
: call({false, Call::Config::BitrateConfig(), 0}),
- video({false, 640, 480, 30, 50, 800, 800, false, "VP8", 1, -1, 0, false,
- false, ""}),
+ video{{false, 640, 480, 30, 50, 800, 800, false, "VP8", 1, -1, 0, false,
+ false, ""},
+ {false, 640, 480, 30, 50, 800, 800, false, "VP8", 1, -1, 0, false,
+ false, ""}},
audio({false, false, false}),
- screenshare({false, false, 10, 0}),
+ screenshare{{false, false, 10, 0}, {false, false, 10, 0}},
analyzer({"", 0.0, 0.0, 0, "", ""}),
pipe(),
- ss({std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()}),
+ ss{{std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()},
+ {std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()}},
logging({false, "", "", ""}) {}
VideoQualityTest::Params::~Params() = default;
@@ -1162,70 +1080,84 @@ void VideoQualityTest::TestBody() {}
std::string VideoQualityTest::GenerateGraphTitle() const {
std::stringstream ss;
- ss << params_.video.codec;
- ss << " (" << params_.video.target_bitrate_bps / 1000 << "kbps";
- ss << ", " << params_.video.fps << " FPS";
- if (params_.screenshare.scroll_duration)
- ss << ", " << params_.screenshare.scroll_duration << "s scroll";
- if (params_.ss.streams.size() > 1)
- ss << ", Stream #" << params_.ss.selected_stream;
- if (params_.ss.num_spatial_layers > 1)
- ss << ", Layer #" << params_.ss.selected_sl;
+ ss << params_.video[0].codec;
+ ss << " (" << params_.video[0].target_bitrate_bps / 1000 << "kbps";
+ ss << ", " << params_.video[0].fps << " FPS";
+ if (params_.screenshare[0].scroll_duration)
+ ss << ", " << params_.screenshare[0].scroll_duration << "s scroll";
+ if (params_.ss[0].streams.size() > 1)
+ ss << ", Stream #" << params_.ss[0].selected_stream;
+ if (params_.ss[0].num_spatial_layers > 1)
+ ss << ", Layer #" << params_.ss[0].selected_sl;
ss << ")";
return ss.str();
}
void VideoQualityTest::CheckParams() {
- if (!params_.video.enabled)
- return;
- // Add a default stream in none specified.
- if (params_.ss.streams.empty())
- params_.ss.streams.push_back(VideoQualityTest::DefaultVideoStream(params_));
- if (params_.ss.num_spatial_layers == 0)
- params_.ss.num_spatial_layers = 1;
-
- if (params_.pipe.loss_percent != 0 ||
- params_.pipe.queue_length_packets != 0) {
- // Since LayerFilteringTransport changes the sequence numbers, we can't
- // use that feature with pack loss, since the NACK request would end up
- // retransmitting the wrong packets.
- RTC_CHECK(params_.ss.selected_sl == -1 ||
- params_.ss.selected_sl == params_.ss.num_spatial_layers - 1);
- RTC_CHECK(params_.video.selected_tl == -1 ||
- params_.video.selected_tl ==
- params_.video.num_temporal_layers - 1);
- }
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ // Iterate over primary and secondary video streams.
+ if (!params_.video[video_idx].enabled)
+ return;
+ // Add a default stream in none specified.
+ if (params_.ss[video_idx].streams.empty())
+ params_.ss[video_idx].streams.push_back(
+ VideoQualityTest::DefaultVideoStream(params_, video_idx));
+ if (params_.ss[video_idx].num_spatial_layers == 0)
+ params_.ss[video_idx].num_spatial_layers = 1;
+
+ if (params_.pipe.loss_percent != 0 ||
+ params_.pipe.queue_length_packets != 0) {
+ // Since LayerFilteringTransport changes the sequence numbers, we can't
+ // use that feature with pack loss, since the NACK request would end up
+ // retransmitting the wrong packets.
+ RTC_CHECK(params_.ss[video_idx].selected_sl == -1 ||
+ params_.ss[video_idx].selected_sl ==
+ params_.ss[video_idx].num_spatial_layers - 1);
+ RTC_CHECK(params_.video[video_idx].selected_tl == -1 ||
+ params_.video[video_idx].selected_tl ==
+ params_.video[video_idx].num_temporal_layers - 1);
+ }
- // TODO(ivica): Should max_bitrate_bps == -1 represent inf max bitrate, as it
- // does in some parts of the code?
- RTC_CHECK_GE(params_.video.max_bitrate_bps, params_.video.target_bitrate_bps);
- RTC_CHECK_GE(params_.video.target_bitrate_bps, params_.video.min_bitrate_bps);
- RTC_CHECK_LT(params_.video.selected_tl, params_.video.num_temporal_layers);
- RTC_CHECK_LE(params_.ss.selected_stream, params_.ss.streams.size());
- for (const VideoStream& stream : params_.ss.streams) {
- RTC_CHECK_GE(stream.min_bitrate_bps, 0);
- RTC_CHECK_GE(stream.target_bitrate_bps, stream.min_bitrate_bps);
- RTC_CHECK_GE(stream.max_bitrate_bps, stream.target_bitrate_bps);
- }
- // TODO(ivica): Should we check if the sum of all streams/layers is equal to
- // the total bitrate? We anyway have to update them in the case bitrate
- // estimator changes the total bitrates.
- RTC_CHECK_GE(params_.ss.num_spatial_layers, 1);
- RTC_CHECK_LE(params_.ss.selected_sl, params_.ss.num_spatial_layers);
- RTC_CHECK(params_.ss.spatial_layers.empty() ||
- params_.ss.spatial_layers.size() ==
- static_cast<size_t>(params_.ss.num_spatial_layers));
- if (params_.video.codec == "VP8") {
- RTC_CHECK_EQ(params_.ss.num_spatial_layers, 1);
- } else if (params_.video.codec == "VP9") {
- RTC_CHECK_EQ(params_.ss.streams.size(), 1);
- }
- RTC_CHECK_GE(params_.call.num_thumbnails, 0);
- if (params_.call.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");
+ // TODO(ivica): Should max_bitrate_bps == -1 represent inf max bitrate, as
+ // it does in some parts of the code?
+ RTC_CHECK_GE(params_.video[video_idx].max_bitrate_bps,
+ params_.video[video_idx].target_bitrate_bps);
+ RTC_CHECK_GE(params_.video[video_idx].target_bitrate_bps,
+ params_.video[video_idx].min_bitrate_bps);
+ RTC_CHECK_LT(params_.video[video_idx].selected_tl,
+ params_.video[video_idx].num_temporal_layers);
+ RTC_CHECK_LE(params_.ss[video_idx].selected_stream,
+ params_.ss[video_idx].streams.size());
+ for (const VideoStream& stream : params_.ss[video_idx].streams) {
+ RTC_CHECK_GE(stream.min_bitrate_bps, 0);
+ RTC_CHECK_GE(stream.target_bitrate_bps, stream.min_bitrate_bps);
+ RTC_CHECK_GE(stream.max_bitrate_bps, stream.target_bitrate_bps);
+ }
+ // TODO(ivica): Should we check if the sum of all streams/layers is equal to
+ // the total bitrate? We anyway have to update them in the case bitrate
+ // estimator changes the total bitrates.
+ RTC_CHECK_GE(params_.ss[video_idx].num_spatial_layers, 1);
+ RTC_CHECK_LE(params_.ss[video_idx].selected_sl,
+ params_.ss[video_idx].num_spatial_layers);
+ RTC_CHECK(
+ params_.ss[video_idx].spatial_layers.empty() ||
+ params_.ss[video_idx].spatial_layers.size() ==
+ static_cast<size_t>(params_.ss[video_idx].num_spatial_layers));
+ if (params_.video[video_idx].codec == "VP8") {
+ RTC_CHECK_EQ(params_.ss[video_idx].num_spatial_layers, 1);
+ } else if (params_.video[video_idx].codec == "VP9") {
+ RTC_CHECK_EQ(params_.ss[video_idx].streams.size(), 1);
+ }
+ RTC_CHECK_GE(params_.call.num_thumbnails, 0);
+ if (params_.call.num_thumbnails > 0) {
+ RTC_CHECK_EQ(params_.ss[video_idx].num_spatial_layers, 1);
+ RTC_CHECK_EQ(params_.ss[video_idx].streams.size(), 3);
+ RTC_CHECK_EQ(params_.video[video_idx].num_temporal_layers, 3);
+ RTC_CHECK_EQ(params_.video[video_idx].codec, "VP8");
+ }
+ // Dual streams with FEC not supported in tests yet.
+ RTC_CHECK(!params_.video[video_idx].flexfec || num_video_streams_ == 1);
+ RTC_CHECK(!params_.video[video_idx].ulpfec || num_video_streams_ == 1);
}
}
@@ -1258,24 +1190,26 @@ std::vector<int> VideoQualityTest::ParseCSV(const std::string& str) {
}
// Static.
-VideoStream VideoQualityTest::DefaultVideoStream(const Params& params) {
+VideoStream VideoQualityTest::DefaultVideoStream(const Params& params,
+ size_t video_idx) {
VideoStream stream;
- stream.width = params.video.width;
- stream.height = params.video.height;
- stream.max_framerate = params.video.fps;
- stream.min_bitrate_bps = params.video.min_bitrate_bps;
- stream.target_bitrate_bps = params.video.target_bitrate_bps;
- stream.max_bitrate_bps = params.video.max_bitrate_bps;
+ stream.width = params.video[video_idx].width;
+ stream.height = params.video[video_idx].height;
+ stream.max_framerate = params.video[video_idx].fps;
+ stream.min_bitrate_bps = params.video[video_idx].min_bitrate_bps;
+ stream.target_bitrate_bps = params.video[video_idx].target_bitrate_bps;
+ stream.max_bitrate_bps = params.video[video_idx].max_bitrate_bps;
stream.max_qp = kDefaultMaxQp;
// TODO(sprang): Can we make this less of a hack?
- if (params.video.num_temporal_layers == 2) {
+ if (params.video[video_idx].num_temporal_layers == 2) {
stream.temporal_layer_thresholds_bps.push_back(stream.target_bitrate_bps);
- } else if (params.video.num_temporal_layers == 3) {
+ } else if (params.video[video_idx].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);
} else {
- RTC_CHECK_LE(params.video.num_temporal_layers, kMaxTemporalStreams);
- for (int i = 0; i < params.video.num_temporal_layers - 1; ++i) {
+ RTC_CHECK_LE(params.video[video_idx].num_temporal_layers,
+ kMaxTemporalStreams);
+ for (int i = 0; i < params.video[video_idx].num_temporal_layers - 1; ++i) {
stream.temporal_layer_thresholds_bps.push_back(static_cast<int>(
stream.max_bitrate_bps * kVp8LayerRateAlloction[0][i] + 0.5));
}
@@ -1299,39 +1233,44 @@ VideoStream VideoQualityTest::DefaultThumbnailStream() {
// Static.
void VideoQualityTest::FillScalabilitySettings(
Params* params,
+ size_t video_idx,
const std::vector<std::string>& stream_descriptors,
int num_streams,
size_t selected_stream,
int num_spatial_layers,
int selected_sl,
const std::vector<std::string>& sl_descriptors) {
- if (params->ss.streams.empty() && params->ss.infer_streams) {
+ if (params->ss[video_idx].streams.empty() &&
+ params->ss[video_idx].infer_streams) {
webrtc::VideoEncoderConfig encoder_config;
encoder_config.content_type =
- params->screenshare.enabled
+ params->screenshare[video_idx].enabled
? webrtc::VideoEncoderConfig::ContentType::kScreen
: webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
- encoder_config.max_bitrate_bps = params->video.max_bitrate_bps;
- encoder_config.min_transmit_bitrate_bps = params->video.min_transmit_bps;
+ encoder_config.max_bitrate_bps = params->video[video_idx].max_bitrate_bps;
+ encoder_config.min_transmit_bitrate_bps =
+ params->video[video_idx].min_transmit_bps;
encoder_config.number_of_streams = num_streams;
- encoder_config.spatial_layers = params->ss.spatial_layers;
+ encoder_config.spatial_layers = params->ss[video_idx].spatial_layers;
encoder_config.video_stream_factory =
new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
- params->video.codec, kDefaultMaxQp, params->video.fps,
- params->screenshare.enabled, true);
- params->ss.streams =
+ params->video[video_idx].codec, kDefaultMaxQp,
+ params->video[video_idx].fps,
+ params->screenshare[video_idx].enabled, true);
+ params->ss[video_idx].streams =
encoder_config.video_stream_factory->CreateEncoderStreams(
- static_cast<int>(params->video.width),
- static_cast<int>(params->video.height), encoder_config);
+ static_cast<int>(params->video[video_idx].width),
+ static_cast<int>(params->video[video_idx].height), encoder_config);
} else {
// Read VideoStream and SpatialLayer elements from a list of comma separated
// lists. To use a default value for an element, use -1 or leave empty.
// Validity checks performed in CheckParams.
- RTC_CHECK(params->ss.streams.empty());
+ RTC_CHECK(params->ss[video_idx].streams.empty());
for (auto descriptor : stream_descriptors) {
if (descriptor.empty())
continue;
- VideoStream stream = VideoQualityTest::DefaultVideoStream(*params);
+ VideoStream stream =
+ VideoQualityTest::DefaultVideoStream(*params, video_idx);
std::vector<int> v = VideoQualityTest::ParseCSV(descriptor);
if (v[0] != -1)
stream.width = static_cast<size_t>(v[0]);
@@ -1353,17 +1292,17 @@ void VideoQualityTest::FillScalabilitySettings(
stream.temporal_layer_thresholds_bps.end(), v.begin() + 7, v.end());
} else {
// Automatic TL thresholds for more than two layers not supported.
- RTC_CHECK_LE(params->video.num_temporal_layers, 2);
+ RTC_CHECK_LE(params->video[video_idx].num_temporal_layers, 2);
}
- params->ss.streams.push_back(stream);
+ params->ss[video_idx].streams.push_back(stream);
}
}
- params->ss.num_spatial_layers = std::max(1, num_spatial_layers);
- params->ss.selected_stream = selected_stream;
+ params->ss[video_idx].num_spatial_layers = std::max(1, num_spatial_layers);
+ params->ss[video_idx].selected_stream = selected_stream;
- params->ss.selected_sl = selected_sl;
- RTC_CHECK(params->ss.spatial_layers.empty());
+ params->ss[video_idx].selected_sl = selected_sl;
+ RTC_CHECK(params->ss[video_idx].spatial_layers.empty());
for (auto descriptor : sl_descriptors) {
if (descriptor.empty())
continue;
@@ -1374,120 +1313,203 @@ void VideoQualityTest::FillScalabilitySettings(
layer.scaling_factor_num = v[0] == -1 ? 1 : v[0];
layer.scaling_factor_den = v[1] == -1 ? 1 : v[1];
layer.target_bitrate_bps = v[2];
- params->ss.spatial_layers.push_back(layer);
+ params->ss[video_idx].spatial_layers.push_back(layer);
}
}
void VideoQualityTest::SetupVideo(Transport* send_transport,
Transport* recv_transport) {
- size_t num_video_streams = params_.ss.streams.size();
- size_t num_flexfec_streams = params_.video.flexfec ? 1 : 0;
- CreateSendConfig(num_video_streams, 0, num_flexfec_streams, send_transport);
-
- int payload_type;
- if (params_.video.codec == "H264") {
- video_encoder_ = H264Encoder::Create(cricket::VideoCodec("H264"));
- payload_type = kPayloadTypeH264;
- } else if (params_.video.codec == "VP8") {
- if (params_.screenshare.enabled && params_.ss.streams.size() > 1) {
- // Simulcast screenshare needs a simulcast encoder adapter to work, since
- // encoders usually can't natively do simulcast with different frame rates
- // for the different layers.
- video_encoder_.reset(
- new SimulcastEncoderAdapter(new InternalEncoderFactory()));
+ size_t total_streams_used = 0;
+ size_t num_flexfec_streams = params_.video[0].flexfec ? 1 : 0;
+ CreateAudioAndFecSendConfigs(0, num_flexfec_streams, send_transport);
+ CreateMatchingAudioAndFecConfigs(recv_transport);
+ video_receive_configs_.clear();
+ video_send_configs_.clear();
+ video_encoders_.clear();
+ video_encoder_configs_.clear();
+ allocated_decoders_.clear();
+ bool decode_all_receive_streams = true;
+ size_t num_video_substreams = params_.ss[0].streams.size();
+ RTC_CHECK(num_video_streams_ > 0);
+ video_encoder_configs_.resize(num_video_streams_);
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ video_send_configs_.push_back(VideoSendStream::Config(send_transport));
+ video_encoders_.push_back(nullptr);
+ video_encoder_configs_.push_back(VideoEncoderConfig());
+ num_video_substreams = params_.ss[video_idx].streams.size();
+ RTC_CHECK_GT(num_video_substreams, 0);
+ CreateVideoSendConfig(&video_send_configs_[video_idx], num_video_substreams,
+ total_streams_used, send_transport);
+
+ int payload_type;
+ if (params_.video[video_idx].codec == "H264") {
+ video_encoders_[video_idx] =
+ H264Encoder::Create(cricket::VideoCodec("H264"));
+ payload_type = kPayloadTypeH264;
+ } else if (params_.video[video_idx].codec == "VP8") {
+ if (params_.screenshare[video_idx].enabled &&
+ params_.ss[video_idx].streams.size() > 1) {
+ // Simulcast screenshare needs a simulcast encoder adapter to work,
+ // since encoders usually can't natively do simulcast with different
+ // frame rates for the different layers.
+ video_encoders_[video_idx].reset(
+ new SimulcastEncoderAdapter(new InternalEncoderFactory()));
+ } else {
+ video_encoders_[video_idx] = VP8Encoder::Create();
+ }
+ payload_type = kPayloadTypeVP8;
+ } else if (params_.video[video_idx].codec == "VP9") {
+ video_encoders_[video_idx] = VP9Encoder::Create();
+ payload_type = kPayloadTypeVP9;
} else {
- video_encoder_ = VP8Encoder::Create();
+ RTC_NOTREACHED() << "Codec not supported!";
+ return;
+ }
+ video_send_configs_[video_idx].encoder_settings.encoder =
+ video_encoders_[video_idx].get();
+ video_send_configs_[video_idx].encoder_settings.payload_name =
+ params_.video[video_idx].codec;
+ video_send_configs_[video_idx].encoder_settings.payload_type = payload_type;
+ video_send_configs_[video_idx].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ video_send_configs_[video_idx].rtp.rtx.payload_type = kSendRtxPayloadType;
+ for (size_t i = 0; i < num_video_substreams; ++i) {
+ video_send_configs_[video_idx].rtp.rtx.ssrcs.push_back(
+ kSendRtxSsrcs[i + total_streams_used]);
+ }
+ video_send_configs_[video_idx].rtp.extensions.clear();
+ if (params_.call.send_side_bwe) {
+ video_send_configs_[video_idx].rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kTransportSequenceNumberUri,
+ test::kTransportSequenceNumberExtensionId));
+ } else {
+ video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
+ }
+ video_send_configs_[video_idx].rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kVideoContentTypeUri,
+ test::kVideoContentTypeExtensionId));
+ video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kVideoTimingUri, test::kVideoTimingExtensionId));
+
+ video_encoder_configs_[video_idx].min_transmit_bitrate_bps =
+ params_.video[video_idx].min_transmit_bps;
+
+ video_send_configs_[video_idx].suspend_below_min_bitrate =
+ params_.video[video_idx].suspend_below_min_bitrate;
+
+ video_encoder_configs_[video_idx].number_of_streams =
+ params_.ss[video_idx].streams.size();
+ video_encoder_configs_[video_idx].max_bitrate_bps = 0;
+ for (size_t i = 0; i < params_.ss[video_idx].streams.size(); ++i) {
+ video_encoder_configs_[video_idx].max_bitrate_bps +=
+ params_.ss[video_idx].streams[i].max_bitrate_bps;
+ }
+ if (params_.ss[video_idx].infer_streams) {
+ video_encoder_configs_[video_idx].video_stream_factory =
+ new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
+ params_.video[video_idx].codec,
+ params_.ss[video_idx].streams[0].max_qp,
+ params_.video[video_idx].fps,
+ params_.screenshare[video_idx].enabled, true);
+ } else {
+ video_encoder_configs_[video_idx].video_stream_factory =
+ new rtc::RefCountedObject<VideoStreamFactory>(
+ params_.ss[video_idx].streams);
}
- payload_type = kPayloadTypeVP8;
- } else if (params_.video.codec == "VP9") {
- video_encoder_ = VP9Encoder::Create();
- payload_type = kPayloadTypeVP9;
- } else {
- RTC_NOTREACHED() << "Codec not supported!";
- return;
- }
- video_send_config_.encoder_settings.encoder = video_encoder_.get();
- video_send_config_.encoder_settings.payload_name = params_.video.codec;
- video_send_config_.encoder_settings.payload_type = payload_type;
- video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
- video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
- for (size_t i = 0; i < num_video_streams; ++i)
- video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
-
- video_send_config_.rtp.extensions.clear();
- if (params_.call.send_side_bwe) {
- video_send_config_.rtp.extensions.push_back(
- RtpExtension(RtpExtension::kTransportSequenceNumberUri,
- test::kTransportSequenceNumberExtensionId));
- } else {
- video_send_config_.rtp.extensions.push_back(RtpExtension(
- RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
- }
- video_send_config_.rtp.extensions.push_back(RtpExtension(
- RtpExtension::kVideoContentTypeUri, test::kVideoContentTypeExtensionId));
- video_send_config_.rtp.extensions.push_back(RtpExtension(
- RtpExtension::kVideoTimingUri, test::kVideoTimingExtensionId));
-
- video_encoder_config_.min_transmit_bitrate_bps =
- params_.video.min_transmit_bps;
-
- video_send_config_.suspend_below_min_bitrate =
- params_.video.suspend_below_min_bitrate;
-
- video_encoder_config_.number_of_streams = params_.ss.streams.size();
- video_encoder_config_.max_bitrate_bps = 0;
- for (size_t i = 0; i < params_.ss.streams.size(); ++i) {
- video_encoder_config_.max_bitrate_bps +=
- params_.ss.streams[i].max_bitrate_bps;
- }
- if (params_.ss.infer_streams) {
- video_encoder_config_.video_stream_factory =
- new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
- params_.video.codec, params_.ss.streams[0].max_qp,
- params_.video.fps, params_.screenshare.enabled, true);
- } else {
- video_encoder_config_.video_stream_factory =
- new rtc::RefCountedObject<VideoStreamFactory>(params_.ss.streams);
- }
- video_encoder_config_.spatial_layers = params_.ss.spatial_layers;
-
- CreateMatchingReceiveConfigs(recv_transport);
-
- const bool decode_all_receive_streams =
- params_.ss.selected_stream == params_.ss.streams.size();
-
- for (size_t i = 0; i < num_video_streams; ++i) {
- video_receive_configs_[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
- video_receive_configs_[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
- video_receive_configs_[i]
- .rtp.rtx_associated_payload_types[kSendRtxPayloadType] = payload_type;
- video_receive_configs_[i].rtp.transport_cc = params_.call.send_side_bwe;
- video_receive_configs_[i].rtp.remb = !params_.call.send_side_bwe;
- // Enable RTT calculation so NTP time estimator will work.
- video_receive_configs_[i].rtp.rtcp_xr.receiver_reference_time_report = true;
- // Force fake decoders on non-selected simulcast streams.
- if (!decode_all_receive_streams && i != params_.ss.selected_stream) {
- VideoReceiveStream::Decoder decoder;
- decoder.decoder = new test::FakeDecoder();
- decoder.payload_type = video_send_config_.encoder_settings.payload_type;
- decoder.payload_name = video_send_config_.encoder_settings.payload_name;
- video_receive_configs_[i].decoders.clear();
- allocated_decoders_.emplace_back(decoder.decoder);
- video_receive_configs_[i].decoders.push_back(decoder);
+ video_encoder_configs_[video_idx].spatial_layers =
+ params_.ss[video_idx].spatial_layers;
+
+ std::vector<VideoReceiveStream::Config> new_receive_configs =
+ CreateMatchingVideoReceiveConfigs(video_send_configs_[video_idx],
+ recv_transport);
+
+ decode_all_receive_streams = params_.ss[video_idx].selected_stream ==
+ params_.ss[video_idx].streams.size();
+
+ for (size_t i = 0; i < num_video_substreams; ++i) {
+ new_receive_configs[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ new_receive_configs[i].rtp.rtx_ssrc =
+ kSendRtxSsrcs[i + total_streams_used];
+ new_receive_configs[i]
+ .rtp.rtx_associated_payload_types[kSendRtxPayloadType] = payload_type;
+ new_receive_configs[i].rtp.transport_cc = params_.call.send_side_bwe;
+ new_receive_configs[i].rtp.remb = !params_.call.send_side_bwe;
+ // Enable RTT calculation so NTP time estimator will work.
+ new_receive_configs[i].rtp.rtcp_xr.receiver_reference_time_report = true;
+ // Force fake decoders on non-selected simulcast streams.
+ if (!decode_all_receive_streams &&
+ i != params_.ss[video_idx].selected_stream) {
+ VideoReceiveStream::Decoder decoder;
+ decoder.decoder = new test::FakeDecoder();
+ decoder.payload_type =
+ video_send_configs_[video_idx].encoder_settings.payload_type;
+ decoder.payload_name =
+ video_send_configs_[video_idx].encoder_settings.payload_name;
+ new_receive_configs[i].decoders.clear();
+ allocated_decoders_.emplace_back(decoder.decoder);
+ new_receive_configs[i].decoders.push_back(decoder);
+ }
+ }
+
+ for (VideoReceiveStream::Config& config : new_receive_configs) {
+ video_receive_configs_.push_back(config.Copy());
}
+
+ if (params_.screenshare[video_idx].enabled) {
+ // Fill out codec settings.
+ video_encoder_configs_[video_idx].content_type =
+ VideoEncoderConfig::ContentType::kScreen;
+ degradation_preference_ =
+ VideoSendStream::DegradationPreference::kMaintainResolution;
+ if (params_.video[video_idx].codec == "VP8") {
+ VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
+ vp8_settings.denoisingOn = false;
+ vp8_settings.frameDroppingOn = false;
+ vp8_settings.numberOfTemporalLayers = static_cast<unsigned char>(
+ params_.video[video_idx].num_temporal_layers);
+ video_encoder_configs_[video_idx].encoder_specific_settings =
+ new rtc::RefCountedObject<
+ VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
+ } else if (params_.video[video_idx].codec == "VP9") {
+ VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
+ vp9_settings.denoisingOn = false;
+ vp9_settings.frameDroppingOn = false;
+ vp9_settings.numberOfTemporalLayers = static_cast<unsigned char>(
+ params_.video[video_idx].num_temporal_layers);
+ vp9_settings.numberOfSpatialLayers = static_cast<unsigned char>(
+ params_.ss[video_idx].num_spatial_layers);
+ video_encoder_configs_[video_idx].encoder_specific_settings =
+ new rtc::RefCountedObject<
+ VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
+ }
+ } else if (params_.ss[video_idx].num_spatial_layers > 1) {
+ // If SVC mode without screenshare, still need to set codec specifics.
+ RTC_CHECK(params_.video[video_idx].codec == "VP9");
+ VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
+ vp9_settings.numberOfTemporalLayers = static_cast<unsigned char>(
+ params_.video[video_idx].num_temporal_layers);
+ vp9_settings.numberOfSpatialLayers =
+ static_cast<unsigned char>(params_.ss[video_idx].num_spatial_layers);
+ video_encoder_configs_[video_idx].encoder_specific_settings =
+ new rtc::RefCountedObject<
+ VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
+ }
+ total_streams_used += num_video_substreams;
}
- if (params_.video.flexfec) {
- // Override send config constructed by CreateSendConfig.
+ // FEC supported only for single video stream mode yet.
+ if (params_.video[0].flexfec) {
+ video_send_configs_[0].rtp.flexfec.payload_type = kFlexfecPayloadType;
+ video_send_configs_[0].rtp.flexfec.ssrc = kFlexfecSendSsrc;
if (decode_all_receive_streams) {
- for (uint32_t media_ssrc : video_send_config_.rtp.ssrcs) {
- video_send_config_.rtp.flexfec.protected_media_ssrcs.push_back(
+ for (uint32_t media_ssrc : video_send_configs_[0].rtp.ssrcs) {
+ video_send_configs_[0].rtp.flexfec.protected_media_ssrcs.push_back(
media_ssrc);
}
} else {
- video_send_config_.rtp.flexfec.protected_media_ssrcs = {
- kVideoSendSsrcs[params_.ss.selected_stream]};
+ video_send_configs_[0].rtp.flexfec.protected_media_ssrcs = {
+ kVideoSendSsrcs[params_.ss[0].selected_stream]};
}
// The matching receive config is _not_ created by
@@ -1495,10 +1517,11 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
// Set up the receive config manually instead.
FlexfecReceiveStream::Config flexfec_receive_config(recv_transport);
flexfec_receive_config.payload_type =
- video_send_config_.rtp.flexfec.payload_type;
- flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
+ video_send_configs_[0].rtp.flexfec.payload_type;
+ flexfec_receive_config.remote_ssrc =
+ video_send_configs_[0].rtp.flexfec.ssrc;
flexfec_receive_config.protected_media_ssrcs =
- video_send_config_.rtp.flexfec.protected_media_ssrcs;
+ video_send_configs_[0].rtp.flexfec.protected_media_ssrcs;
flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
flexfec_receive_config.transport_cc = params_.call.send_side_bwe;
if (params_.call.send_side_bwe) {
@@ -1510,37 +1533,38 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
}
flexfec_receive_configs_.push_back(flexfec_receive_config);
- if (num_video_streams > 0) {
+ if (num_video_substreams > 0) {
video_receive_configs_[0].rtp.protected_by_flexfec = true;
}
}
- if (params_.video.ulpfec) {
- video_send_config_.rtp.ulpfec.red_payload_type = kRedPayloadType;
- video_send_config_.rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
- video_send_config_.rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
+ if (params_.video[0].ulpfec) {
+ video_send_configs_[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
+ video_send_configs_[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
+ video_send_configs_[0].rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
if (decode_all_receive_streams) {
for (auto it = video_receive_configs_.begin();
it != video_receive_configs_.end(); ++it) {
it->rtp.red_payload_type =
- video_send_config_.rtp.ulpfec.red_payload_type;
+ video_send_configs_[0].rtp.ulpfec.red_payload_type;
it->rtp.ulpfec_payload_type =
- video_send_config_.rtp.ulpfec.ulpfec_payload_type;
- it->rtp.rtx_associated_payload_types[video_send_config_.rtp.ulpfec
- .red_rtx_payload_type] =
- video_send_config_.rtp.ulpfec.red_payload_type;
+ video_send_configs_[0].rtp.ulpfec.ulpfec_payload_type;
+ it->rtp.rtx_associated_payload_types
+ [video_send_configs_[0].rtp.ulpfec.red_rtx_payload_type] =
+ video_send_configs_[0].rtp.ulpfec.red_payload_type;
}
} else {
- video_receive_configs_[params_.ss.selected_stream].rtp.red_payload_type =
- video_send_config_.rtp.ulpfec.red_payload_type;
- video_receive_configs_[params_.ss.selected_stream]
+ video_receive_configs_[params_.ss[0].selected_stream]
+ .rtp.red_payload_type =
+ video_send_configs_[0].rtp.ulpfec.red_payload_type;
+ video_receive_configs_[params_.ss[0].selected_stream]
.rtp.ulpfec_payload_type =
- video_send_config_.rtp.ulpfec.ulpfec_payload_type;
- video_receive_configs_[params_.ss.selected_stream]
- .rtp.rtx_associated_payload_types[video_send_config_.rtp.ulpfec
- .red_rtx_payload_type] =
- video_send_config_.rtp.ulpfec.red_payload_type;
+ video_send_configs_[0].rtp.ulpfec.ulpfec_payload_type;
+ video_receive_configs_[params_.ss[0].selected_stream]
+ .rtp.rtx_associated_payload_types
+ [video_send_configs_[0].rtp.ulpfec.red_rtx_payload_type] =
+ video_send_configs_[0].rtp.ulpfec.red_payload_type;
}
}
}
@@ -1556,7 +1580,8 @@ void VideoQualityTest::SetupThumbnails(Transport* 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_name =
+ params_.video[0].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;
@@ -1574,19 +1599,19 @@ void VideoQualityTest::SetupThumbnails(Transport* send_transport,
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;
+ params_.video[0].suspend_below_min_bitrate;
thumbnail_encoder_config.number_of_streams = 1;
thumbnail_encoder_config.max_bitrate_bps = 50000;
- if (params_.ss.infer_streams) {
+ if (params_.ss[0].infer_streams) {
thumbnail_encoder_config.video_stream_factory =
- new rtc::RefCountedObject<VideoStreamFactory>(params_.ss.streams);
+ new rtc::RefCountedObject<VideoStreamFactory>(params_.ss[0].streams);
} else {
thumbnail_encoder_config.video_stream_factory =
new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
- params_.video.codec, params_.ss.streams[0].max_qp,
- params_.video.fps, params_.screenshare.enabled, true);
+ params_.video[0].codec, params_.ss[0].streams[0].max_qp,
+ params_.video[0].fps, params_.screenshare[0].enabled, true);
}
- thumbnail_encoder_config.spatial_layers = params_.ss.spatial_layers;
+ thumbnail_encoder_config.spatial_layers = params_.ss[0].spatial_layers;
VideoReceiveStream::Config thumbnail_receive_config(send_transport);
thumbnail_receive_config.rtp.remb = false;
@@ -1627,12 +1652,14 @@ void VideoQualityTest::SetupThumbnails(Transport* send_transport,
}
void VideoQualityTest::DestroyThumbnailStreams() {
- for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_)
+ 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_)
+ thumbnail_receive_streams_) {
sender_call_->DestroyVideoReceiveStream(thumbnail_receive_stream);
+ }
thumbnail_send_streams_.clear();
thumbnail_receive_streams_.clear();
for (std::unique_ptr<test::VideoCapturer>& video_caputurer :
@@ -1641,85 +1668,6 @@ void VideoQualityTest::DestroyThumbnailStreams() {
}
}
-void VideoQualityTest::SetupScreenshareOrSVC() {
- if (params_.screenshare.enabled) {
- // Fill out codec settings.
- video_encoder_config_.content_type =
- VideoEncoderConfig::ContentType::kScreen;
- degradation_preference_ =
- VideoSendStream::DegradationPreference::kMaintainResolution;
- if (params_.video.codec == "VP8") {
- VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
- vp8_settings.denoisingOn = false;
- vp8_settings.frameDroppingOn = false;
- vp8_settings.numberOfTemporalLayers =
- static_cast<unsigned char>(params_.video.num_temporal_layers);
- video_encoder_config_.encoder_specific_settings =
- new rtc::RefCountedObject<
- VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
- } else if (params_.video.codec == "VP9") {
- VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
- vp9_settings.denoisingOn = false;
- vp9_settings.frameDroppingOn = false;
- vp9_settings.numberOfTemporalLayers =
- static_cast<unsigned char>(params_.video.num_temporal_layers);
- vp9_settings.numberOfSpatialLayers =
- static_cast<unsigned char>(params_.ss.num_spatial_layers);
- video_encoder_config_.encoder_specific_settings =
- new rtc::RefCountedObject<
- VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
- }
- // Setup frame generator.
- const size_t kWidth = 1850;
- const size_t kHeight = 1110;
- if (params_.screenshare.generate_slides) {
- frame_generator_ = test::FrameGenerator::CreateSlideGenerator(
- kWidth, kHeight,
- params_.screenshare.slide_change_interval * params_.video.fps);
- } else {
- std::vector<std::string> slides = params_.screenshare.slides;
- if (slides.size() == 0) {
- slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
- slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
- slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
- slides.push_back(
- test::ResourcePath("difficult_photo_1850_1110", "yuv"));
- }
- if (params_.screenshare.scroll_duration == 0) {
- // Cycle image every slide_change_interval seconds.
- frame_generator_ = test::FrameGenerator::CreateFromYuvFile(
- slides, kWidth, kHeight,
- params_.screenshare.slide_change_interval * params_.video.fps);
- } else {
- RTC_CHECK_LE(params_.video.width, kWidth);
- RTC_CHECK_LE(params_.video.height, kHeight);
- RTC_CHECK_GT(params_.screenshare.slide_change_interval, 0);
- const int kPauseDurationMs =
- (params_.screenshare.slide_change_interval -
- params_.screenshare.scroll_duration) *
- 1000;
- RTC_CHECK_LE(params_.screenshare.scroll_duration,
- params_.screenshare.slide_change_interval);
-
- frame_generator_ =
- test::FrameGenerator::CreateScrollingInputFromYuvFiles(
- clock_, slides, kWidth, kHeight, params_.video.width,
- params_.video.height,
- params_.screenshare.scroll_duration * 1000, kPauseDurationMs);
- }
- }
- } else if (params_.ss.num_spatial_layers > 1) { // For non-screenshare case.
- RTC_CHECK(params_.video.codec == "VP9");
- VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
- vp9_settings.numberOfTemporalLayers =
- static_cast<unsigned char>(params_.video.num_temporal_layers);
- vp9_settings.numberOfSpatialLayers =
- static_cast<unsigned char>(params_.ss.num_spatial_layers);
- video_encoder_config_.encoder_specific_settings = new rtc::RefCountedObject<
- VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
- }
-}
-
void VideoQualityTest::SetupThumbnailCapturers(size_t num_thumbnail_streams) {
VideoStream thumbnail = DefaultThumbnailStream();
for (size_t i = 0; i < num_thumbnail_streams; ++i) {
@@ -1730,47 +1678,106 @@ void VideoQualityTest::SetupThumbnailCapturers(size_t num_thumbnail_streams) {
}
}
-void VideoQualityTest::CreateCapturer() {
- if (params_.screenshare.enabled) {
- test::FrameGeneratorCapturer* frame_generator_capturer =
- new test::FrameGeneratorCapturer(clock_, std::move(frame_generator_),
- params_.video.fps);
- EXPECT_TRUE(frame_generator_capturer->Init());
- video_capturer_.reset(frame_generator_capturer);
+std::unique_ptr<test::FrameGenerator> VideoQualityTest::CreateFrameGenerator(
+ size_t video_idx) {
+ // Setup frame generator.
+ const size_t kWidth = 1850;
+ const size_t kHeight = 1110;
+ std::unique_ptr<test::FrameGenerator> frame_generator;
+ if (params_.screenshare[video_idx].generate_slides) {
+ frame_generator = test::FrameGenerator::CreateSlideGenerator(
+ kWidth, kHeight,
+ params_.screenshare[video_idx].slide_change_interval *
+ params_.video[video_idx].fps);
} else {
- if (params_.video.clip_name == "Generator") {
- video_capturer_.reset(test::FrameGeneratorCapturer::Create(
- static_cast<int>(params_.video.width),
- static_cast<int>(params_.video.height), params_.video.fps, clock_));
- } else if (params_.video.clip_name.empty()) {
- video_capturer_.reset(test::VcmCapturer::Create(
- params_.video.width, params_.video.height, params_.video.fps,
- params_.video.capture_device_index));
- if (!video_capturer_) {
- // Failed to get actual camera, use chroma generator as backup.
- video_capturer_.reset(test::FrameGeneratorCapturer::Create(
- static_cast<int>(params_.video.width),
- static_cast<int>(params_.video.height), params_.video.fps, clock_));
- }
+ std::vector<std::string> slides = params_.screenshare[video_idx].slides;
+ if (slides.size() == 0) {
+ slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
+ slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
+ slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
+ slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
+ }
+ if (params_.screenshare[video_idx].scroll_duration == 0) {
+ // Cycle image every slide_change_interval seconds.
+ frame_generator = test::FrameGenerator::CreateFromYuvFile(
+ slides, kWidth, kHeight,
+ params_.screenshare[video_idx].slide_change_interval *
+ params_.video[video_idx].fps);
} else {
- video_capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile(
- test::ResourcePath(params_.video.clip_name, "yuv"),
- params_.video.width, params_.video.height, params_.video.fps,
- clock_));
- ASSERT_TRUE(video_capturer_) << "Could not create capturer for "
- << params_.video.clip_name
- << ".yuv. Is this resource file present?";
+ RTC_CHECK_LE(params_.video[video_idx].width, kWidth);
+ RTC_CHECK_LE(params_.video[video_idx].height, kHeight);
+ RTC_CHECK_GT(params_.screenshare[video_idx].slide_change_interval, 0);
+ const int kPauseDurationMs =
+ (params_.screenshare[video_idx].slide_change_interval -
+ params_.screenshare[video_idx].scroll_duration) *
+ 1000;
+ RTC_CHECK_LE(params_.screenshare[video_idx].scroll_duration,
+ params_.screenshare[video_idx].slide_change_interval);
+
+ frame_generator = test::FrameGenerator::CreateScrollingInputFromYuvFiles(
+ clock_, slides, kWidth, kHeight, params_.video[video_idx].width,
+ params_.video[video_idx].height,
+ params_.screenshare[video_idx].scroll_duration * 1000,
+ kPauseDurationMs);
}
}
- RTC_DCHECK(video_capturer_.get());
+ return frame_generator;
+}
+
+void VideoQualityTest::CreateCapturers() {
+ video_capturers_.resize(num_video_streams_);
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ if (params_.screenshare[video_idx].enabled) {
+ std::unique_ptr<test::FrameGenerator> frame_generator =
+ CreateFrameGenerator(video_idx);
+ test::FrameGeneratorCapturer* frame_generator_capturer =
+ new test::FrameGeneratorCapturer(clock_, std::move(frame_generator),
+ params_.video[video_idx].fps);
+ EXPECT_TRUE(frame_generator_capturer->Init());
+ video_capturers_[video_idx].reset(frame_generator_capturer);
+ } else {
+ if (params_.video[video_idx].clip_name == "Generator") {
+ video_capturers_[video_idx].reset(test::FrameGeneratorCapturer::Create(
+ static_cast<int>(params_.video[video_idx].width),
+ static_cast<int>(params_.video[video_idx].height),
+ params_.video[video_idx].fps, clock_));
+ } else if (params_.video[video_idx].clip_name.empty()) {
+ video_capturers_[video_idx].reset(test::VcmCapturer::Create(
+ params_.video[video_idx].width, params_.video[video_idx].height,
+ params_.video[video_idx].fps,
+ params_.video[video_idx].capture_device_index));
+ if (!video_capturers_[video_idx]) {
+ // Failed to get actual camera, use chroma generator as backup.
+ video_capturers_[video_idx].reset(
+ test::FrameGeneratorCapturer::Create(
+ static_cast<int>(params_.video[video_idx].width),
+ static_cast<int>(params_.video[video_idx].height),
+ params_.video[video_idx].fps, clock_));
+ }
+ } else {
+ video_capturers_[video_idx].reset(
+ test::FrameGeneratorCapturer::CreateFromYuvFile(
+ test::ResourcePath(params_.video[video_idx].clip_name, "yuv"),
+ params_.video[video_idx].width, params_.video[video_idx].height,
+ params_.video[video_idx].fps, clock_));
+ ASSERT_TRUE(video_capturers_[video_idx])
+ << "Could not create capturer for "
+ << params_.video[video_idx].clip_name
+ << ".yuv. Is this resource file present?";
+ }
+ }
+ RTC_DCHECK(video_capturers_[video_idx].get());
+ }
}
std::unique_ptr<test::LayerFilteringTransport>
VideoQualityTest::CreateSendTransport() {
return rtc::MakeUnique<test::LayerFilteringTransport>(
&task_queue_, params_.pipe, sender_call_.get(), kPayloadTypeVP8,
- kPayloadTypeVP9, params_.video.selected_tl, params_.ss.selected_sl,
- payload_type_map_);
+ kPayloadTypeVP9, params_.video[0].selected_tl, params_.ss[0].selected_sl,
+ payload_type_map_, kVideoSendSsrcs[0],
+ static_cast<uint32_t>(kVideoSendSsrcs[0] + params_.ss[0].streams.size() -
+ 1));
}
std::unique_ptr<test::DirectTransport>
@@ -1779,7 +1786,31 @@ VideoQualityTest::CreateReceiveTransport() {
&task_queue_, params_.pipe, receiver_call_.get(), payload_type_map_);
}
+void VideoQualityTest::CreateVideoStreams() {
+ RTC_DCHECK(video_send_streams_.empty());
+ RTC_DCHECK(video_receive_streams_.empty());
+ RTC_DCHECK_EQ(video_send_configs_.size(), num_video_streams_);
+ for (size_t i = 0; i < video_send_configs_.size(); ++i) {
+ video_send_streams_.push_back(sender_call_->CreateVideoSendStream(
+ video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy()));
+ }
+ for (size_t i = 0; i < video_receive_configs_.size(); ++i) {
+ video_receive_streams_.push_back(receiver_call_->CreateVideoReceiveStream(
+ video_receive_configs_[i].Copy()));
+ }
+
+ AssociateFlexfecStreamsWithVideoStreams();
+}
+
+void VideoQualityTest::DestroyStreams() {
+ CallTest::DestroyStreams();
+
+ for (VideoSendStream* video_send_stream : video_send_streams_)
+ sender_call_->DestroyVideoSendStream(video_send_stream);
+}
+
void VideoQualityTest::RunWithAnalyzer(const Params& params) {
+ num_video_streams_ = params.call.dual_video ? 2 : 1;
std::unique_ptr<test::LayerFilteringTransport> send_transport;
std::unique_ptr<test::DirectTransport> recv_transport;
FILE* graph_data_output_file = nullptr;
@@ -1801,24 +1832,40 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
}
if (!params.logging.rtc_event_log_name.empty()) {
- event_log_ = RtcEventLog::Create(clock_, RtcEventLog::EncodingType::Legacy);
- std::unique_ptr<RtcEventLogOutputFile> output(
+ send_event_log_ =
+ RtcEventLog::Create(clock_, RtcEventLog::EncodingType::Legacy);
+ recv_event_log_ =
+ RtcEventLog::Create(clock_, RtcEventLog::EncodingType::Legacy);
+ std::unique_ptr<RtcEventLogOutputFile> send_output(
+ rtc::MakeUnique<RtcEventLogOutputFile>(
+ params.logging.rtc_event_log_name + "_send",
+ RtcEventLog::kUnlimitedOutput));
+ std::unique_ptr<RtcEventLogOutputFile> recv_output(
rtc::MakeUnique<RtcEventLogOutputFile>(
- params.logging.rtc_event_log_name, RtcEventLog::kUnlimitedOutput));
- bool event_log_started = event_log_->StartLogging(
- std::move(output), RtcEventLog::kImmediateOutput);
+ params.logging.rtc_event_log_name + "_recv",
+ RtcEventLog::kUnlimitedOutput));
+ bool event_log_started =
+ send_event_log_->StartLogging(std::move(send_output),
+ RtcEventLog::kImmediateOutput) &&
+ recv_event_log_->StartLogging(std::move(recv_output),
+ RtcEventLog::kImmediateOutput);
RTC_DCHECK(event_log_started);
+ } else {
+ send_event_log_ = RtcEventLog::CreateNull();
+ recv_event_log_ = RtcEventLog::CreateNull();
}
- Call::Config call_config(event_log_.get());
- call_config.bitrate_config = params.call.call_bitrate_config;
+ Call::Config send_call_config(send_event_log_.get());
+ Call::Config recv_call_config(recv_event_log_.get());
+ send_call_config.bitrate_config = params.call.call_bitrate_config;
+ recv_call_config.bitrate_config = params.call.call_bitrate_config;
- task_queue_.SendTask(
- [this, &call_config, &send_transport, &recv_transport]() {
- CreateCalls(call_config, call_config);
- send_transport = CreateSendTransport();
- recv_transport = CreateReceiveTransport();
- });
+ task_queue_.SendTask([this, &send_call_config, &recv_call_config,
+ &send_transport, &recv_transport]() {
+ CreateCalls(send_call_config, recv_call_config);
+ send_transport = CreateSendTransport();
+ recv_transport = CreateReceiveTransport();
+ });
std::string graph_title = params_.analyzer.graph_title;
if (graph_title.empty())
@@ -1829,13 +1876,13 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
params_.analyzer.avg_psnr_threshold, params_.analyzer.avg_ssim_threshold,
is_quick_test_enabled
? kFramesSentInQuickTest
- : params_.analyzer.test_durations_secs * params_.video.fps,
+ : params_.analyzer.test_durations_secs * params_.video[0].fps,
graph_data_output_file, graph_title,
- kVideoSendSsrcs[params_.ss.selected_stream],
- kSendRtxSsrcs[params_.ss.selected_stream],
- static_cast<size_t>(params_.ss.selected_stream), params.ss.selected_sl,
- params_.video.selected_tl, is_quick_test_enabled, clock_,
- params_.logging.rtp_dump_name);
+ kVideoSendSsrcs[params_.ss[0].selected_stream],
+ kSendRtxSsrcs[params_.ss[0].selected_stream],
+ static_cast<size_t>(params_.ss[0].selected_stream),
+ params.ss[0].selected_sl, params_.video[0].selected_tl,
+ is_quick_test_enabled, clock_, params_.logging.rtp_dump_name);
task_queue_.SendTask([&]() {
analyzer->SetCall(sender_call_.get());
@@ -1845,36 +1892,41 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
SetupVideo(analyzer.get(), recv_transport.get());
SetupThumbnails(analyzer.get(), recv_transport.get());
- video_receive_configs_[params_.ss.selected_stream].renderer =
+ video_receive_configs_[params_.ss[0].selected_stream].renderer =
analyzer.get();
- video_send_config_.pre_encode_callback = analyzer->pre_encode_proxy();
- RTC_DCHECK(!video_send_config_.post_encode_callback);
- video_send_config_.post_encode_callback = analyzer->encode_timing_proxy();
-
- SetupScreenshareOrSVC();
+ video_send_configs_[0].pre_encode_callback = analyzer->pre_encode_proxy();
+ RTC_DCHECK(!video_send_configs_[0].post_encode_callback);
+ video_send_configs_[0].post_encode_callback =
+ analyzer->encode_timing_proxy();
CreateFlexfecStreams();
CreateVideoStreams();
- analyzer->SetSendStream(video_send_stream_);
+ analyzer->SetSendStream(video_send_streams_[0]);
if (video_receive_streams_.size() == 1)
analyzer->SetReceiveStream(video_receive_streams_[0]);
- video_send_stream_->SetSource(analyzer->OutputInterface(),
- degradation_preference_);
-
+ video_send_streams_[0]->SetSource(analyzer->OutputInterface(),
+ degradation_preference_);
SetupThumbnailCapturers(params_.call.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();
+ CreateCapturers();
- analyzer->SetSource(video_capturer_.get(), params_.ss.infer_streams);
+ analyzer->SetSource(video_capturers_[0].get(), params_.ss[0].infer_streams);
- StartEncodedFrameLogs(video_send_stream_);
- StartEncodedFrameLogs(video_receive_streams_[params_.ss.selected_stream]);
- video_send_stream_->Start();
+ for (size_t video_idx = 1; video_idx < num_video_streams_; ++video_idx) {
+ video_send_streams_[video_idx]->SetSource(
+ video_capturers_[video_idx].get(), degradation_preference_);
+ }
+
+ StartEncodedFrameLogs(video_send_streams_[0]);
+ StartEncodedFrameLogs(
+ video_receive_streams_[params_.ss[0].selected_stream]);
+ for (VideoSendStream* video_send_stream : video_send_streams_)
+ video_send_stream->Start();
for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_)
thumbnail_send_stream->Start();
for (VideoReceiveStream* receive_stream : video_receive_streams_)
@@ -1885,7 +1937,9 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
analyzer->StartMeasuringCpuProcessTime();
- video_capturer_->Start();
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ video_capturers_[video_idx]->Start();
+ }
for (std::unique_ptr<test::VideoCapturer>& video_caputurer :
thumbnail_capturers_) {
video_caputurer->Start();
@@ -1900,7 +1954,9 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
for (std::unique_ptr<test::VideoCapturer>& video_caputurer :
thumbnail_capturers_)
video_caputurer->Stop();
- video_capturer_->Stop();
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ video_capturers_[video_idx]->Stop();
+ }
for (VideoReceiveStream* thumbnail_receive_stream :
thumbnail_receive_streams_)
thumbnail_receive_stream->Stop();
@@ -1908,7 +1964,8 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
receive_stream->Stop();
for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_)
thumbnail_send_stream->Stop();
- video_send_stream_->Stop();
+ for (VideoSendStream* video_send_stream : video_send_streams_)
+ video_send_stream->Stop();
DestroyStreams();
DestroyThumbnailStreams();
@@ -1916,7 +1973,7 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
if (graph_data_output_file)
fclose(graph_data_output_file);
- video_capturer_.reset();
+ video_capturers_.clear();
send_transport.reset();
recv_transport.reset();
@@ -1924,12 +1981,9 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
});
}
-void VideoQualityTest::SetupAudio(int send_channel_id,
- int receive_channel_id,
- Transport* transport,
+void VideoQualityTest::SetupAudio(Transport* transport,
AudioReceiveStream** audio_receive_stream) {
audio_send_config_ = AudioSendStream::Config(transport);
- audio_send_config_.voe_channel_id = send_channel_id;
audio_send_config_.rtp.ssrc = kAudioSendSsrc;
// Add extension to enable audio send side BWE, and allow audio bit rate
@@ -1942,25 +1996,23 @@ void VideoQualityTest::SetupAudio(int send_channel_id,
audio_send_config_.min_bitrate_bps = kOpusMinBitrateBps;
audio_send_config_.max_bitrate_bps = kOpusBitrateFbBps;
}
- audio_send_config_.send_codec_spec =
- rtc::Optional<AudioSendStream::Config::SendCodecSpec>(
- {kAudioSendPayloadType,
- {"OPUS", 48000, 2,
- {{"usedtx", (params_.audio.dtx ? "1" : "0")},
- {"stereo", "1"}}}});
+ audio_send_config_.send_codec_spec = AudioSendStream::Config::SendCodecSpec(
+ kAudioSendPayloadType,
+ {"OPUS", 48000, 2,
+ {{"usedtx", (params_.audio.dtx ? "1" : "0")},
+ {"stereo", "1"}}});
audio_send_config_.encoder_factory = encoder_factory_;
audio_send_stream_ = sender_call_->CreateAudioSendStream(audio_send_config_);
AudioReceiveStream::Config audio_config;
audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
audio_config.rtcp_send_transport = transport;
- audio_config.voe_channel_id = receive_channel_id;
audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
audio_config.rtp.transport_cc = params_.call.send_side_bwe;
audio_config.rtp.extensions = audio_send_config_.rtp.extensions;
audio_config.decoder_factory = decoder_factory_;
audio_config.decoder_map = {{kAudioSendPayloadType, {"OPUS", 48000, 2}}};
- if (params_.video.enabled && params_.audio.sync_video)
+ if (params_.video[0].enabled && params_.audio.sync_video)
audio_config.sync_group = kSyncGroup;
*audio_receive_stream =
@@ -1968,10 +2020,9 @@ void VideoQualityTest::SetupAudio(int send_channel_id,
}
void VideoQualityTest::RunWithRenderers(const Params& params) {
+ num_video_streams_ = params.call.dual_video ? 2 : 1;
std::unique_ptr<test::LayerFilteringTransport> send_transport;
std::unique_ptr<test::DirectTransport> recv_transport;
- std::unique_ptr<test::FakeAudioDevice> fake_audio_device;
- ::VoiceEngineState voe;
std::unique_ptr<test::VideoRenderer> local_preview;
std::vector<std::unique_ptr<test::VideoRenderer>> loopback_renderers;
AudioReceiveStream* audio_receive_stream = nullptr;
@@ -1985,21 +2036,17 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
Call::Config call_config(event_log_.get());
call_config.bitrate_config = params_.call.call_bitrate_config;
- fake_audio_device.reset(new test::FakeAudioDevice(
- test::FakeAudioDevice::CreatePulsedNoiseCapturer(32000, 48000),
- test::FakeAudioDevice::CreateDiscardRenderer(48000),
- 1.f));
-
- rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing(
- webrtc::AudioProcessing::Create());
+ rtc::scoped_refptr<test::FakeAudioDevice> fake_audio_device =
+ new rtc::RefCountedObject<test::FakeAudioDevice>(
+ test::FakeAudioDevice::CreatePulsedNoiseCapturer(32000, 48000),
+ test::FakeAudioDevice::CreateDiscardRenderer(48000),
+ 1.f);
if (params_.audio.enabled) {
- CreateVoiceEngine(&voe, fake_audio_device.get(), audio_processing.get(),
- decoder_factory_);
AudioState::Config audio_state_config;
- audio_state_config.voice_engine = voe.voice_engine;
audio_state_config.audio_mixer = AudioMixerImpl::Create();
- audio_state_config.audio_processing = audio_processing;
+ audio_state_config.audio_processing = AudioProcessingBuilder().Create();
+ audio_state_config.audio_device_module = fake_audio_device;
call_config.audio_state = AudioState::Create(audio_state_config);
fake_audio_device->RegisterAudioCallback(
call_config.audio_state->audio_transport());
@@ -2009,13 +2056,9 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
// TODO(minyue): consider if this is a good transport even for audio only
// calls.
- send_transport = rtc::MakeUnique<test::LayerFilteringTransport>(
- &task_queue_, params.pipe, sender_call_.get(), kPayloadTypeVP8,
- kPayloadTypeVP9, params.video.selected_tl, params_.ss.selected_sl,
- payload_type_map_);
+ send_transport = CreateSendTransport();
- recv_transport = rtc::MakeUnique<test::DirectTransport>(
- &task_queue_, params_.pipe, receiver_call_.get(), payload_type_map_);
+ recv_transport = CreateReceiveTransport();
// TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at
// least share as much code as possible. That way this test would also match
@@ -2023,81 +2066,82 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
send_transport->SetReceiver(receiver_call_->Receiver());
recv_transport->SetReceiver(sender_call_->Receiver());
- if (params_.video.enabled) {
+ if (params_.video[0].enabled) {
// Create video renderers.
local_preview.reset(test::VideoRenderer::Create(
- "Local Preview", params_.video.width, params_.video.height));
-
- const size_t selected_stream_id = params_.ss.selected_stream;
- const size_t num_streams = params_.ss.streams.size();
+ "Local Preview", params_.video[0].width, params_.video[0].height));
- if (selected_stream_id == num_streams) {
- for (size_t stream_id = 0; stream_id < num_streams; ++stream_id) {
+ SetupVideo(send_transport.get(), recv_transport.get());
+ video_send_configs_[0].pre_encode_callback = local_preview.get();
+
+ size_t num_streams_processed = 0;
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ const size_t selected_stream_id = params_.ss[video_idx].selected_stream;
+ const size_t num_streams = params_.ss[video_idx].streams.size();
+ if (selected_stream_id == num_streams) {
+ for (size_t stream_id = 0; stream_id < num_streams; ++stream_id) {
+ std::ostringstream oss;
+ oss << "Loopback Video #" << video_idx << " - Stream #"
+ << static_cast<int>(stream_id);
+ loopback_renderers.emplace_back(test::VideoRenderer::Create(
+ oss.str().c_str(),
+ params_.ss[video_idx].streams[stream_id].width,
+ params_.ss[video_idx].streams[stream_id].height));
+ video_receive_configs_[stream_id + num_streams_processed].renderer =
+ loopback_renderers.back().get();
+ if (params_.audio.enabled && params_.audio.sync_video)
+ video_receive_configs_[stream_id + num_streams_processed]
+ .sync_group = kSyncGroup;
+ }
+ } else {
std::ostringstream oss;
- oss << "Loopback Video - Stream #" << static_cast<int>(stream_id);
+ oss << "Loopback Video #" << video_idx;
loopback_renderers.emplace_back(test::VideoRenderer::Create(
- oss.str().c_str(), params_.ss.streams[stream_id].width,
- params_.ss.streams[stream_id].height));
- }
- } else {
- loopback_renderers.emplace_back(test::VideoRenderer::Create(
- "Loopback Video", params_.ss.streams[selected_stream_id].width,
- params_.ss.streams[selected_stream_id].height));
- }
-
- SetupVideo(send_transport.get(), recv_transport.get());
-
- video_send_config_.pre_encode_callback = local_preview.get();
- if (selected_stream_id == num_streams) {
- for (size_t stream_id = 0; stream_id < num_streams; ++stream_id) {
- video_receive_configs_[stream_id].renderer =
- loopback_renderers[stream_id].get();
+ oss.str().c_str(),
+ params_.ss[video_idx].streams[selected_stream_id].width,
+ params_.ss[video_idx].streams[selected_stream_id].height));
+ video_receive_configs_[selected_stream_id + num_streams_processed]
+ .renderer = loopback_renderers.back().get();
if (params_.audio.enabled && params_.audio.sync_video)
- video_receive_configs_[stream_id].sync_group = kSyncGroup;
+ video_receive_configs_[num_streams_processed + selected_stream_id]
+ .sync_group = kSyncGroup;
}
- } else {
- video_receive_configs_[selected_stream_id].renderer =
- loopback_renderers.back().get();
- if (params_.audio.enabled && params_.audio.sync_video)
- video_receive_configs_[selected_stream_id].sync_group = kSyncGroup;
+ num_streams_processed += num_streams;
}
-
- SetupScreenshareOrSVC();
-
CreateFlexfecStreams();
CreateVideoStreams();
- CreateCapturer();
- video_send_stream_->SetSource(video_capturer_.get(),
- degradation_preference_);
+ CreateCapturers();
+ for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
+ video_send_streams_[video_idx]->SetSource(
+ video_capturers_[video_idx].get(), degradation_preference_);
+ }
}
if (params_.audio.enabled) {
- SetupAudio(voe.send_channel_id, voe.receive_channel_id,
- send_transport.get(), &audio_receive_stream);
+ SetupAudio(send_transport.get(), &audio_receive_stream);
}
for (VideoReceiveStream* receive_stream : video_receive_streams_)
StartEncodedFrameLogs(receive_stream);
- StartEncodedFrameLogs(video_send_stream_);
+ StartEncodedFrameLogs(video_send_streams_[0]);
// Start sending and receiving video.
- if (params_.video.enabled) {
+ if (params_.video[0].enabled) {
for (VideoReceiveStream* video_receive_stream : video_receive_streams_)
video_receive_stream->Start();
-
- video_send_stream_->Start();
- video_capturer_->Start();
+ for (VideoSendStream* video_send_stream : video_send_streams_)
+ video_send_stream->Start();
+ for (auto& video_capturer : video_capturers_)
+ video_capturer->Start();
}
if (params_.audio.enabled) {
// Start receiving audio.
audio_receive_stream->Start();
- EXPECT_EQ(0, voe.base->StartPlayout(voe.receive_channel_id));
// Start sending audio.
audio_send_stream_->Start();
- EXPECT_EQ(0, voe.base->StartSend(voe.send_channel_id));
}
});
@@ -2106,42 +2150,25 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
task_queue_.SendTask([&]() {
if (params_.audio.enabled) {
// Stop sending audio.
- EXPECT_EQ(0, voe.base->StopSend(voe.send_channel_id));
audio_send_stream_->Stop();
// Stop receiving audio.
- EXPECT_EQ(0, voe.base->StopPlayout(voe.receive_channel_id));
audio_receive_stream->Stop();
- sender_call_->DestroyAudioSendStream(audio_send_stream_);
- receiver_call_->DestroyAudioReceiveStream(audio_receive_stream);
}
// Stop receiving and sending video.
- if (params_.video.enabled) {
- video_capturer_->Stop();
- video_send_stream_->Stop();
- for (FlexfecReceiveStream* flexfec_receive_stream :
- flexfec_receive_streams_) {
- for (VideoReceiveStream* video_receive_stream :
- video_receive_streams_) {
- video_receive_stream->RemoveSecondarySink(flexfec_receive_stream);
- }
- receiver_call_->DestroyFlexfecReceiveStream(flexfec_receive_stream);
- }
- for (VideoReceiveStream* receive_stream : video_receive_streams_) {
- receive_stream->Stop();
- receiver_call_->DestroyVideoReceiveStream(receive_stream);
- }
- sender_call_->DestroyVideoSendStream(video_send_stream_);
+ if (params_.video[0].enabled) {
+ for (auto& video_capturer : video_capturers_)
+ video_capturer->Stop();
+ for (VideoSendStream* video_send_stream : video_send_streams_)
+ video_send_stream->Stop();
+ DestroyStreams();
}
- video_capturer_.reset();
+ video_capturers_.clear();
send_transport.reset();
recv_transport.reset();
- if (params_.audio.enabled)
- DestroyVoiceEngine(&voe);
-
local_preview.reset();
loopback_renderers.clear();