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

Unified 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: Add log. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/mac/audio_auhal_mac.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/mac/audio_auhal_mac.cc
diff --git a/media/audio/mac/audio_auhal_mac.cc b/media/audio/mac/audio_auhal_mac.cc
index 6badbe9d285a20bbf54f9eb1e0f5c6802b241a65..9fcd46a6a95a71fdd63a3680bb76d91f6277c487 100644
--- a/media/audio/mac/audio_auhal_mac.cc
+++ b/media/audio/mac/audio_auhal_mac.cc
@@ -7,12 +7,11 @@
#include <CoreServices/CoreServices.h>
#include "base/basictypes.h"
-#include "base/command_line.h"
#include "base/debug/trace_event.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"
+#include "media/base/audio_pull_fifo.h"
namespace media {
@@ -58,8 +57,8 @@ AUHALStream::AUHALStream(
volume_(1),
hardware_latency_frames_(0),
stopped_(false),
- notified_for_possible_device_change_(false),
- input_buffer_list_(NULL) {
+ input_buffer_list_(NULL),
+ current_hardware_pending_bytes_(0) {
// We must have a manager.
DCHECK(manager_);
@@ -150,7 +149,7 @@ void AUHALStream::Start(AudioSourceCallback* callback) {
}
stopped_ = false;
- notified_for_possible_device_change_ = false;
+ audio_fifo_.reset();
{
base::AutoLock auto_lock(source_lock_);
source_ = callback;
@@ -200,63 +199,69 @@ OSStatus AUHALStream::Render(
AudioBufferList* io_data) {
TRACE_EVENT0("audio", "AUHALStream::Render");
+ // If the stream parameters change for any reason, we need to insert a FIFO
+ // since the OnMoreData() pipeline can't handle frame size changes. Generally
+ // this is a temporary situation which can occur after a device change has
+ // occurred but the AudioManager hasn't received the notification yet.
if (number_of_frames != number_of_frames_) {
- // This can happen if we've suddenly changed sample-rates.
- // The stream should be stopping very soon.
- //
- // Unfortunately AUAudioInputStream and AUHALStream 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 ConfigureAUHAL().
- // In this case either audio input or audio output will be broken,
- // so just output silence.
- ZeroBufferList(io_data);
- return noErr;
- }
+ // Create a FIFO on the fly to handle any discrepancies in callback rates.
+ if (!audio_fifo_) {
+ VLOG(1) << "Audio frame size change detected; adding FIFO to compensate.";
+ audio_fifo_.reset(new AudioPullFifo(
+ output_channels_,
+ number_of_frames_,
+ base::Bind(&AUHALStream::ProvideInput, base::Unretained(this))));
+ }
- if (input_channels_ > 0 && input_buffer_list_) {
- // Get the input data. |input_buffer_list_| is wrapped
- // to point to the data allocated in |input_bus_|.
- OSStatus result = AudioUnitRender(
- audio_unit_,
- flags,
- output_time_stamp,
- 1,
- number_of_frames,
- input_buffer_list_);
- if (result != noErr)
- ZeroBufferList(input_buffer_list_);
+ // Synchronous IO is not supported in this state.
+ if (input_channels_ > 0)
+ input_bus_->Zero();
+ } else {
+ if (input_channels_ > 0 && input_buffer_list_) {
+ // Get the input data. |input_buffer_list_| is wrapped
+ // to point to the data allocated in |input_bus_|.
+ OSStatus result = AudioUnitRender(audio_unit_,
+ flags,
+ output_time_stamp,
+ 1,
+ number_of_frames,
+ input_buffer_list_);
+ if (result != noErr)
+ ZeroBufferList(input_buffer_list_);
+ }
}
// Make |output_bus_| wrap the output AudioBufferList.
WrapBufferList(io_data, output_bus_.get(), number_of_frames);
// Update the playout latency.
- double playout_latency_frames = GetPlayoutLatency(output_time_stamp);
+ const double playout_latency_frames = GetPlayoutLatency(output_time_stamp);
+ current_hardware_pending_bytes_ = static_cast<uint32>(
+ (playout_latency_frames + 0.5) * params_.GetBytesPerFrame());
- uint32 hardware_pending_bytes = static_cast<uint32>
- ((playout_latency_frames + 0.5) * output_format_.mBytesPerFrame);
+ if (audio_fifo_)
+ audio_fifo_->Consume(output_bus_.get(), output_bus_->frames());
+ else
+ ProvideInput(0, output_bus_.get());
- {
- // 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_) {
- ZeroBufferList(io_data);
- return noErr;
- }
+ return noErr;
+}
- // Supply the input data and render the output data.
- source_->OnMoreIOData(
- input_bus_.get(),
- output_bus_.get(),
- AudioBuffersState(0, hardware_pending_bytes));
- output_bus_->Scale(volume_);
+void AUHALStream::ProvideInput(int frame_delay, AudioBus* dest) {
+ base::AutoLock auto_lock(source_lock_);
+ if (!source_) {
+ dest->Zero();
+ return;
}
- return noErr;
+ // Supply the input data and render the output data.
+ source_->OnMoreIOData(
+ input_bus_.get(),
+ dest,
+ AudioBuffersState(0,
+ current_hardware_pending_bytes_ +
+ frame_delay * params_.GetBytesPerFrame()));
+ dest->Scale(volume_);
}
// AUHAL callback.
« no previous file with comments | « 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