| 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 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 return; | 479 return; |
| 480 } | 480 } |
| 481 | 481 |
| 482 *source_exhausted = false; | 482 *source_exhausted = false; |
| 483 | 483 |
| 484 // Request more data if we have capacity. | 484 // Request more data if we have capacity. |
| 485 if (buffer_->forward_capacity() > buffer_->forward_bytes()) { | 485 if (buffer_->forward_capacity() > buffer_->forward_bytes()) { |
| 486 // Before making a request to source for data. We need to determine the | 486 // Before making a request to source for data. We need to determine the |
| 487 // delay (in bytes) for the requested data to be played. | 487 // delay (in bytes) for the requested data to be played. |
| 488 snd_pcm_sframes_t delay = buffer_->forward_bytes() * bytes_per_frame_ / | 488 snd_pcm_sframes_t delay = buffer_->forward_bytes() * bytes_per_frame_ / |
| 489 bytes_per_output_frame_ + GetCurrentDelay() * bytes_per_output_frame_; | 489 bytes_per_output_frame_; |
| 490 | 490 |
| 491 scoped_refptr<media::DataBuffer> packet = | 491 scoped_refptr<media::DataBuffer> packet = |
| 492 new media::DataBuffer(packet_size_); | 492 new media::DataBuffer(packet_size_); |
| 493 size_t packet_size = | 493 size_t packet_size = |
| 494 shared_data_.OnMoreData(this, packet->GetWritableData(), | 494 shared_data_.OnMoreData(this, packet->GetWritableData(), |
| 495 packet->GetBufferSize(), delay); | 495 packet->GetBufferSize(), delay); |
| 496 CHECK(packet_size <= packet->GetBufferSize()) << | 496 CHECK(packet_size <= packet->GetBufferSize()) << |
| 497 "Data source overran buffer."; | 497 "Data source overran buffer."; |
| 498 | 498 |
| 499 // This should not happen, but incase it does, drop any trailing bytes | 499 // This should not happen, but in case it does, drop any trailing bytes |
| 500 // that aren't large enough to make a frame. Without this, packet writing | 500 // 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 | 501 // may stall because the last few bytes in the packet may never get used by |
| 502 // WritePacket. | 502 // WritePacket. |
| 503 DCHECK(packet_size % bytes_per_frame_ == 0); | 503 DCHECK(packet_size % bytes_per_frame_ == 0); |
| 504 packet_size = (packet_size / bytes_per_frame_) * bytes_per_frame_; | 504 packet_size = (packet_size / bytes_per_frame_) * bytes_per_frame_; |
| 505 | 505 |
| 506 if (should_downmix_) { | 506 if (should_downmix_) { |
| 507 if (media::FoldChannels(packet->GetWritableData(), | 507 if (media::FoldChannels(packet->GetWritableData(), |
| 508 packet_size, | 508 packet_size, |
| 509 channels_, | 509 channels_, |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 } | 794 } |
| 795 if (available_frames < 0) { | 795 if (available_frames < 0) { |
| 796 LOG(ERROR) << "Failed querying available frames. Assuming 0: " | 796 LOG(ERROR) << "Failed querying available frames. Assuming 0: " |
| 797 << wrapper_->StrError(available_frames); | 797 << wrapper_->StrError(available_frames); |
| 798 return 0; | 798 return 0; |
| 799 } | 799 } |
| 800 | 800 |
| 801 return available_frames; | 801 return available_frames; |
| 802 } | 802 } |
| 803 | 803 |
| 804 snd_pcm_sframes_t AlsaPcmOutputStream::GetCurrentDelay() { | |
| 805 snd_pcm_sframes_t delay = 0; | |
| 806 | |
| 807 // Don't query ALSA's delay if we have underrun since it'll be jammed at | |
| 808 // some non-zero value and potentially even negative! | |
| 809 if (wrapper_->PcmState(playback_handle_) != SND_PCM_STATE_XRUN) { | |
| 810 int error = wrapper_->PcmDelay(playback_handle_, &delay); | |
| 811 if (error < 0) { | |
| 812 // Assume a delay of zero and attempt to recover the device. | |
| 813 delay = 0; | |
| 814 error = wrapper_->PcmRecover(playback_handle_, | |
| 815 error, | |
| 816 kPcmRecoverIsSilent); | |
| 817 if (error < 0) { | |
| 818 LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error); | |
| 819 } | |
| 820 } | |
| 821 if (delay < 0) | |
| 822 delay = 0; | |
| 823 } | |
| 824 return delay; | |
| 825 } | |
| 826 | |
| 827 snd_pcm_t* AlsaPcmOutputStream::AutoSelectDevice(unsigned int latency) { | 804 snd_pcm_t* AlsaPcmOutputStream::AutoSelectDevice(unsigned int latency) { |
| 828 // For auto-selection: | 805 // For auto-selection: |
| 829 // 1) Attempt to open a device that best matches the number of channels | 806 // 1) Attempt to open a device that best matches the number of channels |
| 830 // requested. | 807 // requested. |
| 831 // 2) If that fails, attempt the "plug:" version of it incase ALSA can | 808 // 2) If that fails, attempt the "plug:" version of it incase ALSA can |
| 832 // remap do some software conversion to make it work. | 809 // remap do some software conversion to make it work. |
| 833 // 3) Fallback to kDefaultDevice. | 810 // 3) Fallback to kDefaultDevice. |
| 834 // 4) If that fails too, try the "plug:" version of kDefaultDevice. | 811 // 4) If that fails too, try the "plug:" version of kDefaultDevice. |
| 835 // 5) Give up. | 812 // 5) Give up. |
| 836 snd_pcm_t* handle = NULL; | 813 snd_pcm_t* handle = NULL; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 } | 959 } |
| 983 | 960 |
| 984 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to | 961 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to |
| 985 // release ownership of the currently registered callback. | 962 // release ownership of the currently registered callback. |
| 986 void AlsaPcmOutputStream::SharedData::set_source_callback( | 963 void AlsaPcmOutputStream::SharedData::set_source_callback( |
| 987 AudioSourceCallback* callback) { | 964 AudioSourceCallback* callback) { |
| 988 DCHECK_EQ(MessageLoop::current(), state_transition_loop_); | 965 DCHECK_EQ(MessageLoop::current(), state_transition_loop_); |
| 989 AutoLock l(lock_); | 966 AutoLock l(lock_); |
| 990 source_callback_ = callback; | 967 source_callback_ = callback; |
| 991 } | 968 } |
| OLD | NEW |