OLD | NEW |
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/mac/audio_low_latency_output_mac.h" | 5 #include "media/audio/mac/audio_low_latency_output_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/logging.h" | 10 #include "base/logging.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 // 6) The same thread that called stop will call Close() where we cleanup | 43 // 6) The same thread that called stop will call Close() where we cleanup |
44 // and notify the audio manager, which likely will destroy this object. | 44 // and notify the audio manager, which likely will destroy this object. |
45 | 45 |
46 AUAudioOutputStream::AUAudioOutputStream( | 46 AUAudioOutputStream::AUAudioOutputStream( |
47 AudioManagerMac* manager, const AudioParameters& params) | 47 AudioManagerMac* manager, const AudioParameters& params) |
48 : manager_(manager), | 48 : manager_(manager), |
49 source_(NULL), | 49 source_(NULL), |
50 output_unit_(0), | 50 output_unit_(0), |
51 output_device_id_(kAudioObjectUnknown), | 51 output_device_id_(kAudioObjectUnknown), |
52 volume_(1), | 52 volume_(1), |
53 hardware_latency_frames_(0) { | 53 hardware_latency_frames_(0), |
| 54 stopped_(false) { |
54 // We must have a manager. | 55 // We must have a manager. |
55 DCHECK(manager_); | 56 DCHECK(manager_); |
56 // A frame is one sample across all channels. In interleaved audio the per | 57 // A frame is one sample across all channels. In interleaved audio the per |
57 // frame fields identify the set of n |channels|. In uncompressed audio, a | 58 // frame fields identify the set of n |channels|. In uncompressed audio, a |
58 // packet is always one frame. | 59 // packet is always one frame. |
59 format_.mSampleRate = params.sample_rate(); | 60 format_.mSampleRate = params.sample_rate(); |
60 format_.mFormatID = kAudioFormatLinearPCM; | 61 format_.mFormatID = kAudioFormatLinearPCM; |
61 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | | 62 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | |
62 kLinearPCMFormatFlagIsSignedInteger; | 63 kLinearPCMFormatFlagIsSignedInteger; |
63 format_.mBitsPerChannel = params.bits_per_sample(); | 64 format_.mBitsPerChannel = params.bits_per_sample(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 // destruction. | 172 // destruction. |
172 manager_->ReleaseOutputStream(this); | 173 manager_->ReleaseOutputStream(this); |
173 } | 174 } |
174 | 175 |
175 void AUAudioOutputStream::Start(AudioSourceCallback* callback) { | 176 void AUAudioOutputStream::Start(AudioSourceCallback* callback) { |
176 DCHECK(callback); | 177 DCHECK(callback); |
177 DLOG_IF(ERROR, !output_unit_) << "Open() has not been called successfully"; | 178 DLOG_IF(ERROR, !output_unit_) << "Open() has not been called successfully"; |
178 if (!output_unit_) | 179 if (!output_unit_) |
179 return; | 180 return; |
180 | 181 |
| 182 stopped_ = false; |
181 source_ = callback; | 183 source_ = callback; |
182 | 184 |
183 AudioOutputUnitStart(output_unit_); | 185 AudioOutputUnitStart(output_unit_); |
184 } | 186 } |
185 | 187 |
186 void AUAudioOutputStream::Stop() { | 188 void AUAudioOutputStream::Stop() { |
187 // We request a synchronous stop, so the next call can take some time. In | 189 // We request a synchronous stop, so the next call can take some time. In |
188 // the windows implementation we block here as well. | 190 // the windows implementation we block here as well. |
189 source_ = NULL; | 191 if (stopped_) |
| 192 return; |
190 | 193 |
191 AudioOutputUnitStop(output_unit_); | 194 AudioOutputUnitStop(output_unit_); |
| 195 |
| 196 source_ = NULL; |
| 197 stopped_ = true; |
192 } | 198 } |
193 | 199 |
194 void AUAudioOutputStream::SetVolume(double volume) { | 200 void AUAudioOutputStream::SetVolume(double volume) { |
195 if (!output_unit_) | 201 if (!output_unit_) |
196 return; | 202 return; |
197 volume_ = static_cast<float>(volume); | 203 volume_ = static_cast<float>(volume); |
198 | 204 |
199 // TODO(crogers): set volume property | 205 // TODO(crogers): set volume property |
200 } | 206 } |
201 | 207 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 // Get the delay between the moment getting the callback and the scheduled | 343 // Get the delay between the moment getting the callback and the scheduled |
338 // time stamp that tells when the data is going to be played out. | 344 // time stamp that tells when the data is going to be played out. |
339 UInt64 output_time_ns = AudioConvertHostTimeToNanos( | 345 UInt64 output_time_ns = AudioConvertHostTimeToNanos( |
340 output_time_stamp->mHostTime); | 346 output_time_stamp->mHostTime); |
341 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); | 347 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); |
342 double delay_frames = static_cast<double> | 348 double delay_frames = static_cast<double> |
343 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); | 349 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); |
344 | 350 |
345 return (delay_frames + hardware_latency_frames_); | 351 return (delay_frames + hardware_latency_frames_); |
346 } | 352 } |
OLD | NEW |