sdp: set content to rejected if the list of common codecs is empty

which avoids throwing an error when using setCodecPreferences
to set a recvonly codec on a sendonly transceiver. See
  https://github.com/w3c/webrtc-pc/issues/2936

BUG=webrtc:15396

Change-Id: I435a98c944ed2eeef87d9b8a7f791d095ec25502
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/338642
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#41843}
diff --git a/pc/media_session.cc b/pc/media_session.cc
index 3928088..a7352cc 100644
--- a/pc/media_session.cc
+++ b/pc/media_session.cc
@@ -2069,10 +2069,12 @@
   SetMediaProtocol(secure_transport, content_description.get());
 
   content_description->set_direction(media_description_options.direction);
+  bool has_codecs = !content_description->codecs().empty();
 
   session_description->AddContent(
       media_description_options.mid, MediaProtocolType::kRtp,
-      media_description_options.stopped, std::move(content_description));
+      media_description_options.stopped || !has_codecs,
+      std::move(content_description));
   return AddTransportOffer(media_description_options.mid,
                            media_description_options.transport_options,
                            current_description, session_description,
diff --git a/pc/peer_connection_media_unittest.cc b/pc/peer_connection_media_unittest.cc
index 04fb9c9..acefd9e 100644
--- a/pc/peer_connection_media_unittest.cc
+++ b/pc/peer_connection_media_unittest.cc
@@ -2094,6 +2094,31 @@
                     .size());
 }
 
+TEST_F(PeerConnectionMediaTestUnifiedPlan,
+       SetCodecPreferencesReceiveOnlyWithSendOnlyTransceiverStops) {
+  auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
+
+  std::vector<cricket::AudioCodec> audio_codecs;
+  audio_codecs.emplace_back(cricket::CreateAudioCodec(100, "foo", 0, 1));
+  fake_engine->SetAudioRecvCodecs(audio_codecs);
+
+  auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
+
+  auto transceivers = caller->pc()->GetTransceivers();
+  ASSERT_EQ(1u, transceivers.size());
+
+  auto audio_transceiver = caller->pc()->GetTransceivers()[0];
+  auto error = audio_transceiver->SetDirectionWithError(
+      RtpTransceiverDirection::kSendOnly);
+  ASSERT_TRUE(error.ok());
+  auto capabilities = caller->pc_factory()->GetRtpReceiverCapabilities(
+      cricket::MediaType::MEDIA_TYPE_AUDIO);
+  EXPECT_TRUE(audio_transceiver->SetCodecPreferences(capabilities.codecs).ok());
+  RTCOfferAnswerOptions options;
+  EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer(options)));
+  EXPECT_EQ(audio_transceiver->direction(), RtpTransceiverDirection::kStopped);
+}
+
 INSTANTIATE_TEST_SUITE_P(PeerConnectionMediaTest,
                          PeerConnectionMediaTest,
                          Values(SdpSemantics::kPlanB_DEPRECATED,