xref: /aosp_15_r20/external/webrtc/pc/peer_connection_media_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker // This file contains tests that check the interaction between the
12*d9f75844SAndroid Build Coastguard Worker // PeerConnection and the underlying media engine, as well as tests that check
13*d9f75844SAndroid Build Coastguard Worker // the media-related aspects of SDP.
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
16*d9f75844SAndroid Build Coastguard Worker #include <functional>
17*d9f75844SAndroid Build Coastguard Worker #include <iterator>
18*d9f75844SAndroid Build Coastguard Worker #include <map>
19*d9f75844SAndroid Build Coastguard Worker #include <memory>
20*d9f75844SAndroid Build Coastguard Worker #include <set>
21*d9f75844SAndroid Build Coastguard Worker #include <string>
22*d9f75844SAndroid Build Coastguard Worker #include <tuple>
23*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
24*d9f75844SAndroid Build Coastguard Worker #include <utility>
25*d9f75844SAndroid Build Coastguard Worker #include <vector>
26*d9f75844SAndroid Build Coastguard Worker 
27*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
28*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/audio_options.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/call/call_factory_interface.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/jsep.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/media_types.h"
33*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h"
34*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_error.h"
35*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_event_log/rtc_event_log_factory.h"
36*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_event_log/rtc_event_log_factory_interface.h"
37*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
38*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_sender_interface.h"
39*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_transceiver_direction.h"
40*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_transceiver_interface.h"
41*d9f75844SAndroid Build Coastguard Worker #include "api/scoped_refptr.h"
42*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/default_task_queue_factory.h"
43*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_factory.h"
44*d9f75844SAndroid Build Coastguard Worker #include "media/base/codec.h"
45*d9f75844SAndroid Build Coastguard Worker #include "media/base/fake_media_engine.h"
46*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_constants.h"
47*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_engine.h"
48*d9f75844SAndroid Build Coastguard Worker #include "media/base/stream_params.h"
49*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/fake_port_allocator.h"
50*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
51*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port_allocator.h"
52*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_info.h"
53*d9f75844SAndroid Build Coastguard Worker #include "pc/media_session.h"
54*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection_wrapper.h"
55*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_media_utils.h"
56*d9f75844SAndroid Build Coastguard Worker #include "pc/session_description.h"
57*d9f75844SAndroid Build Coastguard Worker #include "pc/test/mock_peer_connection_observers.h"
58*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
59*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate_generator.h"
60*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
61*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
62*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
63*d9f75844SAndroid Build Coastguard Worker #include "pc/test/android_test_initializer.h"
64*d9f75844SAndroid Build Coastguard Worker #endif
65*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
66*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/virtual_socket_server.h"
67*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
70*d9f75844SAndroid Build Coastguard Worker 
71*d9f75844SAndroid Build Coastguard Worker using cricket::FakeMediaEngine;
72*d9f75844SAndroid Build Coastguard Worker using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
73*d9f75844SAndroid Build Coastguard Worker using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
74*d9f75844SAndroid Build Coastguard Worker using ::testing::Bool;
75*d9f75844SAndroid Build Coastguard Worker using ::testing::Combine;
76*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAre;
77*d9f75844SAndroid Build Coastguard Worker using ::testing::Values;
78*d9f75844SAndroid Build Coastguard Worker 
79*d9f75844SAndroid Build Coastguard Worker class PeerConnectionWrapperForMediaTest : public PeerConnectionWrapper {
80*d9f75844SAndroid Build Coastguard Worker  public:
81*d9f75844SAndroid Build Coastguard Worker   using PeerConnectionWrapper::PeerConnectionWrapper;
82*d9f75844SAndroid Build Coastguard Worker 
media_engine()83*d9f75844SAndroid Build Coastguard Worker   FakeMediaEngine* media_engine() { return media_engine_; }
set_media_engine(FakeMediaEngine * media_engine)84*d9f75844SAndroid Build Coastguard Worker   void set_media_engine(FakeMediaEngine* media_engine) {
85*d9f75844SAndroid Build Coastguard Worker     media_engine_ = media_engine;
86*d9f75844SAndroid Build Coastguard Worker   }
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker  private:
89*d9f75844SAndroid Build Coastguard Worker   FakeMediaEngine* media_engine_;
90*d9f75844SAndroid Build Coastguard Worker };
91*d9f75844SAndroid Build Coastguard Worker 
92*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaBaseTest : public ::testing::Test {
93*d9f75844SAndroid Build Coastguard Worker  protected:
94*d9f75844SAndroid Build Coastguard Worker   typedef std::unique_ptr<PeerConnectionWrapperForMediaTest> WrapperPtr;
95*d9f75844SAndroid Build Coastguard Worker 
PeerConnectionMediaBaseTest(SdpSemantics sdp_semantics)96*d9f75844SAndroid Build Coastguard Worker   explicit PeerConnectionMediaBaseTest(SdpSemantics sdp_semantics)
97*d9f75844SAndroid Build Coastguard Worker       : vss_(new rtc::VirtualSocketServer()),
98*d9f75844SAndroid Build Coastguard Worker         main_(vss_.get()),
99*d9f75844SAndroid Build Coastguard Worker         sdp_semantics_(sdp_semantics) {
100*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
101*d9f75844SAndroid Build Coastguard Worker     InitializeAndroidObjects();
102*d9f75844SAndroid Build Coastguard Worker #endif
103*d9f75844SAndroid Build Coastguard Worker   }
104*d9f75844SAndroid Build Coastguard Worker 
CreatePeerConnection()105*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnection() {
106*d9f75844SAndroid Build Coastguard Worker     return CreatePeerConnection(RTCConfiguration());
107*d9f75844SAndroid Build Coastguard Worker   }
108*d9f75844SAndroid Build Coastguard Worker 
CreatePeerConnection(const RTCConfiguration & config)109*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
110*d9f75844SAndroid Build Coastguard Worker     return CreatePeerConnection(config, std::make_unique<FakeMediaEngine>());
111*d9f75844SAndroid Build Coastguard Worker   }
112*d9f75844SAndroid Build Coastguard Worker 
CreatePeerConnection(std::unique_ptr<FakeMediaEngine> media_engine)113*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnection(
114*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<FakeMediaEngine> media_engine) {
115*d9f75844SAndroid Build Coastguard Worker     return CreatePeerConnection(RTCConfiguration(), std::move(media_engine));
116*d9f75844SAndroid Build Coastguard Worker   }
117*d9f75844SAndroid Build Coastguard Worker 
118*d9f75844SAndroid Build Coastguard Worker   // Creates PeerConnectionFactory and PeerConnection for given configuration.
CreatePeerConnection(const RTCConfiguration & config,std::unique_ptr<FakeMediaEngine> media_engine)119*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnection(
120*d9f75844SAndroid Build Coastguard Worker       const RTCConfiguration& config,
121*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<FakeMediaEngine> media_engine) {
122*d9f75844SAndroid Build Coastguard Worker     auto* media_engine_ptr = media_engine.get();
123*d9f75844SAndroid Build Coastguard Worker 
124*d9f75844SAndroid Build Coastguard Worker     PeerConnectionFactoryDependencies factory_dependencies;
125*d9f75844SAndroid Build Coastguard Worker 
126*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.network_thread = rtc::Thread::Current();
127*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.worker_thread = rtc::Thread::Current();
128*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.signaling_thread = rtc::Thread::Current();
129*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
130*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.media_engine = std::move(media_engine);
131*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.call_factory = CreateCallFactory();
132*d9f75844SAndroid Build Coastguard Worker     factory_dependencies.event_log_factory =
133*d9f75844SAndroid Build Coastguard Worker         std::make_unique<RtcEventLogFactory>(
134*d9f75844SAndroid Build Coastguard Worker             factory_dependencies.task_queue_factory.get());
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker     auto pc_factory =
137*d9f75844SAndroid Build Coastguard Worker         CreateModularPeerConnectionFactory(std::move(factory_dependencies));
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker     auto fake_port_allocator = std::make_unique<cricket::FakePortAllocator>(
140*d9f75844SAndroid Build Coastguard Worker         rtc::Thread::Current(),
141*d9f75844SAndroid Build Coastguard Worker         std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()));
142*d9f75844SAndroid Build Coastguard Worker     auto observer = std::make_unique<MockPeerConnectionObserver>();
143*d9f75844SAndroid Build Coastguard Worker     auto modified_config = config;
144*d9f75844SAndroid Build Coastguard Worker     modified_config.sdp_semantics = sdp_semantics_;
145*d9f75844SAndroid Build Coastguard Worker     PeerConnectionDependencies pc_dependencies(observer.get());
146*d9f75844SAndroid Build Coastguard Worker     pc_dependencies.allocator = std::move(fake_port_allocator);
147*d9f75844SAndroid Build Coastguard Worker     auto result = pc_factory->CreatePeerConnectionOrError(
148*d9f75844SAndroid Build Coastguard Worker         modified_config, std::move(pc_dependencies));
149*d9f75844SAndroid Build Coastguard Worker     if (!result.ok()) {
150*d9f75844SAndroid Build Coastguard Worker       return nullptr;
151*d9f75844SAndroid Build Coastguard Worker     }
152*d9f75844SAndroid Build Coastguard Worker 
153*d9f75844SAndroid Build Coastguard Worker     auto pc = result.MoveValue();
154*d9f75844SAndroid Build Coastguard Worker     observer->SetPeerConnectionInterface(pc.get());
155*d9f75844SAndroid Build Coastguard Worker     auto wrapper = std::make_unique<PeerConnectionWrapperForMediaTest>(
156*d9f75844SAndroid Build Coastguard Worker         pc_factory, pc, std::move(observer));
157*d9f75844SAndroid Build Coastguard Worker     wrapper->set_media_engine(media_engine_ptr);
158*d9f75844SAndroid Build Coastguard Worker     return wrapper;
159*d9f75844SAndroid Build Coastguard Worker   }
160*d9f75844SAndroid Build Coastguard Worker 
161*d9f75844SAndroid Build Coastguard Worker   // Accepts the same arguments as CreatePeerConnection and adds default audio
162*d9f75844SAndroid Build Coastguard Worker   // track (but no video).
163*d9f75844SAndroid Build Coastguard Worker   template <typename... Args>
CreatePeerConnectionWithAudio(Args &&...args)164*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnectionWithAudio(Args&&... args) {
165*d9f75844SAndroid Build Coastguard Worker     auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
166*d9f75844SAndroid Build Coastguard Worker     if (!wrapper) {
167*d9f75844SAndroid Build Coastguard Worker       return nullptr;
168*d9f75844SAndroid Build Coastguard Worker     }
169*d9f75844SAndroid Build Coastguard Worker     wrapper->AddAudioTrack("a");
170*d9f75844SAndroid Build Coastguard Worker     return wrapper;
171*d9f75844SAndroid Build Coastguard Worker   }
172*d9f75844SAndroid Build Coastguard Worker 
173*d9f75844SAndroid Build Coastguard Worker   // Accepts the same arguments as CreatePeerConnection and adds default video
174*d9f75844SAndroid Build Coastguard Worker   // track (but no audio).
175*d9f75844SAndroid Build Coastguard Worker   template <typename... Args>
CreatePeerConnectionWithVideo(Args &&...args)176*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnectionWithVideo(Args&&... args) {
177*d9f75844SAndroid Build Coastguard Worker     auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
178*d9f75844SAndroid Build Coastguard Worker     if (!wrapper) {
179*d9f75844SAndroid Build Coastguard Worker       return nullptr;
180*d9f75844SAndroid Build Coastguard Worker     }
181*d9f75844SAndroid Build Coastguard Worker     wrapper->AddVideoTrack("v");
182*d9f75844SAndroid Build Coastguard Worker     return wrapper;
183*d9f75844SAndroid Build Coastguard Worker   }
184*d9f75844SAndroid Build Coastguard Worker 
185*d9f75844SAndroid Build Coastguard Worker   // Accepts the same arguments as CreatePeerConnection and adds default audio
186*d9f75844SAndroid Build Coastguard Worker   // and video tracks.
187*d9f75844SAndroid Build Coastguard Worker   template <typename... Args>
CreatePeerConnectionWithAudioVideo(Args &&...args)188*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
189*d9f75844SAndroid Build Coastguard Worker     auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
190*d9f75844SAndroid Build Coastguard Worker     if (!wrapper) {
191*d9f75844SAndroid Build Coastguard Worker       return nullptr;
192*d9f75844SAndroid Build Coastguard Worker     }
193*d9f75844SAndroid Build Coastguard Worker     wrapper->AddAudioTrack("a");
194*d9f75844SAndroid Build Coastguard Worker     wrapper->AddVideoTrack("v");
195*d9f75844SAndroid Build Coastguard Worker     return wrapper;
196*d9f75844SAndroid Build Coastguard Worker   }
197*d9f75844SAndroid Build Coastguard Worker 
GetMediaContentDirection(const SessionDescriptionInterface * sdesc,cricket::MediaType media_type)198*d9f75844SAndroid Build Coastguard Worker   RtpTransceiverDirection GetMediaContentDirection(
199*d9f75844SAndroid Build Coastguard Worker       const SessionDescriptionInterface* sdesc,
200*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType media_type) {
201*d9f75844SAndroid Build Coastguard Worker     auto* content =
202*d9f75844SAndroid Build Coastguard Worker         cricket::GetFirstMediaContent(sdesc->description(), media_type);
203*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(content);
204*d9f75844SAndroid Build Coastguard Worker     return content->media_description()->direction();
205*d9f75844SAndroid Build Coastguard Worker   }
206*d9f75844SAndroid Build Coastguard Worker 
IsUnifiedPlan() const207*d9f75844SAndroid Build Coastguard Worker   bool IsUnifiedPlan() const {
208*d9f75844SAndroid Build Coastguard Worker     return sdp_semantics_ == SdpSemantics::kUnifiedPlan;
209*d9f75844SAndroid Build Coastguard Worker   }
210*d9f75844SAndroid Build Coastguard Worker 
211*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::VirtualSocketServer> vss_;
212*d9f75844SAndroid Build Coastguard Worker   rtc::AutoSocketServerThread main_;
213*d9f75844SAndroid Build Coastguard Worker   const SdpSemantics sdp_semantics_;
214*d9f75844SAndroid Build Coastguard Worker };
215*d9f75844SAndroid Build Coastguard Worker 
216*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaTest
217*d9f75844SAndroid Build Coastguard Worker     : public PeerConnectionMediaBaseTest,
218*d9f75844SAndroid Build Coastguard Worker       public ::testing::WithParamInterface<SdpSemantics> {
219*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionMediaTest()220*d9f75844SAndroid Build Coastguard Worker   PeerConnectionMediaTest() : PeerConnectionMediaBaseTest(GetParam()) {}
221*d9f75844SAndroid Build Coastguard Worker };
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaTestUnifiedPlan : public PeerConnectionMediaBaseTest {
224*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionMediaTestUnifiedPlan()225*d9f75844SAndroid Build Coastguard Worker   PeerConnectionMediaTestUnifiedPlan()
226*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionMediaBaseTest(SdpSemantics::kUnifiedPlan) {}
227*d9f75844SAndroid Build Coastguard Worker };
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaTestPlanB : public PeerConnectionMediaBaseTest {
230*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionMediaTestPlanB()231*d9f75844SAndroid Build Coastguard Worker   PeerConnectionMediaTestPlanB()
232*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionMediaBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
233*d9f75844SAndroid Build Coastguard Worker };
234*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,FailToSetRemoteDescriptionIfCreateMediaChannelFails)235*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
236*d9f75844SAndroid Build Coastguard Worker        FailToSetRemoteDescriptionIfCreateMediaChannelFails) {
237*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
238*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
239*d9f75844SAndroid Build Coastguard Worker   callee->media_engine()->set_fail_create_channel(true);
240*d9f75844SAndroid Build Coastguard Worker 
241*d9f75844SAndroid Build Coastguard Worker   std::string error;
242*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error));
243*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertStartsWith, error,
244*d9f75844SAndroid Build Coastguard Worker                       "Failed to set remote offer sdp: Failed to create");
245*d9f75844SAndroid Build Coastguard Worker }
246*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,FailToSetLocalDescriptionIfCreateMediaChannelFails)247*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
248*d9f75844SAndroid Build Coastguard Worker        FailToSetLocalDescriptionIfCreateMediaChannelFails) {
249*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
250*d9f75844SAndroid Build Coastguard Worker   caller->media_engine()->set_fail_create_channel(true);
251*d9f75844SAndroid Build Coastguard Worker 
252*d9f75844SAndroid Build Coastguard Worker   std::string error;
253*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(caller->SetLocalDescription(caller->CreateOffer(), &error));
254*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertStartsWith, error,
255*d9f75844SAndroid Build Coastguard Worker                       "Failed to set local offer sdp: Failed to create");
256*d9f75844SAndroid Build Coastguard Worker }
257*d9f75844SAndroid Build Coastguard Worker 
GetIds(const std::vector<cricket::StreamParams> & streams)258*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> GetIds(
259*d9f75844SAndroid Build Coastguard Worker     const std::vector<cricket::StreamParams>& streams) {
260*d9f75844SAndroid Build Coastguard Worker   std::vector<std::string> ids;
261*d9f75844SAndroid Build Coastguard Worker   ids.reserve(streams.size());
262*d9f75844SAndroid Build Coastguard Worker   for (const auto& stream : streams) {
263*d9f75844SAndroid Build Coastguard Worker     ids.push_back(stream.id);
264*d9f75844SAndroid Build Coastguard Worker   }
265*d9f75844SAndroid Build Coastguard Worker   return ids;
266*d9f75844SAndroid Build Coastguard Worker }
267*d9f75844SAndroid Build Coastguard Worker 
268*d9f75844SAndroid Build Coastguard Worker // Test that exchanging an offer and answer with each side having an audio and
269*d9f75844SAndroid Build Coastguard Worker // video stream creates the appropriate send/recv streams in the underlying
270*d9f75844SAndroid Build Coastguard Worker // media engine on both sides.
TEST_P(PeerConnectionMediaTest,AudioVideoOfferAnswerCreateSendRecvStreams)271*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, AudioVideoOfferAnswerCreateSendRecvStreams) {
272*d9f75844SAndroid Build Coastguard Worker   const std::string kCallerAudioId = "caller_a";
273*d9f75844SAndroid Build Coastguard Worker   const std::string kCallerVideoId = "caller_v";
274*d9f75844SAndroid Build Coastguard Worker   const std::string kCalleeAudioId = "callee_a";
275*d9f75844SAndroid Build Coastguard Worker   const std::string kCalleeVideoId = "callee_v";
276*d9f75844SAndroid Build Coastguard Worker 
277*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
278*d9f75844SAndroid Build Coastguard Worker   caller->AddAudioTrack(kCallerAudioId);
279*d9f75844SAndroid Build Coastguard Worker   caller->AddVideoTrack(kCallerVideoId);
280*d9f75844SAndroid Build Coastguard Worker 
281*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
282*d9f75844SAndroid Build Coastguard Worker   callee->AddAudioTrack(kCalleeAudioId);
283*d9f75844SAndroid Build Coastguard Worker   callee->AddVideoTrack(kCalleeVideoId);
284*d9f75844SAndroid Build Coastguard Worker 
285*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
286*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
287*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
288*d9f75844SAndroid Build Coastguard Worker 
289*d9f75844SAndroid Build Coastguard Worker   auto* caller_voice = caller->media_engine()->GetVoiceChannel(0);
290*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(caller_voice->recv_streams()),
291*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCalleeAudioId));
292*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(caller_voice->send_streams()),
293*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCallerAudioId));
294*d9f75844SAndroid Build Coastguard Worker 
295*d9f75844SAndroid Build Coastguard Worker   auto* caller_video = caller->media_engine()->GetVideoChannel(0);
296*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(caller_video->recv_streams()),
297*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCalleeVideoId));
298*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(caller_video->send_streams()),
299*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCallerVideoId));
300*d9f75844SAndroid Build Coastguard Worker 
301*d9f75844SAndroid Build Coastguard Worker   auto* callee_voice = callee->media_engine()->GetVoiceChannel(0);
302*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(callee_voice->recv_streams()),
303*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCallerAudioId));
304*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(callee_voice->send_streams()),
305*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCalleeAudioId));
306*d9f75844SAndroid Build Coastguard Worker 
307*d9f75844SAndroid Build Coastguard Worker   auto* callee_video = callee->media_engine()->GetVideoChannel(0);
308*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(callee_video->recv_streams()),
309*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCallerVideoId));
310*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(GetIds(callee_video->send_streams()),
311*d9f75844SAndroid Build Coastguard Worker               ElementsAre(kCalleeVideoId));
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker 
314*d9f75844SAndroid Build Coastguard Worker // Test that stopping the caller transceivers causes the media channels on the
315*d9f75844SAndroid Build Coastguard Worker // callee to be destroyed after calling SetRemoteDescription on the generated
316*d9f75844SAndroid Build Coastguard Worker // offer.
317*d9f75844SAndroid Build Coastguard Worker // See next test for equivalent behavior with Plan B semantics.
TEST_F(PeerConnectionMediaTestUnifiedPlan,StoppedRemoteTransceiversRemovesMediaChannels)318*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
319*d9f75844SAndroid Build Coastguard Worker        StoppedRemoteTransceiversRemovesMediaChannels) {
320*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
321*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
322*d9f75844SAndroid Build Coastguard Worker 
323*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
324*d9f75844SAndroid Build Coastguard Worker 
325*d9f75844SAndroid Build Coastguard Worker   // Stop both audio and video transceivers on the caller.
326*d9f75844SAndroid Build Coastguard Worker   auto transceivers = caller->pc()->GetTransceivers();
327*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, transceivers.size());
328*d9f75844SAndroid Build Coastguard Worker   transceivers[0]->StopInternal();
329*d9f75844SAndroid Build Coastguard Worker   transceivers[1]->StopInternal();
330*d9f75844SAndroid Build Coastguard Worker 
331*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
332*d9f75844SAndroid Build Coastguard Worker 
333*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(callee->media_engine()->GetVoiceChannel(0));
334*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(callee->media_engine()->GetVideoChannel(0));
335*d9f75844SAndroid Build Coastguard Worker }
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker // Test that removing streams from a subsequent offer causes the receive streams
338*d9f75844SAndroid Build Coastguard Worker // on the callee to be removed.
339*d9f75844SAndroid Build Coastguard Worker // See previous test for equivalent behavior with Unified Plan semantics.
TEST_F(PeerConnectionMediaTestPlanB,EmptyRemoteOfferRemovesRecvStreams)340*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestPlanB, EmptyRemoteOfferRemovesRecvStreams) {
341*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
342*d9f75844SAndroid Build Coastguard Worker   auto caller_audio_track = caller->AddAudioTrack("a");
343*d9f75844SAndroid Build Coastguard Worker   auto caller_video_track = caller->AddVideoTrack("v");
344*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
345*d9f75844SAndroid Build Coastguard Worker 
346*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
347*d9f75844SAndroid Build Coastguard Worker 
348*d9f75844SAndroid Build Coastguard Worker   // Remove both tracks from caller.
349*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RemoveTrackOrError(caller_audio_track);
350*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RemoveTrackOrError(caller_video_track);
351*d9f75844SAndroid Build Coastguard Worker 
352*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
353*d9f75844SAndroid Build Coastguard Worker 
354*d9f75844SAndroid Build Coastguard Worker   auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
355*d9f75844SAndroid Build Coastguard Worker   auto callee_video = callee->media_engine()->GetVideoChannel(0);
356*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->send_streams().size());
357*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, callee_voice->recv_streams().size());
358*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->send_streams().size());
359*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, callee_video->recv_streams().size());
360*d9f75844SAndroid Build Coastguard Worker }
361*d9f75844SAndroid Build Coastguard Worker 
362*d9f75844SAndroid Build Coastguard Worker // Test enabling of simulcast with Plan B semantics.
363*d9f75844SAndroid Build Coastguard Worker // This test creating an offer.
TEST_F(PeerConnectionMediaTestPlanB,SimulcastOffer)364*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestPlanB, SimulcastOffer) {
365*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
366*d9f75844SAndroid Build Coastguard Worker   auto caller_video_track = caller->AddVideoTrack("v");
367*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
368*d9f75844SAndroid Build Coastguard Worker   options.num_simulcast_layers = 3;
369*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
370*d9f75844SAndroid Build Coastguard Worker   auto* description = cricket::GetFirstMediaContent(offer->description(),
371*d9f75844SAndroid Build Coastguard Worker                                                     cricket::MEDIA_TYPE_VIDEO)
372*d9f75844SAndroid Build Coastguard Worker                           ->media_description();
373*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, description->streams().size());
374*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(description->streams()[0].get_ssrc_group("SIM"));
375*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(3u, description->streams()[0].get_ssrc_group("SIM")->ssrcs.size());
376*d9f75844SAndroid Build Coastguard Worker 
377*d9f75844SAndroid Build Coastguard Worker   // Check that it actually creates simulcast aswell.
378*d9f75844SAndroid Build Coastguard Worker   caller->SetLocalDescription(std::move(offer));
379*d9f75844SAndroid Build Coastguard Worker   auto senders = caller->pc()->GetSenders();
380*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, senders.size());
381*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::MediaType::MEDIA_TYPE_VIDEO, senders[0]->media_type());
382*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(3u, senders[0]->GetParameters().encodings.size());
383*d9f75844SAndroid Build Coastguard Worker }
384*d9f75844SAndroid Build Coastguard Worker 
385*d9f75844SAndroid Build Coastguard Worker // Test enabling of simulcast with Plan B semantics.
386*d9f75844SAndroid Build Coastguard Worker // This test creating an answer.
TEST_F(PeerConnectionMediaTestPlanB,SimulcastAnswer)387*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestPlanB, SimulcastAnswer) {
388*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
389*d9f75844SAndroid Build Coastguard Worker   caller->AddVideoTrack("v0");
390*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
391*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
392*d9f75844SAndroid Build Coastguard Worker   auto callee_video_track = callee->AddVideoTrack("v1");
393*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
394*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
395*d9f75844SAndroid Build Coastguard Worker   options.num_simulcast_layers = 3;
396*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(options);
397*d9f75844SAndroid Build Coastguard Worker   auto* description = cricket::GetFirstMediaContent(answer->description(),
398*d9f75844SAndroid Build Coastguard Worker                                                     cricket::MEDIA_TYPE_VIDEO)
399*d9f75844SAndroid Build Coastguard Worker                           ->media_description();
400*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, description->streams().size());
401*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(description->streams()[0].get_ssrc_group("SIM"));
402*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(3u, description->streams()[0].get_ssrc_group("SIM")->ssrcs.size());
403*d9f75844SAndroid Build Coastguard Worker 
404*d9f75844SAndroid Build Coastguard Worker   // Check that it actually creates simulcast aswell.
405*d9f75844SAndroid Build Coastguard Worker   callee->SetLocalDescription(std::move(answer));
406*d9f75844SAndroid Build Coastguard Worker   auto senders = callee->pc()->GetSenders();
407*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, senders.size());
408*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::MediaType::MEDIA_TYPE_VIDEO, senders[0]->media_type());
409*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(3u, senders[0]->GetParameters().encodings.size());
410*d9f75844SAndroid Build Coastguard Worker }
411*d9f75844SAndroid Build Coastguard Worker 
412*d9f75844SAndroid Build Coastguard Worker // Test that stopping the callee transceivers causes the media channels to be
413*d9f75844SAndroid Build Coastguard Worker // destroyed on the callee after calling SetLocalDescription on the local
414*d9f75844SAndroid Build Coastguard Worker // answer.
415*d9f75844SAndroid Build Coastguard Worker // See next test for equivalent behavior with Plan B semantics.
TEST_F(PeerConnectionMediaTestUnifiedPlan,StoppedLocalTransceiversRemovesMediaChannels)416*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
417*d9f75844SAndroid Build Coastguard Worker        StoppedLocalTransceiversRemovesMediaChannels) {
418*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
419*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
420*d9f75844SAndroid Build Coastguard Worker 
421*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
422*d9f75844SAndroid Build Coastguard Worker 
423*d9f75844SAndroid Build Coastguard Worker   // Stop both audio and video transceivers on the callee.
424*d9f75844SAndroid Build Coastguard Worker   auto transceivers = callee->pc()->GetTransceivers();
425*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, transceivers.size());
426*d9f75844SAndroid Build Coastguard Worker   transceivers[0]->StopInternal();
427*d9f75844SAndroid Build Coastguard Worker   transceivers[1]->StopInternal();
428*d9f75844SAndroid Build Coastguard Worker 
429*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
430*d9f75844SAndroid Build Coastguard Worker 
431*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(callee->media_engine()->GetVoiceChannel(0));
432*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(callee->media_engine()->GetVideoChannel(0));
433*d9f75844SAndroid Build Coastguard Worker }
434*d9f75844SAndroid Build Coastguard Worker 
435*d9f75844SAndroid Build Coastguard Worker // Test that removing streams from a subsequent answer causes the send streams
436*d9f75844SAndroid Build Coastguard Worker // on the callee to be removed when applied locally.
437*d9f75844SAndroid Build Coastguard Worker // See previous test for equivalent behavior with Unified Plan semantics.
TEST_F(PeerConnectionMediaTestPlanB,EmptyLocalAnswerRemovesSendStreams)438*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestPlanB, EmptyLocalAnswerRemovesSendStreams) {
439*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
440*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
441*d9f75844SAndroid Build Coastguard Worker   auto callee_audio_track = callee->AddAudioTrack("a");
442*d9f75844SAndroid Build Coastguard Worker   auto callee_video_track = callee->AddVideoTrack("v");
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
445*d9f75844SAndroid Build Coastguard Worker 
446*d9f75844SAndroid Build Coastguard Worker   // Remove both tracks from callee.
447*d9f75844SAndroid Build Coastguard Worker   callee->pc()->RemoveTrackOrError(callee_audio_track);
448*d9f75844SAndroid Build Coastguard Worker   callee->pc()->RemoveTrackOrError(callee_video_track);
449*d9f75844SAndroid Build Coastguard Worker 
450*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
451*d9f75844SAndroid Build Coastguard Worker 
452*d9f75844SAndroid Build Coastguard Worker   auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
453*d9f75844SAndroid Build Coastguard Worker   auto callee_video = callee->media_engine()->GetVideoChannel(0);
454*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, callee_voice->send_streams().size());
455*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->recv_streams().size());
456*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, callee_video->send_streams().size());
457*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->recv_streams().size());
458*d9f75844SAndroid Build Coastguard Worker }
459*d9f75844SAndroid Build Coastguard Worker 
460*d9f75844SAndroid Build Coastguard Worker // Test that a new stream in a subsequent offer causes a new receive stream to
461*d9f75844SAndroid Build Coastguard Worker // be created on the callee.
TEST_P(PeerConnectionMediaTest,NewStreamInRemoteOfferAddsRecvStreams)462*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, NewStreamInRemoteOfferAddsRecvStreams) {
463*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
464*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
465*d9f75844SAndroid Build Coastguard Worker 
466*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
467*d9f75844SAndroid Build Coastguard Worker 
468*d9f75844SAndroid Build Coastguard Worker   // Add second set of tracks to the caller.
469*d9f75844SAndroid Build Coastguard Worker   caller->AddAudioTrack("a2");
470*d9f75844SAndroid Build Coastguard Worker   caller->AddVideoTrack("v2");
471*d9f75844SAndroid Build Coastguard Worker 
472*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
473*d9f75844SAndroid Build Coastguard Worker 
474*d9f75844SAndroid Build Coastguard Worker   auto a1 = callee->media_engine()->GetVoiceChannel(0);
475*d9f75844SAndroid Build Coastguard Worker   auto a2 = callee->media_engine()->GetVoiceChannel(1);
476*d9f75844SAndroid Build Coastguard Worker   auto v1 = callee->media_engine()->GetVideoChannel(0);
477*d9f75844SAndroid Build Coastguard Worker   auto v2 = callee->media_engine()->GetVideoChannel(1);
478*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan()) {
479*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(a1);
480*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, a1->recv_streams().size());
481*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(a2);
482*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, a2->recv_streams().size());
483*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(v1);
484*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, v1->recv_streams().size());
485*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(v2);
486*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, v2->recv_streams().size());
487*d9f75844SAndroid Build Coastguard Worker   } else {
488*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(a1);
489*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(2u, a1->recv_streams().size());
490*d9f75844SAndroid Build Coastguard Worker     ASSERT_FALSE(a2);
491*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(v1);
492*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(2u, v1->recv_streams().size());
493*d9f75844SAndroid Build Coastguard Worker     ASSERT_FALSE(v2);
494*d9f75844SAndroid Build Coastguard Worker   }
495*d9f75844SAndroid Build Coastguard Worker }
496*d9f75844SAndroid Build Coastguard Worker 
497*d9f75844SAndroid Build Coastguard Worker // Test that a new stream in a subsequent answer causes a new send stream to be
498*d9f75844SAndroid Build Coastguard Worker // created on the callee when added locally.
TEST_P(PeerConnectionMediaTest,NewStreamInLocalAnswerAddsSendStreams)499*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) {
500*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
501*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
502*d9f75844SAndroid Build Coastguard Worker 
503*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions offer_options;
504*d9f75844SAndroid Build Coastguard Worker   offer_options.offer_to_receive_audio =
505*d9f75844SAndroid Build Coastguard Worker       RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
506*d9f75844SAndroid Build Coastguard Worker   offer_options.offer_to_receive_video =
507*d9f75844SAndroid Build Coastguard Worker       RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
508*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions answer_options;
509*d9f75844SAndroid Build Coastguard Worker 
510*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get(), offer_options,
511*d9f75844SAndroid Build Coastguard Worker                                               answer_options));
512*d9f75844SAndroid Build Coastguard Worker 
513*d9f75844SAndroid Build Coastguard Worker   // Add second set of tracks to the callee.
514*d9f75844SAndroid Build Coastguard Worker   callee->AddAudioTrack("a2");
515*d9f75844SAndroid Build Coastguard Worker   callee->AddVideoTrack("v2");
516*d9f75844SAndroid Build Coastguard Worker 
517*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get(), offer_options,
518*d9f75844SAndroid Build Coastguard Worker                                               answer_options));
519*d9f75844SAndroid Build Coastguard Worker 
520*d9f75844SAndroid Build Coastguard Worker   auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
521*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_voice);
522*d9f75844SAndroid Build Coastguard Worker   auto callee_video = callee->media_engine()->GetVideoChannel(0);
523*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_video);
524*d9f75844SAndroid Build Coastguard Worker 
525*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan()) {
526*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, callee_voice->send_streams().size());
527*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, callee_video->send_streams().size());
528*d9f75844SAndroid Build Coastguard Worker   } else {
529*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(2u, callee_voice->send_streams().size());
530*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(2u, callee_video->send_streams().size());
531*d9f75844SAndroid Build Coastguard Worker   }
532*d9f75844SAndroid Build Coastguard Worker }
533*d9f75844SAndroid Build Coastguard Worker 
534*d9f75844SAndroid Build Coastguard Worker // A PeerConnection with no local streams and no explicit answer constraints
535*d9f75844SAndroid Build Coastguard Worker // should not reject any offered media sections.
TEST_P(PeerConnectionMediaTest,CreateAnswerWithNoStreamsAndDefaultOptionsDoesNotReject)536*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
537*d9f75844SAndroid Build Coastguard Worker        CreateAnswerWithNoStreamsAndDefaultOptionsDoesNotReject) {
538*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
539*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
540*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
541*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
542*d9f75844SAndroid Build Coastguard Worker 
543*d9f75844SAndroid Build Coastguard Worker   const auto* audio_content =
544*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContent(answer->description());
545*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(audio_content);
546*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(audio_content->rejected);
547*d9f75844SAndroid Build Coastguard Worker 
548*d9f75844SAndroid Build Coastguard Worker   const auto* video_content =
549*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContent(answer->description());
550*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(video_content);
551*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(video_content->rejected);
552*d9f75844SAndroid Build Coastguard Worker }
553*d9f75844SAndroid Build Coastguard Worker 
554*d9f75844SAndroid Build Coastguard Worker // Test that raw packetization is not set in the offer by default.
TEST_P(PeerConnectionMediaTest,RawPacketizationNotSetInOffer)555*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RawPacketizationNotSetInOffer) {
556*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoCodec> fake_codecs;
557*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(111, cricket::kVp8CodecName));
558*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(112, cricket::kRtxCodecName));
559*d9f75844SAndroid Build Coastguard Worker   fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
560*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(113, cricket::kVp9CodecName));
561*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(114, cricket::kH264CodecName));
562*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(115, "HEVC"));
563*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
564*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetVideoCodecs(fake_codecs);
565*d9f75844SAndroid Build Coastguard Worker 
566*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
567*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
568*d9f75844SAndroid Build Coastguard Worker   auto* offer_description =
569*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContentDescription(offer->description());
570*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : offer_description->codecs()) {
571*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(codec.packetization, absl::nullopt);
572*d9f75844SAndroid Build Coastguard Worker   }
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker 
575*d9f75844SAndroid Build Coastguard Worker // Test that raw packetization is set in the offer and answer for all
576*d9f75844SAndroid Build Coastguard Worker // video payload when raw_packetization_for_video is true.
TEST_P(PeerConnectionMediaTest,RawPacketizationSetInOfferAndAnswer)577*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RawPacketizationSetInOfferAndAnswer) {
578*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoCodec> fake_codecs;
579*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(111, cricket::kVp8CodecName));
580*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(112, cricket::kRtxCodecName));
581*d9f75844SAndroid Build Coastguard Worker   fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
582*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(113, cricket::kVp9CodecName));
583*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(114, cricket::kH264CodecName));
584*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(115, "HEVC"));
585*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
586*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetVideoCodecs(fake_codecs);
587*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
588*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetVideoCodecs(fake_codecs);
589*d9f75844SAndroid Build Coastguard Worker 
590*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
591*d9f75844SAndroid Build Coastguard Worker   options.raw_packetization_for_video = true;
592*d9f75844SAndroid Build Coastguard Worker 
593*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
594*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal(options);
595*d9f75844SAndroid Build Coastguard Worker   auto* offer_description =
596*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContentDescription(offer->description());
597*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : offer_description->codecs()) {
598*d9f75844SAndroid Build Coastguard Worker     if (codec.GetCodecType() == cricket::VideoCodec::CODEC_VIDEO) {
599*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(codec.packetization, cricket::kPacketizationParamRaw);
600*d9f75844SAndroid Build Coastguard Worker     }
601*d9f75844SAndroid Build Coastguard Worker   }
602*d9f75844SAndroid Build Coastguard Worker 
603*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithVideo(std::move(callee_fake_engine));
604*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
605*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal(options);
606*d9f75844SAndroid Build Coastguard Worker   auto* answer_description =
607*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContentDescription(answer->description());
608*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : answer_description->codecs()) {
609*d9f75844SAndroid Build Coastguard Worker     if (codec.GetCodecType() == cricket::VideoCodec::CODEC_VIDEO) {
610*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(codec.packetization, cricket::kPacketizationParamRaw);
611*d9f75844SAndroid Build Coastguard Worker     }
612*d9f75844SAndroid Build Coastguard Worker   }
613*d9f75844SAndroid Build Coastguard Worker 
614*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
615*d9f75844SAndroid Build Coastguard Worker }
616*d9f75844SAndroid Build Coastguard Worker 
617*d9f75844SAndroid Build Coastguard Worker // Test that raw packetization is not set in the answer when
618*d9f75844SAndroid Build Coastguard Worker // raw_packetization_for_video is true if it was not set in the offer.
TEST_P(PeerConnectionMediaTest,RawPacketizationNotSetInAnswerWhenNotSetInOffer)619*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
620*d9f75844SAndroid Build Coastguard Worker        RawPacketizationNotSetInAnswerWhenNotSetInOffer) {
621*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoCodec> fake_codecs;
622*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(111, cricket::kVp8CodecName));
623*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(112, cricket::kRtxCodecName));
624*d9f75844SAndroid Build Coastguard Worker   fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
625*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(113, cricket::kVp9CodecName));
626*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(114, cricket::kH264CodecName));
627*d9f75844SAndroid Build Coastguard Worker   fake_codecs.push_back(cricket::VideoCodec(115, "HEVC"));
628*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
629*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetVideoCodecs(fake_codecs);
630*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
631*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetVideoCodecs(fake_codecs);
632*d9f75844SAndroid Build Coastguard Worker 
633*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions caller_options;
634*d9f75844SAndroid Build Coastguard Worker   caller_options.raw_packetization_for_video = false;
635*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions callee_options;
636*d9f75844SAndroid Build Coastguard Worker   callee_options.raw_packetization_for_video = true;
637*d9f75844SAndroid Build Coastguard Worker 
638*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
639*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal(caller_options);
640*d9f75844SAndroid Build Coastguard Worker 
641*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithVideo(std::move(callee_fake_engine));
642*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
643*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal(callee_options);
644*d9f75844SAndroid Build Coastguard Worker 
645*d9f75844SAndroid Build Coastguard Worker   auto* answer_description =
646*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContentDescription(answer->description());
647*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : answer_description->codecs()) {
648*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(codec.packetization, absl::nullopt);
649*d9f75844SAndroid Build Coastguard Worker   }
650*d9f75844SAndroid Build Coastguard Worker 
651*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
652*d9f75844SAndroid Build Coastguard Worker }
653*d9f75844SAndroid Build Coastguard Worker 
654*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaOfferDirectionTest
655*d9f75844SAndroid Build Coastguard Worker     : public PeerConnectionMediaBaseTest,
656*d9f75844SAndroid Build Coastguard Worker       public ::testing::WithParamInterface<
657*d9f75844SAndroid Build Coastguard Worker           std::tuple<SdpSemantics,
658*d9f75844SAndroid Build Coastguard Worker                      std::tuple<bool, int, RtpTransceiverDirection>>> {
659*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionMediaOfferDirectionTest()660*d9f75844SAndroid Build Coastguard Worker   PeerConnectionMediaOfferDirectionTest()
661*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) {
662*d9f75844SAndroid Build Coastguard Worker     auto param = std::get<1>(GetParam());
663*d9f75844SAndroid Build Coastguard Worker     send_media_ = std::get<0>(param);
664*d9f75844SAndroid Build Coastguard Worker     offer_to_receive_ = std::get<1>(param);
665*d9f75844SAndroid Build Coastguard Worker     expected_direction_ = std::get<2>(param);
666*d9f75844SAndroid Build Coastguard Worker   }
667*d9f75844SAndroid Build Coastguard Worker 
668*d9f75844SAndroid Build Coastguard Worker   bool send_media_;
669*d9f75844SAndroid Build Coastguard Worker   int offer_to_receive_;
670*d9f75844SAndroid Build Coastguard Worker   RtpTransceiverDirection expected_direction_;
671*d9f75844SAndroid Build Coastguard Worker };
672*d9f75844SAndroid Build Coastguard Worker 
673*d9f75844SAndroid Build Coastguard Worker // Tests that the correct direction is set on the media description according
674*d9f75844SAndroid Build Coastguard Worker // to the presence of a local media track and the offer_to_receive setting.
TEST_P(PeerConnectionMediaOfferDirectionTest,VerifyDirection)675*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) {
676*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
677*d9f75844SAndroid Build Coastguard Worker   if (send_media_) {
678*d9f75844SAndroid Build Coastguard Worker     caller->AddAudioTrack("a");
679*d9f75844SAndroid Build Coastguard Worker   }
680*d9f75844SAndroid Build Coastguard Worker 
681*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
682*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_audio = offer_to_receive_;
683*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
684*d9f75844SAndroid Build Coastguard Worker 
685*d9f75844SAndroid Build Coastguard Worker   auto* content = cricket::GetFirstMediaContent(offer->description(),
686*d9f75844SAndroid Build Coastguard Worker                                                 cricket::MEDIA_TYPE_AUDIO);
687*d9f75844SAndroid Build Coastguard Worker   if (expected_direction_ == RtpTransceiverDirection::kInactive) {
688*d9f75844SAndroid Build Coastguard Worker     EXPECT_FALSE(content);
689*d9f75844SAndroid Build Coastguard Worker   } else {
690*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(expected_direction_, content->media_description()->direction());
691*d9f75844SAndroid Build Coastguard Worker   }
692*d9f75844SAndroid Build Coastguard Worker }
693*d9f75844SAndroid Build Coastguard Worker 
694*d9f75844SAndroid Build Coastguard Worker // Note that in these tests, MD_INACTIVE indicates that no media section is
695*d9f75844SAndroid Build Coastguard Worker // included in the offer, not that the media direction is inactive.
696*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
697*d9f75844SAndroid Build Coastguard Worker     PeerConnectionMediaTest,
698*d9f75844SAndroid Build Coastguard Worker     PeerConnectionMediaOfferDirectionTest,
699*d9f75844SAndroid Build Coastguard Worker     Combine(
700*d9f75844SAndroid Build Coastguard Worker         Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
701*d9f75844SAndroid Build Coastguard Worker         Values(std::make_tuple(false, -1, RtpTransceiverDirection::kInactive),
702*d9f75844SAndroid Build Coastguard Worker                std::make_tuple(false, 0, RtpTransceiverDirection::kInactive),
703*d9f75844SAndroid Build Coastguard Worker                std::make_tuple(false, 1, RtpTransceiverDirection::kRecvOnly),
704*d9f75844SAndroid Build Coastguard Worker                std::make_tuple(true, -1, RtpTransceiverDirection::kSendRecv),
705*d9f75844SAndroid Build Coastguard Worker                std::make_tuple(true, 0, RtpTransceiverDirection::kSendOnly),
706*d9f75844SAndroid Build Coastguard Worker                std::make_tuple(true, 1, RtpTransceiverDirection::kSendRecv))));
707*d9f75844SAndroid Build Coastguard Worker 
708*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaAnswerDirectionTest
709*d9f75844SAndroid Build Coastguard Worker     : public PeerConnectionMediaBaseTest,
710*d9f75844SAndroid Build Coastguard Worker       public ::testing::WithParamInterface<
711*d9f75844SAndroid Build Coastguard Worker           std::tuple<SdpSemantics, RtpTransceiverDirection, bool, int>> {
712*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionMediaAnswerDirectionTest()713*d9f75844SAndroid Build Coastguard Worker   PeerConnectionMediaAnswerDirectionTest()
714*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) {
715*d9f75844SAndroid Build Coastguard Worker     offer_direction_ = std::get<1>(GetParam());
716*d9f75844SAndroid Build Coastguard Worker     send_media_ = std::get<2>(GetParam());
717*d9f75844SAndroid Build Coastguard Worker     offer_to_receive_ = std::get<3>(GetParam());
718*d9f75844SAndroid Build Coastguard Worker   }
719*d9f75844SAndroid Build Coastguard Worker 
720*d9f75844SAndroid Build Coastguard Worker   RtpTransceiverDirection offer_direction_;
721*d9f75844SAndroid Build Coastguard Worker   bool send_media_;
722*d9f75844SAndroid Build Coastguard Worker   int offer_to_receive_;
723*d9f75844SAndroid Build Coastguard Worker };
724*d9f75844SAndroid Build Coastguard Worker 
725*d9f75844SAndroid Build Coastguard Worker // Tests that the direction in an answer is correct according to direction sent
726*d9f75844SAndroid Build Coastguard Worker // in the offer, the presence of a local media track on the receive side and the
727*d9f75844SAndroid Build Coastguard Worker // offer_to_receive setting.
TEST_P(PeerConnectionMediaAnswerDirectionTest,VerifyDirection)728*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) {
729*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan() &&
730*d9f75844SAndroid Build Coastguard Worker       offer_to_receive_ != RTCOfferAnswerOptions::kUndefined) {
731*d9f75844SAndroid Build Coastguard Worker     // offer_to_receive_ is not implemented when creating answers with Unified
732*d9f75844SAndroid Build Coastguard Worker     // Plan semantics specified.
733*d9f75844SAndroid Build Coastguard Worker     return;
734*d9f75844SAndroid Build Coastguard Worker   }
735*d9f75844SAndroid Build Coastguard Worker 
736*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
737*d9f75844SAndroid Build Coastguard Worker   caller->AddAudioTrack("a");
738*d9f75844SAndroid Build Coastguard Worker 
739*d9f75844SAndroid Build Coastguard Worker   // Create the offer with an audio section and set its direction.
740*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
741*d9f75844SAndroid Build Coastguard Worker   cricket::GetFirstAudioContentDescription(offer->description())
742*d9f75844SAndroid Build Coastguard Worker       ->set_direction(offer_direction_);
743*d9f75844SAndroid Build Coastguard Worker 
744*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
745*d9f75844SAndroid Build Coastguard Worker   if (send_media_) {
746*d9f75844SAndroid Build Coastguard Worker     callee->AddAudioTrack("a");
747*d9f75844SAndroid Build Coastguard Worker   }
748*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
749*d9f75844SAndroid Build Coastguard Worker 
750*d9f75844SAndroid Build Coastguard Worker   // Create the answer according to the test parameters.
751*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
752*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_audio = offer_to_receive_;
753*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(options);
754*d9f75844SAndroid Build Coastguard Worker 
755*d9f75844SAndroid Build Coastguard Worker   // The expected direction in the answer is the intersection of each side's
756*d9f75844SAndroid Build Coastguard Worker   // capability to send/recv media.
757*d9f75844SAndroid Build Coastguard Worker   // For the offerer, the direction is given in the offer (offer_direction_).
758*d9f75844SAndroid Build Coastguard Worker   // For the answerer, the direction has two components:
759*d9f75844SAndroid Build Coastguard Worker   // 1. Send if the answerer has a local track to send.
760*d9f75844SAndroid Build Coastguard Worker   // 2. Receive if the answerer has explicitly set the offer_to_receive to 1 or
761*d9f75844SAndroid Build Coastguard Worker   //    if it has been left as default.
762*d9f75844SAndroid Build Coastguard Worker   bool offer_send = RtpTransceiverDirectionHasSend(offer_direction_);
763*d9f75844SAndroid Build Coastguard Worker   bool offer_recv = RtpTransceiverDirectionHasRecv(offer_direction_);
764*d9f75844SAndroid Build Coastguard Worker 
765*d9f75844SAndroid Build Coastguard Worker   // The negotiated components determine the direction set in the answer.
766*d9f75844SAndroid Build Coastguard Worker   bool negotiate_send = (send_media_ && offer_recv);
767*d9f75844SAndroid Build Coastguard Worker   bool negotiate_recv = ((offer_to_receive_ != 0) && offer_send);
768*d9f75844SAndroid Build Coastguard Worker 
769*d9f75844SAndroid Build Coastguard Worker   auto expected_direction =
770*d9f75844SAndroid Build Coastguard Worker       RtpTransceiverDirectionFromSendRecv(negotiate_send, negotiate_recv);
771*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(expected_direction,
772*d9f75844SAndroid Build Coastguard Worker             GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_AUDIO));
773*d9f75844SAndroid Build Coastguard Worker }
774*d9f75844SAndroid Build Coastguard Worker 
775*d9f75844SAndroid Build Coastguard Worker // Tests that the media section is rejected if and only if the callee has no
776*d9f75844SAndroid Build Coastguard Worker // local media track and has set offer_to_receive to 0, no matter which
777*d9f75844SAndroid Build Coastguard Worker // direction the caller indicated in the offer.
TEST_P(PeerConnectionMediaAnswerDirectionTest,VerifyRejected)778*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyRejected) {
779*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan() &&
780*d9f75844SAndroid Build Coastguard Worker       offer_to_receive_ != RTCOfferAnswerOptions::kUndefined) {
781*d9f75844SAndroid Build Coastguard Worker     // offer_to_receive_ is not implemented when creating answers with Unified
782*d9f75844SAndroid Build Coastguard Worker     // Plan semantics specified.
783*d9f75844SAndroid Build Coastguard Worker     return;
784*d9f75844SAndroid Build Coastguard Worker   }
785*d9f75844SAndroid Build Coastguard Worker 
786*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
787*d9f75844SAndroid Build Coastguard Worker   caller->AddAudioTrack("a");
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker   // Create the offer with an audio section and set its direction.
790*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
791*d9f75844SAndroid Build Coastguard Worker   cricket::GetFirstAudioContentDescription(offer->description())
792*d9f75844SAndroid Build Coastguard Worker       ->set_direction(offer_direction_);
793*d9f75844SAndroid Build Coastguard Worker 
794*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
795*d9f75844SAndroid Build Coastguard Worker   if (send_media_) {
796*d9f75844SAndroid Build Coastguard Worker     callee->AddAudioTrack("a");
797*d9f75844SAndroid Build Coastguard Worker   }
798*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
799*d9f75844SAndroid Build Coastguard Worker 
800*d9f75844SAndroid Build Coastguard Worker   // Create the answer according to the test parameters.
801*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
802*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_audio = offer_to_receive_;
803*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(options);
804*d9f75844SAndroid Build Coastguard Worker 
805*d9f75844SAndroid Build Coastguard Worker   // The media section is rejected if and only if offer_to_receive is explicitly
806*d9f75844SAndroid Build Coastguard Worker   // set to 0 and there is no media to send.
807*d9f75844SAndroid Build Coastguard Worker   auto* audio_content = cricket::GetFirstAudioContent(answer->description());
808*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(audio_content);
809*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ((offer_to_receive_ == 0 && !send_media_), audio_content->rejected);
810*d9f75844SAndroid Build Coastguard Worker }
811*d9f75844SAndroid Build Coastguard Worker 
812*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(PeerConnectionMediaTest,
813*d9f75844SAndroid Build Coastguard Worker                          PeerConnectionMediaAnswerDirectionTest,
814*d9f75844SAndroid Build Coastguard Worker                          Combine(Values(SdpSemantics::kPlanB_DEPRECATED,
815*d9f75844SAndroid Build Coastguard Worker                                         SdpSemantics::kUnifiedPlan),
816*d9f75844SAndroid Build Coastguard Worker                                  Values(RtpTransceiverDirection::kInactive,
817*d9f75844SAndroid Build Coastguard Worker                                         RtpTransceiverDirection::kSendOnly,
818*d9f75844SAndroid Build Coastguard Worker                                         RtpTransceiverDirection::kRecvOnly,
819*d9f75844SAndroid Build Coastguard Worker                                         RtpTransceiverDirection::kSendRecv),
820*d9f75844SAndroid Build Coastguard Worker                                  Bool(),
821*d9f75844SAndroid Build Coastguard Worker                                  Values(-1, 0, 1)));
822*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,OfferHasDifferentDirectionForAudioVideo)823*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) {
824*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
825*d9f75844SAndroid Build Coastguard Worker   caller->AddVideoTrack("v");
826*d9f75844SAndroid Build Coastguard Worker 
827*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
828*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_audio = 1;
829*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_video = 0;
830*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
831*d9f75844SAndroid Build Coastguard Worker 
832*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
833*d9f75844SAndroid Build Coastguard Worker             GetMediaContentDirection(offer.get(), cricket::MEDIA_TYPE_AUDIO));
834*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
835*d9f75844SAndroid Build Coastguard Worker             GetMediaContentDirection(offer.get(), cricket::MEDIA_TYPE_VIDEO));
836*d9f75844SAndroid Build Coastguard Worker }
837*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,AnswerHasDifferentDirectionsForAudioVideo)838*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) {
839*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan()) {
840*d9f75844SAndroid Build Coastguard Worker     // offer_to_receive_ is not implemented when creating answers with Unified
841*d9f75844SAndroid Build Coastguard Worker     // Plan semantics specified.
842*d9f75844SAndroid Build Coastguard Worker     return;
843*d9f75844SAndroid Build Coastguard Worker   }
844*d9f75844SAndroid Build Coastguard Worker 
845*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
846*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
847*d9f75844SAndroid Build Coastguard Worker   callee->AddVideoTrack("v");
848*d9f75844SAndroid Build Coastguard Worker 
849*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
850*d9f75844SAndroid Build Coastguard Worker 
851*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
852*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_audio = 1;
853*d9f75844SAndroid Build Coastguard Worker   options.offer_to_receive_video = 0;
854*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(options);
855*d9f75844SAndroid Build Coastguard Worker 
856*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
857*d9f75844SAndroid Build Coastguard Worker             GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_AUDIO));
858*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
859*d9f75844SAndroid Build Coastguard Worker             GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_VIDEO));
860*d9f75844SAndroid Build Coastguard Worker }
861*d9f75844SAndroid Build Coastguard Worker 
AddComfortNoiseCodecsToSend(cricket::FakeMediaEngine * media_engine)862*d9f75844SAndroid Build Coastguard Worker void AddComfortNoiseCodecsToSend(cricket::FakeMediaEngine* media_engine) {
863*d9f75844SAndroid Build Coastguard Worker   const cricket::AudioCodec kComfortNoiseCodec8k(102, cricket::kCnCodecName,
864*d9f75844SAndroid Build Coastguard Worker                                                  8000, 0, 1);
865*d9f75844SAndroid Build Coastguard Worker   const cricket::AudioCodec kComfortNoiseCodec16k(103, cricket::kCnCodecName,
866*d9f75844SAndroid Build Coastguard Worker                                                   16000, 0, 1);
867*d9f75844SAndroid Build Coastguard Worker 
868*d9f75844SAndroid Build Coastguard Worker   auto codecs = media_engine->voice().send_codecs();
869*d9f75844SAndroid Build Coastguard Worker   codecs.push_back(kComfortNoiseCodec8k);
870*d9f75844SAndroid Build Coastguard Worker   codecs.push_back(kComfortNoiseCodec16k);
871*d9f75844SAndroid Build Coastguard Worker   media_engine->SetAudioCodecs(codecs);
872*d9f75844SAndroid Build Coastguard Worker }
873*d9f75844SAndroid Build Coastguard Worker 
HasAnyComfortNoiseCodecs(const cricket::SessionDescription * desc)874*d9f75844SAndroid Build Coastguard Worker bool HasAnyComfortNoiseCodecs(const cricket::SessionDescription* desc) {
875*d9f75844SAndroid Build Coastguard Worker   const auto* audio_desc = cricket::GetFirstAudioContentDescription(desc);
876*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : audio_desc->codecs()) {
877*d9f75844SAndroid Build Coastguard Worker     if (codec.name == cricket::kCnCodecName) {
878*d9f75844SAndroid Build Coastguard Worker       return true;
879*d9f75844SAndroid Build Coastguard Worker     }
880*d9f75844SAndroid Build Coastguard Worker   }
881*d9f75844SAndroid Build Coastguard Worker   return false;
882*d9f75844SAndroid Build Coastguard Worker }
883*d9f75844SAndroid Build Coastguard Worker 
HasPayloadTypeConflict(const cricket::SessionDescription * desc)884*d9f75844SAndroid Build Coastguard Worker bool HasPayloadTypeConflict(const cricket::SessionDescription* desc) {
885*d9f75844SAndroid Build Coastguard Worker   std::set<int> payload_types;
886*d9f75844SAndroid Build Coastguard Worker   const auto* audio_desc = cricket::GetFirstAudioContentDescription(desc);
887*d9f75844SAndroid Build Coastguard Worker   if (audio_desc) {
888*d9f75844SAndroid Build Coastguard Worker     for (const auto& codec : audio_desc->codecs()) {
889*d9f75844SAndroid Build Coastguard Worker       if (payload_types.count(codec.id) > 0) {
890*d9f75844SAndroid Build Coastguard Worker         return true;
891*d9f75844SAndroid Build Coastguard Worker       }
892*d9f75844SAndroid Build Coastguard Worker       payload_types.insert(codec.id);
893*d9f75844SAndroid Build Coastguard Worker     }
894*d9f75844SAndroid Build Coastguard Worker   }
895*d9f75844SAndroid Build Coastguard Worker   const auto* video_desc = cricket::GetFirstVideoContentDescription(desc);
896*d9f75844SAndroid Build Coastguard Worker   if (video_desc) {
897*d9f75844SAndroid Build Coastguard Worker     for (const auto& codec : video_desc->codecs()) {
898*d9f75844SAndroid Build Coastguard Worker       if (payload_types.count(codec.id) > 0) {
899*d9f75844SAndroid Build Coastguard Worker         return true;
900*d9f75844SAndroid Build Coastguard Worker       }
901*d9f75844SAndroid Build Coastguard Worker       payload_types.insert(codec.id);
902*d9f75844SAndroid Build Coastguard Worker     }
903*d9f75844SAndroid Build Coastguard Worker   }
904*d9f75844SAndroid Build Coastguard Worker   return false;
905*d9f75844SAndroid Build Coastguard Worker }
906*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,CreateOfferWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs)907*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
908*d9f75844SAndroid Build Coastguard Worker        CreateOfferWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs) {
909*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
910*d9f75844SAndroid Build Coastguard Worker   AddComfortNoiseCodecsToSend(fake_engine.get());
911*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
912*d9f75844SAndroid Build Coastguard Worker 
913*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
914*d9f75844SAndroid Build Coastguard Worker   options.voice_activity_detection = false;
915*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
916*d9f75844SAndroid Build Coastguard Worker 
917*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasAnyComfortNoiseCodecs(offer->description()));
918*d9f75844SAndroid Build Coastguard Worker }
919*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,CreateOfferWithVoiceActivityDetectionIncludesComfortNoiseCodecs)920*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
921*d9f75844SAndroid Build Coastguard Worker        CreateOfferWithVoiceActivityDetectionIncludesComfortNoiseCodecs) {
922*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
923*d9f75844SAndroid Build Coastguard Worker   AddComfortNoiseCodecsToSend(fake_engine.get());
924*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
925*d9f75844SAndroid Build Coastguard Worker 
926*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
927*d9f75844SAndroid Build Coastguard Worker   options.voice_activity_detection = true;
928*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
929*d9f75844SAndroid Build Coastguard Worker 
930*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(HasAnyComfortNoiseCodecs(offer->description()));
931*d9f75844SAndroid Build Coastguard Worker }
932*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,CreateAnswerWithVoiceActivityDetectionIncludesNoComfortNoiseCodecs)933*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
934*d9f75844SAndroid Build Coastguard Worker        CreateAnswerWithVoiceActivityDetectionIncludesNoComfortNoiseCodecs) {
935*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
936*d9f75844SAndroid Build Coastguard Worker 
937*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
938*d9f75844SAndroid Build Coastguard Worker   AddComfortNoiseCodecsToSend(callee_fake_engine.get());
939*d9f75844SAndroid Build Coastguard Worker   auto callee =
940*d9f75844SAndroid Build Coastguard Worker       CreatePeerConnectionWithAudioVideo(std::move(callee_fake_engine));
941*d9f75844SAndroid Build Coastguard Worker 
942*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
943*d9f75844SAndroid Build Coastguard Worker 
944*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
945*d9f75844SAndroid Build Coastguard Worker   options.voice_activity_detection = true;
946*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(options);
947*d9f75844SAndroid Build Coastguard Worker 
948*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasAnyComfortNoiseCodecs(answer->description()));
949*d9f75844SAndroid Build Coastguard Worker }
950*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,CreateAnswerWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs)951*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
952*d9f75844SAndroid Build Coastguard Worker        CreateAnswerWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs) {
953*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
954*d9f75844SAndroid Build Coastguard Worker   AddComfortNoiseCodecsToSend(caller_fake_engine.get());
955*d9f75844SAndroid Build Coastguard Worker   auto caller =
956*d9f75844SAndroid Build Coastguard Worker       CreatePeerConnectionWithAudioVideo(std::move(caller_fake_engine));
957*d9f75844SAndroid Build Coastguard Worker 
958*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
959*d9f75844SAndroid Build Coastguard Worker   AddComfortNoiseCodecsToSend(callee_fake_engine.get());
960*d9f75844SAndroid Build Coastguard Worker   auto callee =
961*d9f75844SAndroid Build Coastguard Worker       CreatePeerConnectionWithAudioVideo(std::move(callee_fake_engine));
962*d9f75844SAndroid Build Coastguard Worker 
963*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
964*d9f75844SAndroid Build Coastguard Worker 
965*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
966*d9f75844SAndroid Build Coastguard Worker   options.voice_activity_detection = false;
967*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(options);
968*d9f75844SAndroid Build Coastguard Worker 
969*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasAnyComfortNoiseCodecs(answer->description()));
970*d9f75844SAndroid Build Coastguard Worker }
971*d9f75844SAndroid Build Coastguard Worker 
972*d9f75844SAndroid Build Coastguard Worker // The following test group verifies that we reject answers with invalid media
973*d9f75844SAndroid Build Coastguard Worker // sections as per RFC 3264.
974*d9f75844SAndroid Build Coastguard Worker 
975*d9f75844SAndroid Build Coastguard Worker class PeerConnectionMediaInvalidMediaTest
976*d9f75844SAndroid Build Coastguard Worker     : public PeerConnectionMediaBaseTest,
977*d9f75844SAndroid Build Coastguard Worker       public ::testing::WithParamInterface<std::tuple<
978*d9f75844SAndroid Build Coastguard Worker           SdpSemantics,
979*d9f75844SAndroid Build Coastguard Worker           std::tuple<std::string,
980*d9f75844SAndroid Build Coastguard Worker                      std::function<void(cricket::SessionDescription*)>,
981*d9f75844SAndroid Build Coastguard Worker                      std::string>>> {
982*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionMediaInvalidMediaTest()983*d9f75844SAndroid Build Coastguard Worker   PeerConnectionMediaInvalidMediaTest()
984*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) {
985*d9f75844SAndroid Build Coastguard Worker     auto param = std::get<1>(GetParam());
986*d9f75844SAndroid Build Coastguard Worker     mutator_ = std::get<1>(param);
987*d9f75844SAndroid Build Coastguard Worker     expected_error_ = std::get<2>(param);
988*d9f75844SAndroid Build Coastguard Worker   }
989*d9f75844SAndroid Build Coastguard Worker 
990*d9f75844SAndroid Build Coastguard Worker   std::function<void(cricket::SessionDescription*)> mutator_;
991*d9f75844SAndroid Build Coastguard Worker   std::string expected_error_;
992*d9f75844SAndroid Build Coastguard Worker };
993*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaInvalidMediaTest,FailToSetRemoteAnswer)994*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaInvalidMediaTest, FailToSetRemoteAnswer) {
995*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
996*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
997*d9f75844SAndroid Build Coastguard Worker 
998*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
999*d9f75844SAndroid Build Coastguard Worker 
1000*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1001*d9f75844SAndroid Build Coastguard Worker   mutator_(answer->description());
1002*d9f75844SAndroid Build Coastguard Worker 
1003*d9f75844SAndroid Build Coastguard Worker   std::string error;
1004*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(caller->SetRemoteDescription(std::move(answer), &error));
1005*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("Failed to set remote answer sdp: " + expected_error_, error);
1006*d9f75844SAndroid Build Coastguard Worker }
1007*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaInvalidMediaTest,FailToSetLocalAnswer)1008*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaInvalidMediaTest, FailToSetLocalAnswer) {
1009*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1010*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1011*d9f75844SAndroid Build Coastguard Worker 
1012*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1013*d9f75844SAndroid Build Coastguard Worker 
1014*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1015*d9f75844SAndroid Build Coastguard Worker   mutator_(answer->description());
1016*d9f75844SAndroid Build Coastguard Worker 
1017*d9f75844SAndroid Build Coastguard Worker   std::string error;
1018*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(callee->SetLocalDescription(std::move(answer), &error));
1019*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("Failed to set local answer sdp: " + expected_error_, error);
1020*d9f75844SAndroid Build Coastguard Worker }
1021*d9f75844SAndroid Build Coastguard Worker 
RemoveVideoContent(cricket::SessionDescription * desc)1022*d9f75844SAndroid Build Coastguard Worker void RemoveVideoContent(cricket::SessionDescription* desc) {
1023*d9f75844SAndroid Build Coastguard Worker   auto content_name = cricket::GetFirstVideoContent(desc)->name;
1024*d9f75844SAndroid Build Coastguard Worker   desc->RemoveContentByName(content_name);
1025*d9f75844SAndroid Build Coastguard Worker   desc->RemoveTransportInfoByName(content_name);
1026*d9f75844SAndroid Build Coastguard Worker }
1027*d9f75844SAndroid Build Coastguard Worker 
RenameVideoContent(cricket::SessionDescription * desc)1028*d9f75844SAndroid Build Coastguard Worker void RenameVideoContent(cricket::SessionDescription* desc) {
1029*d9f75844SAndroid Build Coastguard Worker   auto* video_content = cricket::GetFirstVideoContent(desc);
1030*d9f75844SAndroid Build Coastguard Worker   auto* transport_info = desc->GetTransportInfoByName(video_content->name);
1031*d9f75844SAndroid Build Coastguard Worker   video_content->name = "video_renamed";
1032*d9f75844SAndroid Build Coastguard Worker   transport_info->content_name = video_content->name;
1033*d9f75844SAndroid Build Coastguard Worker }
1034*d9f75844SAndroid Build Coastguard Worker 
ReverseMediaContent(cricket::SessionDescription * desc)1035*d9f75844SAndroid Build Coastguard Worker void ReverseMediaContent(cricket::SessionDescription* desc) {
1036*d9f75844SAndroid Build Coastguard Worker   absl::c_reverse(desc->contents());
1037*d9f75844SAndroid Build Coastguard Worker   absl::c_reverse(desc->transport_infos());
1038*d9f75844SAndroid Build Coastguard Worker }
1039*d9f75844SAndroid Build Coastguard Worker 
ChangeMediaTypeAudioToVideo(cricket::SessionDescription * desc)1040*d9f75844SAndroid Build Coastguard Worker void ChangeMediaTypeAudioToVideo(cricket::SessionDescription* desc) {
1041*d9f75844SAndroid Build Coastguard Worker   std::string audio_mid = cricket::GetFirstAudioContent(desc)->name;
1042*d9f75844SAndroid Build Coastguard Worker   desc->RemoveContentByName(audio_mid);
1043*d9f75844SAndroid Build Coastguard Worker   auto* video_content = cricket::GetFirstVideoContent(desc);
1044*d9f75844SAndroid Build Coastguard Worker   desc->AddContent(audio_mid, video_content->type,
1045*d9f75844SAndroid Build Coastguard Worker                    video_content->media_description()->Clone());
1046*d9f75844SAndroid Build Coastguard Worker }
1047*d9f75844SAndroid Build Coastguard Worker 
1048*d9f75844SAndroid Build Coastguard Worker constexpr char kMLinesOutOfOrder[] =
1049*d9f75844SAndroid Build Coastguard Worker     "The order of m-lines in answer doesn't match order in offer. Rejecting "
1050*d9f75844SAndroid Build Coastguard Worker     "answer.";
1051*d9f75844SAndroid Build Coastguard Worker 
1052*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
1053*d9f75844SAndroid Build Coastguard Worker     PeerConnectionMediaTest,
1054*d9f75844SAndroid Build Coastguard Worker     PeerConnectionMediaInvalidMediaTest,
1055*d9f75844SAndroid Build Coastguard Worker     Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
1056*d9f75844SAndroid Build Coastguard Worker             Values(std::make_tuple("remove video",
1057*d9f75844SAndroid Build Coastguard Worker                                    RemoveVideoContent,
1058*d9f75844SAndroid Build Coastguard Worker                                    kMLinesOutOfOrder),
1059*d9f75844SAndroid Build Coastguard Worker                    std::make_tuple("rename video",
1060*d9f75844SAndroid Build Coastguard Worker                                    RenameVideoContent,
1061*d9f75844SAndroid Build Coastguard Worker                                    kMLinesOutOfOrder),
1062*d9f75844SAndroid Build Coastguard Worker                    std::make_tuple("reverse media sections",
1063*d9f75844SAndroid Build Coastguard Worker                                    ReverseMediaContent,
1064*d9f75844SAndroid Build Coastguard Worker                                    kMLinesOutOfOrder),
1065*d9f75844SAndroid Build Coastguard Worker                    std::make_tuple("change audio type to video type",
1066*d9f75844SAndroid Build Coastguard Worker                                    ChangeMediaTypeAudioToVideo,
1067*d9f75844SAndroid Build Coastguard Worker                                    kMLinesOutOfOrder))));
1068*d9f75844SAndroid Build Coastguard Worker 
1069*d9f75844SAndroid Build Coastguard Worker // Test that the correct media engine send/recv streams are created when doing
1070*d9f75844SAndroid Build Coastguard Worker // a series of offer/answers where audio/video are both sent, then audio is
1071*d9f75844SAndroid Build Coastguard Worker // rejected, then both audio/video sent again.
TEST_P(PeerConnectionMediaTest,TestAVOfferWithAudioOnlyAnswer)1072*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) {
1073*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan()) {
1074*d9f75844SAndroid Build Coastguard Worker     // offer_to_receive_ is not implemented when creating answers with Unified
1075*d9f75844SAndroid Build Coastguard Worker     // Plan semantics specified.
1076*d9f75844SAndroid Build Coastguard Worker     return;
1077*d9f75844SAndroid Build Coastguard Worker   }
1078*d9f75844SAndroid Build Coastguard Worker 
1079*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options_reject_video;
1080*d9f75844SAndroid Build Coastguard Worker   options_reject_video.offer_to_receive_audio =
1081*d9f75844SAndroid Build Coastguard Worker       RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
1082*d9f75844SAndroid Build Coastguard Worker   options_reject_video.offer_to_receive_video = 0;
1083*d9f75844SAndroid Build Coastguard Worker 
1084*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
1085*d9f75844SAndroid Build Coastguard Worker   caller->AddAudioTrack("a");
1086*d9f75844SAndroid Build Coastguard Worker   caller->AddVideoTrack("v");
1087*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
1088*d9f75844SAndroid Build Coastguard Worker 
1089*d9f75844SAndroid Build Coastguard Worker   // Caller initially offers to send/recv audio and video.
1090*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1091*d9f75844SAndroid Build Coastguard Worker   // Callee accepts the audio as recv only but rejects the video.
1092*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(
1093*d9f75844SAndroid Build Coastguard Worker       callee->CreateAnswerAndSetAsLocal(options_reject_video)));
1094*d9f75844SAndroid Build Coastguard Worker 
1095*d9f75844SAndroid Build Coastguard Worker   auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1096*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller_voice);
1097*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, caller_voice->recv_streams().size());
1098*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, caller_voice->send_streams().size());
1099*d9f75844SAndroid Build Coastguard Worker   auto caller_video = caller->media_engine()->GetVideoChannel(0);
1100*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller_video);
1101*d9f75844SAndroid Build Coastguard Worker 
1102*d9f75844SAndroid Build Coastguard Worker   // Callee adds its own audio/video stream and offers to receive audio/video
1103*d9f75844SAndroid Build Coastguard Worker   // too.
1104*d9f75844SAndroid Build Coastguard Worker   callee->AddAudioTrack("a");
1105*d9f75844SAndroid Build Coastguard Worker   auto callee_video_track = callee->AddVideoTrack("v");
1106*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1107*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1108*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1109*d9f75844SAndroid Build Coastguard Worker 
1110*d9f75844SAndroid Build Coastguard Worker   auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1111*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_voice);
1112*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->recv_streams().size());
1113*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->send_streams().size());
1114*d9f75844SAndroid Build Coastguard Worker   auto callee_video = callee->media_engine()->GetVideoChannel(0);
1115*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_video);
1116*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->recv_streams().size());
1117*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->send_streams().size());
1118*d9f75844SAndroid Build Coastguard Worker 
1119*d9f75844SAndroid Build Coastguard Worker   // Callee removes video but keeps audio and rejects the video once again.
1120*d9f75844SAndroid Build Coastguard Worker   callee->pc()->RemoveTrackOrError(callee_video_track);
1121*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1122*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1123*d9f75844SAndroid Build Coastguard Worker       callee->SetLocalDescription(callee->CreateAnswer(options_reject_video)));
1124*d9f75844SAndroid Build Coastguard Worker 
1125*d9f75844SAndroid Build Coastguard Worker   callee_voice = callee->media_engine()->GetVoiceChannel(0);
1126*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_voice);
1127*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->recv_streams().size());
1128*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->send_streams().size());
1129*d9f75844SAndroid Build Coastguard Worker   callee_video = callee->media_engine()->GetVideoChannel(0);
1130*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(callee_video);
1131*d9f75844SAndroid Build Coastguard Worker }
1132*d9f75844SAndroid Build Coastguard Worker 
1133*d9f75844SAndroid Build Coastguard Worker // Test that the correct media engine send/recv streams are created when doing
1134*d9f75844SAndroid Build Coastguard Worker // a series of offer/answers where audio/video are both sent, then video is
1135*d9f75844SAndroid Build Coastguard Worker // rejected, then both audio/video sent again.
TEST_P(PeerConnectionMediaTest,TestAVOfferWithVideoOnlyAnswer)1136*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) {
1137*d9f75844SAndroid Build Coastguard Worker   if (IsUnifiedPlan()) {
1138*d9f75844SAndroid Build Coastguard Worker     // offer_to_receive_ is not implemented when creating answers with Unified
1139*d9f75844SAndroid Build Coastguard Worker     // Plan semantics specified.
1140*d9f75844SAndroid Build Coastguard Worker     return;
1141*d9f75844SAndroid Build Coastguard Worker   }
1142*d9f75844SAndroid Build Coastguard Worker 
1143*d9f75844SAndroid Build Coastguard Worker   // Disable the bundling here. If the media is bundled on audio
1144*d9f75844SAndroid Build Coastguard Worker   // transport, then we can't reject the audio because switching the bundled
1145*d9f75844SAndroid Build Coastguard Worker   // transport is not currently supported.
1146*d9f75844SAndroid Build Coastguard Worker   // (https://bugs.chromium.org/p/webrtc/issues/detail?id=6704)
1147*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options_no_bundle;
1148*d9f75844SAndroid Build Coastguard Worker   options_no_bundle.use_rtp_mux = false;
1149*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options_reject_audio = options_no_bundle;
1150*d9f75844SAndroid Build Coastguard Worker   options_reject_audio.offer_to_receive_audio = 0;
1151*d9f75844SAndroid Build Coastguard Worker   options_reject_audio.offer_to_receive_video =
1152*d9f75844SAndroid Build Coastguard Worker       RTCOfferAnswerOptions::kMaxOfferToReceiveMedia;
1153*d9f75844SAndroid Build Coastguard Worker 
1154*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
1155*d9f75844SAndroid Build Coastguard Worker   caller->AddAudioTrack("a");
1156*d9f75844SAndroid Build Coastguard Worker   caller->AddVideoTrack("v");
1157*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
1158*d9f75844SAndroid Build Coastguard Worker 
1159*d9f75844SAndroid Build Coastguard Worker   // Caller initially offers to send/recv audio and video.
1160*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1161*d9f75844SAndroid Build Coastguard Worker   // Callee accepts the video as recv only but rejects the audio.
1162*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(
1163*d9f75844SAndroid Build Coastguard Worker       callee->CreateAnswerAndSetAsLocal(options_reject_audio)));
1164*d9f75844SAndroid Build Coastguard Worker 
1165*d9f75844SAndroid Build Coastguard Worker   auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1166*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller_voice);
1167*d9f75844SAndroid Build Coastguard Worker   auto caller_video = caller->media_engine()->GetVideoChannel(0);
1168*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller_video);
1169*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, caller_video->recv_streams().size());
1170*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, caller_video->send_streams().size());
1171*d9f75844SAndroid Build Coastguard Worker 
1172*d9f75844SAndroid Build Coastguard Worker   // Callee adds its own audio/video stream and offers to receive audio/video
1173*d9f75844SAndroid Build Coastguard Worker   // too.
1174*d9f75844SAndroid Build Coastguard Worker   auto callee_audio_track = callee->AddAudioTrack("a");
1175*d9f75844SAndroid Build Coastguard Worker   callee->AddVideoTrack("v");
1176*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1177*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(
1178*d9f75844SAndroid Build Coastguard Worker       callee->CreateAnswerAndSetAsLocal(options_no_bundle)));
1179*d9f75844SAndroid Build Coastguard Worker 
1180*d9f75844SAndroid Build Coastguard Worker   auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1181*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_voice);
1182*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->recv_streams().size());
1183*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_voice->send_streams().size());
1184*d9f75844SAndroid Build Coastguard Worker   auto callee_video = callee->media_engine()->GetVideoChannel(0);
1185*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_video);
1186*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->recv_streams().size());
1187*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->send_streams().size());
1188*d9f75844SAndroid Build Coastguard Worker 
1189*d9f75844SAndroid Build Coastguard Worker   // Callee removes audio but keeps video and rejects the audio once again.
1190*d9f75844SAndroid Build Coastguard Worker   callee->pc()->RemoveTrackOrError(callee_audio_track);
1191*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1192*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1193*d9f75844SAndroid Build Coastguard Worker       callee->SetLocalDescription(callee->CreateAnswer(options_reject_audio)));
1194*d9f75844SAndroid Build Coastguard Worker 
1195*d9f75844SAndroid Build Coastguard Worker   callee_voice = callee->media_engine()->GetVoiceChannel(0);
1196*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(callee_voice);
1197*d9f75844SAndroid Build Coastguard Worker   callee_video = callee->media_engine()->GetVideoChannel(0);
1198*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee_video);
1199*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->recv_streams().size());
1200*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, callee_video->send_streams().size());
1201*d9f75844SAndroid Build Coastguard Worker }
1202*d9f75844SAndroid Build Coastguard Worker 
1203*d9f75844SAndroid Build Coastguard Worker // Tests that if the underlying video encoder fails to be initialized (signaled
1204*d9f75844SAndroid Build Coastguard Worker // by failing to set send codecs), the PeerConnection signals the error to the
1205*d9f75844SAndroid Build Coastguard Worker // client.
TEST_P(PeerConnectionMediaTest,MediaEngineErrorPropagatedToClients)1206*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, MediaEngineErrorPropagatedToClients) {
1207*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1208*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1209*d9f75844SAndroid Build Coastguard Worker 
1210*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1211*d9f75844SAndroid Build Coastguard Worker 
1212*d9f75844SAndroid Build Coastguard Worker   auto video_channel = caller->media_engine()->GetVideoChannel(0);
1213*d9f75844SAndroid Build Coastguard Worker   video_channel->set_fail_set_send_codecs(true);
1214*d9f75844SAndroid Build Coastguard Worker 
1215*d9f75844SAndroid Build Coastguard Worker   std::string error;
1216*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(),
1217*d9f75844SAndroid Build Coastguard Worker                                             &error));
1218*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string("Failed to set remote answer sdp: Failed to set remote "
1219*d9f75844SAndroid Build Coastguard Worker                         "video description "
1220*d9f75844SAndroid Build Coastguard Worker                         "send parameters for m-section with mid='") +
1221*d9f75844SAndroid Build Coastguard Worker                 (IsUnifiedPlan() ? "1" : "video") + "'.",
1222*d9f75844SAndroid Build Coastguard Worker             error);
1223*d9f75844SAndroid Build Coastguard Worker }
1224*d9f75844SAndroid Build Coastguard Worker 
1225*d9f75844SAndroid Build Coastguard Worker // Tests that if the underlying video encoder fails once then subsequent
1226*d9f75844SAndroid Build Coastguard Worker // attempts at setting the local/remote description will also fail, even if
1227*d9f75844SAndroid Build Coastguard Worker // SetSendCodecs no longer fails.
TEST_P(PeerConnectionMediaTest,FailToApplyDescriptionIfVideoEncoderHasEverFailed)1228*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
1229*d9f75844SAndroid Build Coastguard Worker        FailToApplyDescriptionIfVideoEncoderHasEverFailed) {
1230*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1231*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1232*d9f75844SAndroid Build Coastguard Worker 
1233*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1234*d9f75844SAndroid Build Coastguard Worker 
1235*d9f75844SAndroid Build Coastguard Worker   auto video_channel = caller->media_engine()->GetVideoChannel(0);
1236*d9f75844SAndroid Build Coastguard Worker   video_channel->set_fail_set_send_codecs(true);
1237*d9f75844SAndroid Build Coastguard Worker 
1238*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(
1239*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1240*d9f75844SAndroid Build Coastguard Worker 
1241*d9f75844SAndroid Build Coastguard Worker   video_channel->set_fail_set_send_codecs(false);
1242*d9f75844SAndroid Build Coastguard Worker 
1243*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->SetRemoteDescription(callee->CreateAnswer()));
1244*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->SetLocalDescription(caller->CreateOffer()));
1245*d9f75844SAndroid Build Coastguard Worker }
1246*d9f75844SAndroid Build Coastguard Worker 
RenameContent(cricket::SessionDescription * desc,cricket::MediaType media_type,const std::string & new_name)1247*d9f75844SAndroid Build Coastguard Worker void RenameContent(cricket::SessionDescription* desc,
1248*d9f75844SAndroid Build Coastguard Worker                    cricket::MediaType media_type,
1249*d9f75844SAndroid Build Coastguard Worker                    const std::string& new_name) {
1250*d9f75844SAndroid Build Coastguard Worker   auto* content = cricket::GetFirstMediaContent(desc, media_type);
1251*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(content);
1252*d9f75844SAndroid Build Coastguard Worker   std::string old_name = content->name;
1253*d9f75844SAndroid Build Coastguard Worker   content->name = new_name;
1254*d9f75844SAndroid Build Coastguard Worker   auto* transport = desc->GetTransportInfoByName(old_name);
1255*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(transport);
1256*d9f75844SAndroid Build Coastguard Worker   transport->content_name = new_name;
1257*d9f75844SAndroid Build Coastguard Worker 
1258*d9f75844SAndroid Build Coastguard Worker   // Rename the content name in the BUNDLE group.
1259*d9f75844SAndroid Build Coastguard Worker   cricket::ContentGroup new_bundle_group =
1260*d9f75844SAndroid Build Coastguard Worker       *desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1261*d9f75844SAndroid Build Coastguard Worker   new_bundle_group.RemoveContentName(old_name);
1262*d9f75844SAndroid Build Coastguard Worker   new_bundle_group.AddContentName(new_name);
1263*d9f75844SAndroid Build Coastguard Worker   desc->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1264*d9f75844SAndroid Build Coastguard Worker   desc->AddGroup(new_bundle_group);
1265*d9f75844SAndroid Build Coastguard Worker }
1266*d9f75844SAndroid Build Coastguard Worker 
1267*d9f75844SAndroid Build Coastguard Worker // Tests that an answer responds with the same MIDs as the offer.
TEST_P(PeerConnectionMediaTest,AnswerHasSameMidsAsOffer)1268*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) {
1269*d9f75844SAndroid Build Coastguard Worker   const std::string kAudioMid = "notdefault1";
1270*d9f75844SAndroid Build Coastguard Worker   const std::string kVideoMid = "notdefault2";
1271*d9f75844SAndroid Build Coastguard Worker 
1272*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1273*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1274*d9f75844SAndroid Build Coastguard Worker 
1275*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1276*d9f75844SAndroid Build Coastguard Worker   RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, kAudioMid);
1277*d9f75844SAndroid Build Coastguard Worker   RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, kVideoMid);
1278*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1279*d9f75844SAndroid Build Coastguard Worker 
1280*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1281*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kAudioMid,
1282*d9f75844SAndroid Build Coastguard Worker             cricket::GetFirstAudioContent(answer->description())->name);
1283*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kVideoMid,
1284*d9f75844SAndroid Build Coastguard Worker             cricket::GetFirstVideoContent(answer->description())->name);
1285*d9f75844SAndroid Build Coastguard Worker }
1286*d9f75844SAndroid Build Coastguard Worker 
1287*d9f75844SAndroid Build Coastguard Worker // Test that if the callee creates a re-offer, the MIDs are the same as the
1288*d9f75844SAndroid Build Coastguard Worker // original offer.
TEST_P(PeerConnectionMediaTest,ReOfferHasSameMidsAsFirstOffer)1289*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) {
1290*d9f75844SAndroid Build Coastguard Worker   const std::string kAudioMid = "notdefault1";
1291*d9f75844SAndroid Build Coastguard Worker   const std::string kVideoMid = "notdefault2";
1292*d9f75844SAndroid Build Coastguard Worker 
1293*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1294*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1295*d9f75844SAndroid Build Coastguard Worker 
1296*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1297*d9f75844SAndroid Build Coastguard Worker   RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, kAudioMid);
1298*d9f75844SAndroid Build Coastguard Worker   RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, kVideoMid);
1299*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1300*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1301*d9f75844SAndroid Build Coastguard Worker 
1302*d9f75844SAndroid Build Coastguard Worker   auto reoffer = callee->CreateOffer();
1303*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kAudioMid,
1304*d9f75844SAndroid Build Coastguard Worker             cricket::GetFirstAudioContent(reoffer->description())->name);
1305*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kVideoMid,
1306*d9f75844SAndroid Build Coastguard Worker             cricket::GetFirstVideoContent(reoffer->description())->name);
1307*d9f75844SAndroid Build Coastguard Worker }
1308*d9f75844SAndroid Build Coastguard Worker 
1309*d9f75844SAndroid Build Coastguard Worker // Test that SetRemoteDescription returns an error if there are two m= sections
1310*d9f75844SAndroid Build Coastguard Worker // with the same MID value.
TEST_P(PeerConnectionMediaTest,SetRemoteDescriptionFailsWithDuplicateMids)1311*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, SetRemoteDescriptionFailsWithDuplicateMids) {
1312*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1313*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1314*d9f75844SAndroid Build Coastguard Worker 
1315*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1316*d9f75844SAndroid Build Coastguard Worker   RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, "same");
1317*d9f75844SAndroid Build Coastguard Worker   RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, "same");
1318*d9f75844SAndroid Build Coastguard Worker 
1319*d9f75844SAndroid Build Coastguard Worker   std::string error;
1320*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer), &error));
1321*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(error,
1322*d9f75844SAndroid Build Coastguard Worker             "Failed to set remote offer sdp: Duplicate a=mid value 'same'.");
1323*d9f75844SAndroid Build Coastguard Worker }
1324*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionMediaTest,CombinedAudioVideoBweConfigPropagatedToMediaEngine)1325*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest,
1326*d9f75844SAndroid Build Coastguard Worker        CombinedAudioVideoBweConfigPropagatedToMediaEngine) {
1327*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1328*d9f75844SAndroid Build Coastguard Worker   config.combined_audio_video_bwe.emplace(true);
1329*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(config);
1330*d9f75844SAndroid Build Coastguard Worker 
1331*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1332*d9f75844SAndroid Build Coastguard Worker 
1333*d9f75844SAndroid Build Coastguard Worker   auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1334*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller_voice);
1335*d9f75844SAndroid Build Coastguard Worker   const cricket::AudioOptions& audio_options = caller_voice->options();
1336*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(config.combined_audio_video_bwe,
1337*d9f75844SAndroid Build Coastguard Worker             audio_options.combined_audio_video_bwe);
1338*d9f75844SAndroid Build Coastguard Worker }
1339*d9f75844SAndroid Build Coastguard Worker 
1340*d9f75844SAndroid Build Coastguard Worker // Test that if a RED codec refers to another codec in its fmtp line, but that
1341*d9f75844SAndroid Build Coastguard Worker // codec's payload type was reassigned for some reason (either the remote
1342*d9f75844SAndroid Build Coastguard Worker // endpoint selected a different payload type or there was a conflict), the RED
1343*d9f75844SAndroid Build Coastguard Worker // fmtp line is modified to refer to the correct payload type.
TEST_P(PeerConnectionMediaTest,RedFmtpPayloadTypeReassigned)1344*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RedFmtpPayloadTypeReassigned) {
1345*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> caller_fake_codecs;
1346*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(100, "foo", 0, 0, 1));
1347*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1348*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetAudioCodecs(caller_fake_codecs);
1349*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(caller_fake_engine));
1350*d9f75844SAndroid Build Coastguard Worker 
1351*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> callee_fake_codecs;
1352*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(120, "foo", 0, 0, 1));
1353*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(
1354*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(121, cricket::kRedCodecName, 0, 0, 1));
1355*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1356*d9f75844SAndroid Build Coastguard Worker                                      "120/120");
1357*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1358*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetAudioCodecs(callee_fake_codecs);
1359*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudio(std::move(callee_fake_engine));
1360*d9f75844SAndroid Build Coastguard Worker 
1361*d9f75844SAndroid Build Coastguard Worker   // Offer from the caller establishes 100 as the "foo" payload type.
1362*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1363*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1364*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
1365*d9f75844SAndroid Build Coastguard Worker   auto answer_description =
1366*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(answer->description());
1367*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, answer_description->codecs().size());
1368*d9f75844SAndroid Build Coastguard Worker 
1369*d9f75844SAndroid Build Coastguard Worker   // Offer from the callee should respect the established payload type, and
1370*d9f75844SAndroid Build Coastguard Worker   // attempt to add RED, which should refer to the correct payload type.
1371*d9f75844SAndroid Build Coastguard Worker   offer = callee->CreateOfferAndSetAsLocal();
1372*d9f75844SAndroid Build Coastguard Worker   auto* offer_description =
1373*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(offer->description());
1374*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, offer_description->codecs().size());
1375*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : offer_description->codecs()) {
1376*d9f75844SAndroid Build Coastguard Worker     if (codec.name == "foo") {
1377*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(100, codec.id);
1378*d9f75844SAndroid Build Coastguard Worker     } else if (codec.name == cricket::kRedCodecName) {
1379*d9f75844SAndroid Build Coastguard Worker       std::string fmtp;
1380*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(codec.GetParam("", &fmtp));
1381*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ("100/100", fmtp);
1382*d9f75844SAndroid Build Coastguard Worker     }
1383*d9f75844SAndroid Build Coastguard Worker   }
1384*d9f75844SAndroid Build Coastguard Worker }
1385*d9f75844SAndroid Build Coastguard Worker 
1386*d9f75844SAndroid Build Coastguard Worker // Test that RED without fmtp does match RED without fmtp.
TEST_P(PeerConnectionMediaTest,RedFmtpPayloadTypeNoFmtpMatchNoFmtp)1387*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RedFmtpPayloadTypeNoFmtpMatchNoFmtp) {
1388*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> caller_fake_codecs;
1389*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(100, "foo", 0, 0, 1));
1390*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(
1391*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(101, cricket::kRedCodecName, 0, 0, 1));
1392*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1393*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetAudioCodecs(caller_fake_codecs);
1394*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(caller_fake_engine));
1395*d9f75844SAndroid Build Coastguard Worker 
1396*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> callee_fake_codecs;
1397*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(120, "foo", 0, 0, 1));
1398*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(
1399*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(121, cricket::kRedCodecName, 0, 0, 1));
1400*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1401*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetAudioCodecs(callee_fake_codecs);
1402*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudio(std::move(callee_fake_engine));
1403*d9f75844SAndroid Build Coastguard Worker 
1404*d9f75844SAndroid Build Coastguard Worker   // Offer from the caller establishes 100 as the "foo" payload type.
1405*d9f75844SAndroid Build Coastguard Worker   // Red (without fmtp) is negotiated.
1406*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1407*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1408*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
1409*d9f75844SAndroid Build Coastguard Worker   auto answer_description =
1410*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(answer->description());
1411*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, answer_description->codecs().size());
1412*d9f75844SAndroid Build Coastguard Worker 
1413*d9f75844SAndroid Build Coastguard Worker   // Offer from the callee should respect the established payload type, and
1414*d9f75844SAndroid Build Coastguard Worker   // attempt to add RED.
1415*d9f75844SAndroid Build Coastguard Worker   offer = callee->CreateOfferAndSetAsLocal();
1416*d9f75844SAndroid Build Coastguard Worker   auto* offer_description =
1417*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(offer->description());
1418*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, offer_description->codecs().size());
1419*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : offer_description->codecs()) {
1420*d9f75844SAndroid Build Coastguard Worker     if (codec.name == "foo") {
1421*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(100, codec.id);
1422*d9f75844SAndroid Build Coastguard Worker     } else if (codec.name == cricket::kRedCodecName) {
1423*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(101, codec.id);
1424*d9f75844SAndroid Build Coastguard Worker     }
1425*d9f75844SAndroid Build Coastguard Worker   }
1426*d9f75844SAndroid Build Coastguard Worker }
1427*d9f75844SAndroid Build Coastguard Worker 
1428*d9f75844SAndroid Build Coastguard Worker // Test that RED without fmtp does not match RED with fmtp.
TEST_P(PeerConnectionMediaTest,RedFmtpPayloadTypeNoFmtpNoMatchFmtp)1429*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RedFmtpPayloadTypeNoFmtpNoMatchFmtp) {
1430*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> caller_fake_codecs;
1431*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(100, "foo", 0, 0, 1));
1432*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(
1433*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(101, cricket::kRedCodecName, 0, 0, 1));
1434*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1435*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetAudioCodecs(caller_fake_codecs);
1436*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(caller_fake_engine));
1437*d9f75844SAndroid Build Coastguard Worker 
1438*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> callee_fake_codecs;
1439*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(120, "foo", 0, 0, 1));
1440*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(
1441*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(121, cricket::kRedCodecName, 0, 0, 1));
1442*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1443*d9f75844SAndroid Build Coastguard Worker                                      "120/120");
1444*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1445*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetAudioCodecs(callee_fake_codecs);
1446*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudio(std::move(callee_fake_engine));
1447*d9f75844SAndroid Build Coastguard Worker 
1448*d9f75844SAndroid Build Coastguard Worker   // Offer from the caller establishes 100 as the "foo" payload type.
1449*d9f75844SAndroid Build Coastguard Worker   // It should not negotiate RED.
1450*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1451*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1452*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
1453*d9f75844SAndroid Build Coastguard Worker   auto answer_description =
1454*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(answer->description());
1455*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, answer_description->codecs().size());
1456*d9f75844SAndroid Build Coastguard Worker 
1457*d9f75844SAndroid Build Coastguard Worker   // Offer from the callee should respect the established payload type, and
1458*d9f75844SAndroid Build Coastguard Worker   // attempt to add RED, which should refer to the correct payload type.
1459*d9f75844SAndroid Build Coastguard Worker   offer = callee->CreateOfferAndSetAsLocal();
1460*d9f75844SAndroid Build Coastguard Worker   auto* offer_description =
1461*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(offer->description());
1462*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, offer_description->codecs().size());
1463*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : offer_description->codecs()) {
1464*d9f75844SAndroid Build Coastguard Worker     if (codec.name == "foo") {
1465*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(100, codec.id);
1466*d9f75844SAndroid Build Coastguard Worker     } else if (codec.name == cricket::kRedCodecName) {
1467*d9f75844SAndroid Build Coastguard Worker       std::string fmtp;
1468*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(
1469*d9f75844SAndroid Build Coastguard Worker           codec.GetParam(cricket::kCodecParamNotInNameValueFormat, &fmtp));
1470*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ("100/100", fmtp);
1471*d9f75844SAndroid Build Coastguard Worker     }
1472*d9f75844SAndroid Build Coastguard Worker   }
1473*d9f75844SAndroid Build Coastguard Worker }
1474*d9f75844SAndroid Build Coastguard Worker 
1475*d9f75844SAndroid Build Coastguard Worker // Test that RED with fmtp must match base codecs.
TEST_P(PeerConnectionMediaTest,RedFmtpPayloadTypeMustMatchBaseCodecs)1476*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RedFmtpPayloadTypeMustMatchBaseCodecs) {
1477*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> caller_fake_codecs;
1478*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(100, "foo", 0, 0, 1));
1479*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(
1480*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(101, cricket::kRedCodecName, 0, 0, 1));
1481*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1482*d9f75844SAndroid Build Coastguard Worker                                      "100/100");
1483*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1484*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetAudioCodecs(caller_fake_codecs);
1485*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(caller_fake_engine));
1486*d9f75844SAndroid Build Coastguard Worker 
1487*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> callee_fake_codecs;
1488*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(120, "foo", 0, 0, 1));
1489*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(
1490*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(121, cricket::kRedCodecName, 0, 0, 1));
1491*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(122, "bar", 0, 0, 1));
1492*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1493*d9f75844SAndroid Build Coastguard Worker                                      "122/122");
1494*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1495*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetAudioCodecs(callee_fake_codecs);
1496*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudio(std::move(callee_fake_engine));
1497*d9f75844SAndroid Build Coastguard Worker 
1498*d9f75844SAndroid Build Coastguard Worker   // Offer from the caller establishes 100 as the "foo" payload type.
1499*d9f75844SAndroid Build Coastguard Worker   // It should not negotiate RED since RED is associated with foo, not bar.
1500*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1501*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1502*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
1503*d9f75844SAndroid Build Coastguard Worker   auto answer_description =
1504*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(answer->description());
1505*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, answer_description->codecs().size());
1506*d9f75844SAndroid Build Coastguard Worker }
1507*d9f75844SAndroid Build Coastguard Worker 
1508*d9f75844SAndroid Build Coastguard Worker // Test behaviour when the RED fmtp attempts to specify different codecs
1509*d9f75844SAndroid Build Coastguard Worker // which is not supported.
TEST_P(PeerConnectionMediaTest,RedFmtpPayloadMixed)1510*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RedFmtpPayloadMixed) {
1511*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> caller_fake_codecs;
1512*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(100, "foo", 0, 0, 1));
1513*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(102, "bar", 0, 0, 1));
1514*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(
1515*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(101, cricket::kRedCodecName, 0, 0, 1));
1516*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1517*d9f75844SAndroid Build Coastguard Worker                                      "100/102");
1518*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1519*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetAudioCodecs(caller_fake_codecs);
1520*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(caller_fake_engine));
1521*d9f75844SAndroid Build Coastguard Worker 
1522*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> callee_fake_codecs;
1523*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(120, "foo", 0, 0, 1));
1524*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(
1525*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(121, cricket::kRedCodecName, 0, 0, 1));
1526*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1527*d9f75844SAndroid Build Coastguard Worker                                      "120/120");
1528*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1529*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetAudioCodecs(callee_fake_codecs);
1530*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudio(std::move(callee_fake_engine));
1531*d9f75844SAndroid Build Coastguard Worker 
1532*d9f75844SAndroid Build Coastguard Worker   // Offer from the caller establishes 100 as the "foo" payload type.
1533*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1534*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1535*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
1536*d9f75844SAndroid Build Coastguard Worker   auto answer_description =
1537*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(answer->description());
1538*d9f75844SAndroid Build Coastguard Worker   // RED is not negotiated.
1539*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, answer_description->codecs().size());
1540*d9f75844SAndroid Build Coastguard Worker }
1541*d9f75844SAndroid Build Coastguard Worker 
1542*d9f75844SAndroid Build Coastguard Worker // Test behaviour when the RED fmtp attempts to negotiate different levels of
1543*d9f75844SAndroid Build Coastguard Worker // redundancy.
TEST_P(PeerConnectionMediaTest,RedFmtpPayloadDifferentRedundancy)1544*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionMediaTest, RedFmtpPayloadDifferentRedundancy) {
1545*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> caller_fake_codecs;
1546*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(cricket::AudioCodec(100, "foo", 0, 0, 1));
1547*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.push_back(
1548*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(101, cricket::kRedCodecName, 0, 0, 1));
1549*d9f75844SAndroid Build Coastguard Worker   caller_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1550*d9f75844SAndroid Build Coastguard Worker                                      "100/100");
1551*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1552*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetAudioCodecs(caller_fake_codecs);
1553*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(caller_fake_engine));
1554*d9f75844SAndroid Build Coastguard Worker 
1555*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> callee_fake_codecs;
1556*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(cricket::AudioCodec(120, "foo", 0, 0, 1));
1557*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.push_back(
1558*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec(121, cricket::kRedCodecName, 0, 0, 1));
1559*d9f75844SAndroid Build Coastguard Worker   callee_fake_codecs.back().SetParam(cricket::kCodecParamNotInNameValueFormat,
1560*d9f75844SAndroid Build Coastguard Worker                                      "120/120/120");
1561*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1562*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetAudioCodecs(callee_fake_codecs);
1563*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudio(std::move(callee_fake_engine));
1564*d9f75844SAndroid Build Coastguard Worker 
1565*d9f75844SAndroid Build Coastguard Worker   // Offer from the caller establishes 100 as the "foo" payload type.
1566*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1567*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1568*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
1569*d9f75844SAndroid Build Coastguard Worker   auto answer_description =
1570*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(answer->description());
1571*d9f75844SAndroid Build Coastguard Worker   // RED is negotiated.
1572*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, answer_description->codecs().size());
1573*d9f75844SAndroid Build Coastguard Worker 
1574*d9f75844SAndroid Build Coastguard Worker   // Offer from the callee should respect the established payload type, and
1575*d9f75844SAndroid Build Coastguard Worker   // attempt to add RED, which should refer to the correct payload type.
1576*d9f75844SAndroid Build Coastguard Worker   offer = callee->CreateOfferAndSetAsLocal();
1577*d9f75844SAndroid Build Coastguard Worker   auto* offer_description =
1578*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(offer->description());
1579*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, offer_description->codecs().size());
1580*d9f75844SAndroid Build Coastguard Worker   for (const auto& codec : offer_description->codecs()) {
1581*d9f75844SAndroid Build Coastguard Worker     if (codec.name == "foo") {
1582*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(100, codec.id);
1583*d9f75844SAndroid Build Coastguard Worker     } else if (codec.name == cricket::kRedCodecName) {
1584*d9f75844SAndroid Build Coastguard Worker       std::string fmtp;
1585*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(
1586*d9f75844SAndroid Build Coastguard Worker           codec.GetParam(cricket::kCodecParamNotInNameValueFormat, &fmtp));
1587*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ("100/100", fmtp);
1588*d9f75844SAndroid Build Coastguard Worker     }
1589*d9f75844SAndroid Build Coastguard Worker   }
1590*d9f75844SAndroid Build Coastguard Worker }
1591*d9f75844SAndroid Build Coastguard Worker 
1592*d9f75844SAndroid Build Coastguard Worker template <typename C>
CompareCodecs(const std::vector<webrtc::RtpCodecCapability> & capabilities,const std::vector<C> & codecs)1593*d9f75844SAndroid Build Coastguard Worker bool CompareCodecs(const std::vector<webrtc::RtpCodecCapability>& capabilities,
1594*d9f75844SAndroid Build Coastguard Worker                    const std::vector<C>& codecs) {
1595*d9f75844SAndroid Build Coastguard Worker   bool capability_has_rtx =
1596*d9f75844SAndroid Build Coastguard Worker       absl::c_any_of(capabilities, [](const webrtc::RtpCodecCapability& codec) {
1597*d9f75844SAndroid Build Coastguard Worker         return codec.name == cricket::kRtxCodecName;
1598*d9f75844SAndroid Build Coastguard Worker       });
1599*d9f75844SAndroid Build Coastguard Worker   bool codecs_has_rtx = absl::c_any_of(codecs, [](const C& codec) {
1600*d9f75844SAndroid Build Coastguard Worker     return codec.name == cricket::kRtxCodecName;
1601*d9f75844SAndroid Build Coastguard Worker   });
1602*d9f75844SAndroid Build Coastguard Worker 
1603*d9f75844SAndroid Build Coastguard Worker   std::vector<C> codecs_no_rtx;
1604*d9f75844SAndroid Build Coastguard Worker   absl::c_copy_if(
1605*d9f75844SAndroid Build Coastguard Worker       codecs, std::back_inserter(codecs_no_rtx),
1606*d9f75844SAndroid Build Coastguard Worker       [](const C& codec) { return codec.name != cricket::kRtxCodecName; });
1607*d9f75844SAndroid Build Coastguard Worker 
1608*d9f75844SAndroid Build Coastguard Worker   std::vector<webrtc::RtpCodecCapability> capabilities_no_rtx;
1609*d9f75844SAndroid Build Coastguard Worker   absl::c_copy_if(capabilities, std::back_inserter(capabilities_no_rtx),
1610*d9f75844SAndroid Build Coastguard Worker                   [](const webrtc::RtpCodecCapability& codec) {
1611*d9f75844SAndroid Build Coastguard Worker                     return codec.name != cricket::kRtxCodecName;
1612*d9f75844SAndroid Build Coastguard Worker                   });
1613*d9f75844SAndroid Build Coastguard Worker 
1614*d9f75844SAndroid Build Coastguard Worker   return capability_has_rtx == codecs_has_rtx &&
1615*d9f75844SAndroid Build Coastguard Worker          absl::c_equal(
1616*d9f75844SAndroid Build Coastguard Worker              capabilities_no_rtx, codecs_no_rtx,
1617*d9f75844SAndroid Build Coastguard Worker              [](const webrtc::RtpCodecCapability& capability, const C& codec) {
1618*d9f75844SAndroid Build Coastguard Worker                return codec.MatchesCapability(capability);
1619*d9f75844SAndroid Build Coastguard Worker              });
1620*d9f75844SAndroid Build Coastguard Worker }
1621*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAudioMissingRecvCodec)1622*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1623*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAudioMissingRecvCodec) {
1624*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
1625*d9f75844SAndroid Build Coastguard Worker   auto send_codecs = fake_engine->voice().send_codecs();
1626*d9f75844SAndroid Build Coastguard Worker   send_codecs.push_back(cricket::AudioCodec(send_codecs.back().id + 1,
1627*d9f75844SAndroid Build Coastguard Worker                                             "send_only_codec", 0, 0, 1));
1628*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetAudioSendCodecs(send_codecs);
1629*d9f75844SAndroid Build Coastguard Worker 
1630*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
1631*d9f75844SAndroid Build Coastguard Worker 
1632*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
1633*d9f75844SAndroid Build Coastguard Worker   auto capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
1634*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_AUDIO);
1635*d9f75844SAndroid Build Coastguard Worker 
1636*d9f75844SAndroid Build Coastguard Worker   std::vector<webrtc::RtpCodecCapability> codecs;
1637*d9f75844SAndroid Build Coastguard Worker   absl::c_copy_if(capabilities.codecs, std::back_inserter(codecs),
1638*d9f75844SAndroid Build Coastguard Worker                   [](const webrtc::RtpCodecCapability& codec) {
1639*d9f75844SAndroid Build Coastguard Worker                     return codec.name.find("_only_") != std::string::npos;
1640*d9f75844SAndroid Build Coastguard Worker                   });
1641*d9f75844SAndroid Build Coastguard Worker 
1642*d9f75844SAndroid Build Coastguard Worker   auto result = transceiver->SetCodecPreferences(codecs);
1643*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1644*d9f75844SAndroid Build Coastguard Worker }
1645*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAudioMissingSendCodec)1646*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1647*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAudioMissingSendCodec) {
1648*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
1649*d9f75844SAndroid Build Coastguard Worker   auto recv_codecs = fake_engine->voice().recv_codecs();
1650*d9f75844SAndroid Build Coastguard Worker   recv_codecs.push_back(cricket::AudioCodec(recv_codecs.back().id + 1,
1651*d9f75844SAndroid Build Coastguard Worker                                             "recv_only_codec", 0, 0, 1));
1652*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetAudioRecvCodecs(recv_codecs);
1653*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
1654*d9f75844SAndroid Build Coastguard Worker 
1655*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
1656*d9f75844SAndroid Build Coastguard Worker   auto capabilities = caller->pc_factory()->GetRtpReceiverCapabilities(
1657*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_AUDIO);
1658*d9f75844SAndroid Build Coastguard Worker 
1659*d9f75844SAndroid Build Coastguard Worker   std::vector<webrtc::RtpCodecCapability> codecs;
1660*d9f75844SAndroid Build Coastguard Worker   absl::c_copy_if(capabilities.codecs, std::back_inserter(codecs),
1661*d9f75844SAndroid Build Coastguard Worker                   [](const webrtc::RtpCodecCapability& codec) {
1662*d9f75844SAndroid Build Coastguard Worker                     return codec.name.find("_only_") != std::string::npos;
1663*d9f75844SAndroid Build Coastguard Worker                   });
1664*d9f75844SAndroid Build Coastguard Worker 
1665*d9f75844SAndroid Build Coastguard Worker   auto result = transceiver->SetCodecPreferences(codecs);
1666*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1667*d9f75844SAndroid Build Coastguard Worker }
1668*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAudioRejectsVideoCodec)1669*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1670*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAudioRejectsVideoCodec) {
1671*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio();
1672*d9f75844SAndroid Build Coastguard Worker 
1673*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
1674*d9f75844SAndroid Build Coastguard Worker   auto video_codecs =
1675*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1676*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
1677*d9f75844SAndroid Build Coastguard Worker           .codecs;
1678*d9f75844SAndroid Build Coastguard Worker   auto codecs =
1679*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1680*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
1681*d9f75844SAndroid Build Coastguard Worker           .codecs;
1682*d9f75844SAndroid Build Coastguard Worker   codecs.insert(codecs.end(), video_codecs.begin(), video_codecs.end());
1683*d9f75844SAndroid Build Coastguard Worker   auto result = transceiver->SetCodecPreferences(codecs);
1684*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1685*d9f75844SAndroid Build Coastguard Worker }
1686*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAudioRejectsOnlyRtxRedFec)1687*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1688*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAudioRejectsOnlyRtxRedFec) {
1689*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
1690*d9f75844SAndroid Build Coastguard Worker   auto audio_codecs = fake_engine->voice().send_codecs();
1691*d9f75844SAndroid Build Coastguard Worker   audio_codecs.push_back(cricket::AudioCodec(audio_codecs.back().id + 1,
1692*d9f75844SAndroid Build Coastguard Worker                                              cricket::kRtxCodecName, 0, 0, 1));
1693*d9f75844SAndroid Build Coastguard Worker   audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1694*d9f75844SAndroid Build Coastguard Worker       std::to_string(audio_codecs.back().id - 1);
1695*d9f75844SAndroid Build Coastguard Worker   audio_codecs.push_back(cricket::AudioCodec(audio_codecs.back().id + 1,
1696*d9f75844SAndroid Build Coastguard Worker                                              cricket::kRedCodecName, 0, 0, 1));
1697*d9f75844SAndroid Build Coastguard Worker   audio_codecs.push_back(cricket::AudioCodec(
1698*d9f75844SAndroid Build Coastguard Worker       audio_codecs.back().id + 1, cricket::kUlpfecCodecName, 0, 0, 1));
1699*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetAudioCodecs(audio_codecs);
1700*d9f75844SAndroid Build Coastguard Worker 
1701*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
1702*d9f75844SAndroid Build Coastguard Worker 
1703*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
1704*d9f75844SAndroid Build Coastguard Worker   auto codecs =
1705*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1706*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
1707*d9f75844SAndroid Build Coastguard Worker           .codecs;
1708*d9f75844SAndroid Build Coastguard Worker   auto codecs_only_rtx_red_fec = codecs;
1709*d9f75844SAndroid Build Coastguard Worker   auto it = std::remove_if(codecs_only_rtx_red_fec.begin(),
1710*d9f75844SAndroid Build Coastguard Worker                            codecs_only_rtx_red_fec.end(),
1711*d9f75844SAndroid Build Coastguard Worker                            [](const webrtc::RtpCodecCapability& codec) {
1712*d9f75844SAndroid Build Coastguard Worker                              return !(codec.name == cricket::kRtxCodecName ||
1713*d9f75844SAndroid Build Coastguard Worker                                       codec.name == cricket::kRedCodecName ||
1714*d9f75844SAndroid Build Coastguard Worker                                       codec.name == cricket::kUlpfecCodecName);
1715*d9f75844SAndroid Build Coastguard Worker                            });
1716*d9f75844SAndroid Build Coastguard Worker   codecs_only_rtx_red_fec.erase(it, codecs_only_rtx_red_fec.end());
1717*d9f75844SAndroid Build Coastguard Worker 
1718*d9f75844SAndroid Build Coastguard Worker   auto result = transceiver->SetCodecPreferences(codecs_only_rtx_red_fec);
1719*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1720*d9f75844SAndroid Build Coastguard Worker }
1721*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAllAudioCodecs)1722*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan, SetCodecPreferencesAllAudioCodecs) {
1723*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio();
1724*d9f75844SAndroid Build Coastguard Worker 
1725*d9f75844SAndroid Build Coastguard Worker   auto sender_audio_codecs =
1726*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1727*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO)
1728*d9f75844SAndroid Build Coastguard Worker           .codecs;
1729*d9f75844SAndroid Build Coastguard Worker 
1730*d9f75844SAndroid Build Coastguard Worker   auto audio_transceiver = caller->pc()->GetTransceivers().front();
1731*d9f75844SAndroid Build Coastguard Worker 
1732*d9f75844SAndroid Build Coastguard Worker   // Normal case, set all capabilities as preferences
1733*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio_transceiver->SetCodecPreferences(sender_audio_codecs).ok());
1734*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1735*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1736*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1737*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1738*d9f75844SAndroid Build Coastguard Worker                     ->as_audio()
1739*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1740*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(sender_audio_codecs, codecs));
1741*d9f75844SAndroid Build Coastguard Worker }
1742*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesResetAudioCodecs)1743*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1744*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesResetAudioCodecs) {
1745*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio();
1746*d9f75844SAndroid Build Coastguard Worker 
1747*d9f75844SAndroid Build Coastguard Worker   auto sender_audio_codecs =
1748*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1749*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO)
1750*d9f75844SAndroid Build Coastguard Worker           .codecs;
1751*d9f75844SAndroid Build Coastguard Worker   std::vector<webrtc::RtpCodecCapability> empty_codecs = {};
1752*d9f75844SAndroid Build Coastguard Worker 
1753*d9f75844SAndroid Build Coastguard Worker   auto audio_transceiver = caller->pc()->GetTransceivers().front();
1754*d9f75844SAndroid Build Coastguard Worker 
1755*d9f75844SAndroid Build Coastguard Worker   // Normal case, reset codec preferences
1756*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio_transceiver->SetCodecPreferences(empty_codecs).ok());
1757*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1758*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1759*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1760*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1761*d9f75844SAndroid Build Coastguard Worker                     ->as_audio()
1762*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1763*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(sender_audio_codecs, codecs));
1764*d9f75844SAndroid Build Coastguard Worker }
1765*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVideoRejectsAudioCodec)1766*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1767*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesVideoRejectsAudioCodec) {
1768*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo();
1769*d9f75844SAndroid Build Coastguard Worker 
1770*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
1771*d9f75844SAndroid Build Coastguard Worker   auto audio_codecs =
1772*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1773*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
1774*d9f75844SAndroid Build Coastguard Worker           .codecs;
1775*d9f75844SAndroid Build Coastguard Worker   auto codecs =
1776*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1777*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
1778*d9f75844SAndroid Build Coastguard Worker           .codecs;
1779*d9f75844SAndroid Build Coastguard Worker   codecs.insert(codecs.end(), audio_codecs.begin(), audio_codecs.end());
1780*d9f75844SAndroid Build Coastguard Worker   auto result = transceiver->SetCodecPreferences(codecs);
1781*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1782*d9f75844SAndroid Build Coastguard Worker }
1783*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVideoRejectsOnlyRtxRedFec)1784*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1785*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesVideoRejectsOnlyRtxRedFec) {
1786*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
1787*d9f75844SAndroid Build Coastguard Worker   auto video_codecs = fake_engine->video().send_codecs();
1788*d9f75844SAndroid Build Coastguard Worker   video_codecs.push_back(
1789*d9f75844SAndroid Build Coastguard Worker       cricket::VideoCodec(video_codecs.back().id + 1, cricket::kRtxCodecName));
1790*d9f75844SAndroid Build Coastguard Worker   video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1791*d9f75844SAndroid Build Coastguard Worker       std::to_string(video_codecs.back().id - 1);
1792*d9f75844SAndroid Build Coastguard Worker   video_codecs.push_back(
1793*d9f75844SAndroid Build Coastguard Worker       cricket::VideoCodec(video_codecs.back().id + 1, cricket::kRedCodecName));
1794*d9f75844SAndroid Build Coastguard Worker   video_codecs.push_back(cricket::VideoCodec(video_codecs.back().id + 1,
1795*d9f75844SAndroid Build Coastguard Worker                                              cricket::kUlpfecCodecName));
1796*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetVideoCodecs(video_codecs);
1797*d9f75844SAndroid Build Coastguard Worker 
1798*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(fake_engine));
1799*d9f75844SAndroid Build Coastguard Worker 
1800*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
1801*d9f75844SAndroid Build Coastguard Worker   auto codecs =
1802*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1803*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
1804*d9f75844SAndroid Build Coastguard Worker           .codecs;
1805*d9f75844SAndroid Build Coastguard Worker   auto codecs_only_rtx_red_fec = codecs;
1806*d9f75844SAndroid Build Coastguard Worker   auto it = std::remove_if(codecs_only_rtx_red_fec.begin(),
1807*d9f75844SAndroid Build Coastguard Worker                            codecs_only_rtx_red_fec.end(),
1808*d9f75844SAndroid Build Coastguard Worker                            [](const webrtc::RtpCodecCapability& codec) {
1809*d9f75844SAndroid Build Coastguard Worker                              return !(codec.name == cricket::kRtxCodecName ||
1810*d9f75844SAndroid Build Coastguard Worker                                       codec.name == cricket::kRedCodecName ||
1811*d9f75844SAndroid Build Coastguard Worker                                       codec.name == cricket::kUlpfecCodecName);
1812*d9f75844SAndroid Build Coastguard Worker                            });
1813*d9f75844SAndroid Build Coastguard Worker   codecs_only_rtx_red_fec.erase(it, codecs_only_rtx_red_fec.end());
1814*d9f75844SAndroid Build Coastguard Worker 
1815*d9f75844SAndroid Build Coastguard Worker   auto result = transceiver->SetCodecPreferences(codecs_only_rtx_red_fec);
1816*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1817*d9f75844SAndroid Build Coastguard Worker }
1818*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAllVideoCodecs)1819*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan, SetCodecPreferencesAllVideoCodecs) {
1820*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo();
1821*d9f75844SAndroid Build Coastguard Worker 
1822*d9f75844SAndroid Build Coastguard Worker   auto sender_video_codecs =
1823*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1824*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1825*d9f75844SAndroid Build Coastguard Worker           .codecs;
1826*d9f75844SAndroid Build Coastguard Worker 
1827*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers().front();
1828*d9f75844SAndroid Build Coastguard Worker 
1829*d9f75844SAndroid Build Coastguard Worker   // Normal case, setting preferences to normal capabilities
1830*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video_transceiver->SetCodecPreferences(sender_video_codecs).ok());
1831*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1832*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1833*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1834*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1835*d9f75844SAndroid Build Coastguard Worker                     ->as_video()
1836*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1837*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(sender_video_codecs, codecs));
1838*d9f75844SAndroid Build Coastguard Worker }
1839*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesResetVideoCodecs)1840*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1841*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesResetVideoCodecs) {
1842*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo();
1843*d9f75844SAndroid Build Coastguard Worker 
1844*d9f75844SAndroid Build Coastguard Worker   auto sender_video_codecs =
1845*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1846*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1847*d9f75844SAndroid Build Coastguard Worker           .codecs;
1848*d9f75844SAndroid Build Coastguard Worker 
1849*d9f75844SAndroid Build Coastguard Worker   std::vector<webrtc::RtpCodecCapability> empty_codecs = {};
1850*d9f75844SAndroid Build Coastguard Worker 
1851*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers().front();
1852*d9f75844SAndroid Build Coastguard Worker 
1853*d9f75844SAndroid Build Coastguard Worker   // Normal case, resetting preferences with empty list of codecs
1854*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video_transceiver->SetCodecPreferences(empty_codecs).ok());
1855*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1856*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1857*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1858*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1859*d9f75844SAndroid Build Coastguard Worker                     ->as_video()
1860*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1861*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(sender_video_codecs, codecs));
1862*d9f75844SAndroid Build Coastguard Worker }
1863*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVideoCodecDuplicatesRemoved)1864*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1865*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesVideoCodecDuplicatesRemoved) {
1866*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo();
1867*d9f75844SAndroid Build Coastguard Worker 
1868*d9f75844SAndroid Build Coastguard Worker   auto sender_video_codecs =
1869*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1870*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1871*d9f75844SAndroid Build Coastguard Worker           .codecs;
1872*d9f75844SAndroid Build Coastguard Worker 
1873*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers().front();
1874*d9f75844SAndroid Build Coastguard Worker 
1875*d9f75844SAndroid Build Coastguard Worker   // Check duplicates are removed
1876*d9f75844SAndroid Build Coastguard Worker   auto single_codec = sender_video_codecs;
1877*d9f75844SAndroid Build Coastguard Worker   single_codec.resize(1);
1878*d9f75844SAndroid Build Coastguard Worker   auto duplicate_codec = single_codec;
1879*d9f75844SAndroid Build Coastguard Worker   duplicate_codec.push_back(duplicate_codec.front());
1880*d9f75844SAndroid Build Coastguard Worker   duplicate_codec.push_back(duplicate_codec.front());
1881*d9f75844SAndroid Build Coastguard Worker   duplicate_codec.push_back(duplicate_codec.front());
1882*d9f75844SAndroid Build Coastguard Worker 
1883*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video_transceiver->SetCodecPreferences(duplicate_codec).ok());
1884*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1885*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1886*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1887*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1888*d9f75844SAndroid Build Coastguard Worker                     ->as_video()
1889*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1890*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(single_codec, codecs));
1891*d9f75844SAndroid Build Coastguard Worker }
1892*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVideoWithRtx)1893*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan, SetCodecPreferencesVideoWithRtx) {
1894*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1895*d9f75844SAndroid Build Coastguard Worker   auto caller_video_codecs = caller_fake_engine->video().send_codecs();
1896*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1897*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
1898*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1899*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1900*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1901*d9f75844SAndroid Build Coastguard Worker       std::to_string(caller_video_codecs.back().id - 1);
1902*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1903*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
1904*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1905*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1906*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1907*d9f75844SAndroid Build Coastguard Worker       std::to_string(caller_video_codecs.back().id - 1);
1908*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetVideoCodecs(caller_video_codecs);
1909*d9f75844SAndroid Build Coastguard Worker 
1910*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
1911*d9f75844SAndroid Build Coastguard Worker 
1912*d9f75844SAndroid Build Coastguard Worker   auto sender_video_codecs =
1913*d9f75844SAndroid Build Coastguard Worker       caller->pc_factory()
1914*d9f75844SAndroid Build Coastguard Worker           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1915*d9f75844SAndroid Build Coastguard Worker           .codecs;
1916*d9f75844SAndroid Build Coastguard Worker 
1917*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers().front();
1918*d9f75844SAndroid Build Coastguard Worker 
1919*d9f75844SAndroid Build Coastguard Worker   // Check that RTX codec is properly added
1920*d9f75844SAndroid Build Coastguard Worker   auto video_codecs_vpx_rtx = sender_video_codecs;
1921*d9f75844SAndroid Build Coastguard Worker   auto it =
1922*d9f75844SAndroid Build Coastguard Worker       std::remove_if(video_codecs_vpx_rtx.begin(), video_codecs_vpx_rtx.end(),
1923*d9f75844SAndroid Build Coastguard Worker                      [](const webrtc::RtpCodecCapability& codec) {
1924*d9f75844SAndroid Build Coastguard Worker                        return codec.name != cricket::kRtxCodecName &&
1925*d9f75844SAndroid Build Coastguard Worker                               codec.name != cricket::kVp8CodecName &&
1926*d9f75844SAndroid Build Coastguard Worker                               codec.name != cricket::kVp9CodecName;
1927*d9f75844SAndroid Build Coastguard Worker                      });
1928*d9f75844SAndroid Build Coastguard Worker   video_codecs_vpx_rtx.erase(it, video_codecs_vpx_rtx.end());
1929*d9f75844SAndroid Build Coastguard Worker   absl::c_reverse(video_codecs_vpx_rtx);
1930*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(video_codecs_vpx_rtx.size(), 3u);  // VP8, VP9, RTX
1931*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
1932*d9f75844SAndroid Build Coastguard Worker       video_transceiver->SetCodecPreferences(video_codecs_vpx_rtx).ok());
1933*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1934*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1935*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1936*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1937*d9f75844SAndroid Build Coastguard Worker                     ->as_video()
1938*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1939*d9f75844SAndroid Build Coastguard Worker 
1940*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(video_codecs_vpx_rtx, codecs));
1941*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(codecs.size(), 4u);
1942*d9f75844SAndroid Build Coastguard Worker }
1943*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVideoCodecsNegotiation)1944*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
1945*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesVideoCodecsNegotiation) {
1946*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
1947*d9f75844SAndroid Build Coastguard Worker   auto caller_video_codecs = caller_fake_engine->video().send_codecs();
1948*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1949*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
1950*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1951*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1952*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1953*d9f75844SAndroid Build Coastguard Worker       std::to_string(caller_video_codecs.back().id - 1);
1954*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1955*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
1956*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
1957*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1958*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1959*d9f75844SAndroid Build Coastguard Worker       std::to_string(caller_video_codecs.back().id - 1);
1960*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetVideoCodecs(caller_video_codecs);
1961*d9f75844SAndroid Build Coastguard Worker 
1962*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
1963*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetVideoCodecs(caller_video_codecs);
1964*d9f75844SAndroid Build Coastguard Worker 
1965*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
1966*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection(std::move(callee_fake_engine));
1967*d9f75844SAndroid Build Coastguard Worker 
1968*d9f75844SAndroid Build Coastguard Worker   auto video_codecs = caller->pc_factory()
1969*d9f75844SAndroid Build Coastguard Worker                           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1970*d9f75844SAndroid Build Coastguard Worker                           .codecs;
1971*d9f75844SAndroid Build Coastguard Worker 
1972*d9f75844SAndroid Build Coastguard Worker   auto send_transceiver = caller->pc()->GetTransceivers().front();
1973*d9f75844SAndroid Build Coastguard Worker 
1974*d9f75844SAndroid Build Coastguard Worker   auto video_codecs_vpx = video_codecs;
1975*d9f75844SAndroid Build Coastguard Worker   auto it = std::remove_if(video_codecs_vpx.begin(), video_codecs_vpx.end(),
1976*d9f75844SAndroid Build Coastguard Worker                            [](const webrtc::RtpCodecCapability& codec) {
1977*d9f75844SAndroid Build Coastguard Worker                              return codec.name != cricket::kVp8CodecName &&
1978*d9f75844SAndroid Build Coastguard Worker                                     codec.name != cricket::kVp9CodecName;
1979*d9f75844SAndroid Build Coastguard Worker                            });
1980*d9f75844SAndroid Build Coastguard Worker   video_codecs_vpx.erase(it, video_codecs_vpx.end());
1981*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(video_codecs_vpx.size(), 2u);  // VP8, VP9
1982*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(send_transceiver->SetCodecPreferences(video_codecs_vpx).ok());
1983*d9f75844SAndroid Build Coastguard Worker 
1984*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
1985*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
1986*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
1987*d9f75844SAndroid Build Coastguard Worker                     .media_description()
1988*d9f75844SAndroid Build Coastguard Worker                     ->as_video()
1989*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
1990*d9f75844SAndroid Build Coastguard Worker 
1991*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(codecs.size(), 2u);  // VP8, VP9
1992*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(video_codecs_vpx, codecs));
1993*d9f75844SAndroid Build Coastguard Worker 
1994*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
1995*d9f75844SAndroid Build Coastguard Worker 
1996*d9f75844SAndroid Build Coastguard Worker   auto recv_transceiver = callee->pc()->GetTransceivers().front();
1997*d9f75844SAndroid Build Coastguard Worker   auto video_codecs_vp8_rtx = video_codecs;
1998*d9f75844SAndroid Build Coastguard Worker   it = std::remove_if(video_codecs_vp8_rtx.begin(), video_codecs_vp8_rtx.end(),
1999*d9f75844SAndroid Build Coastguard Worker                       [](const webrtc::RtpCodecCapability& codec) {
2000*d9f75844SAndroid Build Coastguard Worker                         bool r = codec.name != cricket::kVp8CodecName &&
2001*d9f75844SAndroid Build Coastguard Worker                                  codec.name != cricket::kRtxCodecName;
2002*d9f75844SAndroid Build Coastguard Worker                         return r;
2003*d9f75844SAndroid Build Coastguard Worker                       });
2004*d9f75844SAndroid Build Coastguard Worker   video_codecs_vp8_rtx.erase(it, video_codecs_vp8_rtx.end());
2005*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(video_codecs_vp8_rtx.size(), 2u);  // VP8, RTX
2006*d9f75844SAndroid Build Coastguard Worker   recv_transceiver->SetCodecPreferences(video_codecs_vp8_rtx);
2007*d9f75844SAndroid Build Coastguard Worker 
2008*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
2009*d9f75844SAndroid Build Coastguard Worker 
2010*d9f75844SAndroid Build Coastguard Worker   auto recv_codecs = answer->description()
2011*d9f75844SAndroid Build Coastguard Worker                          ->contents()[0]
2012*d9f75844SAndroid Build Coastguard Worker                          .media_description()
2013*d9f75844SAndroid Build Coastguard Worker                          ->as_video()
2014*d9f75844SAndroid Build Coastguard Worker                          ->codecs();
2015*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(recv_codecs.size(), 1u);  // VP8
2016*d9f75844SAndroid Build Coastguard Worker }
2017*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVideoCodecsNegotiationReverseOrder)2018*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
2019*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesVideoCodecsNegotiationReverseOrder) {
2020*d9f75844SAndroid Build Coastguard Worker   auto caller_fake_engine = std::make_unique<FakeMediaEngine>();
2021*d9f75844SAndroid Build Coastguard Worker   auto caller_video_codecs = caller_fake_engine->video().send_codecs();
2022*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
2023*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
2024*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
2025*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
2026*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
2027*d9f75844SAndroid Build Coastguard Worker       std::to_string(caller_video_codecs.back().id - 1);
2028*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
2029*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
2030*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.push_back(cricket::VideoCodec(
2031*d9f75844SAndroid Build Coastguard Worker       caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
2032*d9f75844SAndroid Build Coastguard Worker   caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
2033*d9f75844SAndroid Build Coastguard Worker       std::to_string(caller_video_codecs.back().id - 1);
2034*d9f75844SAndroid Build Coastguard Worker   caller_fake_engine->SetVideoCodecs(caller_video_codecs);
2035*d9f75844SAndroid Build Coastguard Worker 
2036*d9f75844SAndroid Build Coastguard Worker   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
2037*d9f75844SAndroid Build Coastguard Worker   callee_fake_engine->SetVideoCodecs(caller_video_codecs);
2038*d9f75844SAndroid Build Coastguard Worker 
2039*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
2040*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection(std::move(callee_fake_engine));
2041*d9f75844SAndroid Build Coastguard Worker 
2042*d9f75844SAndroid Build Coastguard Worker   auto video_codecs = caller->pc_factory()
2043*d9f75844SAndroid Build Coastguard Worker                           ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
2044*d9f75844SAndroid Build Coastguard Worker                           .codecs;
2045*d9f75844SAndroid Build Coastguard Worker 
2046*d9f75844SAndroid Build Coastguard Worker   auto send_transceiver = caller->pc()->GetTransceivers().front();
2047*d9f75844SAndroid Build Coastguard Worker 
2048*d9f75844SAndroid Build Coastguard Worker   auto video_codecs_vpx = video_codecs;
2049*d9f75844SAndroid Build Coastguard Worker   auto it = std::remove_if(video_codecs_vpx.begin(), video_codecs_vpx.end(),
2050*d9f75844SAndroid Build Coastguard Worker                            [](const webrtc::RtpCodecCapability& codec) {
2051*d9f75844SAndroid Build Coastguard Worker                              return codec.name != cricket::kVp8CodecName &&
2052*d9f75844SAndroid Build Coastguard Worker                                     codec.name != cricket::kVp9CodecName;
2053*d9f75844SAndroid Build Coastguard Worker                            });
2054*d9f75844SAndroid Build Coastguard Worker   video_codecs_vpx.erase(it, video_codecs_vpx.end());
2055*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(video_codecs_vpx.size(), 2u);  // VP8, VP9
2056*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(send_transceiver->SetCodecPreferences(video_codecs_vpx).ok());
2057*d9f75844SAndroid Build Coastguard Worker 
2058*d9f75844SAndroid Build Coastguard Worker   auto video_codecs_vpx_reverse = video_codecs_vpx;
2059*d9f75844SAndroid Build Coastguard Worker   absl::c_reverse(video_codecs_vpx_reverse);
2060*d9f75844SAndroid Build Coastguard Worker 
2061*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
2062*d9f75844SAndroid Build Coastguard Worker   auto codecs = offer->description()
2063*d9f75844SAndroid Build Coastguard Worker                     ->contents()[0]
2064*d9f75844SAndroid Build Coastguard Worker                     .media_description()
2065*d9f75844SAndroid Build Coastguard Worker                     ->as_video()
2066*d9f75844SAndroid Build Coastguard Worker                     ->codecs();
2067*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(codecs.size(), 2u);  // VP9, VP8
2068*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(video_codecs_vpx, codecs));
2069*d9f75844SAndroid Build Coastguard Worker 
2070*d9f75844SAndroid Build Coastguard Worker   callee->SetRemoteDescription(std::move(offer));
2071*d9f75844SAndroid Build Coastguard Worker 
2072*d9f75844SAndroid Build Coastguard Worker   auto recv_transceiver = callee->pc()->GetTransceivers().front();
2073*d9f75844SAndroid Build Coastguard Worker   recv_transceiver->SetCodecPreferences(video_codecs_vpx_reverse);
2074*d9f75844SAndroid Build Coastguard Worker 
2075*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
2076*d9f75844SAndroid Build Coastguard Worker 
2077*d9f75844SAndroid Build Coastguard Worker   auto recv_codecs = answer->description()
2078*d9f75844SAndroid Build Coastguard Worker                          ->contents()[0]
2079*d9f75844SAndroid Build Coastguard Worker                          .media_description()
2080*d9f75844SAndroid Build Coastguard Worker                          ->as_video()
2081*d9f75844SAndroid Build Coastguard Worker                          ->codecs();
2082*d9f75844SAndroid Build Coastguard Worker 
2083*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareCodecs(video_codecs_vpx_reverse, recv_codecs));
2084*d9f75844SAndroid Build Coastguard Worker }
2085*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesVoiceActivityDetection)2086*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
2087*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesVoiceActivityDetection) {
2088*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<FakeMediaEngine>();
2089*d9f75844SAndroid Build Coastguard Worker   AddComfortNoiseCodecsToSend(fake_engine.get());
2090*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
2091*d9f75844SAndroid Build Coastguard Worker 
2092*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
2093*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
2094*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(HasAnyComfortNoiseCodecs(offer->description()));
2095*d9f75844SAndroid Build Coastguard Worker 
2096*d9f75844SAndroid Build Coastguard Worker   auto transceiver = caller->pc()->GetTransceivers().front();
2097*d9f75844SAndroid Build Coastguard Worker   auto capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2098*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_AUDIO);
2099*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(transceiver->SetCodecPreferences(capabilities.codecs).ok());
2100*d9f75844SAndroid Build Coastguard Worker 
2101*d9f75844SAndroid Build Coastguard Worker   options.voice_activity_detection = false;
2102*d9f75844SAndroid Build Coastguard Worker   offer = caller->CreateOffer(options);
2103*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasAnyComfortNoiseCodecs(offer->description()));
2104*d9f75844SAndroid Build Coastguard Worker }
2105*d9f75844SAndroid Build Coastguard Worker 
2106*d9f75844SAndroid Build Coastguard Worker // If the "default" payload types of audio/video codecs are the same, and
2107*d9f75844SAndroid Build Coastguard Worker // audio/video are bundled (as is the default), payload types should be
2108*d9f75844SAndroid Build Coastguard Worker // remapped to avoid conflict, as normally happens without using
2109*d9f75844SAndroid Build Coastguard Worker // SetCodecPreferences.
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAvoidsPayloadTypeConflictInOffer)2110*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
2111*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAvoidsPayloadTypeConflictInOffer) {
2112*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
2113*d9f75844SAndroid Build Coastguard Worker 
2114*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> audio_codecs;
2115*d9f75844SAndroid Build Coastguard Worker   audio_codecs.emplace_back(100, "foo", 0, 0, 1);
2116*d9f75844SAndroid Build Coastguard Worker   audio_codecs.emplace_back(101, cricket::kRtxCodecName, 0, 0, 1);
2117*d9f75844SAndroid Build Coastguard Worker   audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
2118*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetAudioCodecs(audio_codecs);
2119*d9f75844SAndroid Build Coastguard Worker 
2120*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoCodec> video_codecs;
2121*d9f75844SAndroid Build Coastguard Worker   video_codecs.emplace_back(100, "bar");
2122*d9f75844SAndroid Build Coastguard Worker   video_codecs.emplace_back(101, cricket::kRtxCodecName);
2123*d9f75844SAndroid Build Coastguard Worker   video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
2124*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetVideoCodecs(video_codecs);
2125*d9f75844SAndroid Build Coastguard Worker 
2126*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
2127*d9f75844SAndroid Build Coastguard Worker   auto transceivers = caller->pc()->GetTransceivers();
2128*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, transceivers.size());
2129*d9f75844SAndroid Build Coastguard Worker 
2130*d9f75844SAndroid Build Coastguard Worker   auto audio_transceiver = caller->pc()->GetTransceivers()[0];
2131*d9f75844SAndroid Build Coastguard Worker   auto capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2132*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_AUDIO);
2133*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio_transceiver->SetCodecPreferences(capabilities.codecs).ok());
2134*d9f75844SAndroid Build Coastguard Worker 
2135*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers()[1];
2136*d9f75844SAndroid Build Coastguard Worker   capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2137*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_VIDEO);
2138*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video_transceiver->SetCodecPreferences(capabilities.codecs).ok());
2139*d9f75844SAndroid Build Coastguard Worker 
2140*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
2141*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(options);
2142*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasPayloadTypeConflict(offer->description()));
2143*d9f75844SAndroid Build Coastguard Worker   // Sanity check that we got the primary codec and RTX.
2144*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, cricket::GetFirstAudioContentDescription(offer->description())
2145*d9f75844SAndroid Build Coastguard Worker                     ->codecs()
2146*d9f75844SAndroid Build Coastguard Worker                     .size());
2147*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, cricket::GetFirstVideoContentDescription(offer->description())
2148*d9f75844SAndroid Build Coastguard Worker                     ->codecs()
2149*d9f75844SAndroid Build Coastguard Worker                     .size());
2150*d9f75844SAndroid Build Coastguard Worker }
2151*d9f75844SAndroid Build Coastguard Worker 
2152*d9f75844SAndroid Build Coastguard Worker // Same as above, but preferences set for the answer.
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAvoidsPayloadTypeConflictInAnswer)2153*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
2154*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAvoidsPayloadTypeConflictInAnswer) {
2155*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
2156*d9f75844SAndroid Build Coastguard Worker 
2157*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> audio_codecs;
2158*d9f75844SAndroid Build Coastguard Worker   audio_codecs.emplace_back(100, "foo", 0, 0, 1);
2159*d9f75844SAndroid Build Coastguard Worker   audio_codecs.emplace_back(101, cricket::kRtxCodecName, 0, 0, 1);
2160*d9f75844SAndroid Build Coastguard Worker   audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
2161*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetAudioCodecs(audio_codecs);
2162*d9f75844SAndroid Build Coastguard Worker 
2163*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoCodec> video_codecs;
2164*d9f75844SAndroid Build Coastguard Worker   video_codecs.emplace_back(100, "bar");
2165*d9f75844SAndroid Build Coastguard Worker   video_codecs.emplace_back(101, cricket::kRtxCodecName);
2166*d9f75844SAndroid Build Coastguard Worker   video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
2167*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetVideoCodecs(video_codecs);
2168*d9f75844SAndroid Build Coastguard Worker 
2169*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
2170*d9f75844SAndroid Build Coastguard Worker 
2171*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
2172*d9f75844SAndroid Build Coastguard Worker   caller->SetRemoteDescription(caller->CreateOffer(options));
2173*d9f75844SAndroid Build Coastguard Worker 
2174*d9f75844SAndroid Build Coastguard Worker   auto transceivers = caller->pc()->GetTransceivers();
2175*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, transceivers.size());
2176*d9f75844SAndroid Build Coastguard Worker 
2177*d9f75844SAndroid Build Coastguard Worker   auto audio_transceiver = caller->pc()->GetTransceivers()[0];
2178*d9f75844SAndroid Build Coastguard Worker   auto capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2179*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_AUDIO);
2180*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio_transceiver->SetCodecPreferences(capabilities.codecs).ok());
2181*d9f75844SAndroid Build Coastguard Worker 
2182*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers()[1];
2183*d9f75844SAndroid Build Coastguard Worker   capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2184*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_VIDEO);
2185*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video_transceiver->SetCodecPreferences(capabilities.codecs).ok());
2186*d9f75844SAndroid Build Coastguard Worker 
2187*d9f75844SAndroid Build Coastguard Worker   auto answer = caller->CreateAnswer(options);
2188*d9f75844SAndroid Build Coastguard Worker 
2189*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasPayloadTypeConflict(answer->description()));
2190*d9f75844SAndroid Build Coastguard Worker   // Sanity check that we got the primary codec and RTX.
2191*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, cricket::GetFirstAudioContentDescription(answer->description())
2192*d9f75844SAndroid Build Coastguard Worker                     ->codecs()
2193*d9f75844SAndroid Build Coastguard Worker                     .size());
2194*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, cricket::GetFirstVideoContentDescription(answer->description())
2195*d9f75844SAndroid Build Coastguard Worker                     ->codecs()
2196*d9f75844SAndroid Build Coastguard Worker                     .size());
2197*d9f75844SAndroid Build Coastguard Worker }
2198*d9f75844SAndroid Build Coastguard Worker 
2199*d9f75844SAndroid Build Coastguard Worker // Same as above, but preferences set for a subsequent offer.
TEST_F(PeerConnectionMediaTestUnifiedPlan,SetCodecPreferencesAvoidsPayloadTypeConflictInSubsequentOffer)2200*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionMediaTestUnifiedPlan,
2201*d9f75844SAndroid Build Coastguard Worker        SetCodecPreferencesAvoidsPayloadTypeConflictInSubsequentOffer) {
2202*d9f75844SAndroid Build Coastguard Worker   auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
2203*d9f75844SAndroid Build Coastguard Worker 
2204*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::AudioCodec> audio_codecs;
2205*d9f75844SAndroid Build Coastguard Worker   audio_codecs.emplace_back(100, "foo", 0, 0, 1);
2206*d9f75844SAndroid Build Coastguard Worker   audio_codecs.emplace_back(101, cricket::kRtxCodecName, 0, 0, 1);
2207*d9f75844SAndroid Build Coastguard Worker   audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
2208*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetAudioCodecs(audio_codecs);
2209*d9f75844SAndroid Build Coastguard Worker 
2210*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoCodec> video_codecs;
2211*d9f75844SAndroid Build Coastguard Worker   video_codecs.emplace_back(100, "bar");
2212*d9f75844SAndroid Build Coastguard Worker   video_codecs.emplace_back(101, cricket::kRtxCodecName);
2213*d9f75844SAndroid Build Coastguard Worker   video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
2214*d9f75844SAndroid Build Coastguard Worker   fake_engine->SetVideoCodecs(video_codecs);
2215*d9f75844SAndroid Build Coastguard Worker 
2216*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
2217*d9f75844SAndroid Build Coastguard Worker 
2218*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
2219*d9f75844SAndroid Build Coastguard Worker   caller->SetRemoteDescription(caller->CreateOffer(options));
2220*d9f75844SAndroid Build Coastguard Worker   caller->SetLocalDescription(caller->CreateAnswer(options));
2221*d9f75844SAndroid Build Coastguard Worker 
2222*d9f75844SAndroid Build Coastguard Worker   auto transceivers = caller->pc()->GetTransceivers();
2223*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, transceivers.size());
2224*d9f75844SAndroid Build Coastguard Worker 
2225*d9f75844SAndroid Build Coastguard Worker   auto audio_transceiver = caller->pc()->GetTransceivers()[0];
2226*d9f75844SAndroid Build Coastguard Worker   auto capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2227*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_AUDIO);
2228*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio_transceiver->SetCodecPreferences(capabilities.codecs).ok());
2229*d9f75844SAndroid Build Coastguard Worker 
2230*d9f75844SAndroid Build Coastguard Worker   auto video_transceiver = caller->pc()->GetTransceivers()[1];
2231*d9f75844SAndroid Build Coastguard Worker   capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
2232*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType::MEDIA_TYPE_VIDEO);
2233*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video_transceiver->SetCodecPreferences(capabilities.codecs).ok());
2234*d9f75844SAndroid Build Coastguard Worker 
2235*d9f75844SAndroid Build Coastguard Worker   auto reoffer = caller->CreateOffer(options);
2236*d9f75844SAndroid Build Coastguard Worker 
2237*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasPayloadTypeConflict(reoffer->description()));
2238*d9f75844SAndroid Build Coastguard Worker   // Sanity check that we got the primary codec and RTX.
2239*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, cricket::GetFirstAudioContentDescription(reoffer->description())
2240*d9f75844SAndroid Build Coastguard Worker                     ->codecs()
2241*d9f75844SAndroid Build Coastguard Worker                     .size());
2242*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, cricket::GetFirstVideoContentDescription(reoffer->description())
2243*d9f75844SAndroid Build Coastguard Worker                     ->codecs()
2244*d9f75844SAndroid Build Coastguard Worker                     .size());
2245*d9f75844SAndroid Build Coastguard Worker }
2246*d9f75844SAndroid Build Coastguard Worker 
2247*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(PeerConnectionMediaTest,
2248*d9f75844SAndroid Build Coastguard Worker                          PeerConnectionMediaTest,
2249*d9f75844SAndroid Build Coastguard Worker                          Values(SdpSemantics::kPlanB_DEPRECATED,
2250*d9f75844SAndroid Build Coastguard Worker                                 SdpSemantics::kUnifiedPlan));
2251*d9f75844SAndroid Build Coastguard Worker 
2252*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
2253