Index: content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
diff --git a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
index e3eb3b3718fd765a7fe53b509066cf3432764467..bfe5c6c8a624451bb0cd05107ab17fea84fc0dfe 100644 |
--- a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
+++ b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
@@ -6,12 +6,12 @@ |
#include <memory> |
+#include "base/bind.h" |
#include "base/logging.h" |
#include "base/macros.h" |
#include "base/memory/ref_counted.h" |
-#include "content/renderer/media/audio_device_factory.h" |
+#include "content/renderer/media/audio_renderer_sink_cache.h" |
#include "media/audio/audio_device_description.h" |
-#include "media/base/audio_capturer_source.h" |
#include "media/base/audio_parameters.h" |
#include "media/base/audio_renderer_mixer.h" |
#include "media/base/audio_renderer_mixer_input.h" |
@@ -23,6 +23,7 @@ |
namespace content { |
+namespace { |
static const int kBitsPerChannel = 16; |
static const int kSampleRate = 48000; |
static const int kBufferSize = 8192; |
@@ -37,14 +38,63 @@ static const char kNonexistentDeviceId[] = "nonexistent-device-id"; |
static const int kRenderFrameId = 124; |
static const int kAnotherRenderFrameId = 678; |
+} // namespace; |
using media::AudioParameters; |
-class AudioRendererMixerManagerTest : public testing::Test, |
- public AudioDeviceFactory { |
+class FakeAudioRendererSinkCache : public AudioRendererSinkCache { |
+ public: |
+ using GetSinkCallback = |
+ base::Callback<scoped_refptr<media::AudioRendererSink>( |
+ int render_frame_id, |
+ int session_id, |
+ const std::string& device_id, |
+ const url::Origin& security_origin)>; |
+ |
+ using ReleaseSinkCallback = |
+ base::Callback<void(const media::AudioRendererSink*)>; |
+ |
+ FakeAudioRendererSinkCache(const GetSinkCallback& get_sink_cb, |
+ const ReleaseSinkCallback& release_sink_cb) |
+ : get_sink_cb_(get_sink_cb), release_sink_cb_(release_sink_cb) {} |
+ |
+ media::OutputDeviceInfo GetSinkInfo( |
+ int source_render_frame_id, |
+ int session_id, |
+ const std::string& device_id, |
+ const url::Origin& security_origin) final { |
+ return get_sink_cb_ |
+ .Run(source_render_frame_id, session_id, device_id, security_origin) |
+ ->GetOutputDeviceInfo(); |
+ } |
+ |
+ scoped_refptr<media::AudioRendererSink> GetSink( |
+ int source_render_frame_id, |
+ const std::string& device_id, |
+ const url::Origin& security_origin) final { |
+ return get_sink_cb_.Run(source_render_frame_id, 0, device_id, |
+ security_origin); |
+ } |
+ |
+ void ReleaseSink(const media::AudioRendererSink* sink) final { |
+ release_sink_cb_.Run(sink); |
+ } |
+ |
+ private: |
+ GetSinkCallback get_sink_cb_; |
+ ReleaseSinkCallback release_sink_cb_; |
+}; |
+ |
+class AudioRendererMixerManagerTest : public testing::Test { |
public: |
AudioRendererMixerManagerTest() |
- : manager_(new AudioRendererMixerManager()), |
+ : manager_(new AudioRendererMixerManager( |
+ std::unique_ptr<AudioRendererSinkCache>( |
+ new FakeAudioRendererSinkCache( |
+ base::Bind(&AudioRendererMixerManagerTest::GetSinkPtr, |
+ base::Unretained(this)), |
+ base::Bind(&AudioRendererMixerManagerTest::ReleaseSinkPtr, |
+ base::Unretained(this)))))), |
mock_sink_(new media::MockAudioRendererSink()), |
mock_sink_no_device_(new media::MockAudioRendererSink( |
kNonexistentDeviceId, |
@@ -52,9 +102,6 @@ class AudioRendererMixerManagerTest : public testing::Test, |
mock_sink_matched_device_( |
new media::MockAudioRendererSink(kMatchedDeviceId, |
media::OUTPUT_DEVICE_STATUS_OK)), |
- mock_sink_for_session_id_( |
- new media::MockAudioRendererSink(kMatchedDeviceId, |
- media::OUTPUT_DEVICE_STATUS_OK)), |
kSecurityOrigin2(GURL("http://localhost")) {} |
media::AudioRendererMixer* GetMixer( |
@@ -67,11 +114,11 @@ class AudioRendererMixerManagerTest : public testing::Test, |
security_origin, device_status); |
} |
- void RemoveMixer(int source_render_frame_id, |
+ void ReturnMixer(int source_render_frame_id, |
const media::AudioParameters& params, |
const std::string& device_id, |
const url::Origin& security_origin) { |
- return manager_->RemoveMixer(source_render_frame_id, params, device_id, |
+ return manager_->ReturnMixer(source_render_frame_id, params, device_id, |
security_origin); |
} |
@@ -81,24 +128,8 @@ class AudioRendererMixerManagerTest : public testing::Test, |
} |
protected: |
- MOCK_METHOD1(CreateAudioCapturerSource, |
- scoped_refptr<media::AudioCapturerSource>(int)); |
- MOCK_METHOD5( |
- CreateSwitchableAudioRendererSink, |
- scoped_refptr<media::SwitchableAudioRendererSink>(SourceType, |
- int, |
- int, |
- const std::string&, |
- const url::Origin&)); |
- MOCK_METHOD5(CreateAudioRendererSink, |
- scoped_refptr<media::AudioRendererSink>(SourceType, |
- int, |
- int, |
- const std::string&, |
- const url::Origin&)); |
- |
- scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink( |
- int render_frame_id, |
+ scoped_refptr<media::AudioRendererSink> GetSinkPtr( |
+ int source_render_frame_id, |
int session_id, |
const std::string& device_id, |
const url::Origin& security_origin) { |
@@ -110,7 +141,7 @@ class AudioRendererMixerManagerTest : public testing::Test, |
return mock_sink_no_device_; |
if (device_id.empty()) { |
// The sink used to get device ID from session ID if it's not empty |
- return session_id ? mock_sink_for_session_id_ : mock_sink_; |
+ return session_id ? mock_sink_matched_device_ : mock_sink_; |
} |
if (device_id == kMatchedDeviceId) |
return mock_sink_matched_device_; |
@@ -119,11 +150,13 @@ class AudioRendererMixerManagerTest : public testing::Test, |
return nullptr; |
} |
+ MOCK_METHOD1(ReleaseSinkPtr, void(const media::AudioRendererSink*)); |
+ |
std::unique_ptr<AudioRendererMixerManager> manager_; |
+ |
scoped_refptr<media::MockAudioRendererSink> mock_sink_; |
scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_; |
scoped_refptr<media::MockAudioRendererSink> mock_sink_matched_device_; |
- scoped_refptr<media::MockAudioRendererSink> mock_sink_for_session_id_; |
// To avoid global/static non-POD constants. |
const url::Origin kSecurityOrigin; |
@@ -133,14 +166,17 @@ class AudioRendererMixerManagerTest : public testing::Test, |
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest); |
}; |
-// Verify GetMixer() and RemoveMixer() both work as expected; particularly with |
+// Verify GetMixer() and ReturnMixer() both work as expected; particularly with |
// respect to the explicit ref counting done. |
-TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { |
+TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) { |
// Since we're testing two different sets of parameters, we expect |
// AudioRendererMixerManager to call Start and Stop on our mock twice. |
EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
+ // We expect 2 mixers to be created; each of them should release the sink. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
+ |
// There should be no mixers outstanding to start with. |
EXPECT_EQ(0, mixer_count()); |
@@ -158,8 +194,8 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { |
kSecurityOrigin, nullptr)); |
EXPECT_EQ(1, mixer_count()); |
- // Remove the extra mixer we just acquired. |
- RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
+ // Return the extra mixer we just acquired. |
+ ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
media::AudioParameters params2( |
@@ -173,10 +209,10 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { |
// Different parameters should result in a different mixer1. |
EXPECT_NE(mixer1, mixer2); |
- // Remove both outstanding mixers. |
- RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
+ // Return both outstanding mixers. |
+ ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
- RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(0, mixer_count()); |
} |
@@ -187,6 +223,9 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
EXPECT_EQ(mixer_count(), 0); |
+ // We expect 2 mixers to be created; each of them should release the sink. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
+ |
media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR, |
kChannelLayout, |
kSampleRate, |
@@ -207,7 +246,7 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId, |
kSecurityOrigin, nullptr)); |
EXPECT_EQ(1, mixer_count()); |
- RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
// Modify some parameters that do matter: channel layout |
@@ -221,11 +260,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId, |
kSecurityOrigin, nullptr)); |
EXPECT_EQ(2, mixer_count()); |
- RemoveMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
- // Remove final mixer. |
- RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
+ // Return final mixer. |
+ ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(0, mixer_count()); |
} |
@@ -239,6 +278,9 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) { |
EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
+ // We expect 2 mixers to be created; each of them should release the sink. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
+ |
media::AudioParameters params( |
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, |
kBitsPerChannel, kBufferSize); |
@@ -258,7 +300,7 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) { |
EXPECT_EQ(0, mixer_count()); |
// Implicitly test that AudioRendererMixerInput was provided with the expected |
- // callbacks needed to acquire an AudioRendererMixer and remove it. |
+ // callbacks needed to acquire an AudioRendererMixer and return it. |
input->Start(); |
EXPECT_EQ(1, mixer_count()); |
another_input->Start(); |
@@ -287,6 +329,10 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) { |
EXPECT_CALL(*mock_sink_matched_device_.get(), Start()).Times(1); |
EXPECT_CALL(*mock_sink_matched_device_.get(), Stop()).Times(1); |
+ // We expect 3 mixers to be created; each of them should release a sink. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_matched_device_.get())).Times(1); |
+ |
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
kChannelLayout, kSampleRate, kBitsPerChannel, |
kBufferSize); |
@@ -323,7 +369,7 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) { |
EXPECT_EQ(0, mixer_count()); |
// Implicitly test that AudioRendererMixerInput was provided with the expected |
- // callbacks needed to acquire an AudioRendererMixer and remove it. |
+ // callbacks needed to acquire an AudioRendererMixer and return it. |
input_to_default_device->Start(); |
EXPECT_EQ(1, mixer_count()); |
@@ -359,6 +405,9 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) { |
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3); |
EXPECT_EQ(0, mixer_count()); |
+ // We expect 3 mixers to be created; each of them should release a sink. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3); |
+ |
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
kChannelLayout, kSampleRate, kBitsPerChannel, |
kBufferSize); |
@@ -380,11 +429,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) { |
EXPECT_NE(mixer1, mixer3); |
EXPECT_NE(mixer2, mixer3); |
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(2, mixer_count()); |
- RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
- RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2); |
+ ReturnMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2); |
EXPECT_EQ(0, mixer_count()); |
} |
@@ -395,6 +444,9 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1); |
EXPECT_EQ(0, mixer_count()); |
+ // We expect 1 mixers to be created; it should release its sink. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1); |
+ |
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
kChannelLayout, kSampleRate, kBitsPerChannel, |
kBufferSize); |
@@ -421,13 +473,13 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
EXPECT_EQ(1, mixer_count()); |
EXPECT_EQ(mixer1, mixer4); |
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
- RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin); |
+ ReturnMixer(kRenderFrameId, params, std::string(), kSecurityOrigin); |
EXPECT_EQ(1, mixer_count()); |
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2); |
+ ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2); |
EXPECT_EQ(1, mixer_count()); |
- RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2); |
+ ReturnMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2); |
EXPECT_EQ(0, mixer_count()); |
} |
@@ -435,14 +487,19 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
// status code when a nonexistent device is requested. |
TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) { |
EXPECT_EQ(0, mixer_count()); |
+ |
+ // Mixer manager should release a not-ok sink when failing to create a mixer. |
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_no_device_.get())).Times(1); |
+ |
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
kChannelLayout, kSampleRate, kBitsPerChannel, |
kBufferSize); |
media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK; |
- EXPECT_CALL(*mock_sink_no_device_.get(), Stop()); |
+ |
media::AudioRendererMixer* mixer = |
GetMixer(kRenderFrameId, params, kNonexistentDeviceId, kSecurityOrigin, |
&device_status); |
+ |
EXPECT_FALSE(mixer); |
EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status); |
EXPECT_EQ(0, mixer_count()); |