| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // AlsaPcmOutputStream object is *not* thread-safe and should only be used | 7 // AlsaPcmOutputStream object is *not* thread-safe and should only be used | 
| 8 // from the audio thread.  We DCHECK on this assumption whenever we can. | 8 // from the audio thread.  We DCHECK on this assumption whenever we can. | 
| 9 // | 9 // | 
| 10 // SEMANTICS OF Close() | 10 // SEMANTICS OF Close() | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 84 // | 84 // | 
| 85 // This function makes a best guess at the specific > 2 channel device name | 85 // This function makes a best guess at the specific > 2 channel device name | 
| 86 // based on the number of channels requested.  NULL is returned if no device | 86 // based on the number of channels requested.  NULL is returned if no device | 
| 87 // can be found to match the channel numbers.  In this case, using | 87 // can be found to match the channel numbers.  In this case, using | 
| 88 // kDefaultDevice is probably the best bet. | 88 // kDefaultDevice is probably the best bet. | 
| 89 // | 89 // | 
| 90 // A five channel source is assumed to be surround50 instead of surround41 | 90 // A five channel source is assumed to be surround50 instead of surround41 | 
| 91 // (which is also 5 channels). | 91 // (which is also 5 channels). | 
| 92 // | 92 // | 
| 93 // TODO(ajwong): The source data should have enough info to tell us if we want | 93 // TODO(ajwong): The source data should have enough info to tell us if we want | 
| 94 // surround41 versus surround51, etc., instead of needing us to guess base don | 94 // surround41 versus surround51, etc., instead of needing us to guess based on | 
| 95 // channel number.  Fix API to pass that data down. | 95 // channel number.  Fix API to pass that data down. | 
| 96 static const char* GuessSpecificDeviceName(uint32 channels) { | 96 static const char* GuessSpecificDeviceName(uint32 channels) { | 
| 97   switch (channels) { | 97   switch (channels) { | 
| 98     case 8: | 98     case 8: | 
| 99       return "surround71"; | 99       return "surround71"; | 
| 100 | 100 | 
| 101     case 7: | 101     case 7: | 
| 102       return "surround70"; | 102       return "surround70"; | 
| 103 | 103 | 
| 104     case 6: | 104     case 6: | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 168       alsa_buffer_frames_(0), | 168       alsa_buffer_frames_(0), | 
| 169       stop_stream_(false), | 169       stop_stream_(false), | 
| 170       wrapper_(wrapper), | 170       wrapper_(wrapper), | 
| 171       manager_(manager), | 171       manager_(manager), | 
| 172       message_loop_(MessageLoop::current()), | 172       message_loop_(MessageLoop::current()), | 
| 173       playback_handle_(NULL), | 173       playback_handle_(NULL), | 
| 174       frames_per_packet_(packet_size_ / bytes_per_frame_), | 174       frames_per_packet_(packet_size_ / bytes_per_frame_), | 
| 175       ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 175       ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 
| 176       state_(kCreated), | 176       state_(kCreated), | 
| 177       volume_(1.0f), | 177       volume_(1.0f), | 
| 178       source_callback_(NULL) { | 178       source_callback_(NULL), | 
|  | 179       audio_bus_(AudioBus::Create(params)) { | 
| 179   DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 180   DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 
|  | 181   DCHECK_EQ(audio_bus_->frames() * bytes_per_frame_, packet_size_); | 
| 180 | 182 | 
| 181   // Sanity check input values. | 183   // Sanity check input values. | 
| 182   if (params.sample_rate() > kAlsaMaxSampleRate || | 184   if (params.sample_rate() > kAlsaMaxSampleRate || | 
| 183       params.sample_rate() <= 0) { | 185       params.sample_rate() <= 0) { | 
| 184     LOG(WARNING) << "Unsupported audio frequency."; | 186     LOG(WARNING) << "Unsupported audio frequency."; | 
| 185     TransitionTo(kInError); | 187     TransitionTo(kInError); | 
| 186   } | 188   } | 
| 187 | 189 | 
| 188   if (AudioParameters::AUDIO_PCM_LINEAR != params.format() && | 190   if (AudioParameters::AUDIO_PCM_LINEAR != params.format() && | 
| 189       AudioParameters::AUDIO_PCM_LOW_LATENCY != params.format()) { | 191       AudioParameters::AUDIO_PCM_LOW_LATENCY != params.format()) { | 
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 369     // Before making a request to source for data we need to determine the | 371     // Before making a request to source for data we need to determine the | 
| 370     // delay (in bytes) for the requested data to be played. | 372     // delay (in bytes) for the requested data to be played. | 
| 371 | 373 | 
| 372     uint32 buffer_delay = buffer_->forward_bytes() * bytes_per_frame_ / | 374     uint32 buffer_delay = buffer_->forward_bytes() * bytes_per_frame_ / | 
| 373         bytes_per_output_frame_; | 375         bytes_per_output_frame_; | 
| 374 | 376 | 
| 375     uint32 hardware_delay = GetCurrentDelay() * bytes_per_frame_; | 377     uint32 hardware_delay = GetCurrentDelay() * bytes_per_frame_; | 
| 376 | 378 | 
| 377     scoped_refptr<media::DataBuffer> packet = | 379     scoped_refptr<media::DataBuffer> packet = | 
| 378         new media::DataBuffer(packet_size_); | 380         new media::DataBuffer(packet_size_); | 
| 379     int packet_size = RunDataCallback(packet->GetWritableData(), | 381     int frames_filled = RunDataCallback( | 
| 380                                       packet->GetBufferSize(), | 382         audio_bus_.get(), AudioBuffersState(buffer_delay, hardware_delay)); | 
| 381                                       AudioBuffersState(buffer_delay, | 383     size_t packet_size = frames_filled * bytes_per_frame_; | 
| 382                                                         hardware_delay)); | 384     DCHECK_LE(packet_size, packet_size_); | 
| 383     CHECK_LE(packet_size, packet->GetBufferSize()); | 385     // Note: If this ever changes to output raw float the data must be clipped | 
|  | 386     // and sanitized since it may come from an untrusted source such as NaCl. | 
|  | 387     audio_bus_->ToInterleaved( | 
|  | 388         frames_filled, bytes_per_sample_, packet->GetWritableData()); | 
| 384 | 389 | 
| 385     // Reset the |last_fill_time| to avoid back to back RunDataCallback(). | 390     // Reset the |last_fill_time| to avoid back to back RunDataCallback(). | 
| 386     last_fill_time_ = base::Time::Now(); | 391     last_fill_time_ = base::Time::Now(); | 
| 387 | 392 | 
| 388     // This should not happen, but in case it does, drop any trailing bytes | 393     // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer; | 
| 389     // that aren't large enough to make a frame.  Without this, packet writing | 394     // volume adjust should use SSE optimized vector_fmul() prior to interleave. | 
| 390     // may stall because the last few bytes in the packet may never get used by |  | 
| 391     // WritePacket. |  | 
| 392     DCHECK_EQ(0u, packet_size % bytes_per_frame_); |  | 
| 393     packet_size = (packet_size / bytes_per_frame_) * bytes_per_frame_; |  | 
| 394 |  | 
| 395     if (should_downmix_) { | 395     if (should_downmix_) { | 
| 396       if (media::FoldChannels(packet->GetWritableData(), | 396       if (media::FoldChannels(packet->GetWritableData(), | 
| 397                               packet_size, | 397                               packet_size, | 
| 398                               channels_, | 398                               channels_, | 
| 399                               bytes_per_sample_, | 399                               bytes_per_sample_, | 
| 400                               volume_)) { | 400                               volume_)) { | 
| 401         // Adjust packet size for downmix. | 401         // Adjust packet size for downmix. | 
| 402         packet_size = packet_size / bytes_per_frame_ * bytes_per_output_frame_; | 402         packet_size = packet_size / bytes_per_frame_ * bytes_per_output_frame_; | 
| 403       } else { | 403       } else { | 
| 404         LOG(ERROR) << "Folding failed"; | 404         LOG(ERROR) << "Folding failed"; | 
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 777 } | 777 } | 
| 778 | 778 | 
| 779 AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() { | 779 AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() { | 
| 780   return state_; | 780   return state_; | 
| 781 } | 781 } | 
| 782 | 782 | 
| 783 bool AlsaPcmOutputStream::IsOnAudioThread() const { | 783 bool AlsaPcmOutputStream::IsOnAudioThread() const { | 
| 784   return message_loop_ && message_loop_ == MessageLoop::current(); | 784   return message_loop_ && message_loop_ == MessageLoop::current(); | 
| 785 } | 785 } | 
| 786 | 786 | 
| 787 uint32 AlsaPcmOutputStream::RunDataCallback(uint8* dest, | 787 int AlsaPcmOutputStream::RunDataCallback(AudioBus* audio_bus, | 
| 788                                             uint32 max_size, | 788                                          AudioBuffersState buffers_state) { | 
| 789                                             AudioBuffersState buffers_state) { |  | 
| 790   TRACE_EVENT0("audio", "AlsaPcmOutputStream::RunDataCallback"); | 789   TRACE_EVENT0("audio", "AlsaPcmOutputStream::RunDataCallback"); | 
| 791 | 790 | 
| 792   if (source_callback_) | 791   if (source_callback_) | 
| 793     return source_callback_->OnMoreData(dest, max_size, buffers_state); | 792     return source_callback_->OnMoreData(audio_bus, buffers_state); | 
| 794 | 793 | 
| 795   return 0; | 794   return 0; | 
| 796 } | 795 } | 
| 797 | 796 | 
| 798 void AlsaPcmOutputStream::RunErrorCallback(int code) { | 797 void AlsaPcmOutputStream::RunErrorCallback(int code) { | 
| 799   if (source_callback_) | 798   if (source_callback_) | 
| 800     source_callback_->OnError(this, code); | 799     source_callback_->OnError(this, code); | 
| 801 } | 800 } | 
| 802 | 801 | 
| 803 // Changes the AudioSourceCallback to proxy calls to.  Pass in NULL to | 802 // Changes the AudioSourceCallback to proxy calls to.  Pass in NULL to | 
| 804 // release ownership of the currently registered callback. | 803 // release ownership of the currently registered callback. | 
| 805 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) { | 804 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) { | 
| 806   DCHECK(IsOnAudioThread()); | 805   DCHECK(IsOnAudioThread()); | 
| 807   source_callback_ = callback; | 806   source_callback_ = callback; | 
| 808 } | 807 } | 
| 809 | 808 | 
| 810 }  // namespace media | 809 }  // namespace media | 
| OLD | NEW | 
|---|