| 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;
|
| } 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.
|
|
|