Home | History | Annotate | Download | only in media
      1 // Copyright 2014 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 <vector>
      6 
      7 #include "content/renderer/media/audio_device_factory.h"
      8 #include "content/renderer/media/audio_message_filter.h"
      9 #include "content/renderer/media/media_stream_audio_renderer.h"
     10 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
     11 #include "content/renderer/media/webrtc_audio_device_impl.h"
     12 #include "content/renderer/media/webrtc_audio_renderer.h"
     13 #include "media/audio/audio_output_device.h"
     14 #include "media/audio/audio_output_ipc.h"
     15 #include "media/base/audio_bus.h"
     16 #include "media/base/mock_audio_renderer_sink.h"
     17 #include "testing/gmock/include/gmock/gmock.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
     20 
     21 using testing::Return;
     22 
     23 namespace content {
     24 
     25 namespace {
     26 
     27 const int kHardwareSampleRate = 44100;
     28 const int kHardwareBufferSize = 512;
     29 
     30 class MockAudioOutputIPC : public media::AudioOutputIPC {
     31  public:
     32   MockAudioOutputIPC() {}
     33   virtual ~MockAudioOutputIPC() {}
     34 
     35   MOCK_METHOD3(CreateStream, void(media::AudioOutputIPCDelegate* delegate,
     36                                   const media::AudioParameters& params,
     37                                   int session_id));
     38   MOCK_METHOD0(PlayStream, void());
     39   MOCK_METHOD0(PauseStream, void());
     40   MOCK_METHOD0(CloseStream, void());
     41   MOCK_METHOD1(SetVolume, void(double volume));
     42 };
     43 
     44 class FakeAudioOutputDevice
     45     : NON_EXPORTED_BASE(public media::AudioOutputDevice) {
     46  public:
     47   FakeAudioOutputDevice(
     48       scoped_ptr<media::AudioOutputIPC> ipc,
     49       const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
     50       : AudioOutputDevice(ipc.Pass(),
     51                           io_task_runner) {}
     52   MOCK_METHOD0(Start, void());
     53   MOCK_METHOD0(Stop, void());
     54   MOCK_METHOD0(Pause, void());
     55   MOCK_METHOD0(Play, void());
     56   MOCK_METHOD1(SetVolume, bool(double volume));
     57 
     58  protected:
     59   virtual ~FakeAudioOutputDevice() {}
     60 };
     61 
     62 class MockAudioDeviceFactory : public AudioDeviceFactory {
     63  public:
     64   MockAudioDeviceFactory() {}
     65   virtual ~MockAudioDeviceFactory() {}
     66   MOCK_METHOD1(CreateOutputDevice, media::AudioOutputDevice*(int));
     67   MOCK_METHOD1(CreateInputDevice, media::AudioInputDevice*(int));
     68 };
     69 
     70 class MockAudioRendererSource : public WebRtcAudioRendererSource {
     71  public:
     72   MockAudioRendererSource() {}
     73   virtual ~MockAudioRendererSource() {}
     74   MOCK_METHOD4(RenderData, void(media::AudioBus* audio_bus,
     75                                 int sample_rate,
     76                                 int audio_delay_milliseconds,
     77                                 base::TimeDelta* current_time));
     78   MOCK_METHOD1(RemoveAudioRenderer, void(WebRtcAudioRenderer* renderer));
     79 };
     80 
     81 }  // namespace
     82 
     83 class WebRtcAudioRendererTest : public testing::Test {
     84  protected:
     85   WebRtcAudioRendererTest()
     86       : message_loop_(new base::MessageLoopForIO),
     87         mock_ipc_(new MockAudioOutputIPC()),
     88         mock_output_device_(new FakeAudioOutputDevice(
     89             scoped_ptr<media::AudioOutputIPC>(mock_ipc_),
     90             message_loop_->message_loop_proxy())),
     91         factory_(new MockAudioDeviceFactory()),
     92         source_(new MockAudioRendererSource()),
     93         stream_(new rtc::RefCountedObject<MockMediaStream>("label")),
     94         renderer_(new WebRtcAudioRenderer(stream_, 1, 1, 1, 44100,
     95                                           kHardwareBufferSize)) {
     96     EXPECT_CALL(*factory_.get(), CreateOutputDevice(1))
     97         .WillOnce(Return(mock_output_device_.get()));
     98     EXPECT_CALL(*mock_output_device_.get(), Start());
     99     EXPECT_TRUE(renderer_->Initialize(source_.get()));
    100     renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_);
    101   }
    102 
    103   // Used to construct |mock_output_device_|.
    104   scoped_ptr<base::MessageLoopForIO> message_loop_;
    105   MockAudioOutputIPC* mock_ipc_;  // Owned by AudioOuputDevice.
    106 
    107   scoped_refptr<FakeAudioOutputDevice> mock_output_device_;
    108   scoped_ptr<MockAudioDeviceFactory> factory_;
    109   scoped_ptr<MockAudioRendererSource> source_;
    110   scoped_refptr<webrtc::MediaStreamInterface> stream_;
    111   scoped_refptr<WebRtcAudioRenderer> renderer_;
    112   scoped_refptr<MediaStreamAudioRenderer> renderer_proxy_;
    113 };
    114 
    115 // Verify that the renderer will be stopped if the only proxy is stopped.
    116 TEST_F(WebRtcAudioRendererTest, StopRenderer) {
    117   renderer_proxy_->Start();
    118 
    119   // |renderer_| has only one proxy, stopping the proxy should stop the sink of
    120   // |renderer_|.
    121   EXPECT_CALL(*mock_output_device_.get(), Stop());
    122   EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
    123   renderer_proxy_->Stop();
    124 }
    125 
    126 // Verify that the renderer will not be stopped unless the last proxy is
    127 // stopped.
    128 TEST_F(WebRtcAudioRendererTest, MultipleRenderers) {
    129   renderer_proxy_->Start();
    130 
    131   // Create a vector of renderer proxies from the |renderer_|.
    132   std::vector<scoped_refptr<MediaStreamAudioRenderer> > renderer_proxies_;
    133   static const int kNumberOfRendererProxy = 5;
    134   for (int i = 0; i < kNumberOfRendererProxy; ++i) {
    135     scoped_refptr<MediaStreamAudioRenderer> renderer_proxy(
    136         renderer_->CreateSharedAudioRendererProxy(stream_));
    137     renderer_proxy->Start();
    138     renderer_proxies_.push_back(renderer_proxy);
    139   }
    140 
    141   // Stop the |renderer_proxy_| should not stop the sink since it is used by
    142   // other proxies.
    143   EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0);
    144   renderer_proxy_->Stop();
    145 
    146   for (int i = 0; i < kNumberOfRendererProxy; ++i) {
    147     if (i != kNumberOfRendererProxy -1) {
    148       EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0);
    149     } else {
    150       // When the last proxy is stopped, the sink will stop.
    151       EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
    152       EXPECT_CALL(*mock_output_device_.get(), Stop());
    153     }
    154     renderer_proxies_[i]->Stop();
    155   }
    156 }
    157 
    158 // Verify that the sink of the renderer is using the expected sample rate and
    159 // buffer size.
    160 TEST_F(WebRtcAudioRendererTest, VerifySinkParameters) {
    161   renderer_proxy_->Start();
    162 #if defined(OS_LINUX) || defined(OS_MACOSX)
    163   static const int kExpectedBufferSize = kHardwareSampleRate / 100;
    164 #elif defined(OS_ANDROID)
    165   static const int kExpectedBufferSize = 2 * kHardwareSampleRate / 100;
    166 #else
    167   // Windows.
    168   static const int kExpectedBufferSize = kHardwareBufferSize;
    169 #endif
    170   EXPECT_EQ(kExpectedBufferSize, renderer_->frames_per_buffer());
    171   EXPECT_EQ(kHardwareSampleRate, renderer_->sample_rate());
    172   EXPECT_EQ(2, renderer_->channels());
    173 
    174   EXPECT_CALL(*mock_output_device_.get(), Stop());
    175   EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
    176   renderer_proxy_->Stop();
    177 }
    178 
    179 }  // namespace content
    180