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

Unified Diff: media/audio/mac/audio_low_latency_output_mac.cc

Issue 154573002: Remove deprecated non-AUHAL audio path on OSX. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/mac/audio_low_latency_output_mac.h ('k') | media/audio/mac/audio_manager_mac.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/mac/audio_low_latency_output_mac.cc
diff --git a/media/audio/mac/audio_low_latency_output_mac.cc b/media/audio/mac/audio_low_latency_output_mac.cc
deleted file mode 100644
index afa480aefb956e44b219e40ba83efe3d2db5a1de..0000000000000000000000000000000000000000
--- a/media/audio/mac/audio_low_latency_output_mac.cc
+++ /dev/null
@@ -1,416 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/mac/audio_low_latency_output_mac.h"
-
-#include <CoreServices/CoreServices.h>
-
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/mac/mac_logging.h"
-#include "media/audio/mac/audio_manager_mac.h"
-#include "media/base/media_switches.h"
-
-namespace media {
-
-static std::ostream& operator<<(std::ostream& os,
- const AudioStreamBasicDescription& format) {
- os << "sample rate : " << format.mSampleRate << std::endl
- << "format ID : " << format.mFormatID << std::endl
- << "format flags : " << format.mFormatFlags << std::endl
- << "bytes per packet : " << format.mBytesPerPacket << std::endl
- << "frames per packet : " << format.mFramesPerPacket << std::endl
- << "bytes per frame : " << format.mBytesPerFrame << std::endl
- << "channels per frame: " << format.mChannelsPerFrame << std::endl
- << "bits per channel : " << format.mBitsPerChannel;
- return os;
-}
-
-static AudioObjectPropertyAddress kDefaultOutputDeviceAddress = {
- kAudioHardwarePropertyDefaultOutputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
-};
-
-// Overview of operation:
-// 1) An object of AUAudioOutputStream is created by the AudioManager
-// factory: audio_man->MakeAudioStream().
-// 2) Next some thread will call Open(), at that point the underlying
-// default output Audio Unit is created and configured.
-// 3) Then some thread will call Start(source).
-// Then the Audio Unit is started which creates its own thread which
-// periodically will call the source for more data as buffers are being
-// consumed.
-// 4) At some point some thread will call Stop(), which we handle by directly
-// stopping the default output Audio Unit.
-// 6) The same thread that called stop will call Close() where we cleanup
-// and notify the audio manager, which likely will destroy this object.
-
-AUAudioOutputStream::AUAudioOutputStream(
- AudioManagerMac* manager, const AudioParameters& params)
- : manager_(manager),
- source_(NULL),
- output_unit_(0),
- output_device_id_(kAudioObjectUnknown),
- volume_(1),
- hardware_latency_frames_(0),
- stopped_(false),
- audio_bus_(AudioBus::Create(params)) {
- // We must have a manager.
- DCHECK(manager_);
-
- // A frame is one sample across all channels. In interleaved audio the per
- // frame fields identify the set of n |channels|. In uncompressed audio, a
- // packet is always one frame.
- format_.mSampleRate = params.sample_rate();
- format_.mFormatID = kAudioFormatLinearPCM;
- format_.mFormatFlags = kLinearPCMFormatFlagIsPacked |
- kLinearPCMFormatFlagIsSignedInteger;
- format_.mBitsPerChannel = params.bits_per_sample();
- format_.mChannelsPerFrame = params.channels();
- format_.mFramesPerPacket = 1;
- format_.mBytesPerPacket = (format_.mBitsPerChannel * params.channels()) / 8;
- format_.mBytesPerFrame = format_.mBytesPerPacket;
- format_.mReserved = 0;
-
- DVLOG(1) << "Desired ouput format: " << format_;
-
- // Calculate the number of sample frames per callback.
- number_of_frames_ = params.frames_per_buffer();
- DVLOG(1) << "Number of frames per callback: " << number_of_frames_;
-}
-
-AUAudioOutputStream::~AUAudioOutputStream() {
-}
-
-bool AUAudioOutputStream::Open() {
- // Obtain the current input device selected by the user.
- UInt32 size = sizeof(output_device_id_);
- OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
- &kDefaultOutputDeviceAddress,
- 0,
- 0,
- &size,
- &output_device_id_);
- if (result != noErr || output_device_id_ == kAudioObjectUnknown) {
- OSSTATUS_DLOG(ERROR, result)
- << "Could not get default audio output device.";
- return false;
- }
-
- // Open and initialize the DefaultOutputUnit.
- AudioComponent comp;
- AudioComponentDescription desc;
-
- desc.componentType = kAudioUnitType_Output;
- desc.componentSubType = kAudioUnitSubType_DefaultOutput;
- desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- desc.componentFlags = 0;
- desc.componentFlagsMask = 0;
- comp = AudioComponentFindNext(0, &desc);
- if (!comp)
- return false;
-
- result = AudioComponentInstanceNew(comp, &output_unit_);
- if (result != noErr) {
- OSSTATUS_DLOG(ERROR, result) << "AudioComponentInstanceNew() failed.";
- return false;
- }
-
- result = AudioUnitInitialize(output_unit_);
- if (result != noErr) {
- OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed.";
- return false;
- }
-
- hardware_latency_frames_ = GetHardwareLatency();
-
- return Configure();
-}
-
-bool AUAudioOutputStream::Configure() {
- // Set the render callback.
- AURenderCallbackStruct input;
- input.inputProc = InputProc;
- input.inputProcRefCon = this;
- OSStatus result = AudioUnitSetProperty(
- output_unit_,
- kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Global,
- 0,
- &input,
- sizeof(input));
- if (result != noErr) {
- OSSTATUS_DLOG(ERROR, result)
- << "AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed.";
- return false;
- }
-
- // Set the stream format.
- result = AudioUnitSetProperty(
- output_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 0,
- &format_,
- sizeof(format_));
- if (result != noErr) {
- OSSTATUS_DLOG(ERROR, result)
- << "AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed.";
- return false;
- }
-
- // Set the buffer frame size.
- // WARNING: Setting this value changes the frame size for all audio units in
- // the current process. It's imperative that the input and output frame sizes
- // be the same as the frames_per_buffer() returned by
- // GetDefaultOutputStreamParameters.
- // See http://crbug.com/154352 for details.
- const AudioParameters hw_params =
- manager_->GetDefaultOutputStreamParameters();
- if (number_of_frames_ != static_cast<size_t>(hw_params.frames_per_buffer())) {
- DLOG(ERROR) << "Audio buffer size does not match hardware buffer size.";
- return false;
- }
-
- UInt32 buffer_size = number_of_frames_;
- result = AudioUnitSetProperty(
- output_unit_,
- kAudioDevicePropertyBufferFrameSize,
- kAudioUnitScope_Output,
- 0,
- &buffer_size,
- sizeof(buffer_size));
- if (result != noErr) {
- OSSTATUS_DLOG(ERROR, result)
- << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed.";
- return false;
- }
-
- return true;
-}
-
-void AUAudioOutputStream::Close() {
- if (output_unit_)
- AudioComponentInstanceDispose(output_unit_);
-
- // Inform the audio manager that we have been closed. This can cause our
- // destruction.
- manager_->ReleaseOutputStream(this);
-}
-
-void AUAudioOutputStream::Start(AudioSourceCallback* callback) {
- DCHECK(callback);
- if (!output_unit_) {
- DLOG(ERROR) << "Open() has not been called successfully";
- return;
- }
-
- stopped_ = false;
- {
- base::AutoLock auto_lock(source_lock_);
- source_ = callback;
- }
-
- AudioOutputUnitStart(output_unit_);
-}
-
-void AUAudioOutputStream::Stop() {
- if (stopped_)
- return;
-
- AudioOutputUnitStop(output_unit_);
-
- base::AutoLock auto_lock(source_lock_);
- source_ = NULL;
- stopped_ = true;
-}
-
-void AUAudioOutputStream::SetVolume(double volume) {
- if (!output_unit_)
- return;
- volume_ = static_cast<float>(volume);
-
- // TODO(crogers): set volume property
-}
-
-void AUAudioOutputStream::GetVolume(double* volume) {
- if (!output_unit_)
- return;
- *volume = volume_;
-}
-
-// Pulls on our provider to get rendered audio stream.
-// Note to future hackers of this function: Do not add locks here because this
-// is running on a real-time thread (for low-latency).
-OSStatus AUAudioOutputStream::Render(UInt32 number_of_frames,
- AudioBufferList* io_data,
- const AudioTimeStamp* output_time_stamp) {
- // Update the playout latency.
- double playout_latency_frames = GetPlayoutLatency(output_time_stamp);
-
- AudioBuffer& buffer = io_data->mBuffers[0];
- uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
- uint32 hardware_pending_bytes = static_cast<uint32>
- ((playout_latency_frames + 0.5) * format_.mBytesPerFrame);
-
- // Unfortunately AUAudioInputStream and AUAudioOutputStream share the frame
- // size set by kAudioDevicePropertyBufferFrameSize above on a per process
- // basis. What this means is that the |number_of_frames| value may be larger
- // or smaller than the value set during Configure(). In this case either
- // audio input or audio output will be broken, so just output silence.
- // TODO(crogers): Figure out what can trigger a change in |number_of_frames|.
- // See http://crbug.com/154352 for details.
- if (number_of_frames != static_cast<UInt32>(audio_bus_->frames())) {
- memset(audio_data, 0, number_of_frames * format_.mBytesPerFrame);
- return noErr;
- }
-
- int frames_filled = 0;
- {
- // Render() shouldn't be called except between AudioOutputUnitStart() and
- // AudioOutputUnitStop() calls, but crash reports have shown otherwise:
- // http://crbug.com/178765. We use |source_lock_| to prevent races and
- // crashes in Render() when |source_| is cleared.
- base::AutoLock auto_lock(source_lock_);
- if (!source_) {
- memset(audio_data, 0, number_of_frames * format_.mBytesPerFrame);
- return noErr;
- }
-
- frames_filled = source_->OnMoreData(
- audio_bus_.get(), AudioBuffersState(0, hardware_pending_bytes));
- }
-
- // Note: If this ever changes to output raw float the data must be clipped and
- // sanitized since it may come from an untrusted source such as NaCl.
- audio_bus_->Scale(volume_);
- audio_bus_->ToInterleaved(
- frames_filled, format_.mBitsPerChannel / 8, audio_data);
-
- return noErr;
-}
-
-// DefaultOutputUnit callback
-OSStatus AUAudioOutputStream::InputProc(void* user_data,
- AudioUnitRenderActionFlags*,
- const AudioTimeStamp* output_time_stamp,
- UInt32,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- AUAudioOutputStream* audio_output =
- static_cast<AUAudioOutputStream*>(user_data);
- if (!audio_output)
- return -1;
-
- return audio_output->Render(number_of_frames, io_data, output_time_stamp);
-}
-
-int AUAudioOutputStream::HardwareSampleRate() {
- // Determine the default output device's sample-rate.
- AudioDeviceID device_id = kAudioObjectUnknown;
- UInt32 info_size = sizeof(device_id);
- OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
- &kDefaultOutputDeviceAddress,
- 0,
- 0,
- &info_size,
- &device_id);
- if (result != noErr || device_id == kAudioObjectUnknown) {
- OSSTATUS_DLOG(WARNING, result)
- << "Could not get default audio output device.";
- return 0;
- }
-
- Float64 nominal_sample_rate;
- info_size = sizeof(nominal_sample_rate);
-
- AudioObjectPropertyAddress nominal_sample_rate_address = {
- kAudioDevicePropertyNominalSampleRate,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
- result = AudioObjectGetPropertyData(device_id,
- &nominal_sample_rate_address,
- 0,
- 0,
- &info_size,
- &nominal_sample_rate);
- if (result != noErr) {
- OSSTATUS_DLOG(WARNING, result)
- << "Could not get default sample rate for device: " << device_id;
- return 0;
- }
-
- return static_cast<int>(nominal_sample_rate);
-}
-
-double AUAudioOutputStream::GetHardwareLatency() {
- if (!output_unit_ || output_device_id_ == kAudioObjectUnknown) {
- DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown";
- return 0.0;
- }
-
- // Get audio unit latency.
- Float64 audio_unit_latency_sec = 0.0;
- UInt32 size = sizeof(audio_unit_latency_sec);
- OSStatus result = AudioUnitGetProperty(output_unit_,
- kAudioUnitProperty_Latency,
- kAudioUnitScope_Global,
- 0,
- &audio_unit_latency_sec,
- &size);
- if (result != noErr) {
- OSSTATUS_DLOG(WARNING, result) << "Could not get audio unit latency";
- return 0.0;
- }
-
- // Get output audio device latency.
- AudioObjectPropertyAddress property_address = {
- kAudioDevicePropertyLatency,
- kAudioDevicePropertyScopeOutput,
- kAudioObjectPropertyElementMaster
- };
- UInt32 device_latency_frames = 0;
- size = sizeof(device_latency_frames);
- result = AudioObjectGetPropertyData(output_device_id_,
- &property_address,
- 0,
- NULL,
- &size,
- &device_latency_frames);
- if (result != noErr) {
- OSSTATUS_DLOG(WARNING, result) << "Could not get audio unit latency";
- return 0.0;
- }
-
- return static_cast<double>((audio_unit_latency_sec *
- format_.mSampleRate) + device_latency_frames);
-}
-
-double AUAudioOutputStream::GetPlayoutLatency(
- const AudioTimeStamp* output_time_stamp) {
- // Ensure mHostTime is valid.
- if ((output_time_stamp->mFlags & kAudioTimeStampHostTimeValid) == 0)
- return 0;
-
- // Get the delay between the moment getting the callback and the scheduled
- // time stamp that tells when the data is going to be played out.
- UInt64 output_time_ns = AudioConvertHostTimeToNanos(
- output_time_stamp->mHostTime);
- UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
-
- // Prevent overflow leading to huge delay information; occurs regularly on
- // the bots, probably less so in the wild.
- if (now_ns > output_time_ns)
- return 0;
-
- double delay_frames = static_cast<double>
- (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate);
-
- return (delay_frames + hardware_latency_frames_);
-}
-
-} // namespace media
« no previous file with comments | « media/audio/mac/audio_low_latency_output_mac.h ('k') | media/audio/mac/audio_manager_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698