webrtc-m79-VideoReceiveStream中的 task_queue_factory_ 的来源

1 首先来看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( // Linux下 task_queue_factory_ 就是 TaskQueueLibeventFactory 具体见下方分析
          "DecodingQueue", // TaskQueueLibeventFactory->CreateTaskQueue 返回的是 TaskQueueLibevent 
          TaskQueueFactory::Priority::HIGH)) { // class TaskQueueLibevent final : public TaskQueueBase
  RTC_LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); //rtc::TaskQueue 的构造函数中的参数就是 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter> task_queue
                                                                    // 将 TaskQueueLibevent 的指针保存在了 rtc::TaskQueue 的webrtc::TaskQueueBase* const impl_;成员变量中
  RTC_DCHECK(config_.renderer);
  RTC_DCHECK(process_thread_);
  RTC_DCHECK(call_stats_);

  module_process_sequence_checker_.Detach();
  network_sequence_checker_.Detach();

  RTC_DCHECK(!config_.decoders.empty());
  std::set<int> decoder_payload_types;
  for (const Decoder& decoder : config_.decoders) {
    RTC_CHECK(decoder.decoder_factory);
    RTC_CHECK(decoder_payload_types.find(decoder.payload_type) ==
              decoder_payload_types.end())
        << "Duplicate payload type (" << decoder.payload_type
        << ") for different 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);
    }
  }
}

 

2 具体分析

VideoReceiveStream 中的 task_queue_factory_ 来自 webrtc::internal::Call 的成员变量 task_queue_factory_;而 webrtc::internal::Call 中的成员变量 task_queue_factory_ 又来自 PeerConnectionFactory::CreateCall_w 中的call_config.task_queue_factory = task_queue_factory_.get();而 task_queue_factory_ 是 PeerConnectionFactory的成员变量,具体代码如下:

PeerConnectionFactory::PeerConnectionFactory(
    PeerConnectionFactoryDependencies dependencies)
    : wraps_current_thread_(false),
      network_thread_(dependencies.network_thread),
      worker_thread_(dependencies.worker_thread),
      signaling_thread_(dependencies.signaling_thread),
      task_queue_factory_(std::move(dependencies.task_queue_factory)), //注意这里

rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
    rtc::Thread* network_thread,
    rtc::Thread* worker_thread,
    rtc::Thread* signaling_thread,
    rtc::scoped_refptr<AudioDeviceModule> default_adm,
    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
    std::unique_ptr<VideoEncoderFactory> video_encoder_factory,
    std::unique_ptr<VideoDecoderFactory> video_decoder_factory,
    rtc::scoped_refptr<AudioMixer> audio_mixer,
    rtc::scoped_refptr<AudioProcessing> audio_processing) {
  PeerConnectionFactoryDependencies dependencies;
  dependencies.network_thread = network_thread;
  dependencies.worker_thread = worker_thread;
  dependencies.signaling_thread = signaling_thread;
  dependencies.task_queue_factory = CreateDefaultTaskQueueFactory(); //注意这里
  dependencies.call_factory = CreateCallFactory();
  dependencies.event_log_factory = std::make_unique<RtcEventLogFactory>(
      dependencies.task_queue_factory.get());

  cricket::MediaEngineDependencies media_dependencies;
  media_dependencies.task_queue_factory = dependencies.task_queue_factory.get();
  media_dependencies.adm = std::move(default_adm);
  media_dependencies.audio_encoder_factory = std::move(audio_encoder_factory);
  media_dependencies.audio_decoder_factory = std::move(audio_decoder_factory);
  if (audio_processing) {
    media_dependencies.audio_processing = std::move(audio_processing);
  } else {
    media_dependencies.audio_processing = AudioProcessingBuilder().Create();
  }
  media_dependencies.audio_mixer = std::move(audio_mixer);
  media_dependencies.video_encoder_factory = std::move(video_encoder_factory);
  media_dependencies.video_decoder_factory = std::move(video_decoder_factory);
  dependencies.media_engine =
      cricket::CreateMediaEngine(std::move(media_dependencies));

  return CreateModularPeerConnectionFactory(std::move(dependencies));
}

 

3 选择基于libevent实现的进行分析

std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
  return CreateTaskQueueLibeventFactory();
}


std::unique_ptr<TaskQueueFactory> CreateTaskQueueLibeventFactory() {
  return std::make_unique<TaskQueueLibeventFactory>();
}


class TaskQueueLibeventFactory final : public TaskQueueFactory {
 public:
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
      absl::string_view name,
      Priority priority) const override {
    return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
        new TaskQueueLibevent(name,
                              TaskQueuePriorityToThreadPriority(priority)));
  }
};


class TaskQueueLibevent final : public TaskQueueBase {
 public:
  TaskQueueLibevent(absl::string_view queue_name, rtc::ThreadPriority priority);

  void Delete() override;
  void PostTask(std::unique_ptr<QueuedTask> task) override;
  void PostDelayedTask(std::unique_ptr<QueuedTask> task,
                       uint32_t milliseconds) override;

 private:
  class SetTimerTask;
  struct TimerEvent;

  ~TaskQueueLibevent() override = default;

  static void ThreadMain(void* context);
  static void OnWakeup(int socket, short flags, void* context);  // NOLINT
  static void RunTimer(int fd, short flags, void* context);      // NOLINT

  bool is_active_ = true;
  int wakeup_pipe_in_ = -1;
  int wakeup_pipe_out_ = -1;
  event_base* event_base_; //
  event wakeup_event_;
  rtc::PlatformThread thread_; //
  rtc::CriticalSection pending_lock_;
  std::list<std::unique_ptr<QueuedTask>> pending_ RTC_GUARDED_BY(pending_lock_);
  // Holds a list of events pending timers for cleanup when the loop exits.
  std::list<TimerEvent*> pending_timers_;
};



              class PlatformThread {
               public:
                PlatformThread(ThreadRunFunction func,
                               void* obj,
                               absl::string_view thread_name,
                               ThreadPriority priority = kNormalPriority);
                virtual ~PlatformThread();

                const std::string& name() const { return name_; }

                // Spawns a thread and tries to set thread priority according to the priority
                // from when CreateThread was called.
                void Start();

                bool IsRunning() const;

                // Returns an identifier for the worker thread that can be used to do
                // thread checks.
                PlatformThreadRef GetThreadRef() const;

                // Stops (joins) the spawned thread.
                void Stop();

               protected:
              #if defined(WEBRTC_WIN)
                // Exposed to derived classes to allow for special cases specific to Windows.
                bool QueueAPC(PAPCFUNC apc_function, ULONG_PTR data);
              #endif

               private:
                void Run();
                bool SetPriority(ThreadPriority priority);

                ThreadRunFunction const run_function_ = nullptr;
                const ThreadPriority priority_ = kNormalPriority;
                void* const obj_;
                // TODO(pbos): Make sure call sites use string literals and update to a const
                // char* instead of a std::string.
                const std::string name_;
                rtc::ThreadChecker thread_checker_;
                rtc::ThreadChecker spawned_thread_checker_;
              #if defined(WEBRTC_WIN)
                static DWORD WINAPI StartThread(void* param);

                HANDLE thread_ = nullptr;
                DWORD thread_id_ = 0;
              #else
                static void* StartThread(void* param);

                pthread_t thread_ = 0;
              #endif  // defined(WEBRTC_WIN)
                RTC_DISALLOW_COPY_AND_ASSIGN(PlatformThread);
              };


              PlatformThread::PlatformThread(ThreadRunFunction func,
                                             void* obj,
                                             absl::string_view thread_name,
                                             ThreadPriority priority /*= kNormalPriority*/)
                  : run_function_(func), priority_(priority), obj_(obj), name_(thread_name) {
                RTC_DCHECK(func);
                RTC_DCHECK(!name_.empty());
                // TODO(tommi): Consider lowering the limit to 15 (limit on Linux).
                RTC_DCHECK(name_.length() < 64);
                spawned_thread_checker_.Detach();
              }


              void PlatformThread::Start() {
                RTC_DCHECK(thread_checker_.IsCurrent());
                RTC_DCHECK(!thread_) << "Thread already started?";
              #if defined(WEBRTC_WIN)
                // See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
                // Set the reserved stack stack size to 1M, which is the default on Windows
                // and Linux.
                thread_ = ::CreateThread(nullptr, 1024 * 1024, &StartThread, this,
                                         STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id_);
                RTC_CHECK(thread_) << "CreateThread failed";
                RTC_DCHECK(thread_id_);
              #else
                ThreadAttributes attr;
                // Set the stack stack size to 1M.
                pthread_attr_setstacksize(&attr, 1024 * 1024);
                RTC_CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
              #endif  // defined(WEBRTC_WIN)
              }


              #if defined(WEBRTC_WIN)
              DWORD WINAPI PlatformThread::StartThread(void* param) {
                // The GetLastError() function only returns valid results when it is called
                // after a Win32 API function that returns a "failed" result. A crash dump
                // contains the result from GetLastError() and to make sure it does not
                // falsely report a Windows error we call SetLastError here.
                ::SetLastError(ERROR_SUCCESS);
                static_cast<PlatformThread*>(param)->Run();
                return 0;
              }
              #else
              void* PlatformThread::StartThread(void* param) {
                static_cast<PlatformThread*>(param)->Run();
                return 0;
              }
              #endif  // defined(WEBRTC_WIN)


              void PlatformThread::Run() {
                // Attach the worker thread checker to this thread.
                RTC_DCHECK(spawned_thread_checker_.IsCurrent());
                rtc::SetCurrentThreadName(name_.c_str());
                SetPriority(priority_);
                run_function_(obj_);
              }




TaskQueueLibevent::TaskQueueLibevent(absl::string_view queue_name,
                                     rtc::ThreadPriority priority)
    : event_base_(event_base_new()),  
      thread_(&TaskQueueLibevent::ThreadMain, this, queue_name, priority) { //注意这里
  int fds[2];
  RTC_CHECK(pipe(fds) == 0);
  SetNonBlocking(fds[0]);
  SetNonBlocking(fds[1]);
  wakeup_pipe_out_ = fds[0];
  wakeup_pipe_in_ = fds[1];

  EventAssign(&wakeup_event_, event_base_, wakeup_pipe_out_,
              EV_READ | EV_PERSIST, OnWakeup, this);
  event_add(&wakeup_event_, 0);
  thread_.Start();
}

// 线程入口函数是:
void TaskQueueLibevent::ThreadMain(void* context) {
  TaskQueueLibevent* me = static_cast<TaskQueueLibevent*>(context);

  {
    CurrentTaskQueueSetter set_current(me);
    while (me->is_active_)
      event_base_loop(me->event_base_, 0);
  }

  for (TimerEvent* timer : me->pending_timers_)
    delete timer;
}



void TaskQueueLibevent::OnWakeup(int socket,
                                 short flags,  // NOLINT
                                 void* context) {
  TaskQueueLibevent* me = static_cast<TaskQueueLibevent*>(context);
  RTC_DCHECK(me->wakeup_pipe_out_ == socket);
  char buf;
  RTC_CHECK(sizeof(buf) == read(socket, &buf, sizeof(buf)));
  switch (buf) {
    case kQuit:
      me->is_active_ = false;
      event_base_loopbreak(me->event_base_);
      break;
    case kRunTask: {
      std::unique_ptr<QueuedTask> task;
      {
        rtc::CritScope lock(&me->pending_lock_);
        RTC_DCHECK(!me->pending_.empty());
        task = std::move(me->pending_.front());
        me->pending_.pop_front();
        RTC_DCHECK(task.get());
      }
      if (!task->Run()) // 使用libevent的事件循环进行驱动
        task.release();
      break;
    }
    default:
      RTC_NOTREACHED();
      break;
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值