Don't expect a transceiver for stopped m-sections

After implementing transceiver.stop and associated logic with regard
to stopped media sections, there might not be a transceiver for every
media section. Allow this case.

There is a test ready for submission in Chrome:
https://chromium-review.googlesource.com/c/chromium/src/+/2410407

Bug: chromium:1127625
Change-Id: I150ea5f0da4a0cbd2bf214bc659ea0df93b607de
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/184343
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Philipp Hancke <philipp.hancke@googlemail.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32117}
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 2ab4fec..36dc5b2 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -3566,6 +3566,13 @@
         old_remote_content =
             &old_remote_description->description()->contents()[i];
       }
+      // In the case where an m-section has completed its rejection,
+      // and is not being reused, we do not expect a transceiver.
+      if (old_local_content && old_local_content->rejected &&
+          old_remote_content && old_remote_content->rejected &&
+          new_content.rejected) {
+        continue;
+      }
       auto transceiver_or_error =
           AssociateTransceiver(source, new_session.GetType(), i, new_content,
                                old_local_content, old_remote_content);
@@ -5277,10 +5284,19 @@
     if (media_type == cricket::MEDIA_TYPE_AUDIO ||
         media_type == cricket::MEDIA_TYPE_VIDEO) {
       auto transceiver = GetAssociatedTransceiver(content.name);
-      RTC_CHECK(transceiver);
-      session_options->media_description_options.push_back(
-          GetMediaDescriptionOptionsForTransceiver(transceiver, content.name,
-                                                   /*is_create_offer=*/false));
+      if (transceiver) {
+        session_options->media_description_options.push_back(
+            GetMediaDescriptionOptionsForTransceiver(
+                transceiver, content.name,
+                /*is_create_offer=*/false));
+      } else {
+        // This should only happen with rejected transceivers.
+        RTC_DCHECK(content.rejected);
+        session_options->media_description_options.push_back(
+            cricket::MediaDescriptionOptions(media_type, content.name,
+                                             RtpTransceiverDirection::kInactive,
+                                             /*stopped=*/true));
+      }
     } else {
       RTC_CHECK_EQ(cricket::MEDIA_TYPE_DATA, media_type);
       // Reject all data sections if data channels are disabled.