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

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

Issue 12379071: Use multiple shared memory buffers cyclically for audio capture. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: rebase Created 7 years, 9 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) 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 base::SharedMemoryHandle memory, 25 SharedMemoryHandleVector memory,
26 int memory_length, 26 int memory_length,
27 AudioRendererSink::RenderCallback* render_callback); 27 AudioRendererSink::RenderCallback* render_callback);
28 virtual ~AudioThreadCallback(); 28 virtual ~AudioThreadCallback();
29 29
30 virtual void MapSharedMemory() OVERRIDE; 30 virtual void MapSharedMemory() OVERRIDE;
31 31
32 // Called whenever we receive notifications about pending data. 32 // Called whenever we receive notifications about pending data.
33 virtual void Process(int pending_data) OVERRIDE; 33 virtual void Process(int pending_data, int index) OVERRIDE;
34 34
35 private: 35 private:
36 AudioRendererSink::RenderCallback* render_callback_; 36 AudioRendererSink::RenderCallback* render_callback_;
37 scoped_ptr<AudioBus> input_bus_; 37 scoped_ptr<AudioBus> input_bus_;
38 scoped_ptr<AudioBus> output_bus_; 38 scoped_ptr<AudioBus> output_bus_;
39 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); 39 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
40 }; 40 };
41 41
42 AudioOutputDevice::AudioOutputDevice( 42 AudioOutputDevice::AudioOutputDevice(
43 AudioOutputIPC* ipc, 43 AudioOutputIPC* ipc,
44 const scoped_refptr<base::MessageLoopProxy>& io_loop) 44 const scoped_refptr<base::MessageLoopProxy>& io_loop)
45 : ScopedLoopObserver(io_loop), 45 : ScopedLoopObserver(io_loop),
46 callback_(NULL), 46 callback_(NULL),
47 ipc_(ipc), 47 ipc_(ipc),
48 stream_id_(0), 48 stream_id_(0),
49 state_(IDLE), 49 state_(IDLE),
50 play_on_start_(true), 50 play_on_start_(true),
51 audio_thread_(false),
51 stopping_hack_(false) { 52 stopping_hack_(false) {
52 CHECK(ipc_); 53 CHECK(ipc_);
53 } 54 }
54 55
55 void AudioOutputDevice::Initialize(const AudioParameters& params, 56 void AudioOutputDevice::Initialize(const AudioParameters& params,
56 RenderCallback* callback) { 57 RenderCallback* callback) {
57 DCHECK(!callback_) << "Calling Initialize() twice?"; 58 DCHECK(!callback_) << "Calling Initialize() twice?";
58 DCHECK(params.IsValid()); 59 DCHECK(params.IsValid());
59 audio_parameters_ = params; 60 audio_parameters_ = params;
60 callback_ = callback; 61 callback_ = callback;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and 220 // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and
220 // delete as they see fit. AudioOutputDevice should internally use WeakPtr 221 // delete as they see fit. AudioOutputDevice should internally use WeakPtr
221 // to handle teardown and thread hopping. See http://crbug.com/151051 for 222 // to handle teardown and thread hopping. See http://crbug.com/151051 for
222 // details. 223 // details.
223 base::AutoLock auto_lock(audio_thread_lock_); 224 base::AutoLock auto_lock(audio_thread_lock_);
224 if (stopping_hack_) 225 if (stopping_hack_)
225 return; 226 return;
226 227
227 DCHECK(audio_thread_.IsStopped()); 228 DCHECK(audio_thread_.IsStopped());
228 audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback( 229 audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback(
229 audio_parameters_, handle, length, callback_)); 230 audio_parameters_,
231 AudioDeviceThread::Callback::SharedMemoryHandleVector(1, handle),
232 length, callback_));
230 audio_thread_.Start(audio_callback_.get(), socket_handle, 233 audio_thread_.Start(audio_callback_.get(), socket_handle,
231 "AudioOutputDevice"); 234 "AudioOutputDevice");
232 state_ = PAUSED; 235 state_ = PAUSED;
233 236
234 // We handle the case where Play() and/or Pause() may have been called 237 // We handle the case where Play() and/or Pause() may have been called
235 // multiple times before OnStreamCreated() gets called. 238 // multiple times before OnStreamCreated() gets called.
236 if (play_on_start_) 239 if (play_on_start_)
237 PlayOnIOThread(); 240 PlayOnIOThread();
238 } 241 }
239 242
240 void AudioOutputDevice::OnIPCClosed() { 243 void AudioOutputDevice::OnIPCClosed() {
241 DCHECK(message_loop()->BelongsToCurrentThread()); 244 DCHECK(message_loop()->BelongsToCurrentThread());
242 state_ = IPC_CLOSED; 245 state_ = IPC_CLOSED;
243 ipc_ = NULL; 246 ipc_ = NULL;
244 } 247 }
245 248
246 void AudioOutputDevice::WillDestroyCurrentMessageLoop() { 249 void AudioOutputDevice::WillDestroyCurrentMessageLoop() {
247 LOG(ERROR) << "IO loop going away before the audio device has been stopped"; 250 LOG(ERROR) << "IO loop going away before the audio device has been stopped";
248 ShutDownOnIOThread(); 251 ShutDownOnIOThread();
249 } 252 }
250 253
251 // AudioOutputDevice::AudioThreadCallback 254 // AudioOutputDevice::AudioThreadCallback
252 255
253 AudioOutputDevice::AudioThreadCallback::AudioThreadCallback( 256 AudioOutputDevice::AudioThreadCallback::AudioThreadCallback(
254 const AudioParameters& audio_parameters, 257 const AudioParameters& audio_parameters,
255 base::SharedMemoryHandle memory, 258 SharedMemoryHandleVector memory,
256 int memory_length, 259 int memory_length,
257 AudioRendererSink::RenderCallback* render_callback) 260 AudioRendererSink::RenderCallback* render_callback)
258 : AudioDeviceThread::Callback(audio_parameters, 261 : AudioDeviceThread::Callback(audio_parameters,
259 memory, 262 memory,
260 memory_length), 263 memory_length),
261 render_callback_(render_callback) { 264 render_callback_(render_callback) {
262 } 265 }
263 266
264 AudioOutputDevice::AudioThreadCallback::~AudioThreadCallback() { 267 AudioOutputDevice::AudioThreadCallback::~AudioThreadCallback() {
265 } 268 }
266 269
267 void AudioOutputDevice::AudioThreadCallback::MapSharedMemory() { 270 void AudioOutputDevice::AudioThreadCallback::MapSharedMemory() {
268 CHECK(shared_memory_.Map(TotalSharedMemorySizeInBytes(memory_length_))); 271 DCHECK_EQ(shared_memory_.size(), 1u);
272 base::SharedMemory* shared_buffer = shared_memory_[0];
273 CHECK(shared_buffer->Map(TotalSharedMemorySizeInBytes(memory_length_)));
269 274
270 // Calculate output and input memory size. 275 // Calculate output and input memory size.
271 int output_memory_size = AudioBus::CalculateMemorySize(audio_parameters_); 276 int output_memory_size = AudioBus::CalculateMemorySize(audio_parameters_);
272 int input_channels = audio_parameters_.input_channels(); 277 int input_channels = audio_parameters_.input_channels();
273 int frames = audio_parameters_.frames_per_buffer(); 278 int frames = audio_parameters_.frames_per_buffer();
274 int input_memory_size = 279 int input_memory_size =
275 AudioBus::CalculateMemorySize(input_channels, frames); 280 AudioBus::CalculateMemorySize(input_channels, frames);
276 281
277 int io_size = output_memory_size + input_memory_size; 282 int io_size = output_memory_size + input_memory_size;
278 283
279 DCHECK_EQ(memory_length_, io_size); 284 DCHECK_EQ(memory_length_, io_size);
280 285
281 output_bus_ = 286 output_bus_ =
282 AudioBus::WrapMemory(audio_parameters_, shared_memory_.memory()); 287 AudioBus::WrapMemory(audio_parameters_, shared_buffer->memory());
283 288
284 if (input_channels > 0) { 289 if (input_channels > 0) {
285 // The input data is after the output data. 290 // The input data is after the output data.
286 char* input_data = 291 char* input_data =
287 static_cast<char*>(shared_memory_.memory()) + output_memory_size; 292 static_cast<char*>(shared_buffer->memory()) + output_memory_size;
288 input_bus_ = 293 input_bus_ =
289 AudioBus::WrapMemory(input_channels, frames, input_data); 294 AudioBus::WrapMemory(input_channels, frames, input_data);
290 } 295 }
291 } 296 }
292 297
293 // Called whenever we receive notifications about pending data. 298 // Called whenever we receive notifications about pending data.
294 void AudioOutputDevice::AudioThreadCallback::Process(int pending_data) { 299 void AudioOutputDevice::AudioThreadCallback::Process(
300 int pending_data, int index) {
301 base::SharedMemory* shared_buffer = shared_memory_[0];
295 if (pending_data == kPauseMark) { 302 if (pending_data == kPauseMark) {
296 memset(shared_memory_.memory(), 0, memory_length_); 303 memset(shared_buffer->memory(), 0, memory_length_);
297 SetActualDataSizeInBytes(&shared_memory_, memory_length_, 0); 304 SetActualDataSizeInBytes(shared_buffer, memory_length_, 0);
298 return; 305 return;
299 } 306 }
300 307
301 // Convert the number of pending bytes in the render buffer 308 // Convert the number of pending bytes in the render buffer
302 // into milliseconds. 309 // into milliseconds.
303 int audio_delay_milliseconds = pending_data / bytes_per_ms_; 310 int audio_delay_milliseconds = pending_data / bytes_per_ms_;
304 311
305 TRACE_EVENT0("audio", "AudioOutputDevice::FireRenderCallback"); 312 TRACE_EVENT0("audio", "AudioOutputDevice::FireRenderCallback");
306 313
307 // Update the audio-delay measurement then ask client to render audio. Since 314 // Update the audio-delay measurement then ask client to render audio. Since
(...skipping 10 matching lines...) Expand all
318 num_frames = render_callback_->Render(output_bus_.get(), 325 num_frames = render_callback_->Render(output_bus_.get(),
319 audio_delay_milliseconds); 326 audio_delay_milliseconds);
320 } 327 }
321 328
322 // Let the host know we are done. 329 // Let the host know we are done.
323 // TODO(dalecurtis): Technically this is not always correct. Due to channel 330 // TODO(dalecurtis): Technically this is not always correct. Due to channel
324 // padding for alignment, there may be more data available than this. We're 331 // padding for alignment, there may be more data available than this. We're
325 // relying on AudioSyncReader::Read() to parse this with that in mind. Rename 332 // relying on AudioSyncReader::Read() to parse this with that in mind. Rename
326 // these methods to Set/GetActualFrameCount(). 333 // these methods to Set/GetActualFrameCount().
327 SetActualDataSizeInBytes( 334 SetActualDataSizeInBytes(
328 &shared_memory_, memory_length_, 335 shared_buffer, memory_length_,
329 num_frames * sizeof(*output_bus_->channel(0)) * output_bus_->channels()); 336 num_frames * sizeof(*output_bus_->channel(0)) * output_bus_->channels());
330 } 337 }
331 338
332 } // namespace media. 339 } // namespace media.
OLDNEW
« media/audio/audio_input_device.cc ('K') | « media/audio/audio_input_ipc.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698