webrtcWebRtc Video Receiver

WebRtc Video Receiver(一)-模块创建分析

2020-08-30  本文已影响0人  JeffreyLau

1)前言

2)WebRtcVideoReceiveStream的创建流程

WebRtc_Video_Stream_Receiver_00_00.png
bool WebRtcVideoChannel::AddRecvStream(const StreamParams& sp,
                                       bool default_stream) {
  RTC_DCHECK_RUN_ON(&thread_checker_);
  .....
  uint32_t ssrc = sp.first_ssrc();
  ....  
  receive_streams_[ssrc] = new WebRtcVideoReceiveStream(
      this, call_, sp, std::move(config), decoder_factory_, default_stream,
      recv_codecs_, flexfec_config);

  return true;
}
WebRtcVideoChannel::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
    WebRtcVideoChannel* channel,
    webrtc::Call* call,
    const StreamParams& sp,
    webrtc::VideoReceiveStream::Config config,
    webrtc::VideoDecoderFactory* decoder_factory,
    bool default_stream,
    const std::vector<VideoCodecSettings>& recv_codecs,
    const webrtc::FlexfecReceiveStream::Config& flexfec_config)
    : channel_(channel),
      call_(call),
      stream_params_(sp),
      stream_(NULL),
      default_stream_(default_stream),
      config_(std::move(config)),
      flexfec_config_(flexfec_config),
      flexfec_stream_(nullptr),
      decoder_factory_(decoder_factory),
      sink_(NULL),
      first_frame_timestamp_(-1),
      estimated_remote_start_ntp_time_ms_(0) {
  config_.renderer = this;
  ConfigureCodecs(recv_codecs);
  ConfigureFlexfecCodec(flexfec_config.payload_type);
  MaybeRecreateWebRtcFlexfecStream();
  RecreateWebRtcVideoStream();
}
void WebRtcVideoChannel::WebRtcVideoReceiveStream::ConfigureCodecs(
    const std::vector<VideoCodecSettings>& recv_codecs) {
  RTC_DCHECK(!recv_codecs.empty());
  config_.decoders.clear();
  config_.rtp.rtx_associated_payload_types.clear();
  config_.rtp.raw_payload_types.clear();
  for (const auto& recv_codec : recv_codecs) {
    webrtc::SdpVideoFormat video_format(recv_codec.codec.name,
                                        recv_codec.codec.params);

    webrtc::VideoReceiveStream::Decoder decoder;
    decoder.decoder_factory = decoder_factory_;
    decoder.video_format = video_format;
    decoder.payload_type = recv_codec.codec.id;
    decoder.video_format =
        webrtc::SdpVideoFormat(recv_codec.codec.name, recv_codec.codec.params);
    config_.decoders.push_back(decoder);
    config_.rtp.rtx_associated_payload_types[recv_codec.rtx_payload_type] =
        recv_codec.codec.id;
    if (recv_codec.codec.packetization == kPacketizationParamRaw) {
      config_.rtp.raw_payload_types.insert(recv_codec.codec.id);
    }
  }

  const auto& codec = recv_codecs.front();
  config_.rtp.ulpfec_payload_type = codec.ulpfec.ulpfec_payload_type;
  config_.rtp.red_payload_type = codec.ulpfec.red_payload_type;

  config_.rtp.lntf.enabled = HasLntf(codec.codec);
  config_.rtp.nack.rtp_history_ms = HasNack(codec.codec) ? kNackHistoryMs : 0;
  config_.rtp.rtcp_xr.receiver_reference_time_report = HasRrtr(codec.codec);
  if (codec.ulpfec.red_rtx_payload_type != -1) {
    config_.rtp
        .rtx_associated_payload_types[codec.ulpfec.red_rtx_payload_type] =
        codec.ulpfec.red_payload_type;
  }
}

void WebRtcVideoChannel::WebRtcVideoReceiveStream::ConfigureFlexfecCodec(
    int flexfec_payload_type) {
  flexfec_config_.payload_type = flexfec_payload_type;
}

3)webrtc::VideoReceiveStream 创建及其初始化

webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
    webrtc::VideoReceiveStream::Config configuration) {
  TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream");
  RTC_DCHECK_RUN_ON(&configuration_sequence_checker_);
  //如果支持transport wide cc 则不进行周期发送
  receive_side_cc_.SetSendPeriodicFeedback(
      SendPeriodicFeedback(configuration.rtp.extensions));

  RegisterRateObserver();

  VideoReceiveStream* receive_stream = new VideoReceiveStream(
      task_queue_factory_, &video_receiver_controller_, num_cpu_cores_,
      transport_send_ptr_->packet_router(), std::move(configuration),
      module_process_thread_.get(), call_stats_.get(), clock_);

  const webrtc::VideoReceiveStream::Config& config = receive_stream->config();
  {
    WriteLockScoped write_lock(*receive_crit_);
    if (config.rtp.rtx_ssrc) {
      // We record identical config for the rtx stream as for the main
      // stream. Since the transport_send_cc negotiation is per payload
      // type, we may get an incorrect value for the rtx stream, but
      // that is unlikely to matter in practice.
      receive_rtp_config_.emplace(config.rtp.rtx_ssrc,
                                  ReceiveRtpConfig(config));
    }
    receive_rtp_config_.emplace(config.rtp.remote_ssrc,
                                ReceiveRtpConfig(config));
    video_receive_streams_.insert(receive_stream);
    ConfigureSync(config.sync_group);
  }
  receive_stream->SignalNetworkState(video_network_state_);
  UpdateAggregateNetworkState();
  event_log_->Log(std::make_unique<RtcEventVideoReceiveStreamConfig>(
      CreateRtcLogStreamConfig(config)));
  return receive_stream;
}
VideoReceiveStream::VideoReceiveStream(
    TaskQueueFactory* task_queue_factory,
    RtpStreamReceiverControllerInterface* receiver_controller,
    int num_cpu_cores,
    PacketRouter* packet_router,
    VideoReceiveStream::Config config,
    ProcessThread* process_thread,
    CallStats* call_stats,
    Clock* clock,
    VCMTiming* timing)
    : task_queue_factory_(task_queue_factory),
      ....
      rtp_video_stream_receiver_(clock_,
                                 &transport_adapter_,
                                 call_stats,
                                 packet_router,
                                 &config_,
                                 rtp_receive_statistics_.get(),
                                 &stats_proxy_,
                                 process_thread_,
                                 this,     // NackSender
                                 nullptr,  // Use default KeyFrameRequestSender
                                 this,     // OnCompleteFrameCallback
                                 config_.frame_decryptor),
        ....  
    ) {
  RTC_LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString();
  ....
  if (config_.media_transport()) {
    config_.media_transport()->SetReceiveVideoSink(this);
    config_.media_transport()->AddRttObserver(this);
  } else {
    // Register with RtpStreamReceiverController.
    media_receiver_ = receiver_controller->CreateReceiver(
        config_.rtp.remote_ssrc, &rtp_video_stream_receiver_);
    if (config_.rtp.rtx_ssrc) {
      rtx_receive_stream_ = std::make_unique<RtxReceiveStream>(
          &rtp_video_stream_receiver_, config.rtp.rtx_associated_payload_types,
          config_.rtp.remote_ssrc, rtp_receive_statistics_.get());
      rtx_receiver_ = receiver_controller->CreateReceiver(
          config_.rtp.rtx_ssrc, rtx_receive_stream_.get());
    } else {
      rtp_receive_statistics_->EnableRetransmitDetection(config.rtp.remote_ssrc,
                                                         true);
    }
  }
}

4)VideoReceiveStream构造函数分析

VideoReceiveStream::VideoReceiveStream(
    TaskQueueFactory* task_queue_factory,
    RtpStreamReceiverControllerInterface* receiver_controller,
    int num_cpu_cores,
    PacketRouter* packet_router,
    VideoReceiveStream::Config config,
    ProcessThread* process_thread,
    CallStats* call_stats,
    Clock* clock,
    VCMTiming* timing)
    : task_queue_factory_(task_queue_factory),
      transport_adapter_(config.rtcp_send_transport),
      config_(std::move(config)),
      num_cpu_cores_(num_cpu_cores),
      process_thread_(process_thread),
      clock_(clock),
      call_stats_(call_stats),
      source_tracker_(clock_),
      stats_proxy_(&config_, clock_),
      rtp_receive_statistics_(ReceiveStatistics::Create(clock_)),
      timing_(timing),
      video_receiver_(clock_, timing_.get()),
      rtp_video_stream_receiver_(clock_,
                                 &transport_adapter_,
                                 call_stats,
                                 packet_router,
                                 &config_,
                                 rtp_receive_statistics_.get(),
                                 &stats_proxy_,
                                 process_thread_,
                                 this,     // NackSender
                                 nullptr,  // Use default KeyFrameRequestSender
                                 this,     // OnCompleteFrameCallback
                                 config_.frame_decryptor),
      rtp_stream_sync_(this),
      max_wait_for_keyframe_ms_(KeyframeIntervalSettings::ParseFromFieldTrials()
                                    .MaxWaitForKeyframeMs()
                                    .value_or(kMaxWaitForKeyFrameMs)),
      max_wait_for_frame_ms_(KeyframeIntervalSettings::ParseFromFieldTrials()
                                 .MaxWaitForFrameMs()
                                 .value_or(kMaxWaitForFrameMs)),
      decode_queue_(task_queue_factory_->CreateTaskQueue(
          "DecodingQueue",
          TaskQueueFactory::Priority::HIGH)) {
  .....        
  module_process_sequence_checker_.Detach();
  network_sequence_checker_.Detach();

  std::set<int> decoder_payload_types;
  for (const Decoder& decoder : config_.decoders) {
    .....
    decoder_payload_types.insert(decoder.payload_type);
  }
  
  timing_->set_render_delay(config_.render_delay_ms);

  frame_buffer_.reset(
      new video_coding::FrameBuffer(clock_, timing_.get(), &stats_proxy_));

  process_thread_->RegisterModule(&rtp_stream_sync_, RTC_FROM_HERE);
  if (config_.media_transport()) {
    config_.media_transport()->SetReceiveVideoSink(this);
    config_.media_transport()->AddRttObserver(this);
  } else {
    // Register with RtpStreamReceiverController.
    media_receiver_ = receiver_controller->CreateReceiver(
        config_.rtp.remote_ssrc, &rtp_video_stream_receiver_);
    if (config_.rtp.rtx_ssrc) {
      rtx_receive_stream_ = std::make_unique<RtxReceiveStream>(
          &rtp_video_stream_receiver_, config.rtp.rtx_associated_payload_types,
          config_.rtp.remote_ssrc, rtp_receive_statistics_.get());
      rtx_receiver_ = receiver_controller->CreateReceiver(
          config_.rtp.rtx_ssrc, rtx_receive_stream_.get());
    } else {
      rtp_receive_statistics_->EnableRetransmitDetection(config.rtp.remote_ssrc,
                                                         true);
    }
  }
}

5)VideoReceiveStream启动分析

void WebRtcVideoChannel::WebRtcVideoReceiveStream::RecreateWebRtcVideoStream() {
  .....
  stream_ = call_->CreateVideoReceiveStream(std::move(config));
  ....
  stream_->Start();
  ....
}
void VideoReceiveStream::Start() {
  RTC_DCHECK_RUN_ON(&worker_sequence_checker_);

  if (decoder_running_) {
    return;
  }

  const bool protected_by_fec = config_.rtp.protected_by_flexfec ||
                                rtp_video_stream_receiver_.IsUlpfecEnabled();

  frame_buffer_->Start();

  if (rtp_video_stream_receiver_.IsRetransmissionsEnabled() &&
      protected_by_fec) {
    frame_buffer_->SetProtectionMode(kProtectionNackFEC);
  }
  /*使能RTCP和RTP发送*/
  transport_adapter_.Enable();
  rtc::VideoSinkInterface<VideoFrame>* renderer = nullptr;
  /*enable_prerenderer_smoothing默认为true  
    render_delay_ms默认为10ms,定义在VideoReceiveStream::Stats结构中  
    此时的值应该为0,IncomingVideoStream用于平滑渲染,这里将this指针传入,最终VideoFrame
    会触发到VideoReceiveStream::onFrame()函数
  */
  if (config_.enable_prerenderer_smoothing) {
    incoming_video_stream_.reset(new IncomingVideoStream(
        task_queue_factory_, config_.render_delay_ms, this));
    renderer = incoming_video_stream_.get();
  } else {
    renderer = this;
  }

  for (const Decoder& decoder : config_.decoders) {
    std::unique_ptr<VideoDecoder> video_decoder =
      decoder.decoder_factory->LegacyCreateVideoDecoder(
                    decoder.video_format,config_.stream_id);
    // If we still have no valid decoder, we have to create a "Null" decoder
    // that ignores all calls. The reason we can get into this state is that the
    // old decoder factory interface doesn't have a way to query supported
    // codecs.
    if (!video_decoder) {
      video_decoder = std::make_unique<NullVideoDecoder>();
    }
      
    video_decoders_.push_back(std::move(video_decoder));

    video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),
                                            decoder.payload_type);
    VideoCodec codec = CreateDecoderVideoCodec(decoder);

    const bool raw_payload =
        config_.rtp.raw_payload_types.count(codec.plType) > 0;
    rtp_video_stream_receiver_.AddReceiveCodec(
        codec, decoder.video_format.parameters, raw_payload);
    RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec(
                             &codec, num_cpu_cores_, false));
  }

  RTC_DCHECK(renderer != nullptr);
  video_stream_decoder_.reset(
      new VideoStreamDecoder(&video_receiver_, &stats_proxy_, renderer));

  // Make sure we register as a stats observer *after* we've prepared the
  // |video_stream_decoder_|.
  call_stats_->RegisterStatsObserver(this);

  // Start decoding on task queue.
  video_receiver_.DecoderThreadStarting();
  stats_proxy_.DecoderThreadStarting();
  decode_queue_.PostTask([this] {
    RTC_DCHECK_RUN_ON(&decode_queue_);
    decoder_stopped_ = false;
    StartNextDecode();
  });
  decoder_running_ = true;
  rtp_video_stream_receiver_.StartReceive();
}

6)总结:

上一篇下一篇

猜你喜欢

热点阅读