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

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: Update stale comment 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() {
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
125 // IPC::Channel::Listener implementation. 75 // IPC::Channel::Listener implementation.
126 virtual bool OnMessageReceived(const IPC::Message& message) { 76 virtual bool OnMessageReceived(const IPC::Message& message) {
127 NOTIMPLEMENTED(); 77 NOTIMPLEMENTED();
128 return true; 78 return true;
129 } 79 }
130 80
131 static const int kSize; 81 static const int kSize;
132 82
133 AudioRendererImplTest() {} 83 AudioRendererImplTest() {}
134 virtual ~AudioRendererImplTest() {} 84 virtual ~AudioRendererImplTest() {}
135 85
136 virtual void SetUp() { 86 virtual void SetUp() {
137 // This part sets up a RenderThread environment to ensure that 87 // This part sets up a RenderThread environment to ensure that
138 // RenderThread::current() (<=> TLS pointer) is valid. 88 // RenderThread::current() (<=> TLS pointer) is valid.
139 // Main parts are inspired by the RenderViewFakeResourcesTest. 89 // Main parts are inspired by the RenderViewFakeResourcesTest.
140 // Note that, the IPC part is not utilized in this test. 90 // Note that, the IPC part is not utilized in this test.
141 content::GetContentClient()->set_renderer(&mock_content_renderer_client_); 91 content::GetContentClient()->set_renderer(&mock_content_renderer_client_);
142 92
143 static const char kThreadName[] = "RenderThread"; 93 static const char kThreadName[] = "RenderThread";
144 channel_.reset(new IPC::Channel(kThreadName, 94 channel_.reset(new IPC::Channel(kThreadName,
145 IPC::Channel::MODE_SERVER, this)); 95 IPC::Channel::MODE_SERVER, this));
146 ASSERT_TRUE(channel_->Connect()); 96 ASSERT_TRUE(channel_->Connect());
147 97
148 mock_process_.reset(new MockRenderProcess); 98 mock_process_.reset(new MockRenderProcess);
149 render_thread_ = new RenderThreadImpl(kThreadName); 99 render_thread_ = new RenderThreadImpl(kThreadName);
150 mock_process_->set_main_thread(render_thread_); 100 mock_process_->set_main_thread(render_thread_);
151 101
152 // Create temporary shared memory.
153 CHECK(shared_mem_.CreateAnonymous(kSize));
154
155 // Setup expectations for initialization. 102 // Setup expectations for initialization.
156 decoder_ = new media::MockAudioDecoder(); 103 decoder_ = new media::MockAudioDecoder();
157 104
158 EXPECT_CALL(*decoder_, bits_per_channel()) 105 EXPECT_CALL(*decoder_, bits_per_channel())
159 .WillRepeatedly(Return(16)); 106 .WillRepeatedly(Return(16));
160 EXPECT_CALL(*decoder_, channel_layout()) 107 EXPECT_CALL(*decoder_, channel_layout())
161 .WillRepeatedly(Return(CHANNEL_LAYOUT_MONO)); 108 .WillRepeatedly(Return(CHANNEL_LAYOUT_MONO));
162 EXPECT_CALL(*decoder_, samples_per_second()) 109 EXPECT_CALL(*decoder_, samples_per_second())
163 .WillRepeatedly(Return(44100)); 110 .WillRepeatedly(Return(44100));
164 111
165 // Create and initialize the audio renderer. 112 // Create and initialize the audio renderer.
166 renderer_ = new TestAudioRendererImpl(); 113 renderer_ = new TestAudioRendererImpl();
167 renderer_->set_host(&host_);
168 renderer_->Initialize(decoder_, media::NewExpectedClosure(), 114 renderer_->Initialize(decoder_, media::NewExpectedClosure(),
169 NewUnderflowClosure()); 115 NewUnderflowClosure());
170 116
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 117 // We need an event to verify that all tasks are done before leaving
175 // our tests. 118 // our tests.
176 event_.reset(new base::WaitableEvent(false, false)); 119 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 } 120 }
192 121
193 virtual void TearDown() { 122 virtual void TearDown() {
194 mock_process_.reset(); 123 mock_process_.reset();
195 } 124 }
196 125
197 MOCK_METHOD0(OnUnderflow, void()); 126 MOCK_METHOD0(OnUnderflow, void());
198 127
199 base::Closure NewUnderflowClosure() { 128 base::Closure NewUnderflowClosure() {
200 return base::Bind(&AudioRendererImplTest::OnUnderflow, 129 return base::Bind(&AudioRendererImplTest::OnUnderflow,
201 base::Unretained(this)); 130 base::Unretained(this));
202 } 131 }
203 132
204 protected: 133 protected:
205 // Posts a final task to the IO message loop and waits for completion. 134 // Posts a final task to the IO message loop and waits for completion.
206 void WaitForIOThreadCompletion() { 135 void WaitForIOThreadCompletion() {
207 ChildProcess::current()->io_message_loop()->PostTask( 136 ChildProcess::current()->io_message_loop()->PostTask(
208 FROM_HERE, new WaitTask(event_.get())); 137 FROM_HERE, new WaitTask(event_.get()));
209 EXPECT_TRUE(event_->TimedWait( 138 EXPECT_TRUE(event_->TimedWait(
210 base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms()))); 139 base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms())));
211 } 140 }
212 141
213 MessageLoopForIO message_loop_; 142 MessageLoopForIO message_loop_;
214 content::MockContentRendererClient mock_content_renderer_client_; 143 content::MockContentRendererClient mock_content_renderer_client_;
215 scoped_ptr<IPC::Channel> channel_; 144 scoped_ptr<IPC::Channel> channel_;
216 RenderThreadImpl* render_thread_; // owned by mock_process_ 145 RenderThreadImpl* render_thread_; // owned by mock_process_
217 scoped_ptr<MockRenderProcess> mock_process_; 146 scoped_ptr<MockRenderProcess> mock_process_;
218 base::SharedMemory shared_mem_;
219 media::MockFilterHost host_;
220 scoped_refptr<media::MockAudioDecoder> decoder_; 147 scoped_refptr<media::MockAudioDecoder> decoder_;
221 scoped_refptr<AudioRendererImpl> renderer_; 148 scoped_refptr<AudioRendererImpl> renderer_;
222 scoped_ptr<base::WaitableEvent> event_; 149 scoped_ptr<base::WaitableEvent> event_;
223 scoped_refptr<DelegateCaller> delegate_caller_;
224 150
225 private: 151 private:
226 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); 152 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
227 }; 153 };
228 154
229 const int AudioRendererImplTest::kSize = 1024; 155 const int AudioRendererImplTest::kSize = 1024;
230 156
231 TEST_F(AudioRendererImplTest, SetPlaybackRate) { 157 TEST_F(AudioRendererImplTest, SetPlaybackRate) {
232 // Execute SetPlaybackRate() codepath by toggling play/pause. 158 // Execute SetPlaybackRate() codepath by toggling play/pause.
233 // These methods will be called on the pipeline thread but calling from 159 // These methods will be called on the pipeline thread but calling from
(...skipping 15 matching lines...) Expand all
249 175
250 renderer_->Stop(media::NewExpectedClosure()); 176 renderer_->Stop(media::NewExpectedClosure());
251 WaitForIOThreadCompletion(); 177 WaitForIOThreadCompletion();
252 } 178 }
253 179
254 TEST_F(AudioRendererImplTest, Stop) { 180 TEST_F(AudioRendererImplTest, Stop) {
255 // Execute Stop() codepath. 181 // Execute Stop() codepath.
256 // Tasks will be posted internally on the IO thread. 182 // Tasks will be posted internally on the IO thread.
257 renderer_->Stop(media::NewExpectedClosure()); 183 renderer_->Stop(media::NewExpectedClosure());
258 184
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(); 185 WaitForIOThreadCompletion();
291 186
292 // It's possible that the upstream decoder replies right after being stopped. 187 // It's possible that the upstream decoder replies right after being stopped.
293 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); 188 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
294 renderer_->ConsumeAudioSamples(buffer); 189 renderer_->ConsumeAudioSamples(buffer);
295 } 190 }
296 191
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) { 192 TEST_F(AudioRendererImplTest, UpdateEarliestEndTime) {
346 renderer_->SetPlaybackRate(1.0f); 193 renderer_->SetPlaybackRate(1.0f);
347 WaitForIOThreadCompletion(); 194 WaitForIOThreadCompletion();
348 base::Time time_now = base::Time(); // Null time by default. 195 base::Time time_now = base::Time(); // Null time by default.
349 renderer_->set_earliest_end_time(time_now); 196 renderer_->set_earliest_end_time(time_now);
350 renderer_->UpdateEarliestEndTime(renderer_->bytes_per_second(), 197 renderer_->UpdateEarliestEndTime(renderer_->bytes_per_second(),
351 base::TimeDelta::FromMilliseconds(100), 198 base::TimeDelta::FromMilliseconds(100),
352 time_now); 199 time_now);
353 int time_delta = (renderer_->earliest_end_time() - time_now).InMilliseconds(); 200 int time_delta = (renderer_->earliest_end_time() - time_now).InMilliseconds();
354 EXPECT_EQ(1100, time_delta); 201 EXPECT_EQ(1100, time_delta);
355 renderer_->Stop(media::NewExpectedClosure()); 202 renderer_->Stop(media::NewExpectedClosure());
356 WaitForIOThreadCompletion(); 203 WaitForIOThreadCompletion();
357 } 204 }
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