Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(493)

Side by Side Diff: content/renderer/media/audio_renderer_impl_unittest.cc

Issue 8785008: Simplify AudioRendererImpl by using AudioDevice. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes based on latest round of comments Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/renderer/media/audio_renderer_impl.cc ('k') | media/filters/audio_renderer_base.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/message_loop.h" 6 #include "base/message_loop.h"
7 #include "base/process_util.h" 7 #include "base/process_util.h"
8 #include "base/synchronization/waitable_event.h" 8 #include "base/synchronization/waitable_event.h"
9 #include "base/test/test_timeouts.h" 9 #include "base/test/test_timeouts.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "content/common/child_process.h" 11 #include "content/common/child_process.h"
12 #include "content/common/child_thread.h" 12 #include "content/common/child_thread.h"
13 #include "content/common/media/audio_messages.h"
14 #include "content/renderer/media/audio_renderer_impl.h" 13 #include "content/renderer/media/audio_renderer_impl.h"
15 #include "content/renderer/mock_content_renderer_client.h" 14 #include "content/renderer/mock_content_renderer_client.h"
16 #include "content/renderer/render_process.h" 15 #include "content/renderer/render_process.h"
17 #include "content/renderer/render_thread_impl.h" 16 #include "content/renderer/render_thread_impl.h"
18 #include "ipc/ipc_channel.h" 17 #include "ipc/ipc_channel.h"
19 #include "media/base/data_buffer.h" 18 #include "media/base/data_buffer.h"
20 #include "media/base/mock_callback.h" 19 #include "media/base/mock_callback.h"
21 #include "media/base/mock_filter_host.h" 20 #include "media/base/mock_filter_host.h"
22 #include "media/base/mock_filters.h" 21 #include "media/base/mock_filters.h"
23 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
(...skipping 13 matching lines...) Expand all
37 const gfx::Rect& rect) { return NULL; } 36 const gfx::Rect& rect) { return NULL; }
38 virtual void ReleaseTransportDIB(TransportDIB* memory) {} 37 virtual void ReleaseTransportDIB(TransportDIB* memory) {}
39 virtual bool UseInProcessPlugins() const { return false; } 38 virtual bool UseInProcessPlugins() const { return false; }
40 virtual bool HasInitializedMediaLibrary() const { return false; } 39 virtual bool HasInitializedMediaLibrary() const { return false; }
41 40
42 private: 41 private:
43 DISALLOW_COPY_AND_ASSIGN(MockRenderProcess); 42 DISALLOW_COPY_AND_ASSIGN(MockRenderProcess);
44 }; 43 };
45 } 44 }
46 45
47 // This class defines a set of methods which will be used in combination
48 // with NewRunnableMethod to form tasks which will be posted on the
49 // IO thread. All methods emulate AudioMessageFilter::Delegate calls.
50 class DelegateCaller : public base::RefCountedThreadSafe<DelegateCaller> {
51 public:
52 explicit DelegateCaller(AudioRendererImpl* renderer)
53 : renderer_(renderer) {}
54
55 void OnCreated(base::SharedMemoryHandle handle, uint32 length) {
56 if (renderer_->latency_type() == AudioRendererImpl::kHighLatency) {
57 renderer_->OnCreated(handle, length);
58 } else {
59 renderer_->OnLowLatencyCreated(handle, 0, length);
60 }
61 }
62 void OnStateChanged(AudioStreamState state) {
63 renderer_->OnStateChanged(state);
64 }
65 void OnRequestPacket(AudioBuffersState buffers_state) {
66 renderer_->OnRequestPacket(buffers_state);
67 }
68 void OnVolume(double volume) {
69 renderer_->OnVolume(volume);
70 }
71 void DestroyCurrentMessageLoop() {
72 renderer_->WillDestroyCurrentMessageLoop();
73 }
74 private:
75 friend class base::RefCountedThreadSafe<DelegateCaller>;
76 virtual ~DelegateCaller() {}
77
78 scoped_refptr<AudioRendererImpl> renderer_;
79 DISALLOW_COPY_AND_ASSIGN(DelegateCaller);
80 };
81
82 // This task can be posted on the IO thread and will signal an event when 46 // This task can be posted on the IO thread and will signal an event when
83 // done. The caller can then wait for this signal to ensure that no 47 // done. The caller can then wait for this signal to ensure that no
84 // additional tasks remain in the task queue. 48 // additional tasks remain in the task queue.
85 class WaitTask : public Task { 49 class WaitTask : public Task {
86 public: 50 public:
87 explicit WaitTask(base::WaitableEvent* event) 51 explicit WaitTask(base::WaitableEvent* event)
88 : event_(event) {} 52 : event_(event) {}
89 virtual ~WaitTask() {} 53 virtual ~WaitTask() {}
90 virtual void Run() { 54 virtual void Run() {
91 event_->Signal(); 55 event_->Signal();
92 } 56 }
93 57
94 private: 58 private:
95 base::WaitableEvent* event_; 59 base::WaitableEvent* event_;
96 DISALLOW_COPY_AND_ASSIGN(WaitTask); 60 DISALLOW_COPY_AND_ASSIGN(WaitTask);
97 }; 61 };
98 62
99 // Class we would be testing. The only difference between it and "real" one 63 // Class we would be testing.
100 // is that test class does not open sockets and launch audio thread.
101 class TestAudioRendererImpl : public AudioRendererImpl { 64 class TestAudioRendererImpl : public AudioRendererImpl {
102 public: 65 public:
103 explicit TestAudioRendererImpl() 66 explicit TestAudioRendererImpl()
104 : AudioRendererImpl() { 67 : AudioRendererImpl() {
105 } 68 }
106 private:
107 virtual void CreateSocket(base::SyncSocket::Handle socket_handle) {}
108 virtual void CreateAudioThread() {}
109 }; 69 };
110 70
111 class AudioRendererImplTest 71 class AudioRendererImplTest
112 : public ::testing::Test, 72 : public ::testing::Test,
113 public IPC::Channel::Listener { 73 public IPC::Channel::Listener {
114 public: 74 public:
115 static void SetUpTestCase() { 75 static void SetUpTestCase() {}
acolwell GONE FROM CHROMIUM 2011/12/07 17:13:22 Can we remove this since it's empty?
vrk (LEFT CHROMIUM) 2011/12/09 00:16:15 Done.
116 // Set low latency mode, as it soon would be on by default.
117 if (AudioRendererImpl::latency_type() ==
118 AudioRendererImpl::kUninitializedLatency) {
119 AudioRendererImpl::set_latency_type(AudioRendererImpl::kLowLatency);
120 }
121 DCHECK_EQ(AudioRendererImpl::kLowLatency,
122 AudioRendererImpl::latency_type());
123 }
124 76
125 // IPC::Channel::Listener implementation. 77 // IPC::Channel::Listener implementation.
126 virtual bool OnMessageReceived(const IPC::Message& message) { 78 virtual bool OnMessageReceived(const IPC::Message& message) {
127 NOTIMPLEMENTED(); 79 NOTIMPLEMENTED();
128 return true; 80 return true;
129 } 81 }
130 82
131 static const int kSize; 83 static const int kSize;
132 84
133 AudioRendererImplTest() {} 85 AudioRendererImplTest() {}
134 virtual ~AudioRendererImplTest() {} 86 virtual ~AudioRendererImplTest() {}
135 87
136 virtual void SetUp() { 88 virtual void SetUp() {
137 // This part sets up a RenderThread environment to ensure that 89 // This part sets up a RenderThread environment to ensure that
138 // RenderThread::current() (<=> TLS pointer) is valid. 90 // RenderThread::current() (<=> TLS pointer) is valid.
139 // Main parts are inspired by the RenderViewFakeResourcesTest. 91 // Main parts are inspired by the RenderViewFakeResourcesTest.
140 // Note that, the IPC part is not utilized in this test. 92 // Note that, the IPC part is not utilized in this test.
141 content::GetContentClient()->set_renderer(&mock_content_renderer_client_); 93 content::GetContentClient()->set_renderer(&mock_content_renderer_client_);
142 94
143 static const char kThreadName[] = "RenderThread"; 95 static const char kThreadName[] = "RenderThread";
144 channel_.reset(new IPC::Channel(kThreadName, 96 channel_.reset(new IPC::Channel(kThreadName,
145 IPC::Channel::MODE_SERVER, this)); 97 IPC::Channel::MODE_SERVER, this));
146 ASSERT_TRUE(channel_->Connect()); 98 ASSERT_TRUE(channel_->Connect());
147 99
148 mock_process_.reset(new MockRenderProcess); 100 mock_process_.reset(new MockRenderProcess);
149 render_thread_ = new RenderThreadImpl(kThreadName); 101 render_thread_ = new RenderThreadImpl(kThreadName);
150 mock_process_->set_main_thread(render_thread_); 102 mock_process_->set_main_thread(render_thread_);
151 103
152 // Create temporary shared memory.
153 CHECK(shared_mem_.CreateAnonymous(kSize));
154
155 // Setup expectations for initialization. 104 // Setup expectations for initialization.
156 decoder_ = new media::MockAudioDecoder(); 105 decoder_ = new media::MockAudioDecoder();
157 106
158 EXPECT_CALL(*decoder_, bits_per_channel()) 107 EXPECT_CALL(*decoder_, bits_per_channel())
159 .WillRepeatedly(Return(16)); 108 .WillRepeatedly(Return(16));
160 EXPECT_CALL(*decoder_, channel_layout()) 109 EXPECT_CALL(*decoder_, channel_layout())
161 .WillRepeatedly(Return(CHANNEL_LAYOUT_MONO)); 110 .WillRepeatedly(Return(CHANNEL_LAYOUT_MONO));
162 EXPECT_CALL(*decoder_, samples_per_second()) 111 EXPECT_CALL(*decoder_, samples_per_second())
163 .WillRepeatedly(Return(44100)); 112 .WillRepeatedly(Return(44100));
164 113
165 // Create and initialize the audio renderer. 114 // Create and initialize the audio renderer.
166 renderer_ = new TestAudioRendererImpl(); 115 renderer_ = new TestAudioRendererImpl();
167 renderer_->set_host(&host_);
168 renderer_->Initialize(decoder_, media::NewExpectedClosure(), 116 renderer_->Initialize(decoder_, media::NewExpectedClosure(),
169 NewUnderflowClosure()); 117 NewUnderflowClosure());
170 118
171 // Wraps delegate calls into tasks.
172 delegate_caller_ = new DelegateCaller(renderer_);
173
174 // We need an event to verify that all tasks are done before leaving 119 // We need an event to verify that all tasks are done before leaving
175 // our tests. 120 // our tests.
176 event_.reset(new base::WaitableEvent(false, false)); 121 event_.reset(new base::WaitableEvent(false, false));
177
178 // Duplicate the shared memory handle so both the test and the callee can
179 // close their copy.
180 base::SharedMemoryHandle duplicated_handle;
181 EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(),
182 &duplicated_handle));
183
184 // Set things up and ensure that the call comes from the IO thread
185 // as all AudioMessageFilter::Delegate methods.
186 ChildProcess::current()->io_message_loop()->PostTask(
187 FROM_HERE,
188 base::Bind(&DelegateCaller::OnCreated, delegate_caller_.get(),
189 duplicated_handle, kSize));
190 WaitForIOThreadCompletion();
191 } 122 }
192 123
193 virtual void TearDown() { 124 virtual void TearDown() {
194 mock_process_.reset(); 125 mock_process_.reset();
195 } 126 }
196 127
197 MOCK_METHOD0(OnUnderflow, void()); 128 MOCK_METHOD0(OnUnderflow, void());
198 129
199 base::Closure NewUnderflowClosure() { 130 base::Closure NewUnderflowClosure() {
200 return base::Bind(&AudioRendererImplTest::OnUnderflow, 131 return base::Bind(&AudioRendererImplTest::OnUnderflow,
201 base::Unretained(this)); 132 base::Unretained(this));
202 } 133 }
203 134
204 protected: 135 protected:
205 // Posts a final task to the IO message loop and waits for completion. 136 // Posts a final task to the IO message loop and waits for completion.
206 void WaitForIOThreadCompletion() { 137 void WaitForIOThreadCompletion() {
207 ChildProcess::current()->io_message_loop()->PostTask( 138 ChildProcess::current()->io_message_loop()->PostTask(
208 FROM_HERE, new WaitTask(event_.get())); 139 FROM_HERE, new WaitTask(event_.get()));
209 EXPECT_TRUE(event_->TimedWait( 140 EXPECT_TRUE(event_->TimedWait(
210 base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms()))); 141 base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms())));
211 } 142 }
212 143
213 MessageLoopForIO message_loop_; 144 MessageLoopForIO message_loop_;
214 content::MockContentRendererClient mock_content_renderer_client_; 145 content::MockContentRendererClient mock_content_renderer_client_;
215 scoped_ptr<IPC::Channel> channel_; 146 scoped_ptr<IPC::Channel> channel_;
216 RenderThreadImpl* render_thread_; // owned by mock_process_ 147 RenderThreadImpl* render_thread_; // owned by mock_process_
217 scoped_ptr<MockRenderProcess> mock_process_; 148 scoped_ptr<MockRenderProcess> mock_process_;
218 base::SharedMemory shared_mem_;
219 media::MockFilterHost host_;
220 scoped_refptr<media::MockAudioDecoder> decoder_; 149 scoped_refptr<media::MockAudioDecoder> decoder_;
221 scoped_refptr<AudioRendererImpl> renderer_; 150 scoped_refptr<AudioRendererImpl> renderer_;
222 scoped_ptr<base::WaitableEvent> event_; 151 scoped_ptr<base::WaitableEvent> event_;
223 scoped_refptr<DelegateCaller> delegate_caller_;
224 152
225 private: 153 private:
226 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); 154 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
227 }; 155 };
228 156
229 const int AudioRendererImplTest::kSize = 1024; 157 const int AudioRendererImplTest::kSize = 1024;
230 158
231 TEST_F(AudioRendererImplTest, SetPlaybackRate) { 159 TEST_F(AudioRendererImplTest, SetPlaybackRate) {
232 // Execute SetPlaybackRate() codepath by toggling play/pause. 160 // Execute SetPlaybackRate() codepath by toggling play/pause.
233 // These methods will be called on the pipeline thread but calling from 161 // These methods will be called on the pipeline thread but calling from
(...skipping 15 matching lines...) Expand all
249 177
250 renderer_->Stop(media::NewExpectedClosure()); 178 renderer_->Stop(media::NewExpectedClosure());
251 WaitForIOThreadCompletion(); 179 WaitForIOThreadCompletion();
252 } 180 }
253 181
254 TEST_F(AudioRendererImplTest, Stop) { 182 TEST_F(AudioRendererImplTest, Stop) {
255 // Execute Stop() codepath. 183 // Execute Stop() codepath.
256 // Tasks will be posted internally on the IO thread. 184 // Tasks will be posted internally on the IO thread.
257 renderer_->Stop(media::NewExpectedClosure()); 185 renderer_->Stop(media::NewExpectedClosure());
258 186
259 // Run AudioMessageFilter::Delegate methods, which can be executed after being
260 // stopped. AudioRendererImpl shouldn't create any messages in this state.
261 // All delegate method calls are posted on the IO thread since it is
262 // a requirement.
263 if (renderer_->latency_type() == AudioRendererImpl::kHighLatency) {
264 ChildProcess::current()->io_message_loop()->PostTask(
265 FROM_HERE,
266 base::Bind(&DelegateCaller::OnRequestPacket,
267 delegate_caller_.get(), AudioBuffersState(kSize, 0)));
268 }
269 ChildProcess::current()->io_message_loop()->PostTask(
270 FROM_HERE,
271 base::Bind(&DelegateCaller::OnStateChanged,
272 delegate_caller_.get(), kAudioStreamError));
273 ChildProcess::current()->io_message_loop()->PostTask(
274 FROM_HERE,
275 base::Bind(&DelegateCaller::OnStateChanged,
276 delegate_caller_.get(), kAudioStreamPlaying));
277 ChildProcess::current()->io_message_loop()->PostTask(
278 FROM_HERE,
279 base::Bind(&DelegateCaller::OnStateChanged,
280 delegate_caller_.get(), kAudioStreamPaused));
281 ChildProcess::current()->io_message_loop()->PostTask(
282 FROM_HERE,
283 base::Bind(&DelegateCaller::OnCreated,
284 delegate_caller_.get(), shared_mem_.handle(), kSize));
285 ChildProcess::current()->io_message_loop()->PostTask(
286 FROM_HERE,
287 base::Bind(&DelegateCaller::OnVolume,
288 delegate_caller_.get(), 0.5));
289
290 WaitForIOThreadCompletion(); 187 WaitForIOThreadCompletion();
291 188
292 // It's possible that the upstream decoder replies right after being stopped. 189 // It's possible that the upstream decoder replies right after being stopped.
293 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); 190 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
294 renderer_->ConsumeAudioSamples(buffer); 191 renderer_->ConsumeAudioSamples(buffer);
295 } 192 }
296 193
297 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) {
298 // Emulate "killing the message loop" and verify that SetPlaybackRate()
299 // still works.
300 ChildProcess::current()->io_message_loop()->PostTask(
301 FROM_HERE,
302 base::Bind(&DelegateCaller::DestroyCurrentMessageLoop,
303 delegate_caller_.get()));
304 WaitForIOThreadCompletion();
305
306 // No tasks will be posted on the IO thread here since we are in
307 // a "stopped" state.
308 renderer_->SetPlaybackRate(0.0f);
309 renderer_->SetPlaybackRate(1.0f);
310 renderer_->SetPlaybackRate(0.0f);
311 renderer_->Stop(media::NewExpectedClosure());
312 }
313
314 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) {
315 // Emulate "killing the message loop" and verify that SetVolume()
316 // still works.
317 ChildProcess::current()->io_message_loop()->PostTask(
318 FROM_HERE,
319 base::Bind(&DelegateCaller::DestroyCurrentMessageLoop,
320 delegate_caller_.get()));
321 WaitForIOThreadCompletion();
322
323 // No tasks will be posted on the IO thread here since we are in
324 // a "stopped" state.
325 renderer_->SetVolume(0.5f);
326 renderer_->Stop(media::NewExpectedClosure());
327 }
328
329 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_ConsumeAudioSamples) {
330 // Emulate "killing the message loop" and verify that OnReadComplete()
331 // still works.
332 ChildProcess::current()->io_message_loop()->PostTask(
333 FROM_HERE,
334 base::Bind(&DelegateCaller::DestroyCurrentMessageLoop,
335 delegate_caller_.get()));
336 WaitForIOThreadCompletion();
337
338 // No tasks will be posted on the IO thread here since we are in
339 // a "stopped" state.
340 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
341 renderer_->ConsumeAudioSamples(buffer);
342 renderer_->Stop(media::NewExpectedClosure());
343 }
344
345 TEST_F(AudioRendererImplTest, UpdateEarliestEndTime) { 194 TEST_F(AudioRendererImplTest, UpdateEarliestEndTime) {
346 renderer_->SetPlaybackRate(1.0f); 195 renderer_->SetPlaybackRate(1.0f);
347 WaitForIOThreadCompletion(); 196 WaitForIOThreadCompletion();
348 base::Time time_now = base::Time(); // Null time by default. 197 base::Time time_now = base::Time(); // Null time by default.
349 renderer_->set_earliest_end_time(time_now); 198 renderer_->set_earliest_end_time(time_now);
350 renderer_->UpdateEarliestEndTime(renderer_->bytes_per_second(), 199 renderer_->UpdateEarliestEndTime(renderer_->bytes_per_second(),
351 base::TimeDelta::FromMilliseconds(100), 200 base::TimeDelta::FromMilliseconds(100),
352 time_now); 201 time_now);
353 int time_delta = (renderer_->earliest_end_time() - time_now).InMilliseconds(); 202 int time_delta = (renderer_->earliest_end_time() - time_now).InMilliseconds();
354 EXPECT_EQ(1100, time_delta); 203 EXPECT_EQ(1100, time_delta);
355 renderer_->Stop(media::NewExpectedClosure()); 204 renderer_->Stop(media::NewExpectedClosure());
356 WaitForIOThreadCompletion(); 205 WaitForIOThreadCompletion();
357 } 206 }
OLDNEW
« no previous file with comments | « content/renderer/media/audio_renderer_impl.cc ('k') | media/filters/audio_renderer_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698