| 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 #include "media/audio/android/opensles_output.h" | 5 #include "media/audio/android/opensles_output.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/single_thread_task_runner.h" |
| 9 #include "base/thread_task_runner_handle.h" |
| 8 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| 9 #include "media/audio/android/audio_manager_android.h" | 11 #include "media/audio/android/audio_manager_android.h" |
| 10 | 12 |
| 11 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ | 13 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ |
| 12 do { \ | 14 do { \ |
| 13 SLresult err = (op); \ | 15 SLresult err = (op); \ |
| 14 if (err != SL_RESULT_SUCCESS) { \ | 16 if (err != SL_RESULT_SUCCESS) { \ |
| 15 DLOG(ERROR) << #op << " failed: " << err; \ | 17 DLOG(ERROR) << #op << " failed: " << err; \ |
| 16 return __VA_ARGS__; \ | 18 return __VA_ARGS__; \ |
| 17 } \ | 19 } \ |
| 18 } while (0) | 20 } while (0) |
| 19 | 21 |
| 20 namespace media { | 22 namespace media { |
| 21 | 23 |
| 24 // Threshold for consecutive number of empty buffers to let the player enter |
| 25 // idle state. |
| 26 // TODO(qinmin): change this threshold to count the number of frames. |
| 27 static const int kEmptyBufferThreasholdForIdleMode = 2; |
| 28 |
| 22 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, | 29 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, |
| 23 const AudioParameters& params, | 30 const AudioParameters& params, |
| 24 SLint32 stream_type) | 31 SLint32 stream_type) |
| 25 : audio_manager_(manager), | 32 : audio_manager_(manager), |
| 26 stream_type_(stream_type), | 33 stream_type_(stream_type), |
| 27 callback_(NULL), | 34 callback_(NULL), |
| 28 player_(NULL), | 35 player_(NULL), |
| 29 simple_buffer_queue_(NULL), | 36 simple_buffer_queue_(NULL), |
| 30 active_buffer_index_(0), | 37 active_buffer_index_(0), |
| 31 buffer_size_bytes_(0), | 38 buffer_size_bytes_(0), |
| 32 started_(false), | 39 started_(false), |
| 33 muted_(false), | 40 muted_(false), |
| 34 volume_(1.0) { | 41 volume_(1.0), |
| 42 consecutive_empty_buffer_count_(0), |
| 43 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 44 weak_factory_(this) { |
| 35 DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream(" | 45 DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream(" |
| 36 << "stream_type=" << stream_type << ")"; | 46 << "stream_type=" << stream_type << ")"; |
| 37 format_.formatType = SL_DATAFORMAT_PCM; | 47 format_.formatType = SL_DATAFORMAT_PCM; |
| 38 format_.numChannels = static_cast<SLuint32>(params.channels()); | 48 format_.numChannels = static_cast<SLuint32>(params.channels()); |
| 39 // Provides sampling rate in milliHertz to OpenSLES. | 49 // Provides sampling rate in milliHertz to OpenSLES. |
| 40 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); | 50 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); |
| 41 format_.bitsPerSample = params.bits_per_sample(); | 51 format_.bitsPerSample = params.bits_per_sample(); |
| 42 format_.containerSize = params.bits_per_sample(); | 52 format_.containerSize = params.bits_per_sample(); |
| 43 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; | 53 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; |
| 44 if (format_.numChannels == 1) | 54 if (format_.numChannels == 1) |
| 45 format_.channelMask = SL_SPEAKER_FRONT_CENTER; | 55 format_.channelMask = SL_SPEAKER_FRONT_CENTER; |
| 46 else if (format_.numChannels == 2) | 56 else if (format_.numChannels == 2) |
| 47 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; | 57 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; |
| 48 else | 58 else |
| 49 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; | 59 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; |
| 50 | 60 |
| 51 buffer_size_bytes_ = params.GetBytesPerBuffer(); | 61 buffer_size_bytes_ = params.GetBytesPerBuffer(); |
| 52 audio_bus_ = AudioBus::Create(params); | 62 audio_bus_ = AudioBus::Create(params); |
| 53 | 63 |
| 54 memset(&audio_data_, 0, sizeof(audio_data_)); | 64 memset(&audio_data_, 0, sizeof(audio_data_)); |
| 65 weak_this_ = weak_factory_.GetWeakPtr(); |
| 66 audio_timestamp_helper_.reset(new AudioTimestampHelper(params.sample_rate())); |
| 55 } | 67 } |
| 56 | 68 |
| 57 OpenSLESOutputStream::~OpenSLESOutputStream() { | 69 OpenSLESOutputStream::~OpenSLESOutputStream() { |
| 58 DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()"; | 70 DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()"; |
| 59 DCHECK(thread_checker_.CalledOnValidThread()); | 71 DCHECK(thread_checker_.CalledOnValidThread()); |
| 60 DCHECK(!engine_object_.Get()); | 72 DCHECK(!engine_object_.Get()); |
| 61 DCHECK(!player_object_.Get()); | 73 DCHECK(!player_object_.Get()); |
| 62 DCHECK(!output_mixer_.Get()); | 74 DCHECK(!output_mixer_.Get()); |
| 63 DCHECK(!player_); | 75 DCHECK(!player_); |
| 64 DCHECK(!simple_buffer_queue_); | 76 DCHECK(!simple_buffer_queue_); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 88 DCHECK(simple_buffer_queue_); | 100 DCHECK(simple_buffer_queue_); |
| 89 if (started_) | 101 if (started_) |
| 90 return; | 102 return; |
| 91 | 103 |
| 92 base::AutoLock lock(lock_); | 104 base::AutoLock lock(lock_); |
| 93 DCHECK(callback_ == NULL || callback_ == callback); | 105 DCHECK(callback_ == NULL || callback_ == callback); |
| 94 callback_ = callback; | 106 callback_ = callback; |
| 95 | 107 |
| 96 // Avoid start-up glitches by filling up one buffer queue before starting | 108 // Avoid start-up glitches by filling up one buffer queue before starting |
| 97 // the stream. | 109 // the stream. |
| 98 FillBufferQueueNoLock(); | 110 FillBufferQueueNoLock(false); |
| 99 | 111 |
| 100 // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING. | 112 // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING. |
| 101 // For a player object, when the object is in the SL_PLAYSTATE_PLAYING | 113 // For a player object, when the object is in the SL_PLAYSTATE_PLAYING |
| 102 // state, adding buffers will implicitly start playback. | 114 // state, adding buffers will implicitly start playback. |
| 103 LOG_ON_FAILURE_AND_RETURN( | 115 LOG_ON_FAILURE_AND_RETURN( |
| 104 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); | 116 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); |
| 105 | 117 |
| 106 started_ = true; | 118 started_ = true; |
| 107 } | 119 } |
| 108 | 120 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 127 // Verify that the buffer queue is in fact cleared as it should. | 139 // Verify that the buffer queue is in fact cleared as it should. |
| 128 SLAndroidSimpleBufferQueueState buffer_queue_state; | 140 SLAndroidSimpleBufferQueueState buffer_queue_state; |
| 129 LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_)->GetState( | 141 LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_)->GetState( |
| 130 simple_buffer_queue_, &buffer_queue_state)); | 142 simple_buffer_queue_, &buffer_queue_state)); |
| 131 DCHECK_EQ(0u, buffer_queue_state.count); | 143 DCHECK_EQ(0u, buffer_queue_state.count); |
| 132 DCHECK_EQ(0u, buffer_queue_state.index); | 144 DCHECK_EQ(0u, buffer_queue_state.index); |
| 133 #endif | 145 #endif |
| 134 | 146 |
| 135 callback_ = NULL; | 147 callback_ = NULL; |
| 136 started_ = false; | 148 started_ = false; |
| 149 CancelIdleCheck(); |
| 150 consecutive_empty_buffer_count_ = 0; |
| 137 } | 151 } |
| 138 | 152 |
| 139 void OpenSLESOutputStream::Close() { | 153 void OpenSLESOutputStream::Close() { |
| 140 DVLOG(2) << "OpenSLESOutputStream::Close()"; | 154 DVLOG(2) << "OpenSLESOutputStream::Close()"; |
| 141 DCHECK(thread_checker_.CalledOnValidThread()); | 155 DCHECK(thread_checker_.CalledOnValidThread()); |
| 142 | 156 |
| 143 // Stop the stream if it is still playing. | 157 // Stop the stream if it is still playing. |
| 144 Stop(); | 158 Stop(); |
| 145 { | 159 { |
| 146 // Destroy the buffer queue player object and invalidate all associated | 160 // Destroy the buffer queue player object and invalidate all associated |
| (...skipping 13 matching lines...) Expand all Loading... |
| 160 } | 174 } |
| 161 | 175 |
| 162 audio_manager_->ReleaseOutputStream(this); | 176 audio_manager_->ReleaseOutputStream(this); |
| 163 } | 177 } |
| 164 | 178 |
| 165 void OpenSLESOutputStream::SetVolume(double volume) { | 179 void OpenSLESOutputStream::SetVolume(double volume) { |
| 166 DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume << ")"; | 180 DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume << ")"; |
| 167 DCHECK(thread_checker_.CalledOnValidThread()); | 181 DCHECK(thread_checker_.CalledOnValidThread()); |
| 168 | 182 |
| 169 double volume_override = 0; | 183 double volume_override = 0; |
| 170 if (audio_manager_->HasOutputVolumeOverride(&volume_override)) { | 184 if (audio_manager_->HasOutputVolumeOverride(&volume_override)) |
| 171 volume = volume_override; | 185 volume = volume_override; |
| 172 } | |
| 173 | 186 |
| 174 float volume_float = static_cast<float>(volume); | 187 float volume_float = static_cast<float>(volume); |
| 175 if (volume_float < 0.0f || volume_float > 1.0f) { | 188 if (volume_float < 0.0f || volume_float > 1.0f) |
| 176 return; | 189 return; |
| 177 } | |
| 178 volume_ = volume_float; | 190 volume_ = volume_float; |
| 179 } | 191 } |
| 180 | 192 |
| 181 void OpenSLESOutputStream::GetVolume(double* volume) { | 193 void OpenSLESOutputStream::GetVolume(double* volume) { |
| 182 DCHECK(thread_checker_.CalledOnValidThread()); | 194 DCHECK(thread_checker_.CalledOnValidThread()); |
| 183 *volume = static_cast<double>(volume_); | 195 *volume = static_cast<double>(volume_); |
| 184 } | 196 } |
| 185 | 197 |
| 186 void OpenSLESOutputStream::SetMute(bool muted) { | 198 void OpenSLESOutputStream::SetMute(bool muted) { |
| 187 DVLOG(2) << "OpenSLESOutputStream::SetMute(" << muted << ")"; | 199 DVLOG(2) << "OpenSLESOutputStream::SetMute(" << muted << ")"; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 HandleError(err); | 324 HandleError(err); |
| 313 return; | 325 return; |
| 314 } | 326 } |
| 315 if (state != SL_PLAYSTATE_PLAYING) { | 327 if (state != SL_PLAYSTATE_PLAYING) { |
| 316 DLOG(WARNING) << "Received callback in non-playing state"; | 328 DLOG(WARNING) << "Received callback in non-playing state"; |
| 317 return; | 329 return; |
| 318 } | 330 } |
| 319 | 331 |
| 320 // Fill up one buffer in the queue by asking the registered source for | 332 // Fill up one buffer in the queue by asking the registered source for |
| 321 // data using the OnMoreData() callback. | 333 // data using the OnMoreData() callback. |
| 322 FillBufferQueueNoLock(); | 334 FillBufferQueueNoLock(false); |
| 323 } | 335 } |
| 324 | 336 |
| 325 void OpenSLESOutputStream::FillBufferQueueNoLock() { | 337 void OpenSLESOutputStream::FillBufferQueueNoLock(bool in_idle_mode) { |
| 326 // Ensure that the calling thread has acquired the lock since it is not | 338 // Ensure that the calling thread has acquired the lock since it is not |
| 327 // done in this method. | 339 // done in this method. |
| 328 lock_.AssertAcquired(); | 340 lock_.AssertAcquired(); |
| 329 | 341 |
| 330 // Read data from the registered client source. | 342 // Read data from the registered client source. |
| 331 // TODO(henrika): Investigate if it is possible to get a more accurate | 343 // TODO(henrika): Investigate if it is possible to get a more accurate |
| 332 // delay estimation. | 344 // delay estimation. |
| 333 const uint32 hardware_delay = buffer_size_bytes_; | 345 const uint32 hardware_delay = buffer_size_bytes_; |
| 334 int frames_filled = callback_->OnMoreData( | 346 int frames_filled = callback_->OnMoreData(audio_bus_.get(), hardware_delay); |
| 335 audio_bus_.get(), hardware_delay); | |
| 336 if (frames_filled <= 0) { | 347 if (frames_filled <= 0) { |
| 337 // Audio source is shutting down, or halted on error. | 348 // Audio source is shutting down, or halted on error. |
| 338 return; | 349 return; |
| 339 } | 350 } |
| 340 | 351 |
| 352 // Skip enqueueing data if the output is empty to save power. |
| 353 if (audio_bus_->AreFramesZero()) { |
| 354 // TODO(qinmin): check if this variable overflows. |
| 355 consecutive_empty_buffer_count_++; |
| 356 if (consecutive_empty_buffer_count_ >= kEmptyBufferThreasholdForIdleMode) { |
| 357 WaitingForAudio(in_idle_mode, frames_filled, base::TimeTicks::Now()); |
| 358 return; |
| 359 } |
| 360 } else { |
| 361 consecutive_empty_buffer_count_ = 0; |
| 362 } |
| 363 |
| 341 // Note: If the internal representation ever changes from 16-bit PCM to | 364 // Note: If the internal representation ever changes from 16-bit PCM to |
| 342 // raw float, the data must be clipped and sanitized since it may come | 365 // raw float, the data must be clipped and sanitized since it may come |
| 343 // from an untrusted source such as NaCl. | 366 // from an untrusted source such as NaCl. |
| 344 audio_bus_->Scale(muted_ ? 0.0f : volume_); | 367 audio_bus_->Scale(muted_ ? 0.0f : volume_); |
| 345 audio_bus_->ToInterleaved(frames_filled, | 368 audio_bus_->ToInterleaved(frames_filled, |
| 346 format_.bitsPerSample / 8, | 369 format_.bitsPerSample / 8, |
| 347 audio_data_[active_buffer_index_]); | 370 audio_data_[active_buffer_index_]); |
| 348 | 371 |
| 349 const int num_filled_bytes = | 372 const int num_filled_bytes = |
| 350 frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8; | 373 frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8; |
| 351 DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_); | 374 DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_); |
| 352 | 375 |
| 353 // Enqueue the buffer for playback. | 376 // Enqueue the buffer for playback. |
| 354 SLresult err = | 377 SLresult err = |
| 355 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_, | 378 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_, |
| 356 audio_data_[active_buffer_index_], | 379 audio_data_[active_buffer_index_], |
| 357 num_filled_bytes); | 380 num_filled_bytes); |
| 358 if (SL_RESULT_SUCCESS != err) | 381 if (SL_RESULT_SUCCESS != err) |
| 359 HandleError(err); | 382 HandleError(err); |
| 360 | 383 |
| 361 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue; | 384 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue; |
| 362 } | 385 } |
| 363 | 386 |
| 364 void OpenSLESOutputStream::SetupAudioBuffer() { | 387 void OpenSLESOutputStream::SetupAudioBuffer() { |
| 365 DCHECK(thread_checker_.CalledOnValidThread()); | 388 DCHECK(thread_checker_.CalledOnValidThread()); |
| 366 DCHECK(!audio_data_[0]); | 389 DCHECK(!audio_data_[0]); |
| 367 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { | 390 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) |
| 368 audio_data_[i] = new uint8[buffer_size_bytes_]; | 391 audio_data_[i] = new uint8[buffer_size_bytes_]; |
| 369 } | |
| 370 } | 392 } |
| 371 | 393 |
| 372 void OpenSLESOutputStream::ReleaseAudioBuffer() { | 394 void OpenSLESOutputStream::ReleaseAudioBuffer() { |
| 373 DCHECK(thread_checker_.CalledOnValidThread()); | 395 DCHECK(thread_checker_.CalledOnValidThread()); |
| 374 if (audio_data_[0]) { | 396 if (audio_data_[0]) { |
| 375 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { | 397 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { |
| 376 delete[] audio_data_[i]; | 398 delete[] audio_data_[i]; |
| 377 audio_data_[i] = NULL; | 399 audio_data_[i] = NULL; |
| 378 } | 400 } |
| 379 } | 401 } |
| 380 } | 402 } |
| 381 | 403 |
| 382 void OpenSLESOutputStream::HandleError(SLresult error) { | 404 void OpenSLESOutputStream::HandleError(SLresult error) { |
| 383 DLOG(ERROR) << "OpenSLES Output error " << error; | 405 DLOG(ERROR) << "OpenSLES Output error " << error; |
| 384 if (callback_) | 406 if (callback_) |
| 385 callback_->OnError(this); | 407 callback_->OnError(this); |
| 408 CancelIdleCheck(); |
| 409 } |
| 410 |
| 411 void OpenSLESOutputStream::CheckForIdle() { |
| 412 DCHECK(thread_checker_.CalledOnValidThread()); |
| 413 DCHECK(!idle_check_callback_.IsCancelled()); |
| 414 |
| 415 if (!started_) |
| 416 return; |
| 417 base::AutoLock lock(lock_); |
| 418 FillBufferQueueNoLock(true); |
| 419 } |
| 420 |
| 421 void OpenSLESOutputStream::CancelIdleCheck() { |
| 422 if (!task_runner_->BelongsToCurrentThread()) { |
| 423 task_runner_->PostTask( |
| 424 FROM_HERE, |
| 425 base::Bind(&OpenSLESOutputStream::CancelIdleCheck, weak_this_)); |
| 426 return; |
| 427 } |
| 428 idle_check_callback_.Cancel(); |
| 429 } |
| 430 |
| 431 void OpenSLESOutputStream::WaitingForAudio( |
| 432 bool in_idle_mode, int frames_filled, base::TimeTicks idle_start_time) { |
| 433 if (!task_runner_->BelongsToCurrentThread()) { |
| 434 task_runner_->PostTask( |
| 435 FROM_HERE, |
| 436 base::Bind(&OpenSLESOutputStream::WaitingForAudio, |
| 437 weak_this_, in_idle_mode, frames_filled, idle_start_time)); |
| 438 return; |
| 439 } |
| 440 |
| 441 if (!in_idle_mode) { |
| 442 audio_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); |
| 443 idle_start_time_ = idle_start_time; |
| 444 idle_check_callback_.Reset( |
| 445 base::Bind(&OpenSLESOutputStream::CheckForIdle, weak_this_)); |
| 446 } |
| 447 |
| 448 audio_timestamp_helper_->AddFrames(frames_filled); |
| 449 base::TimeDelta delay_to_next_read = audio_timestamp_helper_->GetTimestamp() + |
| 450 (idle_start_time_ - base::TimeTicks::Now()); |
| 451 if (delay_to_next_read < base::TimeDelta()) |
| 452 delay_to_next_read = base::TimeDelta(); |
| 453 task_runner_->PostDelayedTask( |
| 454 FROM_HERE, |
| 455 idle_check_callback_.callback(), |
| 456 delay_to_next_read); |
| 386 } | 457 } |
| 387 | 458 |
| 388 } // namespace media | 459 } // namespace media |
| OLD | NEW |