mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00

This is a reland of commit 1cce1d7ddc
after updating the WPT that broke on Mac.
Original change's description:
> Make setCodecPreferences only look at receive codecs
>
> which is what is noted in JSEP:
> https://www.rfc-editor.org/rfc/rfc8829.html#name-setcodecpreferences
>
> Some W3C spec modifications are required since the W3C specification
> currently takes into account send codecs as well.
>
> Spec issue:
> https://github.com/w3c/webrtc-pc/issues/2888
> Spec PR:
> https://github.com/w3c/webrtc-pc/pull/2926
>
> setCodecPreferences continues to modify the codecs in an offer.
>
> Also rename RtpSender::SetCodecPreferences to RtpSender::SetSendCodecs for consistent semantics.
>
> BUG=webrtc:15396
>
> Change-Id: I1e8fbe77cb2670575578a777ed1336567a1e4031
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/328780
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Philipp Hancke <phancke@microsoft.com>
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#41719}
Bug: webrtc:15396
Change-Id: I0c7b17f00de02286f176b500460e17980b83b35b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/339541
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41807}
284 lines
11 KiB
C++
284 lines
11 KiB
C++
/*
|
|
* Copyright 2022 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.
|
|
*/
|
|
|
|
// Integration tests for PeerConnection.
|
|
// These tests exercise a full stack for the SVC extension.
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <functional>
|
|
#include <vector>
|
|
|
|
#include "absl/strings/match.h"
|
|
#include "api/rtc_error.h"
|
|
#include "api/rtp_parameters.h"
|
|
#include "api/rtp_transceiver_interface.h"
|
|
#include "api/scoped_refptr.h"
|
|
#include "pc/test/integration_test_helpers.h"
|
|
#include "rtc_base/gunit.h"
|
|
#include "rtc_base/helpers.h"
|
|
#include "test/gtest.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
class PeerConnectionSVCIntegrationTest
|
|
: public PeerConnectionIntegrationBaseTest {
|
|
protected:
|
|
PeerConnectionSVCIntegrationTest()
|
|
: PeerConnectionIntegrationBaseTest(SdpSemantics::kUnifiedPlan) {}
|
|
|
|
RTCError SetCodecPreferences(
|
|
rtc::scoped_refptr<RtpTransceiverInterface> transceiver,
|
|
absl::string_view codec_name) {
|
|
RtpCapabilities capabilities =
|
|
caller()->pc_factory()->GetRtpReceiverCapabilities(
|
|
cricket::MEDIA_TYPE_VIDEO);
|
|
std::vector<RtpCodecCapability> codecs;
|
|
for (const RtpCodecCapability& codec_capability : capabilities.codecs) {
|
|
if (codec_capability.name == codec_name)
|
|
codecs.push_back(codec_capability);
|
|
}
|
|
return transceiver->SetCodecPreferences(codecs);
|
|
}
|
|
};
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest, AddTransceiverAcceptsL1T1) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
encoding_parameters.scalability_mode = "L1T1";
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
EXPECT_TRUE(transceiver_or_error.ok());
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest, AddTransceiverAcceptsL3T3) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
encoding_parameters.scalability_mode = "L3T3";
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
EXPECT_TRUE(transceiver_or_error.ok());
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest,
|
|
AddTransceiverRejectsUnknownScalabilityMode) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
encoding_parameters.scalability_mode = "FOOBAR";
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
EXPECT_FALSE(transceiver_or_error.ok());
|
|
EXPECT_EQ(transceiver_or_error.error().type(),
|
|
RTCErrorType::UNSUPPORTED_OPERATION);
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest, SetParametersAcceptsL1T3WithVP8) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
|
|
RtpCapabilities capabilities =
|
|
caller()->pc_factory()->GetRtpReceiverCapabilities(
|
|
cricket::MEDIA_TYPE_VIDEO);
|
|
std::vector<RtpCodecCapability> vp8_codec;
|
|
for (const RtpCodecCapability& codec_capability : capabilities.codecs) {
|
|
if (codec_capability.name == cricket::kVp8CodecName)
|
|
vp8_codec.push_back(codec_capability);
|
|
}
|
|
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
ASSERT_TRUE(transceiver_or_error.ok());
|
|
auto transceiver = transceiver_or_error.MoveValue();
|
|
EXPECT_TRUE(transceiver->SetCodecPreferences(vp8_codec).ok());
|
|
|
|
RtpParameters parameters = transceiver->sender()->GetParameters();
|
|
ASSERT_EQ(parameters.encodings.size(), 1u);
|
|
parameters.encodings[0].scalability_mode = "L1T3";
|
|
auto result = transceiver->sender()->SetParameters(parameters);
|
|
EXPECT_TRUE(result.ok());
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest,
|
|
SetParametersAcceptsL1T3WithVP8AfterNegotiation) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
ASSERT_TRUE(transceiver_or_error.ok());
|
|
auto transceiver = transceiver_or_error.MoveValue();
|
|
EXPECT_TRUE(SetCodecPreferences(transceiver, cricket::kVp8CodecName).ok());
|
|
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
RtpParameters parameters = transceiver->sender()->GetParameters();
|
|
ASSERT_EQ(parameters.encodings.size(), 1u);
|
|
parameters.encodings[0].scalability_mode = "L1T3";
|
|
auto result = transceiver->sender()->SetParameters(parameters);
|
|
EXPECT_TRUE(result.ok());
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest,
|
|
SetParametersAcceptsL3T3WithVP9AfterNegotiation) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
ASSERT_TRUE(transceiver_or_error.ok());
|
|
auto transceiver = transceiver_or_error.MoveValue();
|
|
EXPECT_TRUE(SetCodecPreferences(transceiver, cricket::kVp9CodecName).ok());
|
|
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
RtpParameters parameters = transceiver->sender()->GetParameters();
|
|
ASSERT_EQ(parameters.encodings.size(), 1u);
|
|
parameters.encodings[0].scalability_mode = "L3T3";
|
|
auto result = transceiver->sender()->SetParameters(parameters);
|
|
EXPECT_TRUE(result.ok());
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest,
|
|
SetParametersRejectsL3T3WithVP8AfterNegotiation) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
ASSERT_TRUE(transceiver_or_error.ok());
|
|
auto transceiver = transceiver_or_error.MoveValue();
|
|
EXPECT_TRUE(SetCodecPreferences(transceiver, cricket::kVp8CodecName).ok());
|
|
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
RtpParameters parameters = transceiver->sender()->GetParameters();
|
|
ASSERT_EQ(parameters.encodings.size(), 1u);
|
|
parameters.encodings[0].scalability_mode = "L3T3";
|
|
auto result = transceiver->sender()->SetParameters(parameters);
|
|
EXPECT_FALSE(result.ok());
|
|
EXPECT_EQ(result.type(), RTCErrorType::INVALID_MODIFICATION);
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest,
|
|
SetParametersRejectsInvalidModeWithVP9AfterNegotiation) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
ASSERT_TRUE(transceiver_or_error.ok());
|
|
auto transceiver = transceiver_or_error.MoveValue();
|
|
EXPECT_TRUE(SetCodecPreferences(transceiver, cricket::kVp9CodecName).ok());
|
|
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
RtpParameters parameters = transceiver->sender()->GetParameters();
|
|
ASSERT_EQ(parameters.encodings.size(), 1u);
|
|
parameters.encodings[0].scalability_mode = "FOOBAR";
|
|
auto result = transceiver->sender()->SetParameters(parameters);
|
|
EXPECT_FALSE(result.ok());
|
|
EXPECT_EQ(result.type(), RTCErrorType::INVALID_MODIFICATION);
|
|
}
|
|
|
|
TEST_F(PeerConnectionSVCIntegrationTest, FallbackToL1Tx) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
|
|
RtpTransceiverInit init;
|
|
RtpEncodingParameters encoding_parameters;
|
|
init.send_encodings.push_back(encoding_parameters);
|
|
auto transceiver_or_error =
|
|
caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack(), init);
|
|
ASSERT_TRUE(transceiver_or_error.ok());
|
|
auto caller_transceiver = transceiver_or_error.MoveValue();
|
|
|
|
RtpCapabilities capabilities =
|
|
caller()->pc_factory()->GetRtpReceiverCapabilities(
|
|
cricket::MEDIA_TYPE_VIDEO);
|
|
std::vector<RtpCodecCapability> send_codecs = capabilities.codecs;
|
|
// Only keep VP9 in the caller
|
|
send_codecs.erase(std::partition(send_codecs.begin(), send_codecs.end(),
|
|
[](const auto& codec) -> bool {
|
|
return codec.name ==
|
|
cricket::kVp9CodecName;
|
|
}),
|
|
send_codecs.end());
|
|
ASSERT_FALSE(send_codecs.empty());
|
|
caller_transceiver->SetCodecPreferences(send_codecs);
|
|
|
|
// L3T3 should be supported by VP9
|
|
RtpParameters parameters = caller_transceiver->sender()->GetParameters();
|
|
ASSERT_EQ(parameters.encodings.size(), 1u);
|
|
parameters.encodings[0].scalability_mode = "L3T3";
|
|
auto result = caller_transceiver->sender()->SetParameters(parameters);
|
|
EXPECT_TRUE(result.ok());
|
|
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
parameters = caller_transceiver->sender()->GetParameters();
|
|
ASSERT_TRUE(parameters.encodings[0].scalability_mode.has_value());
|
|
EXPECT_TRUE(
|
|
absl::StartsWith(*parameters.encodings[0].scalability_mode, "L3T3"));
|
|
|
|
// Keep only VP8 in the caller
|
|
send_codecs = capabilities.codecs;
|
|
send_codecs.erase(std::partition(send_codecs.begin(), send_codecs.end(),
|
|
[](const auto& codec) -> bool {
|
|
return codec.name ==
|
|
cricket::kVp8CodecName;
|
|
}),
|
|
send_codecs.end());
|
|
ASSERT_FALSE(send_codecs.empty());
|
|
caller_transceiver->SetCodecPreferences(send_codecs);
|
|
|
|
// Renegotiate to force the new codec list to be used
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
// Fallback should happen and L3T3 is not used anymore
|
|
parameters = caller_transceiver->sender()->GetParameters();
|
|
ASSERT_TRUE(parameters.encodings[0].scalability_mode.has_value());
|
|
EXPECT_TRUE(
|
|
absl::StartsWith(*parameters.encodings[0].scalability_mode, "L1T"));
|
|
}
|
|
} // namespace
|
|
|
|
} // namespace webrtc
|