1/* 2 * libjingle 3 * Copyright 2012, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "talk/app/webrtc/test/fakeaudiocapturemodule.h" 29 30#include <algorithm> 31 32#include "talk/base/gunit.h" 33#include "talk/base/scoped_ref_ptr.h" 34#include "talk/base/thread.h" 35 36using std::min; 37 38class FakeAdmTest : public testing::Test, 39 public webrtc::AudioTransport { 40 protected: 41 static const int kMsInSecond = 1000; 42 43 FakeAdmTest() 44 : push_iterations_(0), 45 pull_iterations_(0), 46 rec_buffer_bytes_(0) { 47 memset(rec_buffer_, 0, sizeof(rec_buffer_)); 48 } 49 50 virtual void SetUp() { 51 fake_audio_capture_module_ = FakeAudioCaptureModule::Create( 52 talk_base::Thread::Current()); 53 EXPECT_TRUE(fake_audio_capture_module_.get() != NULL); 54 } 55 56 // Callbacks inherited from webrtc::AudioTransport. 57 // ADM is pushing data. 58 virtual int32_t RecordedDataIsAvailable(const void* audioSamples, 59 const uint32_t nSamples, 60 const uint8_t nBytesPerSample, 61 const uint8_t nChannels, 62 const uint32_t samplesPerSec, 63 const uint32_t totalDelayMS, 64 const int32_t clockDrift, 65 const uint32_t currentMicLevel, 66 const bool keyPressed, 67 uint32_t& newMicLevel) { 68 rec_buffer_bytes_ = nSamples * nBytesPerSample; 69 if ((rec_buffer_bytes_ <= 0) || 70 (rec_buffer_bytes_ > FakeAudioCaptureModule::kNumberSamples * 71 FakeAudioCaptureModule::kNumberBytesPerSample)) { 72 ADD_FAILURE(); 73 return -1; 74 } 75 memcpy(rec_buffer_, audioSamples, rec_buffer_bytes_); 76 ++push_iterations_; 77 newMicLevel = currentMicLevel; 78 return 0; 79 } 80 81 // ADM is pulling data. 82 virtual int32_t NeedMorePlayData(const uint32_t nSamples, 83 const uint8_t nBytesPerSample, 84 const uint8_t nChannels, 85 const uint32_t samplesPerSec, 86 void* audioSamples, 87#ifdef USE_WEBRTC_DEV_BRANCH 88 uint32_t& nSamplesOut, 89 int64_t* elapsed_time_ms, 90 int64_t* ntp_time_ms) { 91#else 92 uint32_t& nSamplesOut) { 93#endif 94 ++pull_iterations_; 95 const uint32_t audio_buffer_size = nSamples * nBytesPerSample; 96 const uint32_t bytes_out = RecordedDataReceived() ? 97 CopyFromRecBuffer(audioSamples, audio_buffer_size): 98 GenerateZeroBuffer(audioSamples, audio_buffer_size); 99 nSamplesOut = bytes_out / nBytesPerSample; 100#ifdef USE_WEBRTC_DEV_BRANCH 101 *elapsed_time_ms = 0; 102 *ntp_time_ms = 0; 103#endif 104 return 0; 105 } 106 107 int push_iterations() const { return push_iterations_; } 108 int pull_iterations() const { return pull_iterations_; } 109 110 talk_base::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_; 111 112 private: 113 bool RecordedDataReceived() const { 114 return rec_buffer_bytes_ != 0; 115 } 116 int32_t GenerateZeroBuffer(void* audio_buffer, uint32_t audio_buffer_size) { 117 memset(audio_buffer, 0, audio_buffer_size); 118 return audio_buffer_size; 119 } 120 int32_t CopyFromRecBuffer(void* audio_buffer, uint32_t audio_buffer_size) { 121 EXPECT_EQ(audio_buffer_size, rec_buffer_bytes_); 122 const uint32_t min_buffer_size = min(audio_buffer_size, rec_buffer_bytes_); 123 memcpy(audio_buffer, rec_buffer_, min_buffer_size); 124 return min_buffer_size; 125 } 126 127 int push_iterations_; 128 int pull_iterations_; 129 130 char rec_buffer_[FakeAudioCaptureModule::kNumberSamples * 131 FakeAudioCaptureModule::kNumberBytesPerSample]; 132 uint32_t rec_buffer_bytes_; 133}; 134 135TEST_F(FakeAdmTest, TestProccess) { 136 // Next process call must be some time in the future (or now). 137 EXPECT_LE(0, fake_audio_capture_module_->TimeUntilNextProcess()); 138 // Process call updates TimeUntilNextProcess() but there are no guarantees on 139 // timing so just check that Process can ba called successfully. 140 EXPECT_LE(0, fake_audio_capture_module_->Process()); 141} 142 143TEST_F(FakeAdmTest, PlayoutTest) { 144 EXPECT_EQ(0, fake_audio_capture_module_->RegisterAudioCallback(this)); 145 146 bool speaker_available = false; 147 EXPECT_EQ(0, fake_audio_capture_module_->SpeakerIsAvailable( 148 &speaker_available)); 149 EXPECT_TRUE(speaker_available); 150 151 bool stereo_available = false; 152 EXPECT_EQ(0, 153 fake_audio_capture_module_->StereoPlayoutIsAvailable( 154 &stereo_available)); 155 EXPECT_TRUE(stereo_available); 156 157 EXPECT_NE(0, fake_audio_capture_module_->StartPlayout()); 158 EXPECT_FALSE(fake_audio_capture_module_->PlayoutIsInitialized()); 159 EXPECT_FALSE(fake_audio_capture_module_->Playing()); 160 EXPECT_EQ(0, fake_audio_capture_module_->StopPlayout()); 161 162 EXPECT_EQ(0, fake_audio_capture_module_->InitPlayout()); 163 EXPECT_TRUE(fake_audio_capture_module_->PlayoutIsInitialized()); 164 EXPECT_FALSE(fake_audio_capture_module_->Playing()); 165 166 EXPECT_EQ(0, fake_audio_capture_module_->StartPlayout()); 167 EXPECT_TRUE(fake_audio_capture_module_->Playing()); 168 169 uint16_t delay_ms = 10; 170 EXPECT_EQ(0, fake_audio_capture_module_->PlayoutDelay(&delay_ms)); 171 EXPECT_EQ(0, delay_ms); 172 173 EXPECT_TRUE_WAIT(pull_iterations() > 0, kMsInSecond); 174 EXPECT_GE(0, push_iterations()); 175 176 EXPECT_EQ(0, fake_audio_capture_module_->StopPlayout()); 177 EXPECT_FALSE(fake_audio_capture_module_->Playing()); 178} 179 180TEST_F(FakeAdmTest, RecordTest) { 181 EXPECT_EQ(0, fake_audio_capture_module_->RegisterAudioCallback(this)); 182 183 bool microphone_available = false; 184 EXPECT_EQ(0, fake_audio_capture_module_->MicrophoneIsAvailable( 185 µphone_available)); 186 EXPECT_TRUE(microphone_available); 187 188 bool stereo_available = false; 189 EXPECT_EQ(0, fake_audio_capture_module_->StereoRecordingIsAvailable( 190 &stereo_available)); 191 EXPECT_FALSE(stereo_available); 192 193 EXPECT_NE(0, fake_audio_capture_module_->StartRecording()); 194 EXPECT_FALSE(fake_audio_capture_module_->Recording()); 195 EXPECT_EQ(0, fake_audio_capture_module_->StopRecording()); 196 197 EXPECT_EQ(0, fake_audio_capture_module_->InitRecording()); 198 EXPECT_EQ(0, fake_audio_capture_module_->StartRecording()); 199 EXPECT_TRUE(fake_audio_capture_module_->Recording()); 200 201 EXPECT_TRUE_WAIT(push_iterations() > 0, kMsInSecond); 202 EXPECT_GE(0, pull_iterations()); 203 204 EXPECT_EQ(0, fake_audio_capture_module_->StopRecording()); 205 EXPECT_FALSE(fake_audio_capture_module_->Recording()); 206} 207 208TEST_F(FakeAdmTest, DuplexTest) { 209 EXPECT_EQ(0, fake_audio_capture_module_->RegisterAudioCallback(this)); 210 211 EXPECT_EQ(0, fake_audio_capture_module_->InitPlayout()); 212 EXPECT_EQ(0, fake_audio_capture_module_->StartPlayout()); 213 214 EXPECT_EQ(0, fake_audio_capture_module_->InitRecording()); 215 EXPECT_EQ(0, fake_audio_capture_module_->StartRecording()); 216 217 EXPECT_TRUE_WAIT(push_iterations() > 0, kMsInSecond); 218 EXPECT_TRUE_WAIT(pull_iterations() > 0, kMsInSecond); 219 220 EXPECT_EQ(0, fake_audio_capture_module_->StopPlayout()); 221 EXPECT_EQ(0, fake_audio_capture_module_->StopRecording()); 222} 223