Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2013 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 "content/browser/renderer_host/media/audio_mirroring_manager.h"
      6 
      7 #include <map>
      8 
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/synchronization/waitable_event.h"
     13 #include "content/browser/browser_thread_impl.h"
     14 #include "media/audio/audio_parameters.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 using media::AudioOutputStream;
     19 using media::AudioParameters;
     20 using testing::_;
     21 using testing::NotNull;
     22 using testing::Ref;
     23 using testing::Return;
     24 using testing::ReturnRef;
     25 
     26 namespace content {
     27 
     28 namespace {
     29 
     30 class MockDiverter : public AudioMirroringManager::Diverter {
     31  public:
     32   MOCK_METHOD0(GetAudioParameters, const AudioParameters&());
     33   MOCK_METHOD1(StartDiverting, void(AudioOutputStream*));
     34   MOCK_METHOD0(StopDiverting, void());
     35 };
     36 
     37 class MockMirroringDestination
     38     : public AudioMirroringManager::MirroringDestination {
     39  public:
     40   MOCK_METHOD1(AddInput,
     41                media::AudioOutputStream*(const media::AudioParameters& params));
     42 };
     43 
     44 }  // namespace
     45 
     46 class AudioMirroringManagerTest : public testing::Test {
     47  public:
     48   AudioMirroringManagerTest()
     49       : message_loop_(base::MessageLoop::TYPE_IO),
     50         io_thread_(BrowserThread::IO, &message_loop_),
     51         params_(AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
     52                 AudioParameters::kAudioCDSampleRate, 16,
     53                 AudioParameters::kAudioCDSampleRate / 10) {}
     54 
     55   MockDiverter* CreateStream(
     56       int render_process_id, int render_view_id, int expected_times_diverted) {
     57     MockDiverter* const diverter = new MockDiverter();
     58     if (expected_times_diverted > 0) {
     59       EXPECT_CALL(*diverter, GetAudioParameters())
     60           .Times(expected_times_diverted)
     61           .WillRepeatedly(ReturnRef(params_));
     62       EXPECT_CALL(*diverter, StartDiverting(NotNull()))
     63           .Times(expected_times_diverted);
     64       EXPECT_CALL(*diverter, StopDiverting())
     65           .Times(expected_times_diverted);
     66     }
     67 
     68     mirroring_manager_.AddDiverter(render_process_id, render_view_id, diverter);
     69 
     70     return diverter;
     71   }
     72 
     73   void KillStream(
     74       int render_process_id, int render_view_id, MockDiverter* diverter) {
     75     mirroring_manager_.RemoveDiverter(
     76         render_process_id, render_view_id, diverter);
     77 
     78     delete diverter;
     79   }
     80 
     81   MockMirroringDestination* StartMirroringTo(
     82       int render_process_id, int render_view_id, int expected_inputs_added) {
     83     MockMirroringDestination* const dest = new MockMirroringDestination();
     84     if (expected_inputs_added > 0) {
     85       static AudioOutputStream* const kNonNullPointer =
     86           reinterpret_cast<AudioOutputStream*>(0x11111110);
     87       EXPECT_CALL(*dest, AddInput(Ref(params_)))
     88           .Times(expected_inputs_added)
     89           .WillRepeatedly(Return(kNonNullPointer));
     90     }
     91 
     92     mirroring_manager_.StartMirroring(render_process_id, render_view_id, dest);
     93 
     94     return dest;
     95   }
     96 
     97   void StopMirroringTo(int render_process_id, int render_view_id,
     98                        MockMirroringDestination* dest) {
     99     mirroring_manager_.StopMirroring(render_process_id, render_view_id, dest);
    100 
    101     delete dest;
    102 }
    103 
    104  private:
    105   base::MessageLoop message_loop_;
    106   BrowserThreadImpl io_thread_;
    107   AudioParameters params_;
    108   AudioMirroringManager mirroring_manager_;
    109 
    110   DISALLOW_COPY_AND_ASSIGN(AudioMirroringManagerTest);
    111 };
    112 
    113 namespace {
    114 const int kRenderProcessId = 123;
    115 const int kRenderViewId = 456;
    116 const int kAnotherRenderProcessId = 789;
    117 const int kAnotherRenderViewId = 1234;
    118 const int kYetAnotherRenderProcessId = 4560;
    119 const int kYetAnotherRenderViewId = 7890;
    120 }
    121 
    122 TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) {
    123   MockMirroringDestination* const destination =
    124       StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
    125   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    126 }
    127 
    128 TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
    129   MockMirroringDestination* const destination =
    130       StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
    131   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    132 
    133   MockMirroringDestination* const another_destination =
    134       StartMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 0);
    135   StopMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId,
    136                   another_destination);
    137 }
    138 
    139 TEST_F(AudioMirroringManagerTest, SwitchMirroringDestinationNoStreams) {
    140   MockMirroringDestination* const destination =
    141       StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
    142   MockMirroringDestination* const new_destination =
    143       StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
    144   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    145   StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination);
    146 }
    147 
    148 TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) {
    149   MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 1);
    150   MockMirroringDestination* const destination =
    151       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    152   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    153   KillStream(kRenderProcessId, kRenderViewId, stream);
    154 }
    155 
    156 TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinMirroringSession) {
    157   MockMirroringDestination* const destination =
    158       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    159   MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 1);
    160   KillStream(kRenderProcessId, kRenderViewId, stream);
    161   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    162 }
    163 
    164 TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundTwoMirroringSessions) {
    165   MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 2);
    166   MockMirroringDestination* const destination =
    167       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    168   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    169   MockMirroringDestination* const new_destination =
    170       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    171   StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination);
    172   KillStream(kRenderProcessId, kRenderViewId, stream);
    173 }
    174 
    175 TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinTwoMirroringSessions) {
    176   MockMirroringDestination* const destination =
    177       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    178   MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 2);
    179   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    180   MockMirroringDestination* const new_destination =
    181       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    182   KillStream(kRenderProcessId, kRenderViewId, stream);
    183   StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination);
    184 }
    185 
    186 TEST_F(AudioMirroringManagerTest, MultipleStreamsInOneMirroringSession) {
    187   MockDiverter* const stream1 =
    188       CreateStream(kRenderProcessId, kRenderViewId, 1);
    189   MockMirroringDestination* const destination =
    190       StartMirroringTo(kRenderProcessId, kRenderViewId, 3);
    191   MockDiverter* const stream2 =
    192       CreateStream(kRenderProcessId, kRenderViewId, 1);
    193   MockDiverter* const stream3 =
    194       CreateStream(kRenderProcessId, kRenderViewId, 1);
    195   KillStream(kRenderProcessId, kRenderViewId, stream2);
    196   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    197   KillStream(kRenderProcessId, kRenderViewId, stream3);
    198   KillStream(kRenderProcessId, kRenderViewId, stream1);
    199 }
    200 
    201 // A random interleaving of operations for three separate targets, each of which
    202 // has one stream mirrored to one destination.
    203 TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
    204   MockDiverter* const stream =
    205       CreateStream(kRenderProcessId, kRenderViewId, 1);
    206   MockMirroringDestination* const destination =
    207       StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
    208 
    209   MockMirroringDestination* const another_destination =
    210       StartMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 1);
    211   MockDiverter* const another_stream =
    212       CreateStream(kAnotherRenderProcessId, kAnotherRenderViewId, 1);
    213 
    214   KillStream(kRenderProcessId, kRenderViewId, stream);
    215 
    216   MockDiverter* const yet_another_stream =
    217       CreateStream(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 1);
    218   MockMirroringDestination* const yet_another_destination =
    219       StartMirroringTo(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 1);
    220 
    221   StopMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId,
    222                   another_destination);
    223 
    224   StopMirroringTo(kYetAnotherRenderProcessId, kYetAnotherRenderViewId,
    225                   yet_another_destination);
    226 
    227   StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
    228 
    229   KillStream(kAnotherRenderProcessId, kAnotherRenderViewId, another_stream);
    230   KillStream(kYetAnotherRenderProcessId, kYetAnotherRenderViewId,
    231              yet_another_stream);
    232 }
    233 
    234 }  // namespace content
    235