| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/audio_renderer_mixer_manager.h" | 5 #include "content/renderer/media/audio_renderer_mixer_manager.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/macros.h" | 11 #include "base/macros.h" |
| 11 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 12 #include "content/renderer/media/audio_device_factory.h" | 13 #include "content/renderer/media/audio_renderer_sink_cache.h" |
| 13 #include "media/audio/audio_device_description.h" | 14 #include "media/audio/audio_device_description.h" |
| 14 #include "media/base/audio_capturer_source.h" | |
| 15 #include "media/base/audio_parameters.h" | 15 #include "media/base/audio_parameters.h" |
| 16 #include "media/base/audio_renderer_mixer.h" | 16 #include "media/base/audio_renderer_mixer.h" |
| 17 #include "media/base/audio_renderer_mixer_input.h" | 17 #include "media/base/audio_renderer_mixer_input.h" |
| 18 #include "media/base/fake_audio_render_callback.h" | 18 #include "media/base/fake_audio_render_callback.h" |
| 19 #include "media/base/mock_audio_renderer_sink.h" | 19 #include "media/base/mock_audio_renderer_sink.h" |
| 20 #include "testing/gmock/include/gmock/gmock.h" | 20 #include "testing/gmock/include/gmock/gmock.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 22 #include "url/gurl.h" | 22 #include "url/gurl.h" |
| 23 | 23 |
| 24 namespace content { | 24 namespace content { |
| 25 | 25 |
| 26 namespace { |
| 26 static const int kBitsPerChannel = 16; | 27 static const int kBitsPerChannel = 16; |
| 27 static const int kSampleRate = 48000; | 28 static const int kSampleRate = 48000; |
| 28 static const int kBufferSize = 8192; | 29 static const int kBufferSize = 8192; |
| 29 static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; | 30 static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; |
| 30 static const media::ChannelLayout kAnotherChannelLayout = | 31 static const media::ChannelLayout kAnotherChannelLayout = |
| 31 media::CHANNEL_LAYOUT_2_1; | 32 media::CHANNEL_LAYOUT_2_1; |
| 32 static const char* const kDefaultDeviceId = | 33 static const char* const kDefaultDeviceId = |
| 33 media::AudioDeviceDescription::kDefaultDeviceId; | 34 media::AudioDeviceDescription::kDefaultDeviceId; |
| 34 static const char kAnotherDeviceId[] = "another-device-id"; | 35 static const char kAnotherDeviceId[] = "another-device-id"; |
| 35 static const char kMatchedDeviceId[] = "matched-device-id"; | 36 static const char kMatchedDeviceId[] = "matched-device-id"; |
| 36 static const char kNonexistentDeviceId[] = "nonexistent-device-id"; | 37 static const char kNonexistentDeviceId[] = "nonexistent-device-id"; |
| 37 | 38 |
| 38 static const int kRenderFrameId = 124; | 39 static const int kRenderFrameId = 124; |
| 39 static const int kAnotherRenderFrameId = 678; | 40 static const int kAnotherRenderFrameId = 678; |
| 41 } // namespace; |
| 40 | 42 |
| 41 using media::AudioParameters; | 43 using media::AudioParameters; |
| 42 | 44 |
| 43 class AudioRendererMixerManagerTest : public testing::Test, | 45 class FakeAudioRendererSinkCache : public AudioRendererSinkCache { |
| 44 public AudioDeviceFactory { | 46 public: |
| 47 using GetSinkCallback = |
| 48 base::Callback<scoped_refptr<media::AudioRendererSink>( |
| 49 int render_frame_id, |
| 50 int session_id, |
| 51 const std::string& device_id, |
| 52 const url::Origin& security_origin)>; |
| 53 |
| 54 using ReleaseSinkCallback = |
| 55 base::Callback<void(const media::AudioRendererSink*)>; |
| 56 |
| 57 FakeAudioRendererSinkCache(const GetSinkCallback& get_sink_cb, |
| 58 const ReleaseSinkCallback& release_sink_cb) |
| 59 : get_sink_cb_(get_sink_cb), release_sink_cb_(release_sink_cb) {} |
| 60 |
| 61 media::OutputDeviceInfo GetSinkInfo( |
| 62 int source_render_frame_id, |
| 63 int session_id, |
| 64 const std::string& device_id, |
| 65 const url::Origin& security_origin) final { |
| 66 return get_sink_cb_ |
| 67 .Run(source_render_frame_id, session_id, device_id, security_origin) |
| 68 ->GetOutputDeviceInfo(); |
| 69 } |
| 70 |
| 71 scoped_refptr<media::AudioRendererSink> GetSink( |
| 72 int source_render_frame_id, |
| 73 const std::string& device_id, |
| 74 const url::Origin& security_origin) final { |
| 75 return get_sink_cb_.Run(source_render_frame_id, 0, device_id, |
| 76 security_origin); |
| 77 } |
| 78 |
| 79 void ReleaseSink(const media::AudioRendererSink* sink) final { |
| 80 release_sink_cb_.Run(sink); |
| 81 } |
| 82 |
| 83 private: |
| 84 GetSinkCallback get_sink_cb_; |
| 85 ReleaseSinkCallback release_sink_cb_; |
| 86 }; |
| 87 |
| 88 class AudioRendererMixerManagerTest : public testing::Test { |
| 45 public: | 89 public: |
| 46 AudioRendererMixerManagerTest() | 90 AudioRendererMixerManagerTest() |
| 47 : manager_(new AudioRendererMixerManager()), | 91 : manager_(new AudioRendererMixerManager( |
| 92 std::unique_ptr<AudioRendererSinkCache>( |
| 93 new FakeAudioRendererSinkCache( |
| 94 base::Bind(&AudioRendererMixerManagerTest::GetSinkPtr, |
| 95 base::Unretained(this)), |
| 96 base::Bind(&AudioRendererMixerManagerTest::ReleaseSinkPtr, |
| 97 base::Unretained(this)))))), |
| 48 mock_sink_(new media::MockAudioRendererSink()), | 98 mock_sink_(new media::MockAudioRendererSink()), |
| 49 mock_sink_no_device_(new media::MockAudioRendererSink( | 99 mock_sink_no_device_(new media::MockAudioRendererSink( |
| 50 kNonexistentDeviceId, | 100 kNonexistentDeviceId, |
| 51 media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND)), | 101 media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND)), |
| 52 mock_sink_matched_device_( | 102 mock_sink_matched_device_( |
| 53 new media::MockAudioRendererSink(kMatchedDeviceId, | 103 new media::MockAudioRendererSink(kMatchedDeviceId, |
| 54 media::OUTPUT_DEVICE_STATUS_OK)), | 104 media::OUTPUT_DEVICE_STATUS_OK)), |
| 55 mock_sink_for_session_id_( | |
| 56 new media::MockAudioRendererSink(kMatchedDeviceId, | |
| 57 media::OUTPUT_DEVICE_STATUS_OK)), | |
| 58 kSecurityOrigin2(GURL("http://localhost")) {} | 105 kSecurityOrigin2(GURL("http://localhost")) {} |
| 59 | 106 |
| 60 media::AudioRendererMixer* GetMixer( | 107 media::AudioRendererMixer* GetMixer( |
| 61 int source_render_frame_id, | 108 int source_render_frame_id, |
| 62 const media::AudioParameters& params, | 109 const media::AudioParameters& params, |
| 63 const std::string& device_id, | 110 const std::string& device_id, |
| 64 const url::Origin& security_origin, | 111 const url::Origin& security_origin, |
| 65 media::OutputDeviceStatus* device_status) { | 112 media::OutputDeviceStatus* device_status) { |
| 66 return manager_->GetMixer(source_render_frame_id, params, device_id, | 113 return manager_->GetMixer(source_render_frame_id, params, device_id, |
| 67 security_origin, device_status); | 114 security_origin, device_status); |
| 68 } | 115 } |
| 69 | 116 |
| 70 void RemoveMixer(int source_render_frame_id, | 117 void ReturnMixer(int source_render_frame_id, |
| 71 const media::AudioParameters& params, | 118 const media::AudioParameters& params, |
| 72 const std::string& device_id, | 119 const std::string& device_id, |
| 73 const url::Origin& security_origin) { | 120 const url::Origin& security_origin) { |
| 74 return manager_->RemoveMixer(source_render_frame_id, params, device_id, | 121 return manager_->ReturnMixer(source_render_frame_id, params, device_id, |
| 75 security_origin); | 122 security_origin); |
| 76 } | 123 } |
| 77 | 124 |
| 78 // Number of instantiated mixers. | 125 // Number of instantiated mixers. |
| 79 int mixer_count() { | 126 int mixer_count() { |
| 80 return manager_->mixers_.size(); | 127 return manager_->mixers_.size(); |
| 81 } | 128 } |
| 82 | 129 |
| 83 protected: | 130 protected: |
| 84 MOCK_METHOD1(CreateAudioCapturerSource, | 131 scoped_refptr<media::AudioRendererSink> GetSinkPtr( |
| 85 scoped_refptr<media::AudioCapturerSource>(int)); | 132 int source_render_frame_id, |
| 86 MOCK_METHOD5( | |
| 87 CreateSwitchableAudioRendererSink, | |
| 88 scoped_refptr<media::SwitchableAudioRendererSink>(SourceType, | |
| 89 int, | |
| 90 int, | |
| 91 const std::string&, | |
| 92 const url::Origin&)); | |
| 93 MOCK_METHOD5(CreateAudioRendererSink, | |
| 94 scoped_refptr<media::AudioRendererSink>(SourceType, | |
| 95 int, | |
| 96 int, | |
| 97 const std::string&, | |
| 98 const url::Origin&)); | |
| 99 | |
| 100 scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink( | |
| 101 int render_frame_id, | |
| 102 int session_id, | 133 int session_id, |
| 103 const std::string& device_id, | 134 const std::string& device_id, |
| 104 const url::Origin& security_origin) { | 135 const url::Origin& security_origin) { |
| 105 if ((device_id == kDefaultDeviceId) || (device_id == kAnotherDeviceId)) { | 136 if ((device_id == kDefaultDeviceId) || (device_id == kAnotherDeviceId)) { |
| 106 // We don't care about separate sinks for these devices. | 137 // We don't care about separate sinks for these devices. |
| 107 return mock_sink_; | 138 return mock_sink_; |
| 108 } | 139 } |
| 109 if (device_id == kNonexistentDeviceId) | 140 if (device_id == kNonexistentDeviceId) |
| 110 return mock_sink_no_device_; | 141 return mock_sink_no_device_; |
| 111 if (device_id.empty()) { | 142 if (device_id.empty()) { |
| 112 // The sink used to get device ID from session ID if it's not empty | 143 // The sink used to get device ID from session ID if it's not empty |
| 113 return session_id ? mock_sink_for_session_id_ : mock_sink_; | 144 return session_id ? mock_sink_matched_device_ : mock_sink_; |
| 114 } | 145 } |
| 115 if (device_id == kMatchedDeviceId) | 146 if (device_id == kMatchedDeviceId) |
| 116 return mock_sink_matched_device_; | 147 return mock_sink_matched_device_; |
| 117 | 148 |
| 118 NOTREACHED(); | 149 NOTREACHED(); |
| 119 return nullptr; | 150 return nullptr; |
| 120 } | 151 } |
| 121 | 152 |
| 153 MOCK_METHOD1(ReleaseSinkPtr, void(const media::AudioRendererSink*)); |
| 154 |
| 122 std::unique_ptr<AudioRendererMixerManager> manager_; | 155 std::unique_ptr<AudioRendererMixerManager> manager_; |
| 156 |
| 123 scoped_refptr<media::MockAudioRendererSink> mock_sink_; | 157 scoped_refptr<media::MockAudioRendererSink> mock_sink_; |
| 124 scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_; | 158 scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_; |
| 125 scoped_refptr<media::MockAudioRendererSink> mock_sink_matched_device_; | 159 scoped_refptr<media::MockAudioRendererSink> mock_sink_matched_device_; |
| 126 scoped_refptr<media::MockAudioRendererSink> mock_sink_for_session_id_; | |
| 127 | 160 |
| 128 // To avoid global/static non-POD constants. | 161 // To avoid global/static non-POD constants. |
| 129 const url::Origin kSecurityOrigin; | 162 const url::Origin kSecurityOrigin; |
| 130 const url::Origin kSecurityOrigin2; | 163 const url::Origin kSecurityOrigin2; |
| 131 | 164 |
| 132 private: | 165 private: |
| 133 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest); | 166 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest); |
| 134 }; | 167 }; |
| 135 | 168 |
| 136 // Verify GetMixer() and RemoveMixer() both work as expected; particularly with | 169 // Verify GetMixer() and ReturnMixer() both work as expected; particularly with |
| 137 // respect to the explicit ref counting done. | 170 // respect to the explicit ref counting done. |
| 138 TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { | 171 TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) { |
| 139 // Since we're testing two different sets of parameters, we expect | 172 // Since we're testing two different sets of parameters, we expect |
| 140 // AudioRendererMixerManager to call Start and Stop on our mock twice. | 173 // AudioRendererMixerManager to call Start and Stop on our mock twice. |
| 141 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); | 174 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
| 142 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); | 175 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| 143 | 176 |
| 177 // We expect 2 mixers to be created; each of them should release the sink. |
| 178 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| 179 |
| 144 // There should be no mixers outstanding to start with. | 180 // There should be no mixers outstanding to start with. |
| 145 EXPECT_EQ(0, mixer_count()); | 181 EXPECT_EQ(0, mixer_count()); |
| 146 | 182 |
| 147 media::AudioParameters params1( | 183 media::AudioParameters params1( |
| 148 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, | 184 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, |
| 149 kBitsPerChannel, kBufferSize); | 185 kBitsPerChannel, kBufferSize); |
| 150 | 186 |
| 151 media::AudioRendererMixer* mixer1 = GetMixer( | 187 media::AudioRendererMixer* mixer1 = GetMixer( |
| 152 kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr); | 188 kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr); |
| 153 ASSERT_TRUE(mixer1); | 189 ASSERT_TRUE(mixer1); |
| 154 EXPECT_EQ(1, mixer_count()); | 190 EXPECT_EQ(1, mixer_count()); |
| 155 | 191 |
| 156 // The same parameters should return the same mixer1. | 192 // The same parameters should return the same mixer1. |
| 157 EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params1, kDefaultDeviceId, | 193 EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params1, kDefaultDeviceId, |
| 158 kSecurityOrigin, nullptr)); | 194 kSecurityOrigin, nullptr)); |
| 159 EXPECT_EQ(1, mixer_count()); | 195 EXPECT_EQ(1, mixer_count()); |
| 160 | 196 |
| 161 // Remove the extra mixer we just acquired. | 197 // Return the extra mixer we just acquired. |
| 162 RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); | 198 ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| 163 EXPECT_EQ(1, mixer_count()); | 199 EXPECT_EQ(1, mixer_count()); |
| 164 | 200 |
| 165 media::AudioParameters params2( | 201 media::AudioParameters params2( |
| 166 AudioParameters::AUDIO_PCM_LINEAR, kAnotherChannelLayout, kSampleRate * 2, | 202 AudioParameters::AUDIO_PCM_LINEAR, kAnotherChannelLayout, kSampleRate * 2, |
| 167 kBitsPerChannel, kBufferSize * 2); | 203 kBitsPerChannel, kBufferSize * 2); |
| 168 media::AudioRendererMixer* mixer2 = GetMixer( | 204 media::AudioRendererMixer* mixer2 = GetMixer( |
| 169 kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin, nullptr); | 205 kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin, nullptr); |
| 170 ASSERT_TRUE(mixer2); | 206 ASSERT_TRUE(mixer2); |
| 171 EXPECT_EQ(2, mixer_count()); | 207 EXPECT_EQ(2, mixer_count()); |
| 172 | 208 |
| 173 // Different parameters should result in a different mixer1. | 209 // Different parameters should result in a different mixer1. |
| 174 EXPECT_NE(mixer1, mixer2); | 210 EXPECT_NE(mixer1, mixer2); |
| 175 | 211 |
| 176 // Remove both outstanding mixers. | 212 // Return both outstanding mixers. |
| 177 RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); | 213 ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| 178 EXPECT_EQ(1, mixer_count()); | 214 EXPECT_EQ(1, mixer_count()); |
| 179 RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); | 215 ReturnMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
| 180 EXPECT_EQ(0, mixer_count()); | 216 EXPECT_EQ(0, mixer_count()); |
| 181 } | 217 } |
| 182 | 218 |
| 183 // Verify GetMixer() correctly deduplicates mixer with irrelevant AudioParameter | 219 // Verify GetMixer() correctly deduplicates mixer with irrelevant AudioParameter |
| 184 // differences. | 220 // differences. |
| 185 TEST_F(AudioRendererMixerManagerTest, MixerReuse) { | 221 TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
| 186 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); | 222 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
| 187 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); | 223 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| 188 EXPECT_EQ(mixer_count(), 0); | 224 EXPECT_EQ(mixer_count(), 0); |
| 189 | 225 |
| 226 // We expect 2 mixers to be created; each of them should release the sink. |
| 227 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| 228 |
| 190 media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR, | 229 media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR, |
| 191 kChannelLayout, | 230 kChannelLayout, |
| 192 kSampleRate, | 231 kSampleRate, |
| 193 kBitsPerChannel, | 232 kBitsPerChannel, |
| 194 kBufferSize); | 233 kBufferSize); |
| 195 media::AudioRendererMixer* mixer1 = GetMixer( | 234 media::AudioRendererMixer* mixer1 = GetMixer( |
| 196 kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr); | 235 kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr); |
| 197 ASSERT_TRUE(mixer1); | 236 ASSERT_TRUE(mixer1); |
| 198 EXPECT_EQ(1, mixer_count()); | 237 EXPECT_EQ(1, mixer_count()); |
| 199 | 238 |
| 200 // Different sample rates, formats, bit depths, and buffer sizes should not | 239 // Different sample rates, formats, bit depths, and buffer sizes should not |
| 201 // result in a different mixer. | 240 // result in a different mixer. |
| 202 media::AudioParameters params2(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 241 media::AudioParameters params2(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 203 kChannelLayout, | 242 kChannelLayout, |
| 204 kSampleRate * 2, | 243 kSampleRate * 2, |
| 205 kBitsPerChannel * 2, | 244 kBitsPerChannel * 2, |
| 206 kBufferSize * 2); | 245 kBufferSize * 2); |
| 207 EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId, | 246 EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId, |
| 208 kSecurityOrigin, nullptr)); | 247 kSecurityOrigin, nullptr)); |
| 209 EXPECT_EQ(1, mixer_count()); | 248 EXPECT_EQ(1, mixer_count()); |
| 210 RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); | 249 ReturnMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
| 211 EXPECT_EQ(1, mixer_count()); | 250 EXPECT_EQ(1, mixer_count()); |
| 212 | 251 |
| 213 // Modify some parameters that do matter: channel layout | 252 // Modify some parameters that do matter: channel layout |
| 214 media::AudioParameters params3(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 253 media::AudioParameters params3(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 215 kAnotherChannelLayout, | 254 kAnotherChannelLayout, |
| 216 kSampleRate, | 255 kSampleRate, |
| 217 kBitsPerChannel, | 256 kBitsPerChannel, |
| 218 kBufferSize); | 257 kBufferSize); |
| 219 ASSERT_NE(params3.channel_layout(), params1.channel_layout()); | 258 ASSERT_NE(params3.channel_layout(), params1.channel_layout()); |
| 220 | 259 |
| 221 EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId, | 260 EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId, |
| 222 kSecurityOrigin, nullptr)); | 261 kSecurityOrigin, nullptr)); |
| 223 EXPECT_EQ(2, mixer_count()); | 262 EXPECT_EQ(2, mixer_count()); |
| 224 RemoveMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin); | 263 ReturnMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin); |
| 225 EXPECT_EQ(1, mixer_count()); | 264 EXPECT_EQ(1, mixer_count()); |
| 226 | 265 |
| 227 // Remove final mixer. | 266 // Return final mixer. |
| 228 RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); | 267 ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| 229 EXPECT_EQ(0, mixer_count()); | 268 EXPECT_EQ(0, mixer_count()); |
| 230 } | 269 } |
| 231 | 270 |
| 232 // Verify CreateInput() provides AudioRendererMixerInput with the appropriate | 271 // Verify CreateInput() provides AudioRendererMixerInput with the appropriate |
| 233 // callbacks and they are working as expected. Also, verify that separate | 272 // callbacks and they are working as expected. Also, verify that separate |
| 234 // mixers are created for separate render views, even though the AudioParameters | 273 // mixers are created for separate render views, even though the AudioParameters |
| 235 // are the same. | 274 // are the same. |
| 236 TEST_F(AudioRendererMixerManagerTest, CreateInput) { | 275 TEST_F(AudioRendererMixerManagerTest, CreateInput) { |
| 237 // Expect AudioRendererMixerManager to call Start and Stop on our mock twice | 276 // Expect AudioRendererMixerManager to call Start and Stop on our mock twice |
| 238 // each. Note: Under normal conditions, each mixer would get its own sink! | 277 // each. Note: Under normal conditions, each mixer would get its own sink! |
| 239 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); | 278 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
| 240 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); | 279 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| 241 | 280 |
| 281 // We expect 2 mixers to be created; each of them should release the sink. |
| 282 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| 283 |
| 242 media::AudioParameters params( | 284 media::AudioParameters params( |
| 243 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, | 285 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, |
| 244 kBitsPerChannel, kBufferSize); | 286 kBitsPerChannel, kBufferSize); |
| 245 | 287 |
| 246 // Create two mixer inputs and ensure this doesn't instantiate any mixers yet. | 288 // Create two mixer inputs and ensure this doesn't instantiate any mixers yet. |
| 247 EXPECT_EQ(0, mixer_count()); | 289 EXPECT_EQ(0, mixer_count()); |
| 248 media::FakeAudioRenderCallback callback(0); | 290 media::FakeAudioRenderCallback callback(0); |
| 249 scoped_refptr<media::AudioRendererMixerInput> input(manager_->CreateInput( | 291 scoped_refptr<media::AudioRendererMixerInput> input(manager_->CreateInput( |
| 250 kRenderFrameId, 0, kDefaultDeviceId, kSecurityOrigin)); | 292 kRenderFrameId, 0, kDefaultDeviceId, kSecurityOrigin)); |
| 251 input->Initialize(params, &callback); | 293 input->Initialize(params, &callback); |
| 252 EXPECT_EQ(0, mixer_count()); | 294 EXPECT_EQ(0, mixer_count()); |
| 253 media::FakeAudioRenderCallback another_callback(1); | 295 media::FakeAudioRenderCallback another_callback(1); |
| 254 scoped_refptr<media::AudioRendererMixerInput> another_input( | 296 scoped_refptr<media::AudioRendererMixerInput> another_input( |
| 255 manager_->CreateInput(kAnotherRenderFrameId, 0, kDefaultDeviceId, | 297 manager_->CreateInput(kAnotherRenderFrameId, 0, kDefaultDeviceId, |
| 256 kSecurityOrigin)); | 298 kSecurityOrigin)); |
| 257 another_input->Initialize(params, &another_callback); | 299 another_input->Initialize(params, &another_callback); |
| 258 EXPECT_EQ(0, mixer_count()); | 300 EXPECT_EQ(0, mixer_count()); |
| 259 | 301 |
| 260 // Implicitly test that AudioRendererMixerInput was provided with the expected | 302 // Implicitly test that AudioRendererMixerInput was provided with the expected |
| 261 // callbacks needed to acquire an AudioRendererMixer and remove it. | 303 // callbacks needed to acquire an AudioRendererMixer and return it. |
| 262 input->Start(); | 304 input->Start(); |
| 263 EXPECT_EQ(1, mixer_count()); | 305 EXPECT_EQ(1, mixer_count()); |
| 264 another_input->Start(); | 306 another_input->Start(); |
| 265 EXPECT_EQ(2, mixer_count()); | 307 EXPECT_EQ(2, mixer_count()); |
| 266 | 308 |
| 267 // Destroying the inputs should destroy the mixers. | 309 // Destroying the inputs should destroy the mixers. |
| 268 input->Stop(); | 310 input->Stop(); |
| 269 input = nullptr; | 311 input = nullptr; |
| 270 EXPECT_EQ(1, mixer_count()); | 312 EXPECT_EQ(1, mixer_count()); |
| 271 another_input->Stop(); | 313 another_input->Stop(); |
| 272 another_input = nullptr; | 314 another_input = nullptr; |
| 273 EXPECT_EQ(0, mixer_count()); | 315 EXPECT_EQ(0, mixer_count()); |
| 274 } | 316 } |
| 275 | 317 |
| 276 // Verify CreateInput() provided with session id creates AudioRendererMixerInput | 318 // Verify CreateInput() provided with session id creates AudioRendererMixerInput |
| 277 // with the appropriate callbacks and they are working as expected. | 319 // with the appropriate callbacks and they are working as expected. |
| 278 TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) { | 320 TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) { |
| 279 // Expect AudioRendererMixerManager to call Start and Stop on our mock twice | 321 // Expect AudioRendererMixerManager to call Start and Stop on our mock twice |
| 280 // each: for kDefaultDeviceId and for kAnotherDeviceId. Note: Under normal | 322 // each: for kDefaultDeviceId and for kAnotherDeviceId. Note: Under normal |
| 281 // conditions, each mixer would get its own sink! | 323 // conditions, each mixer would get its own sink! |
| 282 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); | 324 EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
| 283 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); | 325 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| 284 | 326 |
| 285 // Expect AudioRendererMixerManager to call Start and Stop on the matched sink | 327 // Expect AudioRendererMixerManager to call Start and Stop on the matched sink |
| 286 // once. | 328 // once. |
| 287 EXPECT_CALL(*mock_sink_matched_device_.get(), Start()).Times(1); | 329 EXPECT_CALL(*mock_sink_matched_device_.get(), Start()).Times(1); |
| 288 EXPECT_CALL(*mock_sink_matched_device_.get(), Stop()).Times(1); | 330 EXPECT_CALL(*mock_sink_matched_device_.get(), Stop()).Times(1); |
| 289 | 331 |
| 332 // We expect 3 mixers to be created; each of them should release a sink. |
| 333 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| 334 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_matched_device_.get())).Times(1); |
| 335 |
| 290 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, | 336 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| 291 kChannelLayout, kSampleRate, kBitsPerChannel, | 337 kChannelLayout, kSampleRate, kBitsPerChannel, |
| 292 kBufferSize); | 338 kBufferSize); |
| 293 media::FakeAudioRenderCallback callback(0); | 339 media::FakeAudioRenderCallback callback(0); |
| 294 EXPECT_EQ(0, mixer_count()); | 340 EXPECT_EQ(0, mixer_count()); |
| 295 | 341 |
| 296 // Empty device id, zero session id; | 342 // Empty device id, zero session id; |
| 297 scoped_refptr<media::AudioRendererMixerInput> input_to_default_device( | 343 scoped_refptr<media::AudioRendererMixerInput> input_to_default_device( |
| 298 manager_->CreateInput(kRenderFrameId, 0, // session_id | 344 manager_->CreateInput(kRenderFrameId, 0, // session_id |
| 299 std::string(), kSecurityOrigin)); | 345 std::string(), kSecurityOrigin)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 316 | 362 |
| 317 // Empty device id, non-zero session id; | 363 // Empty device id, non-zero session id; |
| 318 scoped_refptr<media::AudioRendererMixerInput> | 364 scoped_refptr<media::AudioRendererMixerInput> |
| 319 input_to_matched_device_with_session_id( | 365 input_to_matched_device_with_session_id( |
| 320 manager_->CreateInput(kRenderFrameId, 2, // session id | 366 manager_->CreateInput(kRenderFrameId, 2, // session id |
| 321 std::string(), kSecurityOrigin)); | 367 std::string(), kSecurityOrigin)); |
| 322 input_to_matched_device_with_session_id->Initialize(params, &callback); | 368 input_to_matched_device_with_session_id->Initialize(params, &callback); |
| 323 EXPECT_EQ(0, mixer_count()); | 369 EXPECT_EQ(0, mixer_count()); |
| 324 | 370 |
| 325 // Implicitly test that AudioRendererMixerInput was provided with the expected | 371 // Implicitly test that AudioRendererMixerInput was provided with the expected |
| 326 // callbacks needed to acquire an AudioRendererMixer and remove it. | 372 // callbacks needed to acquire an AudioRendererMixer and return it. |
| 327 input_to_default_device->Start(); | 373 input_to_default_device->Start(); |
| 328 EXPECT_EQ(1, mixer_count()); | 374 EXPECT_EQ(1, mixer_count()); |
| 329 | 375 |
| 330 input_to_another_device->Start(); | 376 input_to_another_device->Start(); |
| 331 EXPECT_EQ(2, mixer_count()); | 377 EXPECT_EQ(2, mixer_count()); |
| 332 | 378 |
| 333 input_to_matched_device->Start(); | 379 input_to_matched_device->Start(); |
| 334 EXPECT_EQ(3, mixer_count()); | 380 EXPECT_EQ(3, mixer_count()); |
| 335 | 381 |
| 336 // Should go to the same device as the input above. | 382 // Should go to the same device as the input above. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 352 EXPECT_EQ(0, mixer_count()); | 398 EXPECT_EQ(0, mixer_count()); |
| 353 } | 399 } |
| 354 | 400 |
| 355 // Verify GetMixer() correctly creates different mixers with the same | 401 // Verify GetMixer() correctly creates different mixers with the same |
| 356 // parameters, but different device ID and/or security origin | 402 // parameters, but different device ID and/or security origin |
| 357 TEST_F(AudioRendererMixerManagerTest, MixerDevices) { | 403 TEST_F(AudioRendererMixerManagerTest, MixerDevices) { |
| 358 EXPECT_CALL(*mock_sink_.get(), Start()).Times(3); | 404 EXPECT_CALL(*mock_sink_.get(), Start()).Times(3); |
| 359 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3); | 405 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3); |
| 360 EXPECT_EQ(0, mixer_count()); | 406 EXPECT_EQ(0, mixer_count()); |
| 361 | 407 |
| 408 // We expect 3 mixers to be created; each of them should release a sink. |
| 409 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3); |
| 410 |
| 362 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, | 411 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| 363 kChannelLayout, kSampleRate, kBitsPerChannel, | 412 kChannelLayout, kSampleRate, kBitsPerChannel, |
| 364 kBufferSize); | 413 kBufferSize); |
| 365 media::AudioRendererMixer* mixer1 = GetMixer( | 414 media::AudioRendererMixer* mixer1 = GetMixer( |
| 366 kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr); | 415 kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr); |
| 367 ASSERT_TRUE(mixer1); | 416 ASSERT_TRUE(mixer1); |
| 368 EXPECT_EQ(1, mixer_count()); | 417 EXPECT_EQ(1, mixer_count()); |
| 369 | 418 |
| 370 media::AudioRendererMixer* mixer2 = GetMixer( | 419 media::AudioRendererMixer* mixer2 = GetMixer( |
| 371 kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin, nullptr); | 420 kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin, nullptr); |
| 372 ASSERT_TRUE(mixer2); | 421 ASSERT_TRUE(mixer2); |
| 373 EXPECT_EQ(2, mixer_count()); | 422 EXPECT_EQ(2, mixer_count()); |
| 374 EXPECT_NE(mixer1, mixer2); | 423 EXPECT_NE(mixer1, mixer2); |
| 375 | 424 |
| 376 media::AudioRendererMixer* mixer3 = GetMixer( | 425 media::AudioRendererMixer* mixer3 = GetMixer( |
| 377 kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2, nullptr); | 426 kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2, nullptr); |
| 378 ASSERT_TRUE(mixer3); | 427 ASSERT_TRUE(mixer3); |
| 379 EXPECT_EQ(3, mixer_count()); | 428 EXPECT_EQ(3, mixer_count()); |
| 380 EXPECT_NE(mixer1, mixer3); | 429 EXPECT_NE(mixer1, mixer3); |
| 381 EXPECT_NE(mixer2, mixer3); | 430 EXPECT_NE(mixer2, mixer3); |
| 382 | 431 |
| 383 RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); | 432 ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
| 384 EXPECT_EQ(2, mixer_count()); | 433 EXPECT_EQ(2, mixer_count()); |
| 385 RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin); | 434 ReturnMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin); |
| 386 EXPECT_EQ(1, mixer_count()); | 435 EXPECT_EQ(1, mixer_count()); |
| 387 RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2); | 436 ReturnMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2); |
| 388 EXPECT_EQ(0, mixer_count()); | 437 EXPECT_EQ(0, mixer_count()); |
| 389 } | 438 } |
| 390 | 439 |
| 391 // Verify GetMixer() correctly deduplicate mixers with the same | 440 // Verify GetMixer() correctly deduplicate mixers with the same |
| 392 // parameters, different security origins but default device ID | 441 // parameters, different security origins but default device ID |
| 393 TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { | 442 TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
| 394 EXPECT_CALL(*mock_sink_.get(), Start()).Times(1); | 443 EXPECT_CALL(*mock_sink_.get(), Start()).Times(1); |
| 395 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1); | 444 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1); |
| 396 EXPECT_EQ(0, mixer_count()); | 445 EXPECT_EQ(0, mixer_count()); |
| 397 | 446 |
| 447 // We expect 1 mixers to be created; it should release its sink. |
| 448 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1); |
| 449 |
| 398 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, | 450 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| 399 kChannelLayout, kSampleRate, kBitsPerChannel, | 451 kChannelLayout, kSampleRate, kBitsPerChannel, |
| 400 kBufferSize); | 452 kBufferSize); |
| 401 media::AudioRendererMixer* mixer1 = GetMixer( | 453 media::AudioRendererMixer* mixer1 = GetMixer( |
| 402 kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr); | 454 kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr); |
| 403 ASSERT_TRUE(mixer1); | 455 ASSERT_TRUE(mixer1); |
| 404 EXPECT_EQ(1, mixer_count()); | 456 EXPECT_EQ(1, mixer_count()); |
| 405 | 457 |
| 406 media::AudioRendererMixer* mixer2 = | 458 media::AudioRendererMixer* mixer2 = |
| 407 GetMixer(kRenderFrameId, params, std::string(), kSecurityOrigin, nullptr); | 459 GetMixer(kRenderFrameId, params, std::string(), kSecurityOrigin, nullptr); |
| 408 ASSERT_TRUE(mixer2); | 460 ASSERT_TRUE(mixer2); |
| 409 EXPECT_EQ(1, mixer_count()); | 461 EXPECT_EQ(1, mixer_count()); |
| 410 EXPECT_EQ(mixer1, mixer2); | 462 EXPECT_EQ(mixer1, mixer2); |
| 411 | 463 |
| 412 media::AudioRendererMixer* mixer3 = GetMixer( | 464 media::AudioRendererMixer* mixer3 = GetMixer( |
| 413 kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2, nullptr); | 465 kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2, nullptr); |
| 414 ASSERT_TRUE(mixer3); | 466 ASSERT_TRUE(mixer3); |
| 415 EXPECT_EQ(1, mixer_count()); | 467 EXPECT_EQ(1, mixer_count()); |
| 416 EXPECT_EQ(mixer1, mixer3); | 468 EXPECT_EQ(mixer1, mixer3); |
| 417 | 469 |
| 418 media::AudioRendererMixer* mixer4 = GetMixer( | 470 media::AudioRendererMixer* mixer4 = GetMixer( |
| 419 kRenderFrameId, params, std::string(), kSecurityOrigin2, nullptr); | 471 kRenderFrameId, params, std::string(), kSecurityOrigin2, nullptr); |
| 420 ASSERT_TRUE(mixer4); | 472 ASSERT_TRUE(mixer4); |
| 421 EXPECT_EQ(1, mixer_count()); | 473 EXPECT_EQ(1, mixer_count()); |
| 422 EXPECT_EQ(mixer1, mixer4); | 474 EXPECT_EQ(mixer1, mixer4); |
| 423 | 475 |
| 424 RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); | 476 ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
| 425 EXPECT_EQ(1, mixer_count()); | 477 EXPECT_EQ(1, mixer_count()); |
| 426 RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin); | 478 ReturnMixer(kRenderFrameId, params, std::string(), kSecurityOrigin); |
| 427 EXPECT_EQ(1, mixer_count()); | 479 EXPECT_EQ(1, mixer_count()); |
| 428 RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2); | 480 ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2); |
| 429 EXPECT_EQ(1, mixer_count()); | 481 EXPECT_EQ(1, mixer_count()); |
| 430 RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2); | 482 ReturnMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2); |
| 431 EXPECT_EQ(0, mixer_count()); | 483 EXPECT_EQ(0, mixer_count()); |
| 432 } | 484 } |
| 433 | 485 |
| 434 // Verify that GetMixer() correctly returns a null mixer and an appropriate | 486 // Verify that GetMixer() correctly returns a null mixer and an appropriate |
| 435 // status code when a nonexistent device is requested. | 487 // status code when a nonexistent device is requested. |
| 436 TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) { | 488 TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) { |
| 437 EXPECT_EQ(0, mixer_count()); | 489 EXPECT_EQ(0, mixer_count()); |
| 490 |
| 491 // Mixer manager should release a not-ok sink when failing to create a mixer. |
| 492 EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_no_device_.get())).Times(1); |
| 493 |
| 438 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, | 494 media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| 439 kChannelLayout, kSampleRate, kBitsPerChannel, | 495 kChannelLayout, kSampleRate, kBitsPerChannel, |
| 440 kBufferSize); | 496 kBufferSize); |
| 441 media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK; | 497 media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK; |
| 442 EXPECT_CALL(*mock_sink_no_device_.get(), Stop()); | 498 |
| 443 media::AudioRendererMixer* mixer = | 499 media::AudioRendererMixer* mixer = |
| 444 GetMixer(kRenderFrameId, params, kNonexistentDeviceId, kSecurityOrigin, | 500 GetMixer(kRenderFrameId, params, kNonexistentDeviceId, kSecurityOrigin, |
| 445 &device_status); | 501 &device_status); |
| 502 |
| 446 EXPECT_FALSE(mixer); | 503 EXPECT_FALSE(mixer); |
| 447 EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status); | 504 EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status); |
| 448 EXPECT_EQ(0, mixer_count()); | 505 EXPECT_EQ(0, mixer_count()); |
| 449 } | 506 } |
| 450 | 507 |
| 451 } // namespace content | 508 } // namespace content |
| OLD | NEW |