webrtc proxy.h头文件分析

简述

src/api/proxy.h里面定义了三种 BEGIN_XXX_PROXY_MAP宏,分别是BEGIN_SIGNALING_PROXY_MAP、BEGIN_PROXY_MAP、BEGIN_OWNED_PROXY_MAP,这三种宏分别用来生成 XXXProxy 类,下面这些头文件使用了这些宏:

api/media_stream.proxy.h

api/medis_stream_track_proxy.h

api/peer_connection_factory_proxy.h

api/peer_connection_proxy.h

api/rtp_receiver_interface.h

api/rtp_sender_interface.h

api/video_track_source_proxy.h

pc/data_channel.h

pc/dtmf_sender.h

pc/jitter_buffer_delay_proxy.

pc/rtp_transceiver.h

BEGIN_SIGNALING_PROXY_MAP 和另外两个BEGIN_XXX_PROXY_MAP宏功能相同,只是在生成类的参数有差别,下面以BEGIN_SIGNALING_PROXY_MAP为例,结合peer_connection_proxy.h分析proxy所生成的类以及proxy机制的特点。

1.生成PeerConnectionProxy类

peer_connection_proxy.h头文件使用了宏 BEGIN_SIGNALING_PROXY_MAP、PROXY_SIGNALING_THREAD_DESTRUCTOR、PROXY_METHOD0/1/2...、END_PROXY_MAP,这些宏在编译器进行宏展开后将会生成如下的类:

template <class INTERNAL_CLASS>
class PeerConnectionProxyWithInternal;
typedef PeerConnectionProxyWithInternal<PeerConnectionInterface> PeerConnectionProxy;
template <class INTERNAL_CLASS>
class PeerConnectionProxyWithInternal : public PeerConnectionInterface {
protected:
	typedef PeerConnectionInterface C;

public:
	const INTERNAL_CLASS* internal() const { return c_; }
	INTERNAL_CLASS* internal() { return c_; }

protected:
	PeerConnectionProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c)
		: signaling_thread_(signaling_thread), c_(c) {}

private:
	mutable rtc::Thread* signaling_thread_;

protected:
	PeerConnectionProxyWithInternal() {
		MethodCall<PeerConnectionProxyWithInternal, void> call(
			this, &PeerConnectionProxyWithInternal::DestroyInternal);
		call.Marshal(RTC_FROM_HERE, destructor_thread());
	}

private:
	void DestroyInternal() { c_ = nullptr; }
	rtc::scoped_refptr<INTERNAL_CLASS> c_;

public:
	static rtc::scoped_refptr<PeerConnectionProxyWithInternal> Create(
		rtc::Thread* signaling_thread, INTERNAL_CLASS* c) {
		return new rtc::RefCountedObject<PeerConnectionProxyWithInternal>(signaling_thread,
			c);
	}

private:
	rtc::Thread* destructor_thread() const { return signaling_thread_; }

public:  // NOLINTNEXTLINE

  // 下面是代理函数的展开
	void Close() override {
		MethodCall<C, void> call(c_, &C::Close);
		return call.Marshal(RTC_FROM_HERE, signaling_thread_);
	}

	void  SetLocalDescription(SetSessionDescriptionObserver* a1) override {
		MethodCall<C, void, SetSessionDescriptionObserver*> call(c_, &C::SetLocalDescription, std::move(a1));
		return call.Marshal(RTC_FROM_HERE, signaling_thread_);
	}
	// 除了上面两个函数, 还代理了很多其它的函数。。。

};

从上面的代码可以看出来,真正生成的类名是PeerConnectionProxyWithInternal , PeerConnectionProxy只是PeerConnectionProxyWithInternal 的一个别名。PeerConnectionProxyWithInternal 类的构造函数在外部是无法直接访问的,但可以通过静态函数 Create来创建PeerConnectionProxyWithInternal 实例,Create函数传入了两个参数,分别是信令线程和所代理对象,当上层调用PeerConnectionProxy的Close/SetLocalDescription函数时,实际时上是调用被代理对象的Close/SetLocalDescription函数。通过在peer_connection_proxy.h文件里面使用不同的宏(PROXY_METHOD0、PROXY_WORKER_METHOD0...)来代理函数,可以决定被代理的函数是否在当前线程执行内执行,但这对上层调用者来说都是透明的,都是同步调用的效果。

2.PeerConnectionProxy的使用

参见PeerConnectionFactory::CreatePeerConnection函数,这个函数返回的是PeerConnectionInterface类型的指针,但这个指针指向的实例是PeerConnectionProxyWithInternal,并非PeerConnection,真正的PeerConnection对象被通过PeerConnectionProxy::Create函数传入到了 PeerConnectionProxyWithInternal内部,后续通过PeerConnectionInterface调用 Close/SetLocalDescription等函数,其实是先执行 PeerConnectionProxyWithInternal类的 Close/SetLocalDescription等函数,最终才执行PeerConnection类的 Close/SetLocalDescription等函数。相关代码如下:

  rtc::scoped_refptr<PeerConnection> pc(
      new rtc::RefCountedObject<PeerConnection>(this, std::move(event_log),
                                                std::move(call)));
  ActionsBeforeInitializeForTesting(pc);
  if (!pc->Initialize(configuration, std::move(dependencies))) {
    return nullptr;
  }
  return PeerConnectionProxy::Create(signaling_thread(), pc);

3.总结

webrtc使用proxy模型带来了两个好处,第一减少冗余代码的生成,在简述段落可以看到,有很多地方使用到了proxy,假如没有借助proxy里面的宏来自动生成类,那么就得为每个 XXXProxy类编写同样的代码,这样的结果就是webrtc存在大量结构类似的 XXXProxy类代码,使用proxy就避免了这样的问题。第二、以统一的同步调用方式封装目标函数的同步或异步执行,被代理对象的一些函数可能需要在调用者线程内执行,而另一些则可能需要在工作线程内执行,通过proxy模型,可以把所有被代理对象的函数都封装起来,对外只提供一个同步调用的方式,这样就简化了被代理对象的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值