Commit 95492705 authored by xians@chromium.org's avatar xians@chromium.org

Reland 7976047 to fix the alsa output scheduling for low latency audio.

This patch is to allow using 10ms buffersize or above, and it also optimize the WebAudio performance by using 5ms as the minimum interview between two OnMoreData() calls.

Bug=None
Test=media_unittests, manully tests:
WebAudio: http://chromium.googlecode.com/svn/trunk/samples/audio/shiny-drum-machine.html (change audio_util.cc to return 512 as buffersize)
WebRTC: Internal test app
Html5: http://www.youtube.com/watch?v=siOHh0uzcuY
Chromebook: http://www.youtube.com/watch?v=-9AtssRoc2Q&feature=related

Review URL: http://codereview.chromium.org/8465018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109852 0039d316-1c4b-4281-b951-d872f2087c98
parent 42130d3f
......@@ -58,6 +58,9 @@
// busy looping.
static const uint32 kNoDataSleepMilliseconds = 10;
// Mininum interval between OnMoreData() calls.
const uint32 kMinIntervalBetweenOnMoreDataCallsInMs = 5;
// According to the linux nanosleep manpage, nanosleep on linux can miss the
// deadline by up to 10ms because the kernel timeslice is 10ms. Give a 2x
// buffer to compensate for the timeslice, and any additional slowdowns.
......@@ -347,7 +350,8 @@ void AlsaPcmOutputStream::OpenTask() {
if (error < 0) {
LOG(ERROR) << "Failed to get playback buffer size from ALSA: "
<< wrapper_->StrError(error);
alsa_buffer_frames_ = frames_per_packet_;
// Buffer size is at least twice of packet size.
alsa_buffer_frames_ = frames_per_packet_ * 2;
} else {
alsa_buffer_frames_ = buffer_size;
}
......@@ -427,8 +431,9 @@ void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
*source_exhausted = false;
// Request more data if we have capacity.
if (buffer_->forward_capacity() > buffer_->forward_bytes()) {
// Request more data only when we run out of data in the buffer, because
// WritePacket() comsumes only the current chunk of data.
if (!buffer_->forward_bytes()) {
// Before making a request to source for data we need to determine the
// delay (in bytes) for the requested data to be played.
......@@ -597,25 +602,38 @@ void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) {
return;
}
// Next write is scheduled for the moment when half of the buffer is
// available.
uint32 frames_avail_wanted = alsa_buffer_frames_ / 2;
uint32 available_frames = GetAvailableFrames();
uint32 next_fill_time_ms = 0;
uint32 frames_in_buffer = buffer_->forward_bytes() / bytes_per_output_frame_;
// It's possible to have more frames available than what we want, in which
// case we'll leave our |next_fill_time_ms| at 0ms.
if (available_frames < frames_avail_wanted) {
uint32 frames_until_empty_enough = frames_avail_wanted - available_frames;
next_fill_time_ms =
FramesToMillis(frames_until_empty_enough, sample_rate_);
}
// Next write is initially scheduled for the moment when half of a packet
// has been played out.
uint32 next_fill_time_ms =
FramesToMillis(frames_per_packet_ / 2, sample_rate_);
// Adjust for timer resolution issues.
if (next_fill_time_ms < kSleepErrorMilliseconds) {
if (frames_in_buffer && (frames_in_buffer <= available_frames)) {
// There is data in the current buffer, consume them immediately if we have
// enough space in the soundcard.
next_fill_time_ms = 0;
} else {
next_fill_time_ms -= kSleepErrorMilliseconds;
// Otherwise schedule the next write for the moment when half of the alsa
// buffer becomes available.
if (available_frames < frames_avail_wanted) {
uint32 frames_until_empty_enough = frames_avail_wanted - available_frames;
next_fill_time_ms =
FramesToMillis(frames_until_empty_enough, sample_rate_);
// Adjust for time resolution.
if (next_fill_time_ms > kNoDataSleepMilliseconds)
next_fill_time_ms -= kNoDataSleepMilliseconds;
// Avoid back-to-back writing.
if (next_fill_time_ms < kMinIntervalBetweenOnMoreDataCallsInMs)
next_fill_time_ms = kMinIntervalBetweenOnMoreDataCallsInMs;
} else if (available_frames == alsa_buffer_frames_) {
// Buffer is empty, invoke next write immediately.
next_fill_time_ms = 0;
}
}
// Avoid busy looping if the data source is exhausted.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment