docs: async def setRemoteDescription(self, sessionDescription):
          """
          Changes the remote description associated with the connection.
  
          :param: sessionDescription: An :class:`RTCSessionDescription` created from
                                      information received over the signaling channel.
          """
          # parse and validate description
          description = sdp.SessionDescription.parse(sessionDescription.sdp)
          description.type = sessionDescription.type
          self.__validate_description(description, is_local=False)
  
          # apply description
          trackEvents = []
          for i, media in enumerate(description.media):
              self.__seenMids.add(media.rtp.muxId)
              if media.kind in ['audio', 'video']:
                  # find transceiver
                  transceiver = None
                  for t in self.__transceivers:
                      if t.kind == media.kind and t.mid in [None, media.rtp.muxId]:
                          transceiver = t
                  if transceiver is None:
                      transceiver = self.__createTransceiver(direction='recvonly', kind=media.kind)
                  if transceiver.mid is None:
                      transceiver._set_mid(media.rtp.muxId)
                      transceiver._set_mline_index(i)
  
                  # negotiate codecs
                  common = filter_preferred_codecs(
                      find_common_codecs(CODECS[media.kind], media.rtp.codecs),
                      transceiver._preferred_codecs)
                  assert len(common)
                  transceiver._codecs = common
                  transceiver._headerExtensions = find_common_header_extensions(
                      HEADER_EXTENSIONS[media.kind], media.rtp.headerExtensions)
  
                  # configure transport
                  iceTransport = transceiver._transport.transport
                  add_remote_candidates(iceTransport, media)
                  self.__remoteDtls[transceiver] = media.dtls
                  self.__remoteIce[transceiver] = media.ice
  
                  # configure direction
                  direction = reverse_direction(media.direction)
                  if description.type in ['answer', 'pranswer']:
                      transceiver._currentDirection = direction
                  else:
                      transceiver._offerDirection = direction
  
                  # create remote stream track
                  if direction in ['recvonly', 'sendrecv'] and not transceiver.receiver._track:
                      transceiver.receiver._track = RemoteStreamTrack(kind=media.kind)
                      trackEvents.append(RTCTrackEvent(
                          receiver=transceiver.receiver,
                          track=transceiver.receiver._track,
                          transceiver=transceiver,
                      ))
  
              elif media.kind == 'application':
                  if not self.__sctp:
                      self.__createSctpTransport()
                  if self.__sctp.mid is None:
                      self.__sctp.mid = media.rtp.muxId
                      self.__sctp_mline_index = i
  
                  # configure sctp
                  if media.profile == 'DTLS/SCTP':
                      self._sctpLegacySdp = True
                      self.__sctpRemotePort = int(media.fmt[0])
                  else:
                      self._sctpLegacySdp = False
                      self.__sctpRemotePort = media.sctp_port
                  self.__sctpRemoteCaps = media.sctpCapabilities
  
                  # configure transport
                  iceTransport = self.__sctp.transport.transport
                  add_remote_candidates(iceTransport, media)
                  self.__remoteDtls[self.__sctp] = media.dtls
                  self.__remoteIce[self.__sctp] = media.ice
  
          # remove bundled transports
          bundle = next((x for x in description.group if x.semantic == 'BUNDLE'), None)
          if bundle and bundle.items:
              # find main media stream
              masterMid = bundle.items[0]
              masterTransport = None
              for transceiver in self.__transceivers:
                  if transceiver.mid == masterMid:
                      masterTransport = transceiver._transport
                      break
              if self.__sctp and self.__sctp.mid == masterMid:
                  masterTransport = self.__sctp.transport
  
              # replace transport for bundled media
              oldTransports = set()
              slaveMids = bundle.items[1:]
              for transceiver in self.__transceivers:
                  if transceiver.mid in slaveMids and not transceiver._bundled:
                      oldTransports.add(transceiver._transport)
                      transceiver.receiver.setTransport(masterTransport)
                      transceiver.sender.setTransport(masterTransport)
                      transceiver._bundled = True
                      transceiver._transport = masterTransport
              if self.__sctp and self.__sctp.mid in slaveMids:
                  oldTransports.add(self.__sctp.transport)
                  self.__sctp.setTransport(masterTransport)
                  self.__sctp._bundled = True
  
              # stop and discard old ICE transports
              for dtlsTransport in oldTransports:
                  await dtlsTransport.stop()
                  await dtlsTransport.transport.stop()
                  self.__iceTransports.discard(dtlsTransport.transport)
              self.__updateIceGatheringState()
              self.__updateIceConnectionState()
  
          # FIXME: in aiortc 1.0.0 emit RTCTrackEvent directly
          for event in trackEvents:
              self.emit('track', event.track)
  
          # connect
          asyncio.ensure_future(self.__connect())
  
          # update signaling state
          if description.type == 'offer':
              self.__setSignalingState('have-remote-offer')
          elif description.type == 'answer':
              self.__setSignalingState('stable')
  
          # replace description
          if description.type == 'answer':
              self.__currentRemoteDescription = description
              self.__pendingRemoteDescription = None
          else:
              self.__pendingRemoteDescription = description