
as described in https://www.rfc-editor.org/rfc/rfc8843#name-payload-type-pt-value-reuse ... all codecs associated with the payload type number MUST share an identical codec configuration See also https://github.com/w3c/webrtc-stats/issues/664 Measure how much this would break in UMA first BUG=webrtc:14420,webrtc:12716 Change-Id: Iafdc70248aa22bc37c15cc88a0c244398cb58176 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/273881 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Philipp Hancke <phancke@microsoft.com> Cr-Commit-Position: refs/heads/main@{#38759}
242 lines
8.2 KiB
C++
242 lines
8.2 KiB
C++
/*
|
|
* Copyright 2017 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 <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "api/audio/audio_mixer.h"
|
|
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
|
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
|
#include "api/create_peerconnection_factory.h"
|
|
#include "api/media_types.h"
|
|
#include "api/peer_connection_interface.h"
|
|
#include "api/rtp_transceiver_interface.h"
|
|
#include "api/scoped_refptr.h"
|
|
#include "api/video_codecs/builtin_video_decoder_factory.h"
|
|
#include "api/video_codecs/builtin_video_encoder_factory.h"
|
|
#include "modules/audio_device/include/audio_device.h"
|
|
#include "modules/audio_processing/include/audio_processing.h"
|
|
#include "p2p/base/port_allocator.h"
|
|
#include "pc/peer_connection_wrapper.h"
|
|
#include "pc/test/fake_audio_capture_module.h"
|
|
#include "pc/test/mock_peer_connection_observers.h"
|
|
#include "rtc_base/rtc_certificate_generator.h"
|
|
#include "rtc_base/thread.h"
|
|
#include "system_wrappers/include/metrics.h"
|
|
#include "test/gtest.h"
|
|
|
|
// This file contains unit tests that relate to the behavior of the
|
|
// SdpOfferAnswer module.
|
|
// Tests are writen as integration tests with PeerConnection, since the
|
|
// behaviors are still linked so closely that it is hard to test them in
|
|
// isolation.
|
|
|
|
namespace webrtc {
|
|
|
|
using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
|
|
|
|
namespace {
|
|
|
|
std::unique_ptr<rtc::Thread> CreateAndStartThread() {
|
|
auto thread = rtc::Thread::Create();
|
|
thread->Start();
|
|
return thread;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class SdpOfferAnswerTest : public ::testing::Test {
|
|
public:
|
|
SdpOfferAnswerTest()
|
|
// Note: We use a PeerConnectionFactory with a distinct
|
|
// signaling thread, so that thread handling can be tested.
|
|
: signaling_thread_(CreateAndStartThread()),
|
|
pc_factory_(
|
|
CreatePeerConnectionFactory(nullptr,
|
|
nullptr,
|
|
signaling_thread_.get(),
|
|
FakeAudioCaptureModule::Create(),
|
|
CreateBuiltinAudioEncoderFactory(),
|
|
CreateBuiltinAudioDecoderFactory(),
|
|
CreateBuiltinVideoEncoderFactory(),
|
|
CreateBuiltinVideoDecoderFactory(),
|
|
nullptr /* audio_mixer */,
|
|
nullptr /* audio_processing */)) {
|
|
webrtc::metrics::Reset();
|
|
}
|
|
|
|
std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection() {
|
|
RTCConfiguration config;
|
|
config.sdp_semantics = SdpSemantics::kUnifiedPlan;
|
|
return CreatePeerConnection(config);
|
|
}
|
|
|
|
std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
|
|
const RTCConfiguration& config) {
|
|
auto observer = std::make_unique<MockPeerConnectionObserver>();
|
|
auto result = pc_factory_->CreatePeerConnectionOrError(
|
|
config, PeerConnectionDependencies(observer.get()));
|
|
EXPECT_TRUE(result.ok());
|
|
observer->SetPeerConnectionInterface(result.value().get());
|
|
return std::make_unique<PeerConnectionWrapper>(
|
|
pc_factory_, result.MoveValue(), std::move(observer));
|
|
}
|
|
|
|
protected:
|
|
std::unique_ptr<rtc::Thread> signaling_thread_;
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
|
|
|
|
private:
|
|
rtc::AutoThread main_thread_;
|
|
};
|
|
|
|
TEST_F(SdpOfferAnswerTest, OnTrackReturnsProxiedObject) {
|
|
auto caller = CreatePeerConnection();
|
|
auto callee = CreatePeerConnection();
|
|
|
|
auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
|
|
|
|
ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
|
|
// Verify that caller->observer->OnTrack() has been called with a
|
|
// proxied transceiver object.
|
|
ASSERT_EQ(callee->observer()->on_track_transceivers_.size(), 1u);
|
|
auto transceiver = callee->observer()->on_track_transceivers_[0];
|
|
// Since the signaling thread is not the current thread,
|
|
// this will DCHECK if the transceiver is not proxied.
|
|
transceiver->stopped();
|
|
}
|
|
|
|
TEST_F(SdpOfferAnswerTest, BundleRejectsCodecCollisionsAudioVideo) {
|
|
auto pc = CreatePeerConnection();
|
|
std::string sdp =
|
|
"v=0\r\n"
|
|
"o=- 0 3 IN IP4 127.0.0.1\r\n"
|
|
"s=-\r\n"
|
|
"t=0 0\r\n"
|
|
"a=group:BUNDLE 0 1\r\n"
|
|
"a=fingerprint:sha-1 "
|
|
"4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
|
|
"a=setup:actpass\r\n"
|
|
"a=ice-ufrag:ETEn\r\n"
|
|
"a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
|
|
"m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n"
|
|
"c=IN IP4 0.0.0.0\r\n"
|
|
"a=rtcp-mux\r\n"
|
|
"a=sendonly\r\n"
|
|
"a=mid:0\r\n"
|
|
"a=rtpmap:111 opus/48000/2\r\n"
|
|
"m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
|
|
"c=IN IP4 0.0.0.0\r\n"
|
|
"a=rtcp-mux\r\n"
|
|
"a=sendonly\r\n"
|
|
"a=mid:1\r\n"
|
|
"a=rtpmap:111 H264/90000\r\n"
|
|
"a=fmtp:111 "
|
|
"level-asymmetry-allowed=1;packetization-mode=0;profile-level-id="
|
|
"42e01f\r\n";
|
|
|
|
auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
|
|
ASSERT_NE(desc, nullptr);
|
|
RTCError error;
|
|
pc->SetRemoteDescription(std::move(desc), &error);
|
|
EXPECT_TRUE(error.ok());
|
|
EXPECT_METRIC_EQ(
|
|
1, webrtc::metrics::NumEvents(
|
|
"WebRTC.PeerConnection.ValidBundledPayloadTypes", false));
|
|
}
|
|
|
|
TEST_F(SdpOfferAnswerTest, BundleRejectsCodecCollisionsVideoFmtp) {
|
|
auto pc = CreatePeerConnection();
|
|
std::string sdp =
|
|
"v=0\r\n"
|
|
"o=- 0 3 IN IP4 127.0.0.1\r\n"
|
|
"s=-\r\n"
|
|
"t=0 0\r\n"
|
|
"a=group:BUNDLE 0 1\r\n"
|
|
"a=fingerprint:sha-1 "
|
|
"4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
|
|
"a=setup:actpass\r\n"
|
|
"a=ice-ufrag:ETEn\r\n"
|
|
"a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
|
|
"m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
|
|
"c=IN IP4 0.0.0.0\r\n"
|
|
"a=rtcp-mux\r\n"
|
|
"a=sendonly\r\n"
|
|
"a=mid:0\r\n"
|
|
"a=rtpmap:111 H264/90000\r\n"
|
|
"a=fmtp:111 "
|
|
"level-asymmetry-allowed=1;packetization-mode=0;profile-level-id="
|
|
"42e01f\r\n"
|
|
"m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
|
|
"c=IN IP4 0.0.0.0\r\n"
|
|
"a=rtcp-mux\r\n"
|
|
"a=sendonly\r\n"
|
|
"a=mid:1\r\n"
|
|
"a=rtpmap:111 H264/90000\r\n"
|
|
"a=fmtp:111 "
|
|
"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id="
|
|
"42e01f\r\n";
|
|
|
|
auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
|
|
ASSERT_NE(desc, nullptr);
|
|
RTCError error;
|
|
pc->SetRemoteDescription(std::move(desc), &error);
|
|
EXPECT_TRUE(error.ok());
|
|
EXPECT_METRIC_EQ(
|
|
1, webrtc::metrics::NumEvents(
|
|
"WebRTC.PeerConnection.ValidBundledPayloadTypes", false));
|
|
}
|
|
|
|
TEST_F(SdpOfferAnswerTest, BundleCodecCollisionInDifferentBundlesAllowed) {
|
|
auto pc = CreatePeerConnection();
|
|
std::string sdp =
|
|
"v=0\r\n"
|
|
"o=- 0 3 IN IP4 127.0.0.1\r\n"
|
|
"s=-\r\n"
|
|
"t=0 0\r\n"
|
|
"a=group:BUNDLE 0\r\n"
|
|
"a=group:BUNDLE 1\r\n"
|
|
"a=fingerprint:sha-1 "
|
|
"4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
|
|
"a=setup:actpass\r\n"
|
|
"a=ice-ufrag:ETEn\r\n"
|
|
"a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
|
|
"m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
|
|
"c=IN IP4 0.0.0.0\r\n"
|
|
"a=rtcp-mux\r\n"
|
|
"a=sendonly\r\n"
|
|
"a=mid:0\r\n"
|
|
"a=rtpmap:111 H264/90000\r\n"
|
|
"a=fmtp:111 "
|
|
"level-asymmetry-allowed=1;packetization-mode=0;profile-level-id="
|
|
"42e01f\r\n"
|
|
"m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
|
|
"c=IN IP4 0.0.0.0\r\n"
|
|
"a=rtcp-mux\r\n"
|
|
"a=sendonly\r\n"
|
|
"a=mid:1\r\n"
|
|
"a=rtpmap:111 H264/90000\r\n"
|
|
"a=fmtp:111 "
|
|
"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id="
|
|
"42e01f\r\n";
|
|
|
|
auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
|
|
ASSERT_NE(desc, nullptr);
|
|
RTCError error;
|
|
pc->SetRemoteDescription(std::move(desc), &error);
|
|
EXPECT_TRUE(error.ok());
|
|
EXPECT_METRIC_EQ(
|
|
0, webrtc::metrics::NumEvents(
|
|
"WebRTC.PeerConnection.ValidBundledPayloadTypes", false));
|
|
}
|
|
|
|
} // namespace webrtc
|