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

Side by Side Diff: media/audio/mac/audio_auhal_mac.cc

Issue 70903002: Dynamically FIFO when OSX requests unexpected frame counts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Polish. Created 7 years, 1 month 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/mac/audio_auhal_mac.h" 5 #include "media/audio/mac/audio_auhal_mac.h"
6 6
7 #include <CoreServices/CoreServices.h> 7 #include <CoreServices/CoreServices.h>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 params_(params), 51 params_(params),
52 input_channels_(params_.input_channels()), 52 input_channels_(params_.input_channels()),
53 output_channels_(params_.channels()), 53 output_channels_(params_.channels()),
54 number_of_frames_(params_.frames_per_buffer()), 54 number_of_frames_(params_.frames_per_buffer()),
55 source_(NULL), 55 source_(NULL),
56 device_(device), 56 device_(device),
57 audio_unit_(0), 57 audio_unit_(0),
58 volume_(1), 58 volume_(1),
59 hardware_latency_frames_(0), 59 hardware_latency_frames_(0),
60 stopped_(false), 60 stopped_(false),
61 notified_for_possible_device_change_(false), 61 input_buffer_list_(NULL),
62 input_buffer_list_(NULL) { 62 current_hardware_pending_bytes_(0) {
63 // We must have a manager. 63 // We must have a manager.
64 DCHECK(manager_); 64 DCHECK(manager_);
65 65
66 VLOG(1) << "AUHALStream::AUHALStream()"; 66 VLOG(1) << "AUHALStream::AUHALStream()";
67 VLOG(1) << "Device: " << device; 67 VLOG(1) << "Device: " << device;
68 VLOG(1) << "Input channels: " << input_channels_; 68 VLOG(1) << "Input channels: " << input_channels_;
69 VLOG(1) << "Output channels: " << output_channels_; 69 VLOG(1) << "Output channels: " << output_channels_;
70 VLOG(1) << "Sample rate: " << params_.sample_rate(); 70 VLOG(1) << "Sample rate: " << params_.sample_rate();
71 VLOG(1) << "Buffer size: " << number_of_frames_; 71 VLOG(1) << "Buffer size: " << number_of_frames_;
72 } 72 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 } 143 }
144 144
145 void AUHALStream::Start(AudioSourceCallback* callback) { 145 void AUHALStream::Start(AudioSourceCallback* callback) {
146 DCHECK(callback); 146 DCHECK(callback);
147 if (!audio_unit_) { 147 if (!audio_unit_) {
148 DLOG(ERROR) << "Open() has not been called successfully"; 148 DLOG(ERROR) << "Open() has not been called successfully";
149 return; 149 return;
150 } 150 }
151 151
152 stopped_ = false; 152 stopped_ = false;
153 notified_for_possible_device_change_ = false; 153 audio_fifo_.reset();
154 { 154 {
155 base::AutoLock auto_lock(source_lock_); 155 base::AutoLock auto_lock(source_lock_);
156 source_ = callback; 156 source_ = callback;
157 } 157 }
158 158
159 OSStatus result = AudioOutputUnitStart(audio_unit_); 159 OSStatus result = AudioOutputUnitStart(audio_unit_);
160 if (result == noErr) 160 if (result == noErr)
161 return; 161 return;
162 162
163 Stop(); 163 Stop();
(...skipping 29 matching lines...) Expand all
193 // be contended in the middle of stream processing here (starting and stopping 193 // be contended in the middle of stream processing here (starting and stopping
194 // the stream are ok) because this is running on a real-time thread. 194 // the stream are ok) because this is running on a real-time thread.
195 OSStatus AUHALStream::Render( 195 OSStatus AUHALStream::Render(
196 AudioUnitRenderActionFlags* flags, 196 AudioUnitRenderActionFlags* flags,
197 const AudioTimeStamp* output_time_stamp, 197 const AudioTimeStamp* output_time_stamp,
198 UInt32 bus_number, 198 UInt32 bus_number,
199 UInt32 number_of_frames, 199 UInt32 number_of_frames,
200 AudioBufferList* io_data) { 200 AudioBufferList* io_data) {
201 TRACE_EVENT0("audio", "AUHALStream::Render"); 201 TRACE_EVENT0("audio", "AUHALStream::Render");
202 202
203 // If the stream parameters change for any reason, we need to insert a FIFO
204 // since our pipeline can't handle frame size changes. Generally this is a
scherkus (not reviewing) 2013/11/13 18:35:19 is this referring to media::Pipeline, or something
DaleCurtis 2013/11/13 20:06:24 Comment clarified. The shared memory is sized to
205 // temporary situation which can occur after a device change has occurred but
206 // the AudioManager hasn't received the notification yet.
203 if (number_of_frames != number_of_frames_) { 207 if (number_of_frames != number_of_frames_) {
204 // This can happen if we've suddenly changed sample-rates. 208 // Create a FIFO on the fly to handle any discrepancies in callback rates.
205 // The stream should be stopping very soon. 209 if (!audio_fifo_) {
206 // 210 audio_fifo_.reset(new AudioPullFifo(
scherkus (not reviewing) 2013/11/13 18:35:19 OOC does using the fifo have a perf impact? (i.e.,
DaleCurtis 2013/11/13 20:06:24 Yes it has a perf impact of at least 6.5% (see Aud
207 // Unfortunately AUAudioInputStream and AUHALStream share the frame 211 output_channels_,
208 // size set by kAudioDevicePropertyBufferFrameSize above on a per process 212 number_of_frames_,
209 // basis. What this means is that the |number_of_frames| value may be 213 base::Bind(&AUHALStream::ProvideInput, base::Unretained(this))));
210 // larger or smaller than the value set during ConfigureAUHAL(). 214 }
211 // In this case either audio input or audio output will be broken,
212 // so just output silence.
213 ZeroBufferList(io_data);
214 return noErr;
215 }
216 215
217 if (input_channels_ > 0 && input_buffer_list_) { 216 // Synchronous IO is not supported in this state.
218 // Get the input data. |input_buffer_list_| is wrapped 217 if (input_channels_ > 0)
219 // to point to the data allocated in |input_bus_|. 218 input_bus_->Zero();
220 OSStatus result = AudioUnitRender( 219 } else {
221 audio_unit_, 220 if (input_channels_ > 0 && input_buffer_list_) {
222 flags, 221 // Get the input data. |input_buffer_list_| is wrapped
223 output_time_stamp, 222 // to point to the data allocated in |input_bus_|.
224 1, 223 OSStatus result = AudioUnitRender(audio_unit_,
225 number_of_frames, 224 flags,
226 input_buffer_list_); 225 output_time_stamp,
227 if (result != noErr) 226 1,
228 ZeroBufferList(input_buffer_list_); 227 number_of_frames,
228 input_buffer_list_);
229 if (result != noErr)
230 ZeroBufferList(input_buffer_list_);
231 }
229 } 232 }
230 233
231 // Make |output_bus_| wrap the output AudioBufferList. 234 // Make |output_bus_| wrap the output AudioBufferList.
232 WrapBufferList(io_data, output_bus_.get(), number_of_frames); 235 WrapBufferList(io_data, output_bus_.get(), number_of_frames);
233 236
234 // Update the playout latency. 237 // Update the playout latency.
235 double playout_latency_frames = GetPlayoutLatency(output_time_stamp); 238 const double playout_latency_frames = GetPlayoutLatency(output_time_stamp);
239 current_hardware_pending_bytes_ = static_cast<uint32>(
240 (playout_latency_frames + 0.5) * params_.GetBytesPerFrame());
236 241
237 uint32 hardware_pending_bytes = static_cast<uint32> 242 if (audio_fifo_)
238 ((playout_latency_frames + 0.5) * output_format_.mBytesPerFrame); 243 audio_fifo_->Consume(output_bus_.get(), output_bus_->frames());
239 244 else
240 { 245 ProvideInput(0, output_bus_.get());
241 // Render() shouldn't be called except between AudioOutputUnitStart() and
242 // AudioOutputUnitStop() calls, but crash reports have shown otherwise:
243 // http://crbug.com/178765. We use |source_lock_| to prevent races and
244 // crashes in Render() when |source_| is cleared.
245 base::AutoLock auto_lock(source_lock_);
246 if (!source_) {
247 ZeroBufferList(io_data);
248 return noErr;
249 }
250
251 // Supply the input data and render the output data.
252 source_->OnMoreIOData(
253 input_bus_.get(),
254 output_bus_.get(),
255 AudioBuffersState(0, hardware_pending_bytes));
256 output_bus_->Scale(volume_);
257 }
258 246
259 return noErr; 247 return noErr;
260 } 248 }
261 249
250 void AUHALStream::ProvideInput(int frame_delay, AudioBus* dest) {
251 base::AutoLock auto_lock(source_lock_);
252 if (!source_) {
253 dest->Zero();
254 return;
255 }
256
257 // Supply the input data and render the output data.
258 source_->OnMoreIOData(
259 input_bus_.get(),
260 dest,
261 AudioBuffersState(0,
262 current_hardware_pending_bytes_ +
263 frame_delay * params_.GetBytesPerFrame()));
264 dest->Scale(volume_);
265 }
266
262 // AUHAL callback. 267 // AUHAL callback.
263 OSStatus AUHALStream::InputProc( 268 OSStatus AUHALStream::InputProc(
264 void* user_data, 269 void* user_data,
265 AudioUnitRenderActionFlags* flags, 270 AudioUnitRenderActionFlags* flags,
266 const AudioTimeStamp* output_time_stamp, 271 const AudioTimeStamp* output_time_stamp,
267 UInt32 bus_number, 272 UInt32 bus_number,
268 UInt32 number_of_frames, 273 UInt32 number_of_frames,
269 AudioBufferList* io_data) { 274 AudioBufferList* io_data) {
270 // Dispatch to our class method. 275 // Dispatch to our class method.
271 AUHALStream* audio_output = 276 AUHALStream* audio_output =
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 result = AudioUnitInitialize(audio_unit_); 528 result = AudioUnitInitialize(audio_unit_);
524 if (result != noErr) { 529 if (result != noErr) {
525 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed."; 530 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed.";
526 return false; 531 return false;
527 } 532 }
528 533
529 return true; 534 return true;
530 } 535 }
531 536
532 } // namespace media 537 } // namespace media
OLDNEW
« media/audio/mac/audio_auhal_mac.h ('K') | « media/audio/mac/audio_auhal_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698