在webrtc中,许多重要的对象实际上都是“代理对象”,如PeerConnection, PeerConnectionFactory,等等,可以看下PeerConnectionFactory的源代码:
rtc::scoped_refptr<PeerConnectionFactoryInterface>
CreatePeerConnectionFactory() {
rtc::scoped_refptr<PeerConnectionFactory> pc_factory(
new rtc::RefCountedObject<PeerConnectionFactory>());
RTC_CHECK(rtc::Thread::Current() == pc_factory->signaling_thread());
if (!pc_factory->Initialize()) {
return nullptr;
}
return PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(), pc_factory);
}
从代码可以看出,创建PeerConnectionFactory实际上返回的是PeerConnectionFactoryProxy对象。那这么做有什么用呢?从PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(), pc_factory); 中可以看到,Create的还有一个参数是pc_factory->signaling_thread(),猜一下也知道,这是为了解决多线程问题的。其实,他是为了保证所有的proxy对象的操作都在singaling线程中,当在另一个线程调用了proxy对象的方法时,proxy对象会将该方法的操作包装成一个message,发送给singaling线程,然后阻塞等待singaling线程中执行完成。
下面可以看一下它的源码是如何实现的,为了简单起见,使用MediaStream为例说明,
rtc::scoped_refptr<MediaStreamInterface>
PeerConnectionFactory::CreateLocalMediaStream(const std::string& label) {
RTC_DCHECK(signaling_thread_->IsCurrent());
return MediaStreamProxy::Create(signaling_thread_,
MediaStream::Create(label));
}
MediaStreamProxy实际上是由一个宏生成的,如下:
BEGIN_SIGNALING_PROXY_MAP(MediaStream)
PROXY_CONSTMETHOD0(std::string, label)
PROXY_METHOD0(AudioTrackVector, GetAudioTracks)
PROXY_METHOD0(VideoTrackVector, GetVideoTracks)
PROXY_METHOD1(rtc::scoped_refptr<AudioTrackInterface>,
FindAudioTrack, const std::string&)
PROXY_METHOD1(rtc::scoped_refptr<VideoTrackInterface>,
FindVideoTrack, const std::string&)
PROXY_METHOD1(bool, AddTrack, AudioTrackInterface*)
PROXY_METHOD1(bool, AddTrack, VideoTrackInterface*)
PROXY_METHOD1(bool, RemoveTrack, AudioTrackInterface*)
PROXY_METHOD1(bool, RemoveTrack, VideoTrackInterface*)
PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
END_SIGNALING_PROXY()
}
把这些宏都展开,如下(为避免太长砍掉了很多函数):
class MediaStreamProxy : public MediaStreamInterface { \
protected:
typedef MediaStreamInterface C;
MediaStreamProxy(rtc::Thread* signaling_thread, C* c)
: signaling_thread_(signaling_thread), c_(c) {}
~MediaStreamProxy() {
MethodCall0<MediaStreamProxy, void> call(
this, &MediaStreamProxy::Release_s);
call.Marshal(signaling_thread_);
}
public:
static rtc::scoped_refptr<C> Create(rtc::Thread* signaling_thread, C* c) {
return new rtc::RefCountedObject<MediaStreamProxy>(
signaling_thread, c);
}
std::string label() const override {
ConstMethodCall0<C, std::string> call(c_.get(), &C::label);
return call.Marshal(signaling_thread_);
}
AudioTrackVector GetAudioTracks() override {
MethodCall0<C, AudioTrackVector> call(c_.get(), &C::GetAudioTracks);
return call.Marshal(signaling_thread_);
}
private:
void Release_s() {
c_ = NULL;
}
mutable rtc::Thread* signaling_thread_;
rtc::scoped_refptr<C> c_;
};
我们以GetAudioTracks()函数分析,可见它实际上是调用
MethodCall0的Marshal方法,MethodCall0的实现如下:
template <typename C, typename R>
class MethodCall0 : public rtc::Message,
public rtc::MessageHandler {
public:
typedef R (C::*Method)();
MethodCall0(C* c, Method m) : c_(c), m_(m) {}
R Marshal(rtc::Thread* t) {
internal::SynchronousMethodCall(this).Invoke(t);
return r_.value();
}
private:
void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
C* c_;
Method m_;
ReturnType<R> r_;
};
MethodCall0的Marshal中实际上调用SynchronousMethodCall的Invoke():
class SynchronousMethodCall
: public rtc::MessageData,
public rtc::MessageHandler {
public:
explicit SynchronousMethodCall(rtc::MessageHandler* proxy)
: e_(), proxy_(proxy) {}
~SynchronousMethodCall() {}
void Invoke(rtc::Thread* t) {
if (t->IsCurrent()) {
proxy_->OnMessage(NULL);
} else {
e_.reset(new rtc::Event(false, false));
t->Post(this, 0);
e_->Wait(rtc::Event::kForever); //阻塞,直到e_->Set();
}
}
private:
void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); } //在另一个线程执行proxy_->OnMessage(真正的任务),然后调用e_->Set();解除等待线程的阻塞
std::unique_ptr<rtc::Event> e_;
rtc::MessageHandler* proxy_;
};
从Invoke中可以看出,它先判断当前线程是不是t(即signaling线程),如果是则直接执行,若不是,则将该消息发送至signaling线程并等待执行完成。