summaryrefslogtreecommitdiffstats
path: root/media/audio/linux/alsa_output.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/audio/linux/alsa_output.cc')
-rw-r--r--media/audio/linux/alsa_output.cc32
1 files changed, 18 insertions, 14 deletions
diff --git a/media/audio/linux/alsa_output.cc b/media/audio/linux/alsa_output.cc
index 1ecd685..0726eff 100644
--- a/media/audio/linux/alsa_output.cc
+++ b/media/audio/linux/alsa_output.cc
@@ -474,21 +474,25 @@ void AlsaPcmOutputStream::BufferPacket(Packet* packet) {
if (packet->used >= packet->size) {
// Before making a request to source for data. We need to determine the
// delay (in bytes) for the requested data to be played.
- snd_pcm_sframes_t delay;
- int error = wrapper_->PcmDelay(playback_handle_, &delay);
- if (error < 0) {
- error = wrapper_->PcmRecover(playback_handle_,
- error,
- kPcmRecoverIsSilent);
- if (error < 0) {
- LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error);
+ snd_pcm_sframes_t delay = 0;
+
+ // Don't query ALSA's delay if we have underrun since it'll be jammed at
+ // some non-zero value and potentially even negative!
+ if (wrapper_->PcmState(playback_handle_) != SND_PCM_STATE_XRUN) {
+ int error = wrapper_->PcmDelay(playback_handle_, &delay);
+ if (error >= 0) {
+ // Convert frames to bytes, but watch out for those negatives!
+ delay = (delay < 0 ? 0 : delay) * bytes_per_output_frame_;
+ } else {
+ // Assume a delay of zero and attempt to recover the device.
+ delay = 0;
+ error = wrapper_->PcmRecover(playback_handle_,
+ error,
+ kPcmRecoverIsSilent);
+ if (error < 0) {
+ LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error);
+ }
}
-
- // TODO(hclam): If we cannot query the delay, we may want to stop
- // the playback and report an error.
- delay = 0;
- } else {
- delay *= bytes_per_output_frame_;
}
packet->used = 0;