| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // THREAD SAFETY | 5 // THREAD SAFETY |
| 6 // | 6 // |
| 7 // The AlsaPcmOutputStream object's internal state is accessed by two threads: | 7 // The AlsaPcmOutputStream object's internal state is accessed by two threads: |
| 8 // | 8 // |
| 9 // client thread - creates the object and calls the public APIs. | 9 // client thread - creates the object and calls the public APIs. |
| 10 // message loop thread - executes all the internal tasks including querying | 10 // message loop thread - executes all the internal tasks including querying |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 // If stopped, simulate a 0-lengthed packet. | 467 // If stopped, simulate a 0-lengthed packet. |
| 468 if (stop_stream_) { | 468 if (stop_stream_) { |
| 469 packet->used = packet->size = 0; | 469 packet->used = packet->size = 0; |
| 470 return; | 470 return; |
| 471 } | 471 } |
| 472 | 472 |
| 473 // Request more data if we don't have any cached. | 473 // Request more data if we don't have any cached. |
| 474 if (packet->used >= packet->size) { | 474 if (packet->used >= packet->size) { |
| 475 // Before making a request to source for data. We need to determine the | 475 // Before making a request to source for data. We need to determine the |
| 476 // delay (in bytes) for the requested data to be played. | 476 // delay (in bytes) for the requested data to be played. |
| 477 snd_pcm_sframes_t delay; | 477 snd_pcm_sframes_t delay = 0; |
| 478 int error = wrapper_->PcmDelay(playback_handle_, &delay); | 478 |
| 479 if (error < 0) { | 479 // Don't query ALSA's delay if we have underrun since it'll be jammed at |
| 480 error = wrapper_->PcmRecover(playback_handle_, | 480 // some non-zero value and potentially even negative! |
| 481 error, | 481 if (wrapper_->PcmState(playback_handle_) != SND_PCM_STATE_XRUN) { |
| 482 kPcmRecoverIsSilent); | 482 int error = wrapper_->PcmDelay(playback_handle_, &delay); |
| 483 if (error < 0) { | 483 if (error >= 0) { |
| 484 LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error); | 484 // Convert frames to bytes, but watch out for those negatives! |
| 485 delay = (delay < 0 ? 0 : delay) * bytes_per_output_frame_; |
| 486 } else { |
| 487 // Assume a delay of zero and attempt to recover the device. |
| 488 delay = 0; |
| 489 error = wrapper_->PcmRecover(playback_handle_, |
| 490 error, |
| 491 kPcmRecoverIsSilent); |
| 492 if (error < 0) { |
| 493 LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error); |
| 494 } |
| 485 } | 495 } |
| 486 | |
| 487 // TODO(hclam): If we cannot query the delay, we may want to stop | |
| 488 // the playback and report an error. | |
| 489 delay = 0; | |
| 490 } else { | |
| 491 delay *= bytes_per_output_frame_; | |
| 492 } | 496 } |
| 493 | 497 |
| 494 packet->used = 0; | 498 packet->used = 0; |
| 495 packet->size = shared_data_.OnMoreData(this, packet->buffer.get(), | 499 packet->size = shared_data_.OnMoreData(this, packet->buffer.get(), |
| 496 packet->capacity, delay); | 500 packet->capacity, delay); |
| 497 CHECK(packet->size <= packet->capacity) << "Data source overran buffer."; | 501 CHECK(packet->size <= packet->capacity) << "Data source overran buffer."; |
| 498 | 502 |
| 499 // This should not happen, but incase it does, drop any trailing bytes | 503 // This should not happen, but incase it does, drop any trailing bytes |
| 500 // that aren't large enough to make a frame. Without this, packet writing | 504 // that aren't large enough to make a frame. Without this, packet writing |
| 501 // may stall because the last few bytes in the packet may never get used by | 505 // may stall because the last few bytes in the packet may never get used by |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 } | 962 } |
| 959 | 963 |
| 960 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to | 964 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to |
| 961 // release ownership of the currently registered callback. | 965 // release ownership of the currently registered callback. |
| 962 void AlsaPcmOutputStream::SharedData::set_source_callback( | 966 void AlsaPcmOutputStream::SharedData::set_source_callback( |
| 963 AudioSourceCallback* callback) { | 967 AudioSourceCallback* callback) { |
| 964 DCHECK_EQ(MessageLoop::current(), state_transition_loop_); | 968 DCHECK_EQ(MessageLoop::current(), state_transition_loop_); |
| 965 AutoLock l(lock_); | 969 AutoLock l(lock_); |
| 966 source_callback_ = callback; | 970 source_callback_ = callback; |
| 967 } | 971 } |
| OLD | NEW |