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

Unified Diff: media/audio/linux/alsa_output.cc

Issue 8465018: Reland 7976047 to fix the alsa output scheduling for low latency audio. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/linux/alsa_output.cc
===================================================================
--- media/audio/linux/alsa_output.cc (revision 108881)
+++ media/audio/linux/alsa_output.cc (working copy)
@@ -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 @@
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;
Raymond Toy (Google) 2011/11/11 22:01:25 Why is this twice now when it used to be the same?
} else {
alsa_buffer_frames_ = buffer_size;
}
@@ -427,8 +431,9 @@
*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 @@
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.
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698