头图

nativeCreateVideoSource

初始化

PeerConnectionFactory(pc/peerconnectionfactory) 创建PeerConnection方法中:

rtc::scoped_refptr<PeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection(
    const PeerConnectionInterface::RTCConfiguration& configuration,
    std::unique_ptr<cricket::PortAllocator> allocator,
    std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
    PeerConnectionObserver* observer) {
  RTC_DCHECK(signaling_thread_->IsCurrent());

  if (!cert_generator.get()) {
    // No certificate generator specified, use the default one.
    cert_generator.reset(
        new rtc::RTCCertificateGenerator(signaling_thread_, network_thread_));
  }

  if (!allocator) {
    allocator.reset(new cricket::BasicPortAllocator(
        default_network_manager_.get(), default_socket_factory_.get()));
  }
  network_thread_->Invoke<void>(
      RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::SetNetworkIgnoreMask,
                               allocator.get(), options_.network_ignore_mask));

  rtc::scoped_refptr<PeerConnection> pc(
      new rtc::RefCountedObject<PeerConnection>(this));

  if (!pc->Initialize(configuration, std::move(allocator),
                      std::move(cert_generator), observer)) {
    return nullptr;
  }
  return PeerConnectionProxy::Create(signaling_thread(), pc);
}

构造PeerConnection对象pc,并调用初始化方法Initialize,Initialize中:

ool PeerConnection::Initialize(
    const PeerConnectionInterface::RTCConfiguration& configuration,
    std::unique_ptr<cricket::PortAllocator> allocator,
    std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
    PeerConnectionObserver* observer) {
  TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
  if (!allocator) {
    LOG(LS_ERROR) << "PeerConnection initialized without a PortAllocator? "
                  << "This shouldn't happen if using PeerConnectionFactory.";
    return false;
  }
  if (!observer) {
    // TODO(deadbeef): Why do we do this?
    LOG(LS_ERROR) << "PeerConnection initialized without a "
                  << "PeerConnectionObserver";
    return false;
  }
  observer_ = observer;
  port_allocator_ = std::move(allocator);

  // The port allocator lives on the network thread and should be initialized
  // there.
  if (!network_thread()->Invoke<bool>(
          RTC_FROM_HERE, rtc::Bind(&PeerConnection::InitializePortAllocator_n,
                                   this, configuration))) {
    return false;
  }

  // Call must be constructed on the worker thread.
  factory_->worker_thread()->Invoke<void>(
      RTC_FROM_HERE, rtc::Bind(&PeerConnection::CreateCall_w,
                               this));

  session_.reset(new WebRtcSession(
      call_.get(), factory_->channel_manager(), configuration.media_config,
      event_log_.get(),
      factory_->network_thread(),
      factory_->worker_thread(), factory_->signaling_thread(),
      port_allocator_.get(),
      std::unique_ptr<cricket::TransportController>(
          factory_->CreateTransportController(
              port_allocator_.get(),
              configuration.redetermine_role_on_ice_restart)),
#ifdef HAVE_SCTP
      std::unique_ptr<cricket::SctpTransportInternalFactory>(
          new cricket::SctpTransportFactory(factory_->network_thread()))
#else
      nullptr
#endif
          ));

  stats_.reset(new StatsCollector(this));
  stats_collector_ = RTCStatsCollector::Create(this);

  // Initialize the WebRtcSession. It creates transport channels etc.
  if (!session_->Initialize(factory_->options(), std::move(cert_generator),
                            configuration)) {
    return false;
  }

  // Register PeerConnection as receiver of local ice candidates.
  // All the callbacks will be posted to the application from PeerConnection.
  session_->RegisterIceObserver(this);
  session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
  session_->SignalVoiceChannelCreated.connect(
      this, &PeerConnection::OnVoiceChannelCreated);
  session_->SignalVoiceChannelDestroyed.connect(
      this, &PeerConnection::OnVoiceChannelDestroyed);
  session_->SignalVideoChannelCreated.connect(
      this, &PeerConnection::OnVideoChannelCreated);
  session_->SignalVideoChannelDestroyed.connect(
      this, &PeerConnection::OnVideoChannelDestroyed);
  session_->SignalDataChannelCreated.connect(
      this, &PeerConnection::OnDataChannelCreated);
  session_->SignalDataChannelDestroyed.connect(
      this, &PeerConnection::OnDataChannelDestroyed);
  session_->SignalDataChannelOpenMessage.connect(
      this, &PeerConnection::OnDataChannelOpenMessage);

  configuration_ = configuration;
  return true;
}

调用CreateCall_w创建call对象:

void PeerConnection::CreateCall_w() {
  RTC_DCHECK(!call_);

  const int kMinBandwidthBps = 30000;
  const int kStartBandwidthBps = 300000;
  const int kMaxBandwidthBps = 2000000;

  webrtc::Call::Config call_config(event_log_.get());
  call_config.audio_state =
      factory_->channel_manager() ->media_engine()->GetAudioState();
  call_config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
  call_config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
  call_config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;

  call_.reset(webrtc::Call::Create(call_config));
}

使用call对象以及PeerConnectionFactory中channel_manager(PeerConnectionFactory中Initialize中创建)构造WebRtcSession对象session_,调用Initialize方法初始化session_,初始化session_槽函数等.session_初始化方法中创建WebRtcSessionDescriptionFactory对象webrtc_session_desc_factory_.

创建Channel

WebRtcSession::SetLocalDescription:

bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
                                        std::string* err_desc) {
  RTC_DCHECK(signaling_thread()->IsCurrent());

  // Takes the ownership of |desc| regardless of the result.
  std::unique_ptr<SessionDescriptionInterface> desc_temp(desc);

  // Validate SDP.
  if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) {
    return false;
  }

  // Update the initial_offerer flag if this session is the initial_offerer.
  Action action = GetAction(desc->type());
  if (state() == STATE_INIT && action == kOffer) {
    initial_offerer_ = true;
    transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
  }

  if (action == kAnswer) {
    current_local_description_.reset(desc_temp.release());
    pending_local_description_.reset(nullptr);
    current_remote_description_.reset(pending_remote_description_.release());
  } else {
    pending_local_description_.reset(desc_temp.release());
  }

  // Transport and Media channels will be created only when offer is set.
  if (action == kOffer && !CreateChannels(local_description()->description())) {
    // TODO(mallinath) - Handle CreateChannel failure, as new local description
    // is applied. Restore back to old description.
    return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc);
  }

  // Remove unused channels if MediaContentDescription is rejected.
  RemoveUnusedChannels(local_description()->description());

  if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
    return false;
  }
  if (remote_description()) {
    // Now that we have a local description, we can push down remote candidates.
    UseCandidatesInSessionDescription(remote_description());
  }

  pending_ice_restarts_.clear();
  if (error() != ERROR_NONE) {
    return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
  }
  return true;
}

action为offer时CreateChannel创建channels:

bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
  const cricket::ContentGroup* bundle_group = nullptr;
  if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) {
    bundle_group = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
    if (!bundle_group) {
      LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified";
      return false;
    }
  }
  // Creating the media channels and transport proxies.
  const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc);
  if (voice && !voice->rejected && !voice_channel_) {
    if (!CreateVoiceChannel(voice,
                            GetBundleTransportName(voice, bundle_group))) {
      LOG(LS_ERROR) << "Failed to create voice channel.";
      return false;
    }
  }

  const cricket::ContentInfo* video = cricket::GetFirstVideoContent(desc);
  if (video && !video->rejected && !video_channel_) {
    if (!CreateVideoChannel(video,
                            GetBundleTransportName(video, bundle_group))) {
      LOG(LS_ERROR) << "Failed to create video channel.";
      return false;
    }
  }

  const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc);
  if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected &&
      !rtp_data_channel_ && !sctp_transport_) {
    if (!CreateDataChannel(data, GetBundleTransportName(data, bundle_group))) {
      LOG(LS_ERROR) << "Failed to create data channel.";
      return false;
    }
  }

  return true;
}

CreateChannels中创建三个Channel,其中CreateVideoChannel创建视频Channel:

bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
                                       const std::string* bundle_transport) {
  bool require_rtcp_mux =
      rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;

  std::string transport_name =
      bundle_transport ? *bundle_transport : content->name;

  cricket::DtlsTransportInternal* rtp_dtls_transport =
      transport_controller_->CreateDtlsTransport(
          transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
  cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
  if (!require_rtcp_mux) {
    rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
        transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
  }

  video_channel_.reset(channel_manager_->CreateVideoChannel(
      call_, media_config_, rtp_dtls_transport, rtcp_dtls_transport,
      transport_controller_->signaling_thread(), content->name, SrtpRequired(),
      video_options_));

  if (!video_channel_) {
    transport_controller_->DestroyDtlsTransport(
        transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
    if (rtcp_dtls_transport) {
      transport_controller_->DestroyDtlsTransport(
          transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
    }
    return false;
  }

  video_channel_->SignalRtcpMuxFullyActive.connect(
      this, &WebRtcSession::DestroyRtcpTransport_n);
  video_channel_->SignalDtlsSrtpSetupFailure.connect(
      this, &WebRtcSession::OnDtlsSrtpSetupFailure);

  SignalVideoChannelCreated();
  video_channel_->SignalSentPacket.connect(this,
                                           &WebRtcSession::OnSentPacket_w);
  return true;
}

调用channel_manager的CreateVideoChannel创建BaseChannel基类的cricket::VideoChannel.
VideoChannel需要传入VideoMediaChannel作为构造参数:

//pc/channelmanager.h/cc
VideoChannel* ChannelManager::CreateVideoChannel_w(
    webrtc::Call* call,
    const cricket::MediaConfig& media_config,
    DtlsTransportInternal* rtp_dtls_transport,
    DtlsTransportInternal* rtcp_dtls_transport,
    rtc::PacketTransportInternal* rtp_packet_transport,
    rtc::PacketTransportInternal* rtcp_packet_transport,
    rtc::Thread* signaling_thread,
    const std::string& content_name,
    bool srtp_required,
    const VideoOptions& options) {
  RTC_DCHECK(initialized_);
  RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
  RTC_DCHECK(nullptr != call);
  VideoMediaChannel* media_channel = media_engine_->CreateVideoChannel(
      call, media_config, options);
  if (media_channel == NULL) {
    return NULL;
  }

  VideoChannel* video_channel = new VideoChannel(
      worker_thread_, network_thread_, signaling_thread, media_channel,
      content_name, rtcp_packet_transport == nullptr, srtp_required);
  if (!video_channel->Init_w(rtp_dtls_transport, rtcp_dtls_transport,
                             rtp_packet_transport, rtcp_packet_transport)) {
    delete video_channel;
    return NULL;
  }
  video_channels_.push_back(video_channel);
  return video_channel;
}

VideoMediaChannel实例media_channel由MediaEngineInterface对象media_engine创建,media_engine由ChannelManager构造方法传入并初始化,ChannelManager由PeerConnectionFactory创建,在PeerConnection初始化方法中,media_engine被创建:

//pc/peerconnectionfactory.cc
bool PeerConnectionFactory::Initialize() {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  rtc::InitRandom(rtc::Time32());

  default_network_manager_.reset(new rtc::BasicNetworkManager());
  if (!default_network_manager_) {
    return false;
  }

  default_socket_factory_.reset(
      new rtc::BasicPacketSocketFactory(network_thread_));
  if (!default_socket_factory_) {
    return false;
  }

  std::unique_ptr<cricket::MediaEngineInterface> media_engine =
      worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>(
          RTC_FROM_HERE,
          rtc::Bind(&PeerConnectionFactory::CreateMediaEngine_w, this));

  channel_manager_.reset(new cricket::ChannelManager(
      std::move(media_engine), worker_thread_, network_thread_));

  channel_manager_->SetVideoRtxEnabled(true);
  if (!channel_manager_->Init()) {
    return false;
  }

  return true;
}

std::unique_ptr<cricket::MediaEngineInterface>
PeerConnectionFactory::CreateMediaEngine_w() {
  RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
  return std::unique_ptr<cricket::MediaEngineInterface>(
      cricket::WebRtcMediaEngineFactory::Create(
          default_adm_.get(), audio_encoder_factory_,
          audio_decoder_factory_,
          video_encoder_factory_.get(), video_decoder_factory_.get(),
          external_audio_mixer_));
}

WebRtcMediaEngine2继承自CompositeMediaEngine,CompositeMediaEngine父类MediaEngineInterface有WebRtcVoiceEngine voiceWebRtcVideoEngine2 video两个对象

WebRtcVideoEngine2

WebRtcVideoEngine2定义在media/engine/webrtcvideoengine2.h下,用于创建WebRtcVideoChannel2(定义在同一头文件),WebRtcVideoChannel2定义了WebRtcVideoSendStream与WebRtcVideoReceiveStream两个内部类.


轻口味
16.9k 声望3.9k 粉丝

移动端十年老人,主要做IM、音视频、AI方向,目前在做鸿蒙化适配,欢迎这些方向的同学交流:wodekouwei