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

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

Issue 2101303004: Pass delay and timestamp to AudioSourceCallback::OnMoreData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Changes based on comments Created 4 years, 3 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
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 <string>
10
9 #include "base/bind.h" 11 #include "base/bind.h"
10 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
11 #include "base/logging.h" 13 #include "base/logging.h"
12 #include "base/mac/mac_logging.h" 14 #include "base/mac/mac_logging.h"
13 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
15 #include "base/time/time.h"
16 #include "base/trace_event/trace_event.h" 17 #include "base/trace_event/trace_event.h"
17 #include "media/audio/mac/audio_manager_mac.h" 18 #include "media/audio/mac/audio_manager_mac.h"
18 #include "media/base/audio_pull_fifo.h" 19 #include "media/base/audio_pull_fifo.h"
19 20
20 namespace media { 21 namespace media {
21 22
22 static void WrapBufferList(AudioBufferList* buffer_list, 23 static void WrapBufferList(AudioBufferList* buffer_list,
23 AudioBus* bus, 24 AudioBus* bus,
24 int frames) { 25 int frames) {
25 DCHECK(buffer_list); 26 DCHECK(buffer_list);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 audio_fifo_.reset(new AudioPullFifo( 230 audio_fifo_.reset(new AudioPullFifo(
230 output_channels_, 231 output_channels_,
231 number_of_frames_, 232 number_of_frames_,
232 base::Bind(&AUHALStream::ProvideInput, base::Unretained(this)))); 233 base::Bind(&AUHALStream::ProvideInput, base::Unretained(this))));
233 } 234 }
234 } 235 }
235 236
236 // Make |output_bus_| wrap the output AudioBufferList. 237 // Make |output_bus_| wrap the output AudioBufferList.
237 WrapBufferList(data, output_bus_.get(), number_of_frames); 238 WrapBufferList(data, output_bus_.get(), number_of_frames);
238 239
239 // Update the playout latency. 240 current_target_playout_time_ = GetTargetPlayoutTime(output_time_stamp);
240 const double playout_latency_frames = GetPlayoutLatency(output_time_stamp);
241 current_hardware_pending_bytes_ = static_cast<uint32_t>(
242 (playout_latency_frames + 0.5) * params_.GetBytesPerFrame());
243 241
244 if (audio_fifo_) 242 if (audio_fifo_)
245 audio_fifo_->Consume(output_bus_.get(), output_bus_->frames()); 243 audio_fifo_->Consume(output_bus_.get(), output_bus_->frames());
246 else 244 else
247 ProvideInput(0, output_bus_.get()); 245 ProvideInput(0, output_bus_.get());
248 246
249 last_number_of_frames_ = number_of_frames; 247 last_number_of_frames_ = number_of_frames;
250 248
251 return noErr; 249 return noErr;
252 } 250 }
253 251
254 void AUHALStream::ProvideInput(int frame_delay, AudioBus* dest) { 252 void AUHALStream::ProvideInput(int frame_delay, AudioBus* dest) {
255 base::AutoLock auto_lock(source_lock_); 253 base::AutoLock auto_lock(source_lock_);
256 if (!source_) { 254 if (!source_) {
257 dest->Zero(); 255 dest->Zero();
258 return; 256 return;
259 } 257 }
260 258
259 const base::TimeDelta delay = base::TimeDelta::FromMicroseconds(
260 frame_delay * base::Time::kMicrosecondsPerSecond / params_.sample_rate());
261 const base::TimeTicks target_playout_time =
262 current_target_playout_time_ + delay;
263
261 // Supply the input data and render the output data. 264 // Supply the input data and render the output data.
262 source_->OnMoreData(dest, current_hardware_pending_bytes_ + 265 source_->OnMoreData(target_playout_time, current_lost_frames_, dest);
263 frame_delay * params_.GetBytesPerFrame(),
264 current_lost_frames_);
265 dest->Scale(volume_); 266 dest->Scale(volume_);
266 current_lost_frames_ = 0; 267 current_lost_frames_ = 0;
267 } 268 }
268 269
269 // AUHAL callback. 270 // AUHAL callback.
270 OSStatus AUHALStream::InputProc( 271 OSStatus AUHALStream::InputProc(
271 void* user_data, 272 void* user_data,
272 AudioUnitRenderActionFlags* flags, 273 AudioUnitRenderActionFlags* flags,
273 const AudioTimeStamp* output_time_stamp, 274 const AudioTimeStamp* output_time_stamp,
274 UInt32 bus_number, 275 UInt32 bus_number,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 &device_latency_frames); 328 &device_latency_frames);
328 if (result != noErr) { 329 if (result != noErr) {
329 OSSTATUS_DLOG(WARNING, result) << "Could not get audio device latency"; 330 OSSTATUS_DLOG(WARNING, result) << "Could not get audio device latency";
330 return 0.0; 331 return 0.0;
331 } 332 }
332 333
333 return static_cast<double>((audio_unit_latency_sec * 334 return static_cast<double>((audio_unit_latency_sec *
334 output_format_.mSampleRate) + device_latency_frames); 335 output_format_.mSampleRate) + device_latency_frames);
335 } 336 }
336 337
337 double AUHALStream::GetPlayoutLatency( 338 base::TimeTicks AUHALStream::GetTargetPlayoutTime(
338 const AudioTimeStamp* output_time_stamp) { 339 const AudioTimeStamp* output_time_stamp) {
339 // Ensure mHostTime is valid. 340 // Ensure mHostTime is valid.
340 if ((output_time_stamp->mFlags & kAudioTimeStampHostTimeValid) == 0) 341 if ((output_time_stamp->mFlags & kAudioTimeStampHostTimeValid) == 0)
341 return 0; 342 return 0;
miu 2016/08/31 23:26:54 The two "return 0" statements in this method won't
jameswest 2016/09/07 21:52:16 I'll add the TODO, but it looks like it was writte
miu 2016/09/07 22:19:36 That's correct. He left several years ago. Hmm...G
miu 2016/09/08 20:56:23 Looking at this again, I think it hides a bug, but
James West 2016/09/13 07:40:50 Done.
342 343
343 // Get the delay between the moment getting the callback and the scheduled 344 // Get the delay between the moment getting the callback and the scheduled
344 // time stamp that tells when the data is going to be played out. 345 // time stamp that tells when the data is going to be played out.
345 UInt64 output_time_ns = AudioConvertHostTimeToNanos( 346 UInt64 output_time_ns = AudioConvertHostTimeToNanos(
346 output_time_stamp->mHostTime); 347 output_time_stamp->mHostTime);
347 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); 348 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
348 349
349 // Prevent overflow leading to huge delay information; occurs regularly on 350 // Prevent overflow leading to huge delay information; occurs regularly on
350 // the bots, probably less so in the wild. 351 // the bots, probably less so in the wild.
351 if (now_ns > output_time_ns) 352 if (now_ns > output_time_ns)
352 return 0; 353 return 0;
353 354
354 double delay_frames = static_cast<double> 355 // TODO(jameswest): Find an alternative to FromInternalValue.
355 (1e-9 * (output_time_ns - now_ns) * output_format_.mSampleRate); 356 return base::TimeTicks::FromInternalValue(
miu 2016/08/31 23:26:54 I'd suggest adding a TimeTicks::FromMachAbsoluteTi
James West 2016/09/13 07:40:50 Done.
356 357 output_time_ns / base::Time::kNanosecondsPerMicrosecond);
357 return (delay_frames + hardware_latency_frames_);
358 } 358 }
359 359
360 void AUHALStream::UpdatePlayoutTimestamp(const AudioTimeStamp* timestamp) { 360 void AUHALStream::UpdatePlayoutTimestamp(const AudioTimeStamp* timestamp) {
361 if ((timestamp->mFlags & kAudioTimeStampSampleTimeValid) == 0) 361 if ((timestamp->mFlags & kAudioTimeStampSampleTimeValid) == 0)
362 return; 362 return;
363 363
364 if (last_sample_time_) { 364 if (last_sample_time_) {
365 DCHECK_NE(0U, last_number_of_frames_); 365 DCHECK_NE(0U, last_number_of_frames_);
366 UInt32 diff = 366 UInt32 diff =
367 static_cast<UInt32>(timestamp->mSampleTime - last_sample_time_); 367 static_cast<UInt32>(timestamp->mSampleTime - last_sample_time_);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 OSStatus result = AudioUnitUninitialize(audio_unit_); 555 OSStatus result = AudioUnitUninitialize(audio_unit_);
556 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 556 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
557 << "AudioUnitUninitialize() failed."; 557 << "AudioUnitUninitialize() failed.";
558 result = AudioComponentInstanceDispose(audio_unit_); 558 result = AudioComponentInstanceDispose(audio_unit_);
559 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 559 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
560 << "AudioComponentInstanceDispose() failed."; 560 << "AudioComponentInstanceDispose() failed.";
561 audio_unit_ = 0; 561 audio_unit_ = 0;
562 } 562 }
563 563
564 } // namespace media 564 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698