This source file includes following definitions.
- ACTION_P3
- bytes_to_write_
- OnData
- OnError
- CanRunAudioTests
- CreateDefaultAudioInputStream
- CreateAudioInputStream
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/basictypes.h"
#include "base/environment.h"
#include "base/message_loop/message_loop.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/mac/audio_low_latency_input_mac.h"
#include "media/base/seekable_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using ::testing::Ge;
using ::testing::NotNull;
namespace media {
ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) {
if (++*count >= limit) {
loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
}
}
class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
public:
MOCK_METHOD5(OnData, void(AudioInputStream* stream,
const uint8* src, uint32 size,
uint32 hardware_delay_bytes, double volume));
MOCK_METHOD1(OnError, void(AudioInputStream* stream));
};
class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
public:
static const int kMaxBufferSize = 2 * 2 * 480 * 100 * 10;
explicit WriteToFileAudioSink(const char* file_name)
: buffer_(0, kMaxBufferSize),
file_(fopen(file_name, "wb")),
bytes_to_write_(0) {
}
virtual ~WriteToFileAudioSink() {
int bytes_written = 0;
while (bytes_written < bytes_to_write_) {
const uint8* chunk;
int chunk_size;
if (!buffer_.GetCurrentChunk(&chunk, &chunk_size))
break;
fwrite(chunk, 1, chunk_size, file_);
buffer_.Seek(chunk_size);
bytes_written += chunk_size;
}
fclose(file_);
}
virtual void OnData(AudioInputStream* stream,
const uint8* src, uint32 size,
uint32 hardware_delay_bytes, double volume) OVERRIDE {
if (buffer_.Append(src, size)) {
bytes_to_write_ += size;
}
}
virtual void OnError(AudioInputStream* stream) OVERRIDE {}
private:
media::SeekableBuffer buffer_;
FILE* file_;
int bytes_to_write_;
};
class MacAudioInputTest : public testing::Test {
protected:
MacAudioInputTest() : audio_manager_(AudioManager::CreateForTesting()) {}
virtual ~MacAudioInputTest() {}
bool CanRunAudioTests() {
bool has_input = audio_manager_->HasAudioInputDevices();
if (!has_input)
LOG(WARNING) << "No input devices detected";
return has_input;
}
AudioInputStream* CreateDefaultAudioInputStream() {
int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
int samples_per_packet = fs / 100;
AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
CHANNEL_LAYOUT_STEREO, fs, 16, samples_per_packet),
AudioManagerBase::kDefaultDeviceId);
EXPECT_TRUE(ais);
return ais;
}
AudioInputStream* CreateAudioInputStream(ChannelLayout channel_layout) {
int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
int samples_per_packet = fs / 100;
AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout, fs, 16, samples_per_packet),
AudioManagerBase::kDefaultDeviceId);
EXPECT_TRUE(ais);
return ais;
}
scoped_ptr<AudioManager> audio_manager_;
};
TEST_F(MacAudioInputTest, AUAudioInputStreamCreateAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
ais->Close();
}
TEST_F(MacAudioInputTest, AUAudioInputStreamOpenAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
EXPECT_TRUE(ais->Open());
ais->Close();
}
TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
ais->Close();
}
TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartStopAndClose) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
EXPECT_TRUE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
ais->Stop();
ais->Close();
}
TEST_F(MacAudioInputTest, AUAudioInputStreamMiscCallingSequences) {
if (!CanRunAudioTests())
return;
AudioInputStream* ais = CreateDefaultAudioInputStream();
AUAudioInputStream* auais = static_cast<AUAudioInputStream*>(ais);
EXPECT_TRUE(ais->Open());
EXPECT_FALSE(ais->Open());
MockAudioInputCallback sink;
ais->Start(&sink);
EXPECT_TRUE(auais->started());
ais->Start(&sink);
EXPECT_TRUE(auais->started());
ais->Stop();
EXPECT_FALSE(auais->started());
ais->Stop();
EXPECT_FALSE(auais->started());
ais->Close();
}
TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) {
if (!CanRunAudioTests())
return;
int count = 0;
base::MessageLoopForUI loop;
AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO);
EXPECT_TRUE(ais->Open());
int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
int samples_per_packet = fs / 100;
int bits_per_sample = 16;
uint32 bytes_per_packet = samples_per_packet * (bits_per_sample / 8);
MockAudioInputCallback sink;
EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _))
.Times(AtLeast(10))
.WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
ais->Start(&sink);
loop.Run();
ais->Stop();
ais->Close();
}
TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) {
if (!CanRunAudioTests())
return;
int count = 0;
base::MessageLoopForUI loop;
AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO);
EXPECT_TRUE(ais->Open());
int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
int samples_per_packet = fs / 100;
int bits_per_sample = 16;
uint32 bytes_per_packet = 2 * samples_per_packet * (bits_per_sample / 8);
MockAudioInputCallback sink;
EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _))
.Times(AtLeast(10))
.WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
ais->Start(&sink);
loop.Run();
ais->Stop();
ais->Close();
}
TEST_F(MacAudioInputTest, DISABLED_AUAudioInputStreamRecordToFile) {
if (!CanRunAudioTests())
return;
const char* file_name = "out_stereo_10sec.pcm";
int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
AudioInputStream* ais = CreateDefaultAudioInputStream();
EXPECT_TRUE(ais->Open());
fprintf(stderr, " File name : %s\n", file_name);
fprintf(stderr, " Sample rate: %d\n", fs);
WriteToFileAudioSink file_sink(file_name);
fprintf(stderr, " >> Speak into the mic while recording...\n");
ais->Start(&file_sink);
base::PlatformThread::Sleep(TestTimeouts::action_timeout());
ais->Stop();
fprintf(stderr, " >> Recording has stopped.\n");
ais->Close();
}
}