WebRtcConnection源码分析(二)

Licode服务与启动过程分析

WebRtcConnection源码分析(一)

WebRtcConnection源码分析(二)

WebRtcConnection源码分析(三)

MediaStream源码分析(一)

MediaStream源码分析(二)

MediaStream源码分析(三)

继续对licode中的WebRtcConnection源码进行分析:

// 设置远端sdp信息
boost::future<void> WebRtcConnection::setRemoteSdpInfo(
    std::shared_ptr<SdpInfo> sdp) {
  std::weak_ptr<WebRtcConnection> weak_this = shared_from_this();
  auto task_promise = std::make_shared<boost::promise<void>>();
  worker_->task([weak_this, sdp, task_promise] {
    if (auto connection = weak_this.lock()) {
      ELOG_DEBUG("%s message: setting remote SDPInfo", connection->toLog());
      if (!connection->sending_) {
        task_promise->set_value();
        return;
      }
      connection->remote_sdp_ = sdp;
      boost::future<void> future = connection->processRemoteSdp().then(
        [task_promise] (boost::future<void>) {
          task_promise->set_value();
        });
      return;
    }
    task_promise->set_value();
  });

  return task_promise->get_future();
}

// 拷贝sdp info到local_sdp_中
void WebRtcConnection::copyDataToLocalSdpIndo(std::shared_ptr<SdpInfo> sdp_info) {
  asyncTask([sdp_info] (std::shared_ptr<WebRtcConnection> connection) {
    if (connection->sending_) {
      connection->local_sdp_->copyInfoFromSdp(sdp_info);
      connection->local_sdp_->updateSupportedExtensionMap(connection->extension_processor_.getSupportedExtensionMap());
    }
  });
}

// 获取local_sdp_的内容
std::shared_ptr<SdpInfo> WebRtcConnection::getLocalSdpInfo() {
  boost::mutex::scoped_lock lock(update_state_mutex_);
  ELOG_DEBUG("%s message: getting local SDPInfo", toLog());
  forEachMediaStream([this] (const std::shared_ptr<MediaStream> &media_stream) {
    if (!media_stream->isReady() || media_stream->isPublisher()) {
      ELOG_DEBUG("%s message: getting local SDPInfo stream not running, stream_id: %s", toLog(), media_stream->getId());
      return;
    }
    std::vector<uint32_t> video_ssrc_list = std::vector<uint32_t>();
    if (media_stream->getVideoSinkSSRC() != kDefaultVideoSinkSSRC && media_stream->getVideoSinkSSRC() != 0) {
      video_ssrc_list.push_back(media_stream->getVideoSinkSSRC());
    }
    ELOG_DEBUG("%s message: getting local SDPInfo, stream_id: %s, audio_ssrc: %u",
               toLog(), media_stream->getId(), media_stream->getAudioSinkSSRC());
    if (!video_ssrc_list.empty()) {
      local_sdp_->video_ssrc_map[media_stream->getLabel()] = video_ssrc_list;
    }
    if (media_stream->getAudioSinkSSRC() != kDefaultAudioSinkSSRC && media_stream->getAudioSinkSSRC() != 0) {
      local_sdp_->audio_ssrc_map[media_stream->getLabel()] = media_stream->getAudioSinkSSRC();
    }
  });

  bool sending_audio = local_sdp_->audio_ssrc_map.size() > 0;
  bool sending_video = local_sdp_->video_ssrc_map.size() > 0;

  bool receiving_audio = remote_sdp_->audio_ssrc_map.size() > 0;
  bool receiving_video = remote_sdp_->video_ssrc_map.size() > 0;

  audio_enabled_ = sending_audio || receiving_audio;
  video_enabled_ = sending_video || receiving_video;

  if (!sending_audio && receiving_audio) {
    local_sdp_->audioDirection = erizo::RECVONLY;
  } else if (sending_audio && !receiving_audio) {
    local_sdp_->audioDirection = erizo::SENDONLY;
  } else {
    local_sdp_->audioDirection = erizo::SENDRECV;
  }

  if (!sending_video && receiving_video) {
    local_sdp_->videoDirection = erizo::RECVONLY;
  } else if (sending_video && !receiving_video) {
    local_sdp_->videoDirection = erizo::SENDONLY;
  } else {
    local_sdp_->videoDirection = erizo::SENDRECV;
  }

  return local_sdp_;
}

// 设置远端sdp,remote_sdp_,较上面的setRemoteSdpInfo多了一步操作:processRemoteSdp
boost::future<void> WebRtcConnection::setRemoteSdp(const std::string &sdp) {
  std::shared_ptr<boost::promise<void>> p = std::make_shared<boost::promise<void>>();
  boost::future<void> f = p->get_future();
  asyncTask([sdp, p] (std::shared_ptr<WebRtcConnection> connection) {
    ELOG_DEBUG("%s message: setting remote SDP", connection->toLog());
    if (!connection->sending_) {
      p->set_value();
      return;
    }

    connection->remote_sdp_->initWithSdp(sdp, "");
    boost::future<void> f = connection->processRemoteSdp();
    f.then([p](boost::future<void> future) {
      p->set_value();
    });
  });
  return f;
}

// 将远端sdp内容设置到media_streams_中
boost::future<void> WebRtcConnection::setRemoteSdpsToMediaStreams() {
  ELOG_DEBUG("%s message: setting remote SDP, streams: %d", toLog(), media_streams_.size());
  std::weak_ptr<WebRtcConnection> weak_this = shared_from_this();
  std::shared_ptr<SdpInfo> remote_sdp = std::make_shared<SdpInfo>(*remote_sdp_.get());
  return forEachMediaStreamAsync([weak_this, remote_sdp](std::shared_ptr<MediaStream> media_stream) {
    if (auto connection = weak_this.lock()) {
      media_stream->setRemoteSdp(remote_sdp);
      ELOG_DEBUG("%s message: setting remote SDP to stream, stream: %s",
        connection->toLog(), media_stream->getId());
    }
  });
}

// 将remote_sdp_相关内容设置到audio_transport_和video_transport_中
boost::future<void> WebRtcConnection::processRemoteSdp() {
  ELOG_DEBUG("%s message: processing remote SDP", toLog());
  if (!first_remote_sdp_processed_ && local_sdp_->internal_dtls_role == ACTPASS) {
    local_sdp_->internal_dtls_role = ACTIVE;
  }
  local_sdp_->dtlsRole = local_sdp_->internal_dtls_role;
  ELOG_DEBUG("%s message: process remote sdp, setup: %d", toLog(), local_sdp_->internal_dtls_role);

  if (first_remote_sdp_processed_) {
    return setRemoteSdpsToMediaStreams();
  }

  bundle_ = remote_sdp_->isBundle;
  local_sdp_->setOfferSdp(remote_sdp_);
  extension_processor_.setSdpInfo(local_sdp_);
  local_sdp_->updateSupportedExtensionMap(extension_processor_.getSupportedExtensionMap());


  audio_enabled_ = remote_sdp_->hasAudio;
  video_enabled_ = remote_sdp_->hasVideo;

  if (remote_sdp_->profile == SAVPF) {
    if (remote_sdp_->isFingerprint) {
      auto listener = std::dynamic_pointer_cast<TransportListener>(shared_from_this());
      if (remote_sdp_->hasVideo || bundle_) {
        std::string username = remote_sdp_->getUsername(VIDEO_TYPE);
        std::string password = remote_sdp_->getPassword(VIDEO_TYPE);
        if (video_transport_.get() == nullptr) {
          ELOG_DEBUG("%s message: Creating videoTransport, ufrag: %s, pass: %s",
                      toLog(), username.c_str(), password.c_str());
          video_transport_.reset(new DtlsTransport(VIDEO_TYPE, "video", connection_id_, bundle_, remote_sdp_->isRtcpMux,
                                                  listener, ice_config_ , username, password, false,
                                                  worker_, io_worker_));
          video_transport_->copyLogContextFrom(*this);
          video_transport_->start();
        } else {
          ELOG_DEBUG("%s message: Updating videoTransport, ufrag: %s, pass: %s",
                      toLog(), username.c_str(), password.c_str());
          video_transport_->getIceConnection()->setRemoteCredentials(username, password);
        }
      }
      if (!bundle_ && remote_sdp_->hasAudio) {
        std::string username = remote_sdp_->getUsername(AUDIO_TYPE);
        std::string password = remote_sdp_->getPassword(AUDIO_TYPE);
        if (audio_transport_.get() == nullptr) {
          ELOG_DEBUG("%s message: Creating audioTransport, ufrag: %s, pass: %s",
                      toLog(), username.c_str(), password.c_str());
          audio_transport_.reset(new DtlsTransport(AUDIO_TYPE, "audio", connection_id_, bundle_, remote_sdp_->isRtcpMux,
                                                  listener, ice_config_, username, password, false,
                                                  worker_, io_worker_));
          audio_transport_->copyLogContextFrom(*this);
          audio_transport_->start();
        } else {
          ELOG_DEBUG("%s message: Update audioTransport, ufrag: %s, pass: %s",
                      toLog(), username.c_str(), password.c_str());
          audio_transport_->getIceConnection()->setRemoteCredentials(username, password);
        }
      }
    }
  }
  if (this->getCurrentState() >= CONN_GATHERED) {
    if (!remote_sdp_->getCandidateInfos().empty()) {
      ELOG_DEBUG("%s message: Setting remote candidates after gathered", toLog());
      if (remote_sdp_->hasVideo) {
        video_transport_->setRemoteCandidates(remote_sdp_->getCandidateInfos(), bundle_);
      }
      if (!bundle_ && remote_sdp_->hasAudio) {
        audio_transport_->setRemoteCandidates(remote_sdp_->getCandidateInfos(), bundle_);
      }
    }
  }

  first_remote_sdp_processed_ = true;
  return setRemoteSdpsToMediaStreams();
}

// 异步将远端candidate加入remote_sdp_中
boost::future<void> WebRtcConnection::addRemoteCandidate(std::string mid, int mLineIndex, std::string sdp) {
  return asyncTask([mid, mLineIndex, sdp] (std::shared_ptr<WebRtcConnection> connection) {
    connection->addRemoteCandidateSync(mid, mLineIndex, sdp);
  });
}

// 将远端candidate加入remote_sdp_中
bool WebRtcConnection::addRemoteCandidateSync(std::string mid, int mLineIndex, std::string sdp) {
  // TODO(pedro) Check type of transport.
  ELOG_DEBUG("%s message: Adding remote Candidate, candidate: %s, mid: %s, sdpMLine: %d",
              toLog(), sdp.c_str(), mid.c_str(), mLineIndex);
  if (video_transport_ == nullptr && audio_transport_ == nullptr) {
    ELOG_WARN("%s message: addRemoteCandidate on NULL transport", toLog());
    return false;
  }
  MediaType theType;
  std::string theMid;

  // TODO(pedro) check if this works with video+audio and no bundle
  if (mLineIndex == -1) {
    ELOG_DEBUG("%s message: All candidates received", toLog());
    if (video_transport_) {
      video_transport_->getIceConnection()->setReceivedLastCandidate(true);
    } else if (audio_transport_) {
      audio_transport_->getIceConnection()->setReceivedLastCandidate(true);
    }
    return true;
  }

  if ((!mid.compare("video")) || (mLineIndex == remote_sdp_->videoSdpMLine)) {
    theType = VIDEO_TYPE;
    theMid = "video";
  } else {
    theType = AUDIO_TYPE;
    theMid = "audio";
  }
  SdpInfo tempSdp(rtp_mappings_);
  std::string username = remote_sdp_->getUsername(theType);
  std::string password = remote_sdp_->getPassword(theType);
  tempSdp.setCredentials(username, password, OTHER);
  bool res = false;
  if (tempSdp.initWithSdp(sdp, theMid)) {
    if (theType == VIDEO_TYPE || bundle_) {
      res = video_transport_->setRemoteCandidates(tempSdp.getCandidateInfos(), bundle_);
    } else if (theType == AUDIO_TYPE) {
      res = audio_transport_->setRemoteCandidates(tempSdp.getCandidateInfos(), bundle_);
    } else {
      ELOG_ERROR("%s message: add remote candidate with no Media (video or audio), candidate: %s",
                  toLog(), sdp.c_str() );
    }
  }

  for (uint8_t it = 0; it < tempSdp.getCandidateInfos().size(); it++) {
    remote_sdp_->addCandidate(tempSdp.getCandidateInfos()[it]);
  }
  return res;
}

猜你喜欢

转载自blog.csdn.net/tong5956/article/details/108241462