(Auto)update libjingle 61549749-> 61608469
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5555 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
e2fc13e42f
commit
b8c254abd6
@ -28,74 +28,119 @@
|
||||
#ifndef TALK_BASE_ASYNCINVOKER_INL_H_
|
||||
#define TALK_BASE_ASYNCINVOKER_INL_H_
|
||||
|
||||
#include "talk/base/bind.h"
|
||||
#include "talk/base/callback.h"
|
||||
#include "talk/base/criticalsection.h"
|
||||
#include "talk/base/messagehandler.h"
|
||||
#include "talk/base/refcount.h"
|
||||
#include "talk/base/scoped_ref_ptr.h"
|
||||
#include "talk/base/sigslot.h"
|
||||
#include "talk/base/thread.h"
|
||||
|
||||
namespace talk_base {
|
||||
|
||||
// Helper class for AsyncInvoker. Runs a functor on a message queue or thread
|
||||
// and doesn't execute the callback when finished if the calling thread ends.
|
||||
template <class ReturnT, class FunctorT>
|
||||
class AsyncFunctorMessageHandler
|
||||
: public FunctorMessageHandler<ReturnT, FunctorT>,
|
||||
public sigslot::has_slots<> {
|
||||
typedef AsyncFunctorMessageHandler<ReturnT, FunctorT> ThisT;
|
||||
class AsyncInvoker;
|
||||
|
||||
// Helper class for AsyncInvoker. Runs a task and triggers a callback
|
||||
// on the calling thread if necessary. Instances are ref-counted so their
|
||||
// lifetime can be independent of AsyncInvoker.
|
||||
class AsyncClosure : public RefCountInterface {
|
||||
public:
|
||||
explicit AsyncFunctorMessageHandler(const FunctorT& functor)
|
||||
: FunctorMessageHandler<ReturnT, FunctorT>(functor),
|
||||
thread_(Thread::Current()),
|
||||
shutting_down_(false) {
|
||||
thread_->SignalQueueDestroyed.connect(this, &ThisT::OnThreadDestroyed);
|
||||
}
|
||||
virtual ~AsyncClosure() {}
|
||||
// Runs the asynchronous task, and triggers a callback to the calling
|
||||
// thread if needed. Should be called from the target thread.
|
||||
virtual void Execute() = 0;
|
||||
};
|
||||
|
||||
virtual ~AsyncFunctorMessageHandler() {
|
||||
CritScope cs(&running_crit_);
|
||||
shutting_down_ = true;
|
||||
// Simple closure that doesn't trigger a callback for the calling thread.
|
||||
template <class FunctorT>
|
||||
class FireAndForgetAsyncClosure : public AsyncClosure {
|
||||
public:
|
||||
explicit FireAndForgetAsyncClosure(const FunctorT& functor)
|
||||
: functor_(functor) {}
|
||||
virtual void Execute() {
|
||||
functor_();
|
||||
}
|
||||
private:
|
||||
FunctorT functor_;
|
||||
};
|
||||
|
||||
virtual void OnMessage(Message* msg) {
|
||||
CritScope cs(&running_crit_);
|
||||
if (!shutting_down_) {
|
||||
FunctorMessageHandler<ReturnT, FunctorT>::OnMessage(msg);
|
||||
// Base class for closures that may trigger a callback for the calling thread.
|
||||
// Listens for the "destroyed" signals from the calling thread and the invoker,
|
||||
// and cancels the callback to the calling thread if either is destroyed.
|
||||
class NotifyingAsyncClosureBase : public AsyncClosure,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
virtual ~NotifyingAsyncClosureBase() { disconnect_all(); }
|
||||
|
||||
protected:
|
||||
NotifyingAsyncClosureBase(AsyncInvoker* invoker, Thread* calling_thread);
|
||||
void TriggerCallback();
|
||||
void SetCallback(const Callback0<void>& callback) {
|
||||
CritScope cs(&crit_);
|
||||
callback_ = callback;
|
||||
}
|
||||
bool CallbackCanceled() const { return calling_thread_ == NULL; }
|
||||
|
||||
private:
|
||||
Callback0<void> callback_;
|
||||
CriticalSection crit_;
|
||||
AsyncInvoker* invoker_;
|
||||
Thread* calling_thread_;
|
||||
|
||||
void CancelCallback();
|
||||
};
|
||||
|
||||
// Closures that have a non-void return value and require a callback.
|
||||
template <class ReturnT, class FunctorT, class HostT>
|
||||
class NotifyingAsyncClosure : public NotifyingAsyncClosureBase {
|
||||
public:
|
||||
NotifyingAsyncClosure(AsyncInvoker* invoker,
|
||||
Thread* calling_thread,
|
||||
const FunctorT& functor,
|
||||
void (HostT::*callback)(ReturnT),
|
||||
HostT* callback_host)
|
||||
: NotifyingAsyncClosureBase(invoker, calling_thread),
|
||||
functor_(functor),
|
||||
callback_(callback),
|
||||
callback_host_(callback_host) {}
|
||||
virtual void Execute() {
|
||||
ReturnT result = functor_();
|
||||
if (!CallbackCanceled()) {
|
||||
SetCallback(Callback0<void>(Bind(callback_, callback_host_, result)));
|
||||
TriggerCallback();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the thread that initiated the async call.
|
||||
Thread* thread() const { return thread_; }
|
||||
|
||||
// Wraps a callback so that it won't execute if |thread_| goes away.
|
||||
void WrapCallback(Callback0<void> cb) {
|
||||
this->SetCallback(
|
||||
Callback0<void>(Bind(&ThisT::MaybeRunCallback, this, cb)));
|
||||
}
|
||||
|
||||
private:
|
||||
void OnThreadDestroyed() {
|
||||
CritScope cs(&thread_crit_);
|
||||
thread_ = NULL;
|
||||
this->SetCallback(Callback0<void>()); // Clear out the callback.
|
||||
}
|
||||
|
||||
void MaybeRunCallback(Callback0<void> cb) {
|
||||
#ifdef _DEBUG
|
||||
ASSERT(running_crit_.CurrentThreadIsOwner());
|
||||
#endif
|
||||
CritScope cs(&thread_crit_);
|
||||
if (thread_ && !shutting_down_) {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
FunctorT functor_;
|
||||
Thread* thread_;
|
||||
CriticalSection thread_crit_;
|
||||
CriticalSection running_crit_;
|
||||
bool shutting_down_;
|
||||
void (HostT::*callback_)(ReturnT);
|
||||
HostT* callback_host_;
|
||||
};
|
||||
|
||||
// Closures that have a void return value and require a callback.
|
||||
template <class FunctorT, class HostT>
|
||||
class NotifyingAsyncClosure<void, FunctorT, HostT>
|
||||
: public NotifyingAsyncClosureBase {
|
||||
public:
|
||||
NotifyingAsyncClosure(AsyncInvoker* invoker,
|
||||
Thread* calling_thread,
|
||||
const FunctorT& functor,
|
||||
void (HostT::*callback)(),
|
||||
HostT* callback_host)
|
||||
: NotifyingAsyncClosureBase(invoker, calling_thread),
|
||||
functor_(functor) {
|
||||
SetCallback(Callback0<void>(Bind(callback, callback_host)));
|
||||
}
|
||||
virtual void Execute() {
|
||||
functor_();
|
||||
TriggerCallback();
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorT functor_;
|
||||
};
|
||||
|
||||
} // namespace talk_base
|
||||
|
||||
|
||||
#endif // TALK_BASE_ASYNCINVOKER_INL_H_
|
||||
|
@ -29,50 +29,80 @@
|
||||
|
||||
namespace talk_base {
|
||||
|
||||
// Synchronously execute all outstanding calls we own pending
|
||||
// on |thread|. Optionally filter by message id.
|
||||
AsyncInvoker::AsyncInvoker() : destroying_(false) {}
|
||||
|
||||
AsyncInvoker::~AsyncInvoker() {
|
||||
destroying_ = true;
|
||||
SignalInvokerDestroyed();
|
||||
// Messages for this need to be cleared *before* our destructor is complete.
|
||||
MessageQueueManager::Clear(this);
|
||||
}
|
||||
|
||||
void AsyncInvoker::OnMessage(Message* msg) {
|
||||
// Get the AsyncClosure shared ptr from this message's data.
|
||||
ScopedRefMessageData<AsyncClosure>* data =
|
||||
static_cast<ScopedRefMessageData<AsyncClosure>*>(msg->pdata);
|
||||
scoped_refptr<AsyncClosure> closure = data->data();
|
||||
delete msg->pdata;
|
||||
msg->pdata = NULL;
|
||||
|
||||
// Execute the closure and trigger the return message if needed.
|
||||
closure->Execute();
|
||||
}
|
||||
|
||||
void AsyncInvoker::Flush(Thread* thread, uint32 id /*= MQID_ANY*/) {
|
||||
if (destroying_) return;
|
||||
|
||||
// Run this on |thread| to reduce the number of context switches.
|
||||
if (Thread::Current() != thread) {
|
||||
thread->Invoke<void>(Bind(&AsyncInvoker::Flush, this, thread, id));
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a copy of handlers_, since it'll be modified by
|
||||
// callbacks to RemoveHandler when each is done executing.
|
||||
crit_.Enter();
|
||||
std::vector<MessageHandler*> handlers(handlers_.collection());
|
||||
crit_.Leave();
|
||||
MessageList removed;
|
||||
for (size_t i = 0; i < handlers.size(); ++i) {
|
||||
removed.clear();
|
||||
thread->Clear(handlers[i], id, &removed);
|
||||
if (!removed.empty()) {
|
||||
// Since each message gets its own handler with AsyncInvoker,
|
||||
// we expect a maximum of one removed.
|
||||
ASSERT(removed.size() == 1);
|
||||
// This handler was pending on this thread, so run it now.
|
||||
const Message& msg = removed.front();
|
||||
thread->Send(msg.phandler,
|
||||
msg.message_id,
|
||||
msg.pdata);
|
||||
}
|
||||
thread->Clear(this, id, &removed);
|
||||
for (MessageList::iterator it = removed.begin(); it != removed.end(); ++it) {
|
||||
// This message was pending on this thread, so run it now.
|
||||
thread->Send(it->phandler,
|
||||
it->message_id,
|
||||
it->pdata);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncInvoker::InvokeHandler(Thread* thread, MessageHandler* handler,
|
||||
uint32 id) {
|
||||
{
|
||||
CritScope cs(&crit_);
|
||||
handlers_.PushBack(handler);
|
||||
void AsyncInvoker::DoInvoke(Thread* thread, AsyncClosure* closure,
|
||||
uint32 id) {
|
||||
if (destroying_) {
|
||||
LOG(LS_WARNING) << "Tried to invoke while destroying the invoker.";
|
||||
// Since this call transwers ownership of |closure|, we clean it up here.
|
||||
delete closure;
|
||||
return;
|
||||
}
|
||||
thread->Post(handler, id);
|
||||
thread->Post(this, id, new ScopedRefMessageData<AsyncClosure>(closure));
|
||||
}
|
||||
|
||||
void AsyncInvoker::RemoveHandler(MessageHandler* handler) {
|
||||
NotifyingAsyncClosureBase::NotifyingAsyncClosureBase(AsyncInvoker* invoker,
|
||||
Thread* calling_thread)
|
||||
: invoker_(invoker), calling_thread_(calling_thread) {
|
||||
calling_thread->SignalQueueDestroyed.connect(
|
||||
this, &NotifyingAsyncClosureBase::CancelCallback);
|
||||
invoker->SignalInvokerDestroyed.connect(
|
||||
this, &NotifyingAsyncClosureBase::CancelCallback);
|
||||
}
|
||||
|
||||
void NotifyingAsyncClosureBase::TriggerCallback() {
|
||||
CritScope cs(&crit_);
|
||||
handlers_.Remove(handler);
|
||||
delete handler;
|
||||
if (!CallbackCanceled() && !callback_.empty()) {
|
||||
invoker_->AsyncInvoke<void>(calling_thread_, callback_);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyingAsyncClosureBase::CancelCallback() {
|
||||
// If the callback is triggering when this is called, block the
|
||||
// destructor of the dying object here by waiting until the callback
|
||||
// is done triggering.
|
||||
CritScope cs(&crit_);
|
||||
// calling_thread_ == NULL means do not trigger the callback.
|
||||
calling_thread_ = NULL;
|
||||
}
|
||||
|
||||
} // namespace talk_base
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "talk/base/asyncinvoker-inl.h"
|
||||
#include "talk/base/bind.h"
|
||||
#include "talk/base/sigslot.h"
|
||||
#include "talk/base/scopedptrcollection.h"
|
||||
#include "talk/base/thread.h"
|
||||
|
||||
@ -82,18 +83,20 @@ namespace talk_base {
|
||||
// AsyncInvoker invoker_;
|
||||
// int result_;
|
||||
// };
|
||||
class AsyncInvoker {
|
||||
class AsyncInvoker : public MessageHandler {
|
||||
public:
|
||||
AsyncInvoker();
|
||||
virtual ~AsyncInvoker();
|
||||
|
||||
// Call |functor| asynchronously on |thread|, with no callback upon
|
||||
// completion. Returns immediately.
|
||||
template <class ReturnT, class FunctorT>
|
||||
void AsyncInvoke(Thread* thread,
|
||||
const FunctorT& functor,
|
||||
uint32 id = 0) {
|
||||
FunctorMessageHandler<ReturnT, FunctorT>* handler =
|
||||
new FunctorMessageHandler<ReturnT, FunctorT>(functor);
|
||||
handler->SetCallback(Bind(&AsyncInvoker::RemoveHandler, this, handler));
|
||||
InvokeHandler(thread, handler, id);
|
||||
AsyncClosure* closure =
|
||||
new RefCountedObject<FireAndForgetAsyncClosure<FunctorT> >(functor);
|
||||
DoInvoke(thread, closure, id);
|
||||
}
|
||||
|
||||
// Call |functor| asynchronously on |thread|, calling |callback| when done.
|
||||
@ -103,12 +106,10 @@ class AsyncInvoker {
|
||||
void (HostT::*callback)(ReturnT),
|
||||
HostT* callback_host,
|
||||
uint32 id = 0) {
|
||||
AsyncFunctorMessageHandler<ReturnT, FunctorT>* handler =
|
||||
new AsyncFunctorMessageHandler<ReturnT, FunctorT>(functor);
|
||||
handler->WrapCallback(
|
||||
Bind(&AsyncInvoker::OnAsyncCallCompleted<ReturnT, FunctorT, HostT>,
|
||||
this, handler, callback, callback_host));
|
||||
InvokeHandler(thread, handler, id);
|
||||
AsyncClosure* closure =
|
||||
new RefCountedObject<NotifyingAsyncClosure<ReturnT, FunctorT, HostT> >(
|
||||
this, Thread::Current(), functor, callback, callback_host);
|
||||
DoInvoke(thread, closure, id);
|
||||
}
|
||||
|
||||
// Call |functor| asynchronously on |thread|, calling |callback| when done.
|
||||
@ -119,12 +120,10 @@ class AsyncInvoker {
|
||||
void (HostT::*callback)(),
|
||||
HostT* callback_host,
|
||||
uint32 id = 0) {
|
||||
AsyncFunctorMessageHandler<void, FunctorT>* handler =
|
||||
new AsyncFunctorMessageHandler<ReturnT, FunctorT>(functor);
|
||||
handler->WrapCallback(
|
||||
Bind(&AsyncInvoker::OnAsyncVoidCallCompleted<FunctorT, HostT>,
|
||||
this, handler, callback, callback_host));
|
||||
InvokeHandler(thread, handler, id);
|
||||
AsyncClosure* closure =
|
||||
new RefCountedObject<NotifyingAsyncClosure<void, FunctorT, HostT> >(
|
||||
this, Thread::Current(), functor, callback, callback_host);
|
||||
DoInvoke(thread, closure, id);
|
||||
}
|
||||
|
||||
// Synchronously execute on |thread| all outstanding calls we own
|
||||
@ -134,31 +133,16 @@ class AsyncInvoker {
|
||||
// behavior is desired, call Flush() before destroying this object.
|
||||
void Flush(Thread* thread, uint32 id = MQID_ANY);
|
||||
|
||||
// Signaled when this object is destructed.
|
||||
sigslot::signal0<> SignalInvokerDestroyed;
|
||||
|
||||
private:
|
||||
void InvokeHandler(Thread* thread, MessageHandler* handler, uint32 id);
|
||||
void RemoveHandler(MessageHandler* handler);
|
||||
virtual void OnMessage(Message* msg);
|
||||
void DoInvoke(Thread* thread, AsyncClosure* closure, uint32 id);
|
||||
|
||||
template <class ReturnT, class FunctorT, class HostT>
|
||||
void OnAsyncCallCompleted(
|
||||
AsyncFunctorMessageHandler<ReturnT, FunctorT>* handler,
|
||||
void (HostT::*callback)(ReturnT),
|
||||
HostT* callback_host) {
|
||||
AsyncInvoke<void>(handler->thread(),
|
||||
Bind(callback, callback_host, handler->result()));
|
||||
RemoveHandler(handler);
|
||||
}
|
||||
bool destroying_;
|
||||
|
||||
template <class FunctorT, class HostT>
|
||||
void OnAsyncVoidCallCompleted(
|
||||
AsyncFunctorMessageHandler<void, FunctorT>* handler,
|
||||
void (HostT::*callback)(),
|
||||
HostT* callback_host) {
|
||||
AsyncInvoke<void>(handler->thread(), Bind(callback, callback_host));
|
||||
RemoveHandler(handler);
|
||||
}
|
||||
|
||||
CriticalSection crit_;
|
||||
ScopedPtrCollection<MessageHandler> handlers_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AsyncInvoker);
|
||||
};
|
||||
|
||||
} // namespace talk_base
|
||||
|
@ -28,7 +28,6 @@
|
||||
#ifndef TALK_BASE_MESSAGEHANDLER_H_
|
||||
#define TALK_BASE_MESSAGEHANDLER_H_
|
||||
|
||||
#include "talk/base/callback.h"
|
||||
#include "talk/base/constructormagic.h"
|
||||
|
||||
namespace talk_base {
|
||||
@ -57,14 +56,12 @@ class FunctorMessageHandler : public MessageHandler {
|
||||
: functor_(functor) {}
|
||||
virtual void OnMessage(Message* msg) {
|
||||
result_ = functor_();
|
||||
if (!callback_.empty()) callback_();
|
||||
}
|
||||
const ReturnT& result() const { return result_; }
|
||||
void SetCallback(const Callback0<void>& callback) { callback_ = callback; }
|
||||
|
||||
private:
|
||||
FunctorT functor_;
|
||||
ReturnT result_;
|
||||
Callback0<void> callback_;
|
||||
};
|
||||
|
||||
// Specialization for ReturnT of void.
|
||||
@ -75,13 +72,11 @@ class FunctorMessageHandler<void, FunctorT> : public MessageHandler {
|
||||
: functor_(functor) {}
|
||||
virtual void OnMessage(Message* msg) {
|
||||
functor_();
|
||||
if (!callback_.empty()) callback_();
|
||||
}
|
||||
void result() const {}
|
||||
void SetCallback(const Callback0<void>& callback) { callback_ = callback; }
|
||||
|
||||
private:
|
||||
FunctorT functor_;
|
||||
Callback0<void> callback_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -339,7 +339,7 @@ class AsyncInvokeTest : public testing::Test {
|
||||
Thread* expected_thread_;
|
||||
};
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_FireAndForget) {
|
||||
TEST_F(AsyncInvokeTest, FireAndForget) {
|
||||
AsyncInvoker invoker;
|
||||
// Create and start the thread.
|
||||
Thread thread;
|
||||
@ -350,7 +350,7 @@ TEST_F(AsyncInvokeTest, DISABLED_FireAndForget) {
|
||||
EXPECT_TRUE_WAIT(called, kWaitTimeout);
|
||||
}
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_WithCallback) {
|
||||
TEST_F(AsyncInvokeTest, WithCallback) {
|
||||
AsyncInvoker invoker;
|
||||
// Create and start the thread.
|
||||
Thread thread;
|
||||
@ -363,7 +363,7 @@ TEST_F(AsyncInvokeTest, DISABLED_WithCallback) {
|
||||
EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
|
||||
}
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_CancelInvoker) {
|
||||
TEST_F(AsyncInvokeTest, CancelInvoker) {
|
||||
// Create and start the thread.
|
||||
Thread thread;
|
||||
thread.Start();
|
||||
@ -379,7 +379,7 @@ TEST_F(AsyncInvokeTest, DISABLED_CancelInvoker) {
|
||||
EXPECT_EQ(0, int_value_);
|
||||
}
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_CancelCallingThread) {
|
||||
TEST_F(AsyncInvokeTest, CancelCallingThread) {
|
||||
AsyncInvoker invoker;
|
||||
{ // Create and start the thread.
|
||||
Thread thread;
|
||||
@ -396,7 +396,7 @@ TEST_F(AsyncInvokeTest, DISABLED_CancelCallingThread) {
|
||||
EXPECT_EQ(0, int_value_);
|
||||
}
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_KillInvokerBeforeExecute) {
|
||||
TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
|
||||
Thread thread;
|
||||
thread.Start();
|
||||
{
|
||||
@ -413,7 +413,7 @@ TEST_F(AsyncInvokeTest, DISABLED_KillInvokerBeforeExecute) {
|
||||
EXPECT_EQ(0, int_value_);
|
||||
}
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_Flush) {
|
||||
TEST_F(AsyncInvokeTest, Flush) {
|
||||
AsyncInvoker invoker;
|
||||
bool flag1 = false;
|
||||
bool flag2 = false;
|
||||
@ -431,7 +431,7 @@ TEST_F(AsyncInvokeTest, DISABLED_Flush) {
|
||||
EXPECT_TRUE(flag2);
|
||||
}
|
||||
|
||||
TEST_F(AsyncInvokeTest, DISABLED_FlushWithIds) {
|
||||
TEST_F(AsyncInvokeTest, FlushWithIds) {
|
||||
AsyncInvoker invoker;
|
||||
bool flag1 = false;
|
||||
bool flag2 = false;
|
||||
|
@ -749,7 +749,13 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
|
||||
jitter_buffer_preferred_ms(0),
|
||||
delay_estimate_ms(0),
|
||||
audio_level(0),
|
||||
expand_rate(0) {
|
||||
expand_rate(0),
|
||||
decoding_calls_to_silence_generator(0),
|
||||
decoding_calls_to_neteq(0),
|
||||
decoding_normal(0),
|
||||
decoding_plc(0),
|
||||
decoding_cng(0),
|
||||
decoding_plc_cng(0) {
|
||||
}
|
||||
|
||||
int ext_seqnum;
|
||||
@ -760,6 +766,12 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
|
||||
int audio_level;
|
||||
// fraction of synthesized speech inserted through pre-emptive expansion
|
||||
float expand_rate;
|
||||
int decoding_calls_to_silence_generator;
|
||||
int decoding_calls_to_neteq;
|
||||
int decoding_normal;
|
||||
int decoding_plc;
|
||||
int decoding_cng;
|
||||
int decoding_plc_cng;
|
||||
};
|
||||
|
||||
struct VideoSenderInfo : public MediaSenderInfo {
|
||||
|
@ -3200,6 +3200,20 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||
rinfo.expand_rate =
|
||||
static_cast<float>(ns.currentExpandRate) / (1 << 14);
|
||||
}
|
||||
|
||||
webrtc::AudioDecodingCallStats ds;
|
||||
if (engine()->voe()->neteq() &&
|
||||
engine()->voe()->neteq()->GetDecodingCallStatistics(
|
||||
*it, &ds) != -1) {
|
||||
rinfo.decoding_calls_to_silence_generator =
|
||||
ds.calls_to_silence_generator;
|
||||
rinfo.decoding_calls_to_neteq = ds.calls_to_neteq;
|
||||
rinfo.decoding_normal = ds.decoded_normal;
|
||||
rinfo.decoding_plc = ds.decoded_plc;
|
||||
rinfo.decoding_cng = ds.decoded_cng;
|
||||
rinfo.decoding_plc_cng = ds.decoded_plc_cng;
|
||||
}
|
||||
|
||||
if (engine()->voe()->sync()) {
|
||||
int jitter_buffer_delay_ms = 0;
|
||||
int playout_buffer_delay_ms = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user