Add support of specifying concrete codec for video stream

Bug: webrtc:10138
Change-Id: I074bfccfa5c8f619ea7fa17d6ca99f9b4cbb18b3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/123386
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27864}
This commit is contained in:
Artem Titov
2019-05-07 11:56:44 +02:00
committed by Commit Bot
parent 237272ef38
commit f65a89b7f7
9 changed files with 198 additions and 4 deletions

View File

@ -268,6 +268,7 @@ rtc_source_set("peer_connection_quality_test_fixture_api") {
":simulated_network_api",
":video_quality_analyzer_api",
"../logging:rtc_event_log_api",
"../media:rtc_media_base",
"../rtc_base:rtc_base",
"transport:network_control",
"units:time_delta",

View File

@ -24,5 +24,6 @@ specific_include_rules = {
"+rtc_base/rtc_certificate_generator.h",
"+rtc_base/ssl_certificate.h",
"+rtc_base/thread.h",
"+media/base/media_constants.h",
],
}

View File

@ -10,6 +10,7 @@
#ifndef API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_
#define API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
@ -30,6 +31,7 @@
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "logging/rtc_event_log/rtc_event_log_factory_interface.h"
#include "media/base/media_constants.h"
#include "rtc_base/network.h"
#include "rtc_base/rtc_certificate_generator.h"
#include "rtc_base/ssl_certificate.h"
@ -184,6 +186,21 @@ class PeerConnectionE2EQualityTestFixture {
// it will be shut downed.
TimeDelta run_duration;
// Next two fields are used to specify concrete video codec, that should be
// used in the test. Video code will be negotiated in SDP during offer/
// answer exchange.
// Video codec name. You can find valid names in
// media/base/media_constants.h
std::string video_codec_name = cricket::kVp8CodecName;
// Map of parameters, that have to be specified on SDP codec. Each parameter
// is described by key and value. Codec parameters will match the specified
// map if and only if for each key from |video_codec_required_params| there
// will be a parameter with name equal to this key and parameter value will
// be equal to the value from |video_codec_required_params| for this key.
// If empty then only name will be used to match the codec.
std::map<std::string, std::string> video_codec_required_params;
bool use_ulp_fec = false;
bool use_flex_fec = false;
// Specifies how much video encoder target bitrate should be different than
// target bitrate, provided by WebRTC stack. Must be greater then 0. Can be
// used to emulate overshooting of video encoders. This multiplier will

View File

@ -249,6 +249,7 @@ if (rtc_include_tests) {
":default_audio_quality_analyzer",
":default_video_quality_analyzer",
":peer_connection_quality_test_params",
":sdp_changer",
":single_process_encoded_image_data_injector",
":stats_poller",
":test_peer",
@ -265,6 +266,7 @@ if (rtc_include_tests) {
"../../../logging:rtc_event_log_api",
"../../../logging:rtc_event_log_impl_output",
"../../../pc:pc_test_utils",
"../../../pc:peerconnection",
"../../../rtc_base",
"../../../rtc_base:gunit_helpers",
"../../../rtc_base:rtc_base_approved",
@ -476,3 +478,17 @@ rtc_source_set("network_quality_metrics_reporter") {
"../../../rtc_base:rtc_event",
]
}
rtc_source_set("sdp_changer") {
testonly = true
sources = [
"sdp/sdp_changer.cc",
"sdp/sdp_changer.h",
]
deps = [
"../../../api:libjingle_peerconnection_api",
"../../../media:rtc_media_base",
"../../../rtc_base:stringutils",
"//third_party/abseil-cpp/absl/strings:strings",
]
}

View File

@ -119,6 +119,10 @@ TEST(PeerConnectionE2EQualityTestSmokeTest, MAYBE_RunWithEmulatedNetwork) {
bob_network));
RunParams run_params(TimeDelta::seconds(7));
run_params.video_codec_name = cricket::kVp9CodecName;
run_params.video_codec_required_params = {{"profile-id", "0"}};
run_params.use_flex_fec = true;
run_params.use_ulp_fec = true;
run_params.video_encoder_bitrate_multiplier = 1.1;
fixture->Run(run_params);

View File

@ -22,6 +22,7 @@
#include "api/units/time_delta.h"
#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "pc/sdp_utils.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/bind.h"
#include "rtc_base/gunit.h"
@ -29,6 +30,7 @@
#include "system_wrappers/include/cpu_info.h"
#include "test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h"
#include "test/pc/e2e/sdp/sdp_changer.h"
#include "test/pc/e2e/stats_poller.h"
#include "test/testsupport/file_utils.h"
@ -318,8 +320,8 @@ void PeerConnectionE2EQualityTest::Run(
// Setup call.
signaling_thread->Invoke<void>(
RTC_FROM_HERE,
rtc::Bind(&PeerConnectionE2EQualityTest::SetupCallOnSignalingThread,
this));
rtc::Bind(&PeerConnectionE2EQualityTest::SetupCallOnSignalingThread, this,
run_params));
{
rtc::CritScope crit(&lock_);
start_time_ = Now();
@ -513,7 +515,8 @@ void PeerConnectionE2EQualityTest::OnTrackCallback(
output_video_sinks_.push_back(std::move(video_sink));
}
void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread() {
void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread(
const RunParams& run_params) {
// We need receive-only transceivers for Bob's media stream, so there will
// be media section in SDP for that streams in Alice's offer, because it is
// forbidden to add new media sections in answer in Unified Plan.
@ -534,6 +537,9 @@ void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread() {
alice_video_sources_ = MaybeAddMedia(alice_.get());
bob_video_sources_ = MaybeAddMedia(bob_.get());
SetPeerCodecPreferences(alice_.get(), run_params);
SetPeerCodecPreferences(bob_.get(), run_params);
SetupCall();
}
@ -631,6 +637,24 @@ void PeerConnectionE2EQualityTest::MaybeAddAudio(TestPeer* peer) {
peer->AddTrack(track, {*audio_config.stream_label});
}
void PeerConnectionE2EQualityTest::SetPeerCodecPreferences(
TestPeer* peer,
const RunParams& run_params) {
std::vector<RtpCodecCapability> video_capabilities = FilterCodecCapabilities(
run_params.video_codec_name, run_params.video_codec_required_params,
run_params.use_ulp_fec, run_params.use_flex_fec,
peer->pc_factory()
->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
.codecs);
// Set codecs for transceivers
for (auto transceiver : peer->pc()->GetTransceivers()) {
if (transceiver->media_type() == cricket::MediaType::MEDIA_TYPE_VIDEO) {
transceiver->SetCodecPreferences(video_capabilities);
}
}
}
void PeerConnectionE2EQualityTest::SetupCall() {
// Connect peers.
ASSERT_TRUE(alice_->ExchangeOfferAnswerWith(bob_.get()));

View File

@ -211,7 +211,7 @@ class PeerConnectionE2EQualityTest
void OnTrackCallback(rtc::scoped_refptr<RtpTransceiverInterface> transceiver,
std::vector<VideoConfig> remote_video_configs);
// Have to be run on the signaling thread.
void SetupCallOnSignalingThread();
void SetupCallOnSignalingThread(const RunParams& run_params);
void TearDownCallOnSignalingThread();
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
MaybeAddMedia(TestPeer* peer);
@ -220,6 +220,7 @@ class PeerConnectionE2EQualityTest
std::unique_ptr<test::FrameGenerator> CreateFrameGenerator(
const VideoConfig& video_config);
void MaybeAddAudio(TestPeer* peer);
void SetPeerCodecPreferences(TestPeer* peer, const RunParams& run_params);
void SetupCall();
void StartVideo(
const std::vector<

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "test/pc/e2e/sdp/sdp_changer.h"
#include <utility>
#include "media/base/media_constants.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace webrtc_pc_e2e {
namespace {
std::string CodecRequiredParamsToString(
const std::map<std::string, std::string>& codec_required_params) {
rtc::StringBuilder out;
for (auto entry : codec_required_params) {
out << entry.first << "=" << entry.second << ";";
}
return out.str();
}
} // namespace
std::vector<RtpCodecCapability> FilterCodecCapabilities(
absl::string_view codec_name,
const std::map<std::string, std::string>& codec_required_params,
bool ulpfec,
bool flexfec,
std::vector<RtpCodecCapability> supported_codecs) {
std::vector<RtpCodecCapability> output_codecs;
// Find main requested codecs among supported and add them to output.
for (auto& codec : supported_codecs) {
if (codec.name != codec_name) {
continue;
}
bool parameters_matched = true;
for (auto item : codec_required_params) {
auto it = codec.parameters.find(item.first);
if (it == codec.parameters.end()) {
parameters_matched = false;
break;
}
if (item.second != it->second) {
parameters_matched = false;
break;
}
}
if (parameters_matched) {
output_codecs.push_back(codec);
}
}
RTC_CHECK_GT(output_codecs.size(), 0)
<< "Codec with name=" << codec_name << " and params {"
<< CodecRequiredParamsToString(codec_required_params)
<< "} is unsupported for this peer connection";
// Add required FEC and RTX codecs to output.
for (auto& codec : supported_codecs) {
if (codec.name == cricket::kRtxCodecName) {
output_codecs.push_back(codec);
} else if (codec.name == cricket::kFlexfecCodecName && flexfec) {
output_codecs.push_back(codec);
} else if ((codec.name == cricket::kRedCodecName ||
codec.name == cricket::kUlpfecCodecName) &&
ulpfec) {
// Red and ulpfec should be enabled or disabled together.
output_codecs.push_back(codec);
}
}
return output_codecs;
}
} // namespace webrtc_pc_e2e
} // namespace webrtc

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef TEST_PC_E2E_SDP_SDP_CHANGER_H_
#define TEST_PC_E2E_SDP_SDP_CHANGER_H_
#include <map>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/rtp_parameters.h"
namespace webrtc {
namespace webrtc_pc_e2e {
// Creates list of capabilities, which can be set on RtpTransceiverInterface via
// RtpTransceiverInterface::SetCodecPreferences(...) to negotiate use of codec
// from list of |supported_codecs| with specified |codec_name| and parameters,
// which contains all of |codec_required_params|. If flags |ulpfec| or |flexfec|
// set to true corresponding FEC codec will be added. FEC and RTX codecs will be
// added after required codecs.
//
// All codecs will be added only if they exists in the list of
// |supported_codecs|. If multiple codecs from this list will have |codec_name|
// and |codec_required_params|, then all of them will be added to the output
// vector and they will be added in the same order, as they were in
// |supported_codecs|.
std::vector<RtpCodecCapability> FilterCodecCapabilities(
absl::string_view codec_name,
const std::map<std::string, std::string>& codec_required_params,
bool ulpfec,
bool flexfec,
std::vector<RtpCodecCapability> supported_codecs);
} // namespace webrtc_pc_e2e
} // namespace webrtc
#endif // TEST_PC_E2E_SDP_SDP_CHANGER_H_