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:
@ -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",
|
||||
|
||||
@ -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",
|
||||
],
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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()));
|
||||
|
||||
@ -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<
|
||||
|
||||
84
test/pc/e2e/sdp/sdp_changer.cc
Normal file
84
test/pc/e2e/sdp/sdp_changer.cc
Normal 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
|
||||
46
test/pc/e2e/sdp/sdp_changer.h
Normal file
46
test/pc/e2e/sdp/sdp_changer.h
Normal 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_
|
||||
Reference in New Issue
Block a user