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

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

Issue 7157001: Implements AudioMessageFilter as member in RenderThread (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Added input message filter and audio input device Created 9 years, 5 months 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
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/message_loop.h"
5 #include "base/process_util.h" 6 #include "base/process_util.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/time.h"
6 #include "content/common/media/audio_messages.h" 9 #include "content/common/media/audio_messages.h"
10 #include "chrome/renderer/chrome_content_renderer_client.h"
7 #include "content/renderer/media/audio_renderer_impl.h" 11 #include "content/renderer/media/audio_renderer_impl.h"
12 #include "chrome/renderer/mock_render_process.h"
13 #include "content/renderer/render_thread.h"
14 #include "ipc/ipc_channel.h"
8 #include "media/base/data_buffer.h" 15 #include "media/base/data_buffer.h"
9 #include "media/base/mock_callback.h" 16 #include "media/base/mock_callback.h"
10 #include "media/base/mock_filter_host.h" 17 #include "media/base/mock_filter_host.h"
11 #include "media/base/mock_filters.h" 18 #include "media/base/mock_filters.h"
12 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
13 20
14 using ::testing::Return; 21 using ::testing::Return;
15 22
16 class AudioRendererImplTest : public ::testing::Test { 23 // This class defines a set of methods which will be used in combination
24 // with NewRunnableMethod to form tasks which will be posted on the
25 // IO thread. All methods emulate AudioMessageFilter::Delegate calls.
26 class DelegateCaller: public base::RefCountedThreadSafe<DelegateCaller> {
scherkus (not reviewing) 2011/07/07 21:26:47 nit: space before :
henrika_dont_use 2011/07/08 12:47:58 Done.
17 public: 27 public:
18 static const int kRouteId = 0; 28 explicit DelegateCaller(AudioRendererImpl* renderer)
29 : renderer_(renderer) {}
scherkus (not reviewing) 2011/07/07 21:26:47 indent by two more spaces
henrika_dont_use 2011/07/08 12:47:58 Done.
30
31 void OnCreated(base::SharedMemoryHandle handle, uint32 length) {
32 renderer_->OnCreated(handle, length);
33 }
34 void OnStateChanged(AudioStreamState state) {
35 renderer_->OnStateChanged(state);
36 }
37 void OnRequestPacket(AudioBuffersState buffers_state) {
38 renderer_->OnRequestPacket(buffers_state);
39 }
40 void OnVolume(double volume) {
41 renderer_->OnVolume(volume);
42 }
43 void DestroyCurrentMessageLoop() {
44 renderer_->WillDestroyCurrentMessageLoop();
45 }
46 private:
scherkus (not reviewing) 2011/07/07 21:26:47 nit: add blank line before public/private labels
henrika_dont_use 2011/07/08 12:47:58 Done.
47 friend class base::RefCountedThreadSafe<DelegateCaller>;
48 ~DelegateCaller() {}
scherkus (not reviewing) 2011/07/07 21:26:47 virtual
henrika_dont_use 2011/07/08 12:47:58 Done.
49
50 scoped_refptr<AudioRendererImpl> renderer_;
51 DISALLOW_COPY_AND_ASSIGN(DelegateCaller);
52 };
53
54 // This task can be posted on the IO thread and will signal an event when
55 // done. The caller can then wait for this signal to ensure that no
56 // additional tasks remain in the task queue.
57 class WaitTask : public Task {
58 public:
59 explicit WaitTask(base::WaitableEvent* event)
60 : event_(event) {}
scherkus (not reviewing) 2011/07/07 21:26:47 nit: indent by two more spaces
henrika_dont_use 2011/07/08 12:47:58 Done.
61 virtual ~WaitTask() {}
62 virtual void Run() {
63 event_->Signal();
64 }
65
66 private:
67 base::WaitableEvent* event_;
68 DISALLOW_COPY_AND_ASSIGN(WaitTask);
69 };
70
71 class AudioRendererImplTest : public ::testing::Test,
scherkus (not reviewing) 2011/07/07 21:26:47 use initializer list style (i.e., drop : to next l
henrika_dont_use 2011/07/08 12:47:58 Done.
72 public IPC::Channel::Listener {
73 public:
74 // IPC::Channel::Listener implementation.
75 virtual bool OnMessageReceived(const IPC::Message& message);
76
77 protected:
19 static const int kSize = 1024; 78 static const int kSize = 1024;
79 static const int kMaxWait = 500;
scherkus (not reviewing) 2011/07/07 21:26:47 use base/test/test_timeouts.h instead
henrika_dont_use 2011/07/08 12:47:58 Done.
20 80
21 AudioRendererImplTest() { 81 AudioRendererImplTest() { }
scherkus (not reviewing) 2011/07/07 21:26:47 nit: { } -> {}
henrika_dont_use 2011/07/08 12:47:58 Done.
22 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); 82 virtual ~AudioRendererImplTest() { }
23 83
24 // TODO(scherkus): use gmock with AudioMessageFilter to verify 84 // Test fixture's SetUp.
scherkus (not reviewing) 2011/07/07 21:26:47 nit: comment is useless (SetUp for a test case is
henrika_dont_use 2011/07/08 12:47:58 Done.
25 // AudioRendererImpl calls or doesn't call Send(). 85 virtual void SetUp() {
26 filter_ = new AudioMessageFilter(kRouteId); 86 // This part sets up a RenderThread environment to ensure that
27 filter_->message_loop_ = message_loop_.get(); 87 // RenderThread::current() (<=> TLS pointer) is valid.
88 // Main parts are inspired by the RenderViewFakeResourcesTest.
89 // Note that, the IPC part is not utilized in this test.
90 content::GetContentClient()->set_renderer(&chrome_content_renderer_client_);
91
92 static const char kThreadName[] = "RenderThread";
93 channel_.reset(new IPC::Channel(kThreadName,
94 IPC::Channel::MODE_SERVER, this));
95 ASSERT_TRUE(channel_->Connect());
96
97 mock_process_.reset(new MockRenderProcess);
98 render_thread_ = new RenderThread(kThreadName);
99 mock_process_->set_main_thread(render_thread_);
28 100
29 // Create temporary shared memory. 101 // Create temporary shared memory.
30 CHECK(shared_mem_.CreateAnonymous(kSize)); 102 CHECK(shared_mem_.CreateAnonymous(kSize));
31 103
32 // Setup expectations for initialization. 104 // Setup expectations for initialization.
33 decoder_ = new media::MockAudioDecoder(); 105 decoder_ = new media::MockAudioDecoder();
34 106
35 ON_CALL(*decoder_, config()) 107 ON_CALL(*decoder_, config())
36 .WillByDefault(Return(media::AudioDecoderConfig(16, 108 .WillByDefault(Return(media::AudioDecoderConfig(16,
37 CHANNEL_LAYOUT_MONO, 109 CHANNEL_LAYOUT_MONO,
38 44100))); 110 44100)));
39 111
40 // Create and initialize audio renderer. 112 // Create and initialize the audio renderer.
41 renderer_ = new AudioRendererImpl(filter_); 113 renderer_ = new AudioRendererImpl();
42 renderer_->set_host(&host_); 114 renderer_->set_host(&host_);
43 renderer_->Initialize(decoder_, media::NewExpectedCallback()); 115 renderer_->Initialize(decoder_, media::NewExpectedCallback());
44 116
45 // Run pending tasks and simulate responding with a created audio stream. 117 // Wraps delegate calls into tasks.
46 message_loop_->RunAllPending(); 118 delegate_caller_ = new DelegateCaller(renderer_);
119
120 // We need an event to verify that all tasks are done before leaving
121 // our tests.
122 event_.reset(new base::WaitableEvent(false, false));
47 123
48 // Duplicate the shared memory handle so both the test and the callee can 124 // Duplicate the shared memory handle so both the test and the callee can
49 // close their copy. 125 // close their copy.
50 base::SharedMemoryHandle duplicated_handle; 126 base::SharedMemoryHandle duplicated_handle;
51 EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(), 127 EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(),
52 &duplicated_handle)); 128 &duplicated_handle));
53 129
54 renderer_->OnCreated(duplicated_handle, kSize); 130 // Set things up and ensure that the call comes from the IO thread
131 // as all AudioMessageFilter::Delegate methods. Don't have to wait
132 // here.
133 ChildProcess::current()->io_message_loop()->PostTask(
134 FROM_HERE,
135 NewRunnableMethod(delegate_caller_.get(),
136 &DelegateCaller::OnCreated, duplicated_handle, kSize));
55 } 137 }
56 138
57 virtual ~AudioRendererImplTest() { 139 // Test fixture's TearDown.
scherkus (not reviewing) 2011/07/07 21:26:47 ditto w/ comment
henrika_dont_use 2011/07/08 12:47:58 Done.
140 virtual void TearDown() {
141 mock_process_.reset();
58 } 142 }
59 143
60 protected: 144 // Fixture members
scherkus (not reviewing) 2011/07/07 21:26:47 ditto w/ comment
henrika_dont_use 2011/07/08 12:47:58 Done.
61 // Fixtures. 145 MessageLoopForIO message_loop_;
62 scoped_ptr<MessageLoop> message_loop_; 146 chrome::ChromeContentRendererClient chrome_content_renderer_client_;
63 scoped_refptr<AudioMessageFilter> filter_; 147 scoped_ptr<IPC::Channel> channel_;
148 RenderThread* render_thread_; // owned by mock_process_
149 scoped_ptr<MockRenderProcess> mock_process_;
64 base::SharedMemory shared_mem_; 150 base::SharedMemory shared_mem_;
65 media::MockFilterHost host_; 151 media::MockFilterHost host_;
66 scoped_refptr<media::MockAudioDecoder> decoder_; 152 scoped_refptr<media::MockAudioDecoder> decoder_;
67 scoped_refptr<AudioRendererImpl> renderer_; 153 scoped_refptr<AudioRendererImpl> renderer_;
154 scoped_ptr<base::WaitableEvent> event_;
155 scoped_refptr<DelegateCaller> delegate_caller_;
68 156
69 private: 157 private:
70 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); 158 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
71 }; 159 };
72 160
161 bool AudioRendererImplTest::OnMessageReceived(
scherkus (not reviewing) 2011/07/07 21:26:47 nit: fits on one line also typically we just inli
henrika_dont_use 2011/07/08 12:47:58 Done.
162 const IPC::Message& message) {
163 NOTIMPLEMENTED();
164 return true;
165 }
166
73 TEST_F(AudioRendererImplTest, SetPlaybackRate) { 167 TEST_F(AudioRendererImplTest, SetPlaybackRate) {
74 // Execute SetPlaybackRate() codepath to create an IPC message. 168 // Execute SetPlaybackRate() codepath by toggling play/pause.
75 169 // These methods will be called on the pipeline thread but calling from
76 // Toggle play/pause to generate some IPC messages. 170 // here is fine for this test. Tasks will be posted internally on
171 // the IO thread.
77 renderer_->SetPlaybackRate(0.0f); 172 renderer_->SetPlaybackRate(0.0f);
78 renderer_->SetPlaybackRate(1.0f); 173 renderer_->SetPlaybackRate(1.0f);
79 renderer_->SetPlaybackRate(0.0f); 174 renderer_->SetPlaybackRate(0.0f);
80 175
81 renderer_->Stop(media::NewExpectedCallback()); 176 renderer_->Stop(media::NewExpectedCallback());
82 message_loop_->RunAllPending(); 177
178 // Post a final task to the IO message loop and wait for completion.
179 // When the event is signaled, we know that all posted task in this
180 // test are done.
181 ChildProcess::current()->io_message_loop()->PostTask(
scherkus (not reviewing) 2011/07/07 21:26:47 what about having a PostIOTask() helper function d
henrika_dont_use 2011/07/08 12:47:58 Will fix it in a separate CL.
182 FROM_HERE, new WaitTask(event_.get()));
183 EXPECT_TRUE(event_->TimedWait(base::TimeDelta::FromMilliseconds(kMaxWait)));
83 } 184 }
84 185
85 TEST_F(AudioRendererImplTest, SetVolume) { 186 TEST_F(AudioRendererImplTest, SetVolume) {
86 // Execute SetVolume() codepath to create an IPC message. 187 // Execute SetVolume() codepath.
188 // This method will be called on the pipeline thread IRL.
189 // Tasks will be posted internally on the IO thread.
87 renderer_->SetVolume(0.5f); 190 renderer_->SetVolume(0.5f);
191
88 renderer_->Stop(media::NewExpectedCallback()); 192 renderer_->Stop(media::NewExpectedCallback());
89 message_loop_->RunAllPending(); 193
194 // Post a final task to the IO message loop and wait for completion.
195 ChildProcess::current()->io_message_loop()->PostTask(
scherkus (not reviewing) 2011/07/07 21:26:47 this code is duplicated a lot typically I try to
henrika_dont_use 2011/07/08 12:47:58 Will fix it in a separate CL.
196 FROM_HERE, new WaitTask(event_.get()));
197 EXPECT_TRUE(event_->TimedWait(base::TimeDelta::FromMilliseconds(kMaxWait)));
90 } 198 }
91 199
92 TEST_F(AudioRendererImplTest, Stop) { 200 TEST_F(AudioRendererImplTest, Stop) {
93 // Execute Stop() codepath to create an IPC message. 201 // Execute Stop() codepath.
202 // Tasks will be posted internally on the IO thread.
94 renderer_->Stop(media::NewExpectedCallback()); 203 renderer_->Stop(media::NewExpectedCallback());
95 message_loop_->RunAllPending();
96 204
97 // Run AudioMessageFilter::Delegate methods, which can be executed after being 205 // Run AudioMessageFilter::Delegate methods, which can be executed after being
98 // stopped. AudioRendererImpl shouldn't create any messages. 206 // stopped. AudioRendererImpl shouldn't create any messages in this state.
99 renderer_->OnRequestPacket(AudioBuffersState(kSize, 0)); 207 // All delegate method calls are posted on the IO thread since it is
100 renderer_->OnStateChanged(kAudioStreamError); 208 // a requirement.
101 renderer_->OnStateChanged(kAudioStreamPlaying); 209 ChildProcess::current()->io_message_loop()->PostTask(
102 renderer_->OnStateChanged(kAudioStreamPaused); 210 FROM_HERE,
103 renderer_->OnCreated(shared_mem_.handle(), kSize); 211 NewRunnableMethod(delegate_caller_.get(),
104 renderer_->OnVolume(0.5); 212 &DelegateCaller::OnRequestPacket, AudioBuffersState(kSize, 0)));
213 ChildProcess::current()->io_message_loop()->PostTask(
214 FROM_HERE,
215 NewRunnableMethod(delegate_caller_.get(),
216 &DelegateCaller::OnStateChanged, kAudioStreamError));
217 ChildProcess::current()->io_message_loop()->PostTask(
218 FROM_HERE,
219 NewRunnableMethod(delegate_caller_.get(),
220 &DelegateCaller::OnStateChanged, kAudioStreamPlaying));
221 ChildProcess::current()->io_message_loop()->PostTask(
222 FROM_HERE,
223 NewRunnableMethod(delegate_caller_.get(),
224 &DelegateCaller::OnStateChanged, kAudioStreamPaused));
225 ChildProcess::current()->io_message_loop()->PostTask(
226 FROM_HERE,
227 NewRunnableMethod(delegate_caller_.get(),
228 &DelegateCaller::OnCreated, shared_mem_.handle(), kSize));
229 ChildProcess::current()->io_message_loop()->PostTask(
230 FROM_HERE,
231 NewRunnableMethod(delegate_caller_.get(),
232 &DelegateCaller::OnVolume, 0.5));
233
234 // Post a final task to the IO message loop and wait for completion.
235 ChildProcess::current()->io_message_loop()->PostTask(
236 FROM_HERE, new WaitTask(event_.get()));
237 EXPECT_TRUE(event_->TimedWait(base::TimeDelta::FromMilliseconds(kMaxWait)));
105 238
106 // It's possible that the upstream decoder replies right after being stopped. 239 // It's possible that the upstream decoder replies right after being stopped.
107 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); 240 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
108 renderer_->ConsumeAudioSamples(buffer); 241 renderer_->ConsumeAudioSamples(buffer);
109 } 242 }
110 243
111 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) { 244 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) {
112 // Kill the message loop and verify SetPlaybackRate() still works. 245 // Emulate "killing the message loop" and verify that SetPlaybackRate()
113 message_loop_.reset(); 246 // still works.
247 ChildProcess::current()->io_message_loop()->PostTask(
scherkus (not reviewing) 2011/07/07 21:26:47 ditto here with "DestroyIOMessageLoop()" helper fu
henrika_dont_use 2011/07/08 12:47:58 Will fix it in a separate CL.
248 FROM_HERE,
249 NewRunnableMethod(delegate_caller_.get(),
250 &DelegateCaller::DestroyCurrentMessageLoop));
251
252 // No tasks will be posted on the IO thread here since we are in
253 // a "stopped" state.
114 renderer_->SetPlaybackRate(0.0f); 254 renderer_->SetPlaybackRate(0.0f);
115 renderer_->SetPlaybackRate(1.0f); 255 renderer_->SetPlaybackRate(1.0f);
116 renderer_->SetPlaybackRate(0.0f); 256 renderer_->SetPlaybackRate(0.0f);
117 renderer_->Stop(media::NewExpectedCallback()); 257 renderer_->Stop(media::NewExpectedCallback());
118 } 258 }
119 259
120 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) { 260 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) {
121 // Kill the message loop and verify SetVolume() still works. 261 // Emulate "killing the message loop" and verify that SetVolume()
122 message_loop_.reset(); 262 // still works.
263 ChildProcess::current()->io_message_loop()->PostTask(
264 FROM_HERE,
265 NewRunnableMethod(delegate_caller_.get(),
266 &DelegateCaller::DestroyCurrentMessageLoop));
267
268 // No tasks will be posted on the IO thread here since we are in
269 // a "stopped" state.
123 renderer_->SetVolume(0.5f); 270 renderer_->SetVolume(0.5f);
124 renderer_->Stop(media::NewExpectedCallback()); 271 renderer_->Stop(media::NewExpectedCallback());
125 } 272 }
126 273
127 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_ConsumeAudioSamples) { 274 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_ConsumeAudioSamples) {
128 // Kill the message loop and verify OnReadComplete() still works. 275 // Emulate "killing the message loop" and verify thata OnReadComplete()
129 message_loop_.reset(); 276 // still works.
277 ChildProcess::current()->io_message_loop()->PostTask(
278 FROM_HERE,
279 NewRunnableMethod(delegate_caller_.get(),
280 &DelegateCaller::DestroyCurrentMessageLoop));
281
282 // No tasks will be posted on the IO thread here since we are in
283 // a "stopped" state.
130 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); 284 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
131 renderer_->ConsumeAudioSamples(buffer); 285 renderer_->ConsumeAudioSamples(buffer);
132 renderer_->Stop(media::NewExpectedCallback()); 286 renderer_->Stop(media::NewExpectedCallback());
133 } 287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698