This CL adds the following interfaces: * RtpTransportController * RtpTransport * RtpSender * RtpReceiver They're implemented on top of the "BaseChannel" object, which is normally used in a PeerConnection, and roughly corresponds to an SDP "m=" section. As a result of this, there are several limitations: * You can only have one of each type of sender and receiver (audio/video) on top of the same transport controller. * The sender/receiver with the same media type must use the same RTP transport. * You can't change the transport after creating the sender or receiver. * Some of the parameters aren't supported. Later, these "adapter" objects will be gradually replaced by real objects that don't have these limitations, as "BaseChannel", "MediaChannel" and related code is restructured. In this CL, we essentially have: ORTC adapter objects -> BaseChannel -> Media engine PeerConnection -> BaseChannel -> Media engine And later we hope to have simply: PeerConnection -> "Real" ORTC objects -> Media engine See the linked bug for more context. BUG=webrtc:7013 TBR=stefan@webrtc.org Review-Url: https://codereview.webrtc.org/2675173003 Cr-Commit-Position: refs/heads/master@{#16842}
580 lines
21 KiB
C++
580 lines
21 KiB
C++
/*
|
|
* Copyright 2013 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
// This file contains Macros for creating proxies for webrtc MediaStream and
|
|
// PeerConnection classes.
|
|
// TODO(deadbeef): Move this to pc/; this is part of the implementation.
|
|
|
|
//
|
|
// Example usage:
|
|
//
|
|
// class TestInterface : public rtc::RefCountInterface {
|
|
// public:
|
|
// std::string FooA() = 0;
|
|
// std::string FooB(bool arg1) const = 0;
|
|
// std::string FooC(bool arg1) = 0;
|
|
// };
|
|
//
|
|
// Note that return types can not be a const reference.
|
|
//
|
|
// class Test : public TestInterface {
|
|
// ... implementation of the interface.
|
|
// };
|
|
//
|
|
// BEGIN_PROXY_MAP(Test)
|
|
// PROXY_SIGNALING_THREAD_DESTRUCTOR()
|
|
// PROXY_METHOD0(std::string, FooA)
|
|
// PROXY_CONSTMETHOD1(std::string, FooB, arg1)
|
|
// PROXY_WORKER_METHOD1(std::string, FooC, arg1)
|
|
// END_PROXY_MAP()
|
|
//
|
|
// Where the destructor and first two methods are invoked on the signaling
|
|
// thread, and the third is invoked on the worker thread.
|
|
//
|
|
// The proxy can be created using
|
|
//
|
|
// TestProxy::Create(Thread* signaling_thread, Thread* worker_thread,
|
|
// TestInterface*).
|
|
//
|
|
// The variant defined with BEGIN_SIGNALING_PROXY_MAP is unaware of
|
|
// the worker thread, and invokes all methods on the signaling thread.
|
|
//
|
|
// The variant defined with BEGIN_OWNED_PROXY_MAP does not use
|
|
// refcounting, and instead just takes ownership of the object being proxied.
|
|
|
|
#ifndef WEBRTC_API_PROXY_H_
|
|
#define WEBRTC_API_PROXY_H_
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "webrtc/base/event.h"
|
|
#include "webrtc/base/thread.h"
|
|
|
|
namespace webrtc {
|
|
|
|
template <typename R>
|
|
class ReturnType {
|
|
public:
|
|
template<typename C, typename M>
|
|
void Invoke(C* c, M m) { r_ = (c->*m)(); }
|
|
template <typename C, typename M, typename T1>
|
|
void Invoke(C* c, M m, T1 a1) {
|
|
r_ = (c->*m)(std::move(a1));
|
|
}
|
|
template <typename C, typename M, typename T1, typename T2>
|
|
void Invoke(C* c, M m, T1 a1, T2 a2) {
|
|
r_ = (c->*m)(std::move(a1), std::move(a2));
|
|
}
|
|
template <typename C, typename M, typename T1, typename T2, typename T3>
|
|
void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) {
|
|
r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3));
|
|
}
|
|
template<typename C, typename M, typename T1, typename T2, typename T3,
|
|
typename T4>
|
|
void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) {
|
|
r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4));
|
|
}
|
|
template<typename C, typename M, typename T1, typename T2, typename T3,
|
|
typename T4, typename T5>
|
|
void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
|
|
r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4),
|
|
std::move(a5));
|
|
}
|
|
|
|
R moved_result() { return std::move(r_); }
|
|
|
|
private:
|
|
R r_;
|
|
};
|
|
|
|
template <>
|
|
class ReturnType<void> {
|
|
public:
|
|
template<typename C, typename M>
|
|
void Invoke(C* c, M m) { (c->*m)(); }
|
|
template <typename C, typename M, typename T1>
|
|
void Invoke(C* c, M m, T1 a1) {
|
|
(c->*m)(std::move(a1));
|
|
}
|
|
template <typename C, typename M, typename T1, typename T2>
|
|
void Invoke(C* c, M m, T1 a1, T2 a2) {
|
|
(c->*m)(std::move(a1), std::move(a2));
|
|
}
|
|
template <typename C, typename M, typename T1, typename T2, typename T3>
|
|
void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) {
|
|
(c->*m)(std::move(a1), std::move(a2), std::move(a3));
|
|
}
|
|
|
|
void moved_result() {}
|
|
};
|
|
|
|
namespace internal {
|
|
|
|
class SynchronousMethodCall
|
|
: public rtc::MessageData,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
explicit SynchronousMethodCall(rtc::MessageHandler* proxy)
|
|
: e_(), proxy_(proxy) {}
|
|
~SynchronousMethodCall() {}
|
|
|
|
void Invoke(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
if (t->IsCurrent()) {
|
|
proxy_->OnMessage(NULL);
|
|
} else {
|
|
e_.reset(new rtc::Event(false, false));
|
|
t->Post(posted_from, this, 0);
|
|
e_->Wait(rtc::Event::kForever);
|
|
}
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); }
|
|
std::unique_ptr<rtc::Event> e_;
|
|
rtc::MessageHandler* proxy_;
|
|
};
|
|
|
|
} // namespace internal
|
|
|
|
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(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
};
|
|
|
|
template <typename C, typename R>
|
|
class ConstMethodCall0 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)() const;
|
|
ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
};
|
|
|
|
template <typename C, typename R, typename T1>
|
|
class MethodCall1 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)(T1 a1);
|
|
MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(std::move(a1)) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, std::move(a1_)); }
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
T1 a1_;
|
|
};
|
|
|
|
template <typename C, typename R, typename T1>
|
|
class ConstMethodCall1 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)(T1 a1) const;
|
|
ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(std::move(a1)) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, std::move(a1_)); }
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
T1 a1_;
|
|
};
|
|
|
|
template <typename C, typename R, typename T1, typename T2>
|
|
class MethodCall2 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)(T1 a1, T2 a2);
|
|
MethodCall2(C* c, Method m, T1 a1, T2 a2)
|
|
: c_(c), m_(m), a1_(std::move(a1)), a2_(std::move(a2)) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) {
|
|
r_.Invoke(c_, m_, std::move(a1_), std::move(a2_));
|
|
}
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
T1 a1_;
|
|
T2 a2_;
|
|
};
|
|
|
|
template <typename C, typename R, typename T1, typename T2, typename T3>
|
|
class MethodCall3 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)(T1 a1, T2 a2, T3 a3);
|
|
MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3)
|
|
: c_(c),
|
|
m_(m),
|
|
a1_(std::move(a1)),
|
|
a2_(std::move(a2)),
|
|
a3_(std::move(a3)) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) {
|
|
r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_));
|
|
}
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
T1 a1_;
|
|
T2 a2_;
|
|
T3 a3_;
|
|
};
|
|
|
|
template <typename C, typename R, typename T1, typename T2, typename T3,
|
|
typename T4>
|
|
class MethodCall4 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4);
|
|
MethodCall4(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4)
|
|
: c_(c),
|
|
m_(m),
|
|
a1_(std::move(a1)),
|
|
a2_(std::move(a2)),
|
|
a3_(std::move(a3)),
|
|
a4_(std::move(a4)) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) {
|
|
r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_),
|
|
std::move(a4_));
|
|
}
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
T1 a1_;
|
|
T2 a2_;
|
|
T3 a3_;
|
|
T4 a4_;
|
|
};
|
|
|
|
template <typename C, typename R, typename T1, typename T2, typename T3,
|
|
typename T4, typename T5>
|
|
class MethodCall5 : public rtc::Message,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
|
|
MethodCall5(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
|
: c_(c),
|
|
m_(m),
|
|
a1_(std::move(a1)),
|
|
a2_(std::move(a2)),
|
|
a3_(std::move(a3)),
|
|
a4_(std::move(a4)),
|
|
a5_(std::move(a5)) {}
|
|
|
|
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
|
|
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
|
|
return r_.moved_result();
|
|
}
|
|
|
|
private:
|
|
void OnMessage(rtc::Message*) {
|
|
r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_),
|
|
std::move(a4_), std::move(a5_));
|
|
}
|
|
|
|
C* c_;
|
|
Method m_;
|
|
ReturnType<R> r_;
|
|
T1 a1_;
|
|
T2 a2_;
|
|
T3 a3_;
|
|
T4 a4_;
|
|
T5 a5_;
|
|
};
|
|
|
|
|
|
// Helper macros to reduce code duplication.
|
|
#define PROXY_MAP_BOILERPLATE(c) \
|
|
template <class INTERNAL_CLASS> \
|
|
class c##ProxyWithInternal; \
|
|
typedef c##ProxyWithInternal<c##Interface> c##Proxy; \
|
|
template <class INTERNAL_CLASS> \
|
|
class c##ProxyWithInternal : public c##Interface { \
|
|
protected: \
|
|
typedef c##Interface C; \
|
|
\
|
|
public: \
|
|
const INTERNAL_CLASS* internal() const { return c_; } \
|
|
INTERNAL_CLASS* internal() { return c_; }
|
|
|
|
#define END_PROXY_MAP() \
|
|
};
|
|
|
|
#define SIGNALING_PROXY_MAP_BOILERPLATE(c) \
|
|
protected: \
|
|
c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \
|
|
: signaling_thread_(signaling_thread), c_(c) {} \
|
|
\
|
|
private: \
|
|
mutable rtc::Thread* signaling_thread_;
|
|
|
|
#define WORKER_PROXY_MAP_BOILERPLATE(c) \
|
|
protected: \
|
|
c##ProxyWithInternal(rtc::Thread* signaling_thread, \
|
|
rtc::Thread* worker_thread, INTERNAL_CLASS* c) \
|
|
: signaling_thread_(signaling_thread), \
|
|
worker_thread_(worker_thread), \
|
|
c_(c) {} \
|
|
\
|
|
private: \
|
|
mutable rtc::Thread* signaling_thread_; \
|
|
mutable rtc::Thread* worker_thread_;
|
|
|
|
// Note that the destructor is protected so that the proxy can only be
|
|
// destroyed via RefCountInterface.
|
|
#define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
|
|
protected: \
|
|
~c##ProxyWithInternal() { \
|
|
MethodCall0<c##ProxyWithInternal, void> call( \
|
|
this, &c##ProxyWithInternal::DestroyInternal); \
|
|
call.Marshal(RTC_FROM_HERE, destructor_thread()); \
|
|
} \
|
|
\
|
|
private: \
|
|
void DestroyInternal() { c_ = nullptr; } \
|
|
rtc::scoped_refptr<INTERNAL_CLASS> c_;
|
|
|
|
// Note: This doesn't use a unique_ptr, because it intends to handle a corner
|
|
// case where an object's deletion triggers a callback that calls back into
|
|
// this proxy object. If relying on a unique_ptr to delete the object, its
|
|
// inner pointer would be set to null before this reentrant callback would have
|
|
// a chance to run, resulting in a segfault.
|
|
#define OWNED_PROXY_MAP_BOILERPLATE(c) \
|
|
public: \
|
|
~c##ProxyWithInternal() { \
|
|
MethodCall0<c##ProxyWithInternal, void> call( \
|
|
this, &c##ProxyWithInternal::DestroyInternal); \
|
|
call.Marshal(RTC_FROM_HERE, destructor_thread()); \
|
|
} \
|
|
\
|
|
private: \
|
|
void DestroyInternal() { delete c_; } \
|
|
INTERNAL_CLASS* c_;
|
|
|
|
#define BEGIN_SIGNALING_PROXY_MAP(c) \
|
|
PROXY_MAP_BOILERPLATE(c) \
|
|
SIGNALING_PROXY_MAP_BOILERPLATE(c) \
|
|
REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
|
|
public: \
|
|
static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
|
|
rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \
|
|
return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
|
|
c); \
|
|
}
|
|
|
|
#define BEGIN_PROXY_MAP(c) \
|
|
PROXY_MAP_BOILERPLATE(c) \
|
|
WORKER_PROXY_MAP_BOILERPLATE(c) \
|
|
REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
|
|
public: \
|
|
static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
|
|
rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
|
|
INTERNAL_CLASS* c) { \
|
|
return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
|
|
worker_thread, c); \
|
|
}
|
|
|
|
#define BEGIN_OWNED_PROXY_MAP(c) \
|
|
PROXY_MAP_BOILERPLATE(c) \
|
|
WORKER_PROXY_MAP_BOILERPLATE(c) \
|
|
OWNED_PROXY_MAP_BOILERPLATE(c) \
|
|
public: \
|
|
static std::unique_ptr<c##Interface> Create( \
|
|
rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
|
|
std::unique_ptr<INTERNAL_CLASS> c) { \
|
|
return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \
|
|
signaling_thread, worker_thread, c.release())); \
|
|
}
|
|
|
|
#define PROXY_SIGNALING_THREAD_DESTRUCTOR() \
|
|
private: \
|
|
rtc::Thread* destructor_thread() const { return signaling_thread_; } \
|
|
\
|
|
public: // NOLINTNEXTLINE
|
|
|
|
#define PROXY_WORKER_THREAD_DESTRUCTOR() \
|
|
private: \
|
|
rtc::Thread* destructor_thread() const { return worker_thread_; } \
|
|
\
|
|
public: // NOLINTNEXTLINE
|
|
|
|
#define PROXY_METHOD0(r, method) \
|
|
r method() override { \
|
|
MethodCall0<C, r> call(c_, &C::method); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_CONSTMETHOD0(r, method) \
|
|
r method() const override { \
|
|
ConstMethodCall0<C, r> call(c_, &C::method); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_METHOD1(r, method, t1) \
|
|
r method(t1 a1) override { \
|
|
MethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_CONSTMETHOD1(r, method, t1) \
|
|
r method(t1 a1) const override { \
|
|
ConstMethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_METHOD2(r, method, t1, t2) \
|
|
r method(t1 a1, t2 a2) override { \
|
|
MethodCall2<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2)); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_METHOD3(r, method, t1, t2, t3) \
|
|
r method(t1 a1, t2 a2, t3 a3) override { \
|
|
MethodCall3<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2), std::move(a3)); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
|
|
r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
|
|
MethodCall4<C, r, t1, t2, t3, t4> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2), std::move(a3), \
|
|
std::move(a4)); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
|
|
r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
|
|
MethodCall5<C, r, t1, t2, t3, t4, t5> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2), std::move(a3), \
|
|
std::move(a4), std::move(a5)); \
|
|
return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
|
|
}
|
|
|
|
// Define methods which should be invoked on the worker thread.
|
|
#define PROXY_WORKER_METHOD0(r, method) \
|
|
r method() override { \
|
|
MethodCall0<C, r> call(c_, &C::method); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_CONSTMETHOD0(r, method) \
|
|
r method() const override { \
|
|
ConstMethodCall0<C, r> call(c_, &C::method); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_METHOD1(r, method, t1) \
|
|
r method(t1 a1) override { \
|
|
MethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \
|
|
r method(t1 a1) const override { \
|
|
ConstMethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_METHOD2(r, method, t1, t2) \
|
|
r method(t1 a1, t2 a2) override { \
|
|
MethodCall2<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2)); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \
|
|
r method(t1 a1, t2 a2) const override { \
|
|
ConstMethodCall2<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2)); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \
|
|
r method(t1 a1, t2 a2, t3 a3) override { \
|
|
MethodCall3<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2), std::move(a3)); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
#define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \
|
|
r method(t1 a1, t2 a2, t3 a3) const override { \
|
|
ConstMethodCall3<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
|
|
std::move(a2), std::move(a3)); \
|
|
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
|
|
}
|
|
|
|
} // namespace webrtc
|
|
|
|
#endif // WEBRTC_API_PROXY_H_
|