版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liwenlong_only/article/details/80166016
webrtc proxy 分析
在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_;
};