Home | History | Annotate | Download | only in audio
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/basictypes.h"
      6 #include "base/environment.h"
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/run_loop.h"
     10 #include "base/synchronization/waitable_event.h"
     11 #include "base/threading/platform_thread.h"
     12 #include "media/audio/audio_io.h"
     13 #include "media/audio/audio_manager_base.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace media {
     17 
     18 // This class allows to find out if the callbacks are occurring as
     19 // expected and if any error has been reported.
     20 class TestInputCallback : public AudioInputStream::AudioInputCallback {
     21  public:
     22   explicit TestInputCallback()
     23       : callback_count_(0),
     24         had_error_(0) {
     25   }
     26   virtual void OnData(AudioInputStream* stream,
     27                       const AudioBus* source,
     28                       uint32 hardware_delay_bytes,
     29                       double volume) OVERRIDE {
     30     ++callback_count_;
     31   }
     32   virtual void OnError(AudioInputStream* stream) OVERRIDE {
     33     ++had_error_;
     34   }
     35   // Returns how many times OnData() has been called.
     36   int callback_count() const {
     37     return callback_count_;
     38   }
     39   // Returns how many times the OnError callback was called.
     40   int had_error() const {
     41     return had_error_;
     42   }
     43 
     44  private:
     45   int callback_count_;
     46   int had_error_;
     47 };
     48 
     49 class AudioInputTest : public testing::Test {
     50   public:
     51    AudioInputTest() :
     52       message_loop_(base::MessageLoop::TYPE_UI),
     53       audio_manager_(AudioManager::CreateForTesting()),
     54       audio_input_stream_(NULL) {
     55     // Wait for the AudioManager to finish any initialization on the audio loop.
     56     base::RunLoop().RunUntilIdle();
     57   }
     58 
     59   virtual ~AudioInputTest() {
     60     base::RunLoop().RunUntilIdle();
     61   }
     62 
     63  protected:
     64   AudioManager* audio_manager() { return audio_manager_.get(); }
     65 
     66   bool CanRunAudioTests() {
     67     bool has_input = audio_manager()->HasAudioInputDevices();
     68     LOG_IF(WARNING, !has_input) << "No input devices detected";
     69     return has_input;
     70   }
     71 
     72   void MakeAudioInputStreamOnAudioThread() {
     73     RunOnAudioThread(
     74         base::Bind(&AudioInputTest::MakeAudioInputStream,
     75                    base::Unretained(this)));
     76   }
     77 
     78   void CloseAudioInputStreamOnAudioThread() {
     79     RunOnAudioThread(
     80         base::Bind(&AudioInputStream::Close,
     81                    base::Unretained(audio_input_stream_)));
     82     audio_input_stream_ = NULL;
     83   }
     84 
     85   void OpenAndCloseAudioInputStreamOnAudioThread() {
     86     RunOnAudioThread(
     87         base::Bind(&AudioInputTest::OpenAndClose,
     88                    base::Unretained(this)));
     89   }
     90 
     91   void OpenStopAndCloseAudioInputStreamOnAudioThread() {
     92     RunOnAudioThread(
     93         base::Bind(&AudioInputTest::OpenStopAndClose,
     94                    base::Unretained(this)));
     95   }
     96 
     97   void OpenAndStartAudioInputStreamOnAudioThread(
     98       AudioInputStream::AudioInputCallback* sink) {
     99     RunOnAudioThread(
    100         base::Bind(&AudioInputTest::OpenAndStart,
    101                    base::Unretained(this),
    102                    sink));
    103   }
    104 
    105   void StopAndCloseAudioInputStreamOnAudioThread() {
    106     RunOnAudioThread(
    107         base::Bind(&AudioInputTest::StopAndClose,
    108                    base::Unretained(this)));
    109   }
    110 
    111   void MakeAudioInputStream() {
    112     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    113     AudioParameters params = audio_manager()->GetInputStreamParameters(
    114         AudioManagerBase::kDefaultDeviceId);
    115     audio_input_stream_ = audio_manager()->MakeAudioInputStream(params,
    116         AudioManagerBase::kDefaultDeviceId);
    117     EXPECT_TRUE(audio_input_stream_);
    118   }
    119 
    120   void OpenAndClose() {
    121     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    122     EXPECT_TRUE(audio_input_stream_->Open());
    123     audio_input_stream_->Close();
    124     audio_input_stream_ = NULL;
    125   }
    126 
    127   void OpenAndStart(AudioInputStream::AudioInputCallback* sink) {
    128     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    129     EXPECT_TRUE(audio_input_stream_->Open());
    130     audio_input_stream_->Start(sink);
    131   }
    132 
    133   void OpenStopAndClose() {
    134     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    135     EXPECT_TRUE(audio_input_stream_->Open());
    136     audio_input_stream_->Stop();
    137     audio_input_stream_->Close();
    138     audio_input_stream_ = NULL;
    139   }
    140 
    141   void StopAndClose() {
    142     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    143     audio_input_stream_->Stop();
    144     audio_input_stream_->Close();
    145     audio_input_stream_ = NULL;
    146   }
    147 
    148   // Synchronously runs the provided callback/closure on the audio thread.
    149   void RunOnAudioThread(const base::Closure& closure) {
    150     if (!audio_manager()->GetTaskRunner()->BelongsToCurrentThread()) {
    151       base::WaitableEvent event(false, false);
    152       audio_manager()->GetTaskRunner()->PostTask(
    153           FROM_HERE,
    154           base::Bind(&AudioInputTest::RunOnAudioThreadImpl,
    155                      base::Unretained(this),
    156                      closure,
    157                      &event));
    158       event.Wait();
    159     } else {
    160       closure.Run();
    161     }
    162   }
    163 
    164   void RunOnAudioThreadImpl(const base::Closure& closure,
    165                             base::WaitableEvent* event) {
    166     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    167     closure.Run();
    168     event->Signal();
    169   }
    170 
    171   base::MessageLoop message_loop_;
    172   scoped_ptr<AudioManager> audio_manager_;
    173   AudioInputStream* audio_input_stream_;
    174 
    175  private:
    176   DISALLOW_COPY_AND_ASSIGN(AudioInputTest);
    177 };
    178 
    179 // Test create and close of an AudioInputStream without recording audio.
    180 TEST_F(AudioInputTest, CreateAndClose) {
    181   if (!CanRunAudioTests())
    182     return;
    183   MakeAudioInputStreamOnAudioThread();
    184   CloseAudioInputStreamOnAudioThread();
    185 }
    186 
    187 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
    188 // This test is failing on ARM linux: http://crbug.com/238490
    189 #define MAYBE_OpenAndClose DISABLED_OpenAndClose
    190 #else
    191 #define MAYBE_OpenAndClose OpenAndClose
    192 #endif
    193 // Test create, open and close of an AudioInputStream without recording audio.
    194 TEST_F(AudioInputTest, MAYBE_OpenAndClose) {
    195   if (!CanRunAudioTests())
    196     return;
    197   MakeAudioInputStreamOnAudioThread();
    198   OpenAndCloseAudioInputStreamOnAudioThread();
    199 }
    200 
    201 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
    202 // This test is failing on ARM linux: http://crbug.com/238490
    203 #define MAYBE_OpenStopAndClose DISABLED_OpenStopAndClose
    204 #else
    205 #define MAYBE_OpenStopAndClose OpenStopAndClose
    206 #endif
    207 // Test create, open, stop and close of an AudioInputStream without recording.
    208 TEST_F(AudioInputTest, MAYBE_OpenStopAndClose) {
    209   if (!CanRunAudioTests())
    210     return;
    211   MakeAudioInputStreamOnAudioThread();
    212   OpenStopAndCloseAudioInputStreamOnAudioThread();
    213 }
    214 
    215 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
    216 // This test is failing on ARM linux: http://crbug.com/238490
    217 #define MAYBE_Record DISABLED_Record
    218 #else
    219 #define MAYBE_Record Record
    220 #endif
    221 // Test a normal recording sequence using an AudioInputStream.
    222 // Very simple test which starts capturing during half a second and verifies
    223 // that recording starts.
    224 TEST_F(AudioInputTest, MAYBE_Record) {
    225   if (!CanRunAudioTests())
    226     return;
    227   MakeAudioInputStreamOnAudioThread();
    228 
    229   TestInputCallback test_callback;
    230   OpenAndStartAudioInputStreamOnAudioThread(&test_callback);
    231 
    232   message_loop_.PostDelayedTask(
    233       FROM_HERE,
    234       base::MessageLoop::QuitClosure(),
    235       base::TimeDelta::FromMilliseconds(500));
    236   message_loop_.Run();
    237   EXPECT_GE(test_callback.callback_count(), 2);
    238   EXPECT_FALSE(test_callback.had_error());
    239 
    240   StopAndCloseAudioInputStreamOnAudioThread();
    241 }
    242 
    243 }  // namespace media
    244