Chromium Code Reviews| 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. |