In PeerConnectionTestWrapper, put audio input on a separate thread.

This will prevent it from blocking network input when it falls behind,
which is happening when running with ThreadSanitizer.

BUG=webrtc:4663

Review URL: https://codereview.webrtc.org/1236023010

Cr-Commit-Position: refs/heads/master@{#9707}
This commit is contained in:
deadbeef
2015-08-13 14:27:18 -07:00
committed by Commit bot
parent 7437588168
commit ee8c6d3273
7 changed files with 49 additions and 70 deletions

View File

@ -518,8 +518,7 @@ class PeerConnectionTestClientBase
if (!allocator_factory_) { if (!allocator_factory_) {
return false; return false;
} }
fake_audio_capture_module_ = FakeAudioCaptureModule::Create( fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
rtc::Thread::Current());
if (fake_audio_capture_module_ == NULL) { if (fake_audio_capture_module_ == NULL) {
return false; return false;

View File

@ -268,17 +268,7 @@ class PeerConnectionEndToEndTest
DataChannelList callee_signaled_data_channels_; DataChannelList callee_signaled_data_channels_;
}; };
// Disable for TSan v2, see TEST_F(PeerConnectionEndToEndTest, Call) {
// https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
#if !defined(THREAD_SANITIZER)
// Flaky on Windows. Disabled per issue 4464.
#ifdef WEBRTC_WIN
#define MAYBE_Call DISABLED_Call
#else
#define MAYBE_Call Call
#endif
TEST_F(PeerConnectionEndToEndTest, MAYBE_Call) {
CreatePcs(); CreatePcs();
GetAndAddUserMedia(); GetAndAddUserMedia();
Negotiate(); Negotiate();
@ -427,4 +417,3 @@ TEST_F(PeerConnectionEndToEndTest,
EXPECT_EQ(1U, dc_1_observer->received_message_count()); EXPECT_EQ(1U, dc_1_observer->received_message_count());
EXPECT_EQ(1U, dc_2_observer->received_message_count()); EXPECT_EQ(1U, dc_2_observer->received_message_count());
} }
#endif // if !defined(THREAD_SANITIZER)

View File

@ -54,13 +54,11 @@ static const uint32_t kMaxVolume = 14392;
enum { enum {
MSG_START_PROCESS, MSG_START_PROCESS,
MSG_RUN_PROCESS, MSG_RUN_PROCESS,
MSG_STOP_PROCESS,
}; };
FakeAudioCaptureModule::FakeAudioCaptureModule( FakeAudioCaptureModule::FakeAudioCaptureModule()
rtc::Thread* process_thread)
: last_process_time_ms_(0), : last_process_time_ms_(0),
audio_callback_(NULL), audio_callback_(nullptr),
recording_(false), recording_(false),
playing_(false), playing_(false),
play_is_initialized_(false), play_is_initialized_(false),
@ -68,23 +66,20 @@ FakeAudioCaptureModule::FakeAudioCaptureModule(
current_mic_level_(kMaxVolume), current_mic_level_(kMaxVolume),
started_(false), started_(false),
next_frame_time_(0), next_frame_time_(0),
process_thread_(process_thread),
frames_received_(0) { frames_received_(0) {
} }
FakeAudioCaptureModule::~FakeAudioCaptureModule() { FakeAudioCaptureModule::~FakeAudioCaptureModule() {
// Ensure that thread stops calling ProcessFrame(). if (process_thread_) {
process_thread_->Send(this, MSG_STOP_PROCESS); process_thread_->Stop();
}
} }
rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create( rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
rtc::Thread* process_thread) {
if (process_thread == NULL) return NULL;
rtc::scoped_refptr<FakeAudioCaptureModule> capture_module( rtc::scoped_refptr<FakeAudioCaptureModule> capture_module(
new rtc::RefCountedObject<FakeAudioCaptureModule>(process_thread)); new rtc::RefCountedObject<FakeAudioCaptureModule>());
if (!capture_module->Initialize()) { if (!capture_module->Initialize()) {
return NULL; return nullptr;
} }
return capture_module; return capture_module;
} }
@ -601,9 +596,6 @@ void FakeAudioCaptureModule::OnMessage(rtc::Message* msg) {
case MSG_RUN_PROCESS: case MSG_RUN_PROCESS:
ProcessFrameP(); ProcessFrameP();
break; break;
case MSG_STOP_PROCESS:
StopProcessP();
break;
default: default:
// All existing messages should be caught. Getting here should never // All existing messages should be caught. Getting here should never
// happen. // happen.
@ -650,14 +642,22 @@ bool FakeAudioCaptureModule::ShouldStartProcessing() {
void FakeAudioCaptureModule::UpdateProcessing(bool start) { void FakeAudioCaptureModule::UpdateProcessing(bool start) {
if (start) { if (start) {
if (!process_thread_) {
process_thread_.reset(new rtc::Thread());
process_thread_->Start();
}
process_thread_->Post(this, MSG_START_PROCESS); process_thread_->Post(this, MSG_START_PROCESS);
} else { } else {
process_thread_->Send(this, MSG_STOP_PROCESS); if (process_thread_) {
process_thread_->Stop();
process_thread_.reset(nullptr);
}
started_ = false;
} }
} }
void FakeAudioCaptureModule::StartProcessP() { void FakeAudioCaptureModule::StartProcessP() {
ASSERT(rtc::Thread::Current() == process_thread_); ASSERT(process_thread_->IsCurrent());
if (started_) { if (started_) {
// Already started. // Already started.
return; return;
@ -666,27 +666,22 @@ void FakeAudioCaptureModule::StartProcessP() {
} }
void FakeAudioCaptureModule::ProcessFrameP() { void FakeAudioCaptureModule::ProcessFrameP() {
ASSERT(rtc::Thread::Current() == process_thread_); ASSERT(process_thread_->IsCurrent());
if (!started_) { if (!started_) {
next_frame_time_ = rtc::Time(); next_frame_time_ = rtc::Time();
started_ = true; started_ = true;
} }
bool playing;
bool recording;
{ {
rtc::CritScope cs(&crit_); rtc::CritScope cs(&crit_);
playing = playing_;
recording = recording_;
}
// Receive and send frames every kTimePerFrameMs. // Receive and send frames every kTimePerFrameMs.
if (playing) { if (playing_) {
ReceiveFrameP(); ReceiveFrameP();
} }
if (recording) { if (recording_) {
SendFrameP(); SendFrameP();
} }
}
next_frame_time_ += kTimePerFrameMs; next_frame_time_ += kTimePerFrameMs;
const uint32 current_time = rtc::Time(); const uint32 current_time = rtc::Time();
@ -696,7 +691,7 @@ void FakeAudioCaptureModule::ProcessFrameP() {
} }
void FakeAudioCaptureModule::ReceiveFrameP() { void FakeAudioCaptureModule::ReceiveFrameP() {
ASSERT(rtc::Thread::Current() == process_thread_); ASSERT(process_thread_->IsCurrent());
{ {
rtc::CritScope cs(&crit_callback_); rtc::CritScope cs(&crit_callback_);
if (!audio_callback_) { if (!audio_callback_) {
@ -727,7 +722,7 @@ void FakeAudioCaptureModule::ReceiveFrameP() {
} }
void FakeAudioCaptureModule::SendFrameP() { void FakeAudioCaptureModule::SendFrameP() {
ASSERT(rtc::Thread::Current() == process_thread_); ASSERT(process_thread_->IsCurrent());
rtc::CritScope cs(&crit_callback_); rtc::CritScope cs(&crit_callback_);
if (!audio_callback_) { if (!audio_callback_) {
return; return;
@ -747,8 +742,3 @@ void FakeAudioCaptureModule::SendFrameP() {
SetMicrophoneVolume(current_mic_level); SetMicrophoneVolume(current_mic_level);
} }
void FakeAudioCaptureModule::StopProcessP() {
ASSERT(rtc::Thread::Current() == process_thread_);
started_ = false;
process_thread_->Clear(this);
}

View File

@ -40,14 +40,13 @@
#include "webrtc/base/basictypes.h" #include "webrtc/base/basictypes.h"
#include "webrtc/base/criticalsection.h" #include "webrtc/base/criticalsection.h"
#include "webrtc/base/messagehandler.h" #include "webrtc/base/messagehandler.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/common_types.h" #include "webrtc/common_types.h"
#include "webrtc/modules/audio_device/include/audio_device.h" #include "webrtc/modules/audio_device/include/audio_device.h"
namespace rtc { namespace rtc {
class Thread; class Thread;
} // namespace rtc } // namespace rtc
class FakeAudioCaptureModule class FakeAudioCaptureModule
@ -62,10 +61,7 @@ class FakeAudioCaptureModule
static const int kNumberBytesPerSample = sizeof(Sample); static const int kNumberBytesPerSample = sizeof(Sample);
// Creates a FakeAudioCaptureModule or returns NULL on failure. // Creates a FakeAudioCaptureModule or returns NULL on failure.
// |process_thread| is used to push and pull audio frames to and from the static rtc::scoped_refptr<FakeAudioCaptureModule> Create();
// returned instance. Note: ownership of |process_thread| is not handed over.
static rtc::scoped_refptr<FakeAudioCaptureModule> Create(
rtc::Thread* process_thread);
// Returns the number of frames that have been successfully pulled by the // Returns the number of frames that have been successfully pulled by the
// instance. Note that correctly detecting success can only be done if the // instance. Note that correctly detecting success can only be done if the
@ -206,7 +202,7 @@ class FakeAudioCaptureModule
// exposed in which case the burden of proper instantiation would be put on // exposed in which case the burden of proper instantiation would be put on
// the creator of a FakeAudioCaptureModule instance. To create an instance of // the creator of a FakeAudioCaptureModule instance. To create an instance of
// this class use the Create(..) API. // this class use the Create(..) API.
explicit FakeAudioCaptureModule(rtc::Thread* process_thread); explicit FakeAudioCaptureModule();
// The destructor is protected because it is reference counted and should not // The destructor is protected because it is reference counted and should not
// be deleted directly. // be deleted directly.
virtual ~FakeAudioCaptureModule(); virtual ~FakeAudioCaptureModule();
@ -239,8 +235,6 @@ class FakeAudioCaptureModule
void ReceiveFrameP(); void ReceiveFrameP();
// Pushes frames to the registered webrtc::AudioTransport. // Pushes frames to the registered webrtc::AudioTransport.
void SendFrameP(); void SendFrameP();
// Stops the periodic calling of ProcessFrame() in a thread safe way.
void StopProcessP();
// The time in milliseconds when Process() was last called or 0 if no call // The time in milliseconds when Process() was last called or 0 if no call
// has been made. // has been made.
@ -266,8 +260,7 @@ class FakeAudioCaptureModule
bool started_; bool started_;
uint32 next_frame_time_; uint32 next_frame_time_;
// User provided thread context. rtc::scoped_ptr<rtc::Thread> process_thread_;
rtc::Thread* process_thread_;
// Buffer for storing samples received from the webrtc::AudioTransport. // Buffer for storing samples received from the webrtc::AudioTransport.
char rec_buffer_[kNumberSamples * kNumberBytesPerSample]; char rec_buffer_[kNumberSamples * kNumberBytesPerSample];

View File

@ -29,6 +29,7 @@
#include <algorithm> #include <algorithm>
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/gunit.h" #include "webrtc/base/gunit.h"
#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/base/thread.h" #include "webrtc/base/thread.h"
@ -48,8 +49,7 @@ class FakeAdmTest : public testing::Test,
} }
virtual void SetUp() { virtual void SetUp() {
fake_audio_capture_module_ = FakeAudioCaptureModule::Create( fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
rtc::Thread::Current());
EXPECT_TRUE(fake_audio_capture_module_.get() != NULL); EXPECT_TRUE(fake_audio_capture_module_.get() != NULL);
} }
@ -65,6 +65,7 @@ class FakeAdmTest : public testing::Test,
const uint32_t currentMicLevel, const uint32_t currentMicLevel,
const bool keyPressed, const bool keyPressed,
uint32_t& newMicLevel) override { uint32_t& newMicLevel) override {
rtc::CritScope cs(&crit_);
rec_buffer_bytes_ = nSamples * nBytesPerSample; rec_buffer_bytes_ = nSamples * nBytesPerSample;
if ((rec_buffer_bytes_ == 0) || if ((rec_buffer_bytes_ == 0) ||
(rec_buffer_bytes_ > FakeAudioCaptureModule::kNumberSamples * (rec_buffer_bytes_ > FakeAudioCaptureModule::kNumberSamples *
@ -87,6 +88,7 @@ class FakeAdmTest : public testing::Test,
uint32_t& nSamplesOut, uint32_t& nSamplesOut,
int64_t* elapsed_time_ms, int64_t* elapsed_time_ms,
int64_t* ntp_time_ms) override { int64_t* ntp_time_ms) override {
rtc::CritScope cs(&crit_);
++pull_iterations_; ++pull_iterations_;
const uint32_t audio_buffer_size = nSamples * nBytesPerSample; const uint32_t audio_buffer_size = nSamples * nBytesPerSample;
const uint32_t bytes_out = RecordedDataReceived() ? const uint32_t bytes_out = RecordedDataReceived() ?
@ -98,8 +100,14 @@ class FakeAdmTest : public testing::Test,
return 0; return 0;
} }
int push_iterations() const { return push_iterations_; } int push_iterations() const {
int pull_iterations() const { return pull_iterations_; } rtc::CritScope cs(&crit_);
return push_iterations_;
}
int pull_iterations() const {
rtc::CritScope cs(&crit_);
return pull_iterations_;
}
rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_; rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_;
@ -118,6 +126,8 @@ class FakeAdmTest : public testing::Test,
return min_buffer_size; return min_buffer_size;
} }
mutable rtc::CriticalSection crit_;
int push_iterations_; int push_iterations_;
int pull_iterations_; int pull_iterations_;

View File

@ -75,8 +75,7 @@ bool PeerConnectionTestWrapper::CreatePc(
return false; return false;
} }
fake_audio_capture_module_ = FakeAudioCaptureModule::Create( fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
rtc::Thread::Current());
if (fake_audio_capture_module_ == NULL) { if (fake_audio_capture_module_ == NULL) {
return false; return false;
} }

View File

@ -33,7 +33,6 @@
#include "talk/app/webrtc/test/fakeconstraints.h" #include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/app/webrtc/test/fakevideotrackrenderer.h" #include "talk/app/webrtc/test/fakevideotrackrenderer.h"
#include "webrtc/base/sigslot.h" #include "webrtc/base/sigslot.h"
#include "webrtc/base/thread.h"
namespace webrtc { namespace webrtc {
class DtlsIdentityStoreInterface; class DtlsIdentityStoreInterface;