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;
}
}