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

Side by Side Diff: media/audio/audio_output_device.cc

Issue 11878032: Plumb |input_channels| all the way to AudioManager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 10 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
« no previous file with comments | « media/audio/audio_output_device.h ('k') | media/audio/audio_output_device_unittest.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) 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 "media/audio/audio_output_device.h" 5 #include "media/audio/audio_output_device.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/threading/thread_restrictions.h" 9 #include "base/threading/thread_restrictions.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "media/audio/audio_output_controller.h" 11 #include "media/audio/audio_output_controller.h"
12 #include "media/audio/audio_util.h" 12 #include "media/audio/audio_util.h"
13 #include "media/audio/shared_memory_util.h" 13 #include "media/audio/shared_memory_util.h"
14 #include "media/base/limits.h" 14 #include "media/base/limits.h"
15 15
16 namespace media { 16 namespace media {
17 17
18 // Takes care of invoking the render callback on the audio thread. 18 // Takes care of invoking the render callback on the audio thread.
19 // An instance of this class is created for each capture stream in 19 // An instance of this class is created for each capture stream in
20 // OnStreamCreated(). 20 // OnStreamCreated().
21 class AudioOutputDevice::AudioThreadCallback 21 class AudioOutputDevice::AudioThreadCallback
22 : public AudioDeviceThread::Callback { 22 : public AudioDeviceThread::Callback {
23 public: 23 public:
24 AudioThreadCallback(const AudioParameters& audio_parameters, 24 AudioThreadCallback(const AudioParameters& audio_parameters,
25 int input_channels,
26 base::SharedMemoryHandle memory, 25 base::SharedMemoryHandle memory,
27 int memory_length, 26 int memory_length,
28 AudioRendererSink::RenderCallback* render_callback); 27 AudioRendererSink::RenderCallback* render_callback);
29 virtual ~AudioThreadCallback(); 28 virtual ~AudioThreadCallback();
30 29
31 virtual void MapSharedMemory() OVERRIDE; 30 virtual void MapSharedMemory() OVERRIDE;
32 31
33 // Called whenever we receive notifications about pending data. 32 // Called whenever we receive notifications about pending data.
34 virtual void Process(int pending_data) OVERRIDE; 33 virtual void Process(int pending_data) OVERRIDE;
35 34
36 private: 35 private:
37 AudioRendererSink::RenderCallback* render_callback_; 36 AudioRendererSink::RenderCallback* render_callback_;
38 scoped_ptr<AudioBus> input_bus_; 37 scoped_ptr<AudioBus> input_bus_;
39 scoped_ptr<AudioBus> output_bus_; 38 scoped_ptr<AudioBus> output_bus_;
40 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); 39 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
41 }; 40 };
42 41
43 AudioOutputDevice::AudioOutputDevice( 42 AudioOutputDevice::AudioOutputDevice(
44 AudioOutputIPC* ipc, 43 AudioOutputIPC* ipc,
45 const scoped_refptr<base::MessageLoopProxy>& io_loop) 44 const scoped_refptr<base::MessageLoopProxy>& io_loop)
46 : ScopedLoopObserver(io_loop), 45 : ScopedLoopObserver(io_loop),
47 input_channels_(0),
48 callback_(NULL), 46 callback_(NULL),
49 ipc_(ipc), 47 ipc_(ipc),
50 state_(IDLE), 48 state_(IDLE),
51 play_on_start_(true), 49 play_on_start_(true),
52 stopping_hack_(false) { 50 stopping_hack_(false) {
53 CHECK(ipc_); 51 CHECK(ipc_);
54 stream_id_ = ipc_->AddDelegate(this); 52 stream_id_ = ipc_->AddDelegate(this);
55 } 53 }
56 54
57 void AudioOutputDevice::Initialize(const AudioParameters& params, 55 void AudioOutputDevice::Initialize(const AudioParameters& params,
58 RenderCallback* callback) { 56 RenderCallback* callback) {
59 DCHECK(!callback_) << "Calling Initialize() twice?"; 57 DCHECK(!callback_) << "Calling Initialize() twice?";
58 DCHECK(params.IsValid());
60 audio_parameters_ = params; 59 audio_parameters_ = params;
61 callback_ = callback; 60 callback_ = callback;
62 } 61 }
63 62
64 void AudioOutputDevice::InitializeIO(const AudioParameters& params,
65 int input_channels,
66 RenderCallback* callback) {
67 DCHECK_GE(input_channels, 0);
68 DCHECK_LT(input_channels, limits::kMaxChannels);
69 input_channels_ = input_channels;
70 Initialize(params, callback);
71 }
72
73 AudioOutputDevice::~AudioOutputDevice() { 63 AudioOutputDevice::~AudioOutputDevice() {
74 // The current design requires that the user calls Stop() before deleting 64 // The current design requires that the user calls Stop() before deleting
75 // this class. 65 // this class.
76 DCHECK(audio_thread_.IsStopped()); 66 DCHECK(audio_thread_.IsStopped());
77 67
78 if (ipc_) 68 if (ipc_)
79 ipc_->RemoveDelegate(stream_id_); 69 ipc_->RemoveDelegate(stream_id_);
80 } 70 }
81 71
82 void AudioOutputDevice::Start() { 72 void AudioOutputDevice::Start() {
83 DCHECK(callback_) << "Initialize hasn't been called"; 73 DCHECK(callback_) << "Initialize hasn't been called";
84 message_loop()->PostTask(FROM_HERE, 74 message_loop()->PostTask(FROM_HERE,
85 base::Bind(&AudioOutputDevice::CreateStreamOnIOThread, this, 75 base::Bind(&AudioOutputDevice::CreateStreamOnIOThread, this,
86 audio_parameters_, input_channels_)); 76 audio_parameters_));
87 } 77 }
88 78
89 void AudioOutputDevice::Stop() { 79 void AudioOutputDevice::Stop() {
90 { 80 {
91 base::AutoLock auto_lock(audio_thread_lock_); 81 base::AutoLock auto_lock(audio_thread_lock_);
92 audio_thread_.Stop(MessageLoop::current()); 82 audio_thread_.Stop(MessageLoop::current());
93 stopping_hack_ = true; 83 stopping_hack_ = true;
94 } 84 }
95 85
96 message_loop()->PostTask(FROM_HERE, 86 message_loop()->PostTask(FROM_HERE,
(...skipping 15 matching lines...) Expand all
112 return false; 102 return false;
113 103
114 if (!message_loop()->PostTask(FROM_HERE, 104 if (!message_loop()->PostTask(FROM_HERE,
115 base::Bind(&AudioOutputDevice::SetVolumeOnIOThread, this, volume))) { 105 base::Bind(&AudioOutputDevice::SetVolumeOnIOThread, this, volume))) {
116 return false; 106 return false;
117 } 107 }
118 108
119 return true; 109 return true;
120 } 110 }
121 111
122 void AudioOutputDevice::CreateStreamOnIOThread(const AudioParameters& params, 112 void AudioOutputDevice::CreateStreamOnIOThread(const AudioParameters& params) {
123 int input_channels) {
124 DCHECK(message_loop()->BelongsToCurrentThread()); 113 DCHECK(message_loop()->BelongsToCurrentThread());
125 if (state_ == IDLE) { 114 if (state_ == IDLE) {
126 state_ = CREATING_STREAM; 115 state_ = CREATING_STREAM;
127 ipc_->CreateStream(stream_id_, params, input_channels); 116 ipc_->CreateStream(stream_id_, params);
128 } 117 }
129 } 118 }
130 119
131 void AudioOutputDevice::PlayOnIOThread() { 120 void AudioOutputDevice::PlayOnIOThread() {
132 DCHECK(message_loop()->BelongsToCurrentThread()); 121 DCHECK(message_loop()->BelongsToCurrentThread());
133 if (state_ == PAUSED) { 122 if (state_ == PAUSED) {
134 ipc_->PlayStream(stream_id_); 123 ipc_->PlayStream(stream_id_);
135 state_ = PLAYING; 124 state_ = PLAYING;
136 play_on_start_ = false; 125 play_on_start_ = false;
137 } else { 126 } else {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and 219 // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and
231 // delete as they see fit. AudioOutputDevice should internally use WeakPtr 220 // delete as they see fit. AudioOutputDevice should internally use WeakPtr
232 // to handle teardown and thread hopping. See http://crbug.com/151051 for 221 // to handle teardown and thread hopping. See http://crbug.com/151051 for
233 // details. 222 // details.
234 base::AutoLock auto_lock(audio_thread_lock_); 223 base::AutoLock auto_lock(audio_thread_lock_);
235 if (stopping_hack_) 224 if (stopping_hack_)
236 return; 225 return;
237 226
238 DCHECK(audio_thread_.IsStopped()); 227 DCHECK(audio_thread_.IsStopped());
239 audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback( 228 audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback(
240 audio_parameters_, input_channels_, handle, length, callback_)); 229 audio_parameters_, handle, length, callback_));
241 audio_thread_.Start(audio_callback_.get(), socket_handle, 230 audio_thread_.Start(audio_callback_.get(), socket_handle,
242 "AudioOutputDevice"); 231 "AudioOutputDevice");
243 state_ = PAUSED; 232 state_ = PAUSED;
244 233
245 // We handle the case where Play() and/or Pause() may have been called 234 // We handle the case where Play() and/or Pause() may have been called
246 // multiple times before OnStreamCreated() gets called. 235 // multiple times before OnStreamCreated() gets called.
247 if (play_on_start_) 236 if (play_on_start_)
248 PlayOnIOThread(); 237 PlayOnIOThread();
249 } 238 }
250 239
251 void AudioOutputDevice::OnIPCClosed() { 240 void AudioOutputDevice::OnIPCClosed() {
252 DCHECK(message_loop()->BelongsToCurrentThread()); 241 DCHECK(message_loop()->BelongsToCurrentThread());
253 state_ = IPC_CLOSED; 242 state_ = IPC_CLOSED;
254 ipc_ = NULL; 243 ipc_ = NULL;
255 } 244 }
256 245
257 void AudioOutputDevice::WillDestroyCurrentMessageLoop() { 246 void AudioOutputDevice::WillDestroyCurrentMessageLoop() {
258 LOG(ERROR) << "IO loop going away before the audio device has been stopped"; 247 LOG(ERROR) << "IO loop going away before the audio device has been stopped";
259 ShutDownOnIOThread(); 248 ShutDownOnIOThread();
260 } 249 }
261 250
262 // AudioOutputDevice::AudioThreadCallback 251 // AudioOutputDevice::AudioThreadCallback
263 252
264 AudioOutputDevice::AudioThreadCallback::AudioThreadCallback( 253 AudioOutputDevice::AudioThreadCallback::AudioThreadCallback(
265 const AudioParameters& audio_parameters, 254 const AudioParameters& audio_parameters,
266 int input_channels,
267 base::SharedMemoryHandle memory, 255 base::SharedMemoryHandle memory,
268 int memory_length, 256 int memory_length,
269 AudioRendererSink::RenderCallback* render_callback) 257 AudioRendererSink::RenderCallback* render_callback)
270 : AudioDeviceThread::Callback(audio_parameters, 258 : AudioDeviceThread::Callback(audio_parameters,
271 input_channels,
272 memory, 259 memory,
273 memory_length), 260 memory_length),
274 render_callback_(render_callback) { 261 render_callback_(render_callback) {
275 } 262 }
276 263
277 AudioOutputDevice::AudioThreadCallback::~AudioThreadCallback() { 264 AudioOutputDevice::AudioThreadCallback::~AudioThreadCallback() {
278 } 265 }
279 266
280 void AudioOutputDevice::AudioThreadCallback::MapSharedMemory() { 267 void AudioOutputDevice::AudioThreadCallback::MapSharedMemory() {
281 shared_memory_.Map(TotalSharedMemorySizeInBytes(memory_length_)); 268 shared_memory_.Map(TotalSharedMemorySizeInBytes(memory_length_));
282 269
283 // Calculate output and input memory size. 270 // Calculate output and input memory size.
284 int output_memory_size = AudioBus::CalculateMemorySize(audio_parameters_); 271 int output_memory_size = AudioBus::CalculateMemorySize(audio_parameters_);
272 int input_channels = audio_parameters_.input_channels();
285 int frames = audio_parameters_.frames_per_buffer(); 273 int frames = audio_parameters_.frames_per_buffer();
286 int input_memory_size = 274 int input_memory_size =
287 AudioBus::CalculateMemorySize(input_channels_, frames); 275 AudioBus::CalculateMemorySize(input_channels, frames);
288 276
289 int io_size = output_memory_size + input_memory_size; 277 int io_size = output_memory_size + input_memory_size;
290 278
291 DCHECK_EQ(memory_length_, io_size); 279 DCHECK_EQ(memory_length_, io_size);
292 280
293 output_bus_ = 281 output_bus_ =
294 AudioBus::WrapMemory(audio_parameters_, shared_memory_.memory()); 282 AudioBus::WrapMemory(audio_parameters_, shared_memory_.memory());
295 283
296 if (input_channels_ > 0) { 284 if (input_channels > 0) {
297 // The input data is after the output data. 285 // The input data is after the output data.
298 char* input_data = 286 char* input_data =
299 static_cast<char*>(shared_memory_.memory()) + output_memory_size; 287 static_cast<char*>(shared_memory_.memory()) + output_memory_size;
300 input_bus_ = 288 input_bus_ =
301 AudioBus::WrapMemory(input_channels_, frames, input_data); 289 AudioBus::WrapMemory(input_channels, frames, input_data);
302 } 290 }
303 } 291 }
304 292
305 // Called whenever we receive notifications about pending data. 293 // Called whenever we receive notifications about pending data.
306 void AudioOutputDevice::AudioThreadCallback::Process(int pending_data) { 294 void AudioOutputDevice::AudioThreadCallback::Process(int pending_data) {
307 if (pending_data == kPauseMark) { 295 if (pending_data == kPauseMark) {
308 memset(shared_memory_.memory(), 0, memory_length_); 296 memset(shared_memory_.memory(), 0, memory_length_);
309 SetActualDataSizeInBytes(&shared_memory_, memory_length_, 0); 297 SetActualDataSizeInBytes(&shared_memory_, memory_length_, 0);
310 return; 298 return;
311 } 299 }
312 300
313 // Convert the number of pending bytes in the render buffer 301 // Convert the number of pending bytes in the render buffer
314 // into milliseconds. 302 // into milliseconds.
315 int audio_delay_milliseconds = pending_data / bytes_per_ms_; 303 int audio_delay_milliseconds = pending_data / bytes_per_ms_;
316 304
317 TRACE_EVENT0("audio", "AudioOutputDevice::FireRenderCallback"); 305 TRACE_EVENT0("audio", "AudioOutputDevice::FireRenderCallback");
318 306
319 // Update the audio-delay measurement then ask client to render audio. Since 307 // Update the audio-delay measurement then ask client to render audio. Since
320 // |output_bus_| is wrapping the shared memory the Render() call is writing 308 // |output_bus_| is wrapping the shared memory the Render() call is writing
321 // directly into the shared memory. 309 // directly into the shared memory.
310 int input_channels = audio_parameters_.input_channels();
322 size_t num_frames = audio_parameters_.frames_per_buffer(); 311 size_t num_frames = audio_parameters_.frames_per_buffer();
323 312
324 if (input_bus_.get() && input_channels_ > 0) { 313 if (input_bus_.get() && input_channels > 0) {
325 render_callback_->RenderIO(input_bus_.get(), 314 render_callback_->RenderIO(input_bus_.get(),
326 output_bus_.get(), 315 output_bus_.get(),
327 audio_delay_milliseconds); 316 audio_delay_milliseconds);
328 } else { 317 } else {
329 num_frames = render_callback_->Render(output_bus_.get(), 318 num_frames = render_callback_->Render(output_bus_.get(),
330 audio_delay_milliseconds); 319 audio_delay_milliseconds);
331 } 320 }
332 321
333 // Let the host know we are done. 322 // Let the host know we are done.
334 // TODO(dalecurtis): Technically this is not always correct. Due to channel 323 // TODO(dalecurtis): Technically this is not always correct. Due to channel
335 // padding for alignment, there may be more data available than this. We're 324 // padding for alignment, there may be more data available than this. We're
336 // relying on AudioSyncReader::Read() to parse this with that in mind. Rename 325 // relying on AudioSyncReader::Read() to parse this with that in mind. Rename
337 // these methods to Set/GetActualFrameCount(). 326 // these methods to Set/GetActualFrameCount().
338 SetActualDataSizeInBytes( 327 SetActualDataSizeInBytes(
339 &shared_memory_, memory_length_, 328 &shared_memory_, memory_length_,
340 num_frames * sizeof(*output_bus_->channel(0)) * output_bus_->channels()); 329 num_frames * sizeof(*output_bus_->channel(0)) * output_bus_->channels());
341 } 330 }
342 331
343 } // namespace media. 332 } // namespace media.
OLDNEW
« no previous file with comments | « media/audio/audio_output_device.h ('k') | media/audio/audio_output_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698