| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/audio_device/android/opensles_player.h" | 11 #include "webrtc/modules/audio_device/android/opensles_player.h" |
| 12 | 12 |
| 13 #include <android/log.h> | 13 #include <android/log.h> |
| 14 | 14 |
| 15 #include "webrtc/base/arraysize.h" | 15 #include "webrtc/base/arraysize.h" |
| 16 #include "webrtc/base/checks.h" | 16 #include "webrtc/base/checks.h" |
| 17 #include "webrtc/base/format_macros.h" | 17 #include "webrtc/base/format_macros.h" |
| 18 #include "webrtc/base/timeutils.h" |
| 18 #include "webrtc/modules/audio_device/android/audio_manager.h" | 19 #include "webrtc/modules/audio_device/android/audio_manager.h" |
| 19 #include "webrtc/modules/audio_device/fine_audio_buffer.h" | 20 #include "webrtc/modules/audio_device/fine_audio_buffer.h" |
| 20 | 21 |
| 21 #define TAG "OpenSLESPlayer" | 22 #define TAG "OpenSLESPlayer" |
| 22 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) | 23 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) |
| 23 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) | 24 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) |
| 24 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) | 25 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) |
| 25 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) | 26 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) |
| 26 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) | 27 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) |
| 27 | 28 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 39 OpenSLESPlayer::OpenSLESPlayer(AudioManager* audio_manager) | 40 OpenSLESPlayer::OpenSLESPlayer(AudioManager* audio_manager) |
| 40 : audio_parameters_(audio_manager->GetPlayoutAudioParameters()), | 41 : audio_parameters_(audio_manager->GetPlayoutAudioParameters()), |
| 41 audio_device_buffer_(NULL), | 42 audio_device_buffer_(NULL), |
| 42 initialized_(false), | 43 initialized_(false), |
| 43 playing_(false), | 44 playing_(false), |
| 44 bytes_per_buffer_(0), | 45 bytes_per_buffer_(0), |
| 45 buffer_index_(0), | 46 buffer_index_(0), |
| 46 engine_(nullptr), | 47 engine_(nullptr), |
| 47 player_(nullptr), | 48 player_(nullptr), |
| 48 simple_buffer_queue_(nullptr), | 49 simple_buffer_queue_(nullptr), |
| 49 volume_(nullptr) { | 50 volume_(nullptr), |
| 51 last_play_time_(0) { |
| 50 ALOGD("ctor%s", GetThreadInfo().c_str()); | 52 ALOGD("ctor%s", GetThreadInfo().c_str()); |
| 51 // Use native audio output parameters provided by the audio manager and | 53 // Use native audio output parameters provided by the audio manager and |
| 52 // define the PCM format structure. | 54 // define the PCM format structure. |
| 53 pcm_format_ = CreatePCMConfiguration(audio_parameters_.channels(), | 55 pcm_format_ = CreatePCMConfiguration(audio_parameters_.channels(), |
| 54 audio_parameters_.sample_rate(), | 56 audio_parameters_.sample_rate(), |
| 55 audio_parameters_.bits_per_sample()); | 57 audio_parameters_.bits_per_sample()); |
| 56 // Detach from this thread since we want to use the checker to verify calls | 58 // Detach from this thread since we want to use the checker to verify calls |
| 57 // from the internal audio thread. | 59 // from the internal audio thread. |
| 58 thread_checker_opensles_.DetachFromThread(); | 60 thread_checker_opensles_.DetachFromThread(); |
| 59 } | 61 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 88 | 90 |
| 89 int OpenSLESPlayer::InitPlayout() { | 91 int OpenSLESPlayer::InitPlayout() { |
| 90 ALOGD("InitPlayout%s", GetThreadInfo().c_str()); | 92 ALOGD("InitPlayout%s", GetThreadInfo().c_str()); |
| 91 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 93 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 92 RTC_DCHECK(!initialized_); | 94 RTC_DCHECK(!initialized_); |
| 93 RTC_DCHECK(!playing_); | 95 RTC_DCHECK(!playing_); |
| 94 CreateEngine(); | 96 CreateEngine(); |
| 95 CreateMix(); | 97 CreateMix(); |
| 96 initialized_ = true; | 98 initialized_ = true; |
| 97 buffer_index_ = 0; | 99 buffer_index_ = 0; |
| 100 last_play_time_ = rtc::Time(); |
| 98 return 0; | 101 return 0; |
| 99 } | 102 } |
| 100 | 103 |
| 101 int OpenSLESPlayer::StartPlayout() { | 104 int OpenSLESPlayer::StartPlayout() { |
| 102 ALOGD("StartPlayout%s", GetThreadInfo().c_str()); | 105 ALOGD("StartPlayout%s", GetThreadInfo().c_str()); |
| 103 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 106 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 104 RTC_DCHECK(initialized_); | 107 RTC_DCHECK(initialized_); |
| 105 RTC_DCHECK(!playing_); | 108 RTC_DCHECK(!playing_); |
| 106 // The number of lower latency audio players is limited, hence we create the | 109 // The number of lower latency audio players is limited, hence we create the |
| 107 // audio player in Start() and destroy it in Stop(). | 110 // audio player in Start() and destroy it in Stop(). |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 RTC_CHECK(false) << "Unsupported number of channels: " | 229 RTC_CHECK(false) << "Unsupported number of channels: " |
| 227 << format.numChannels; | 230 << format.numChannels; |
| 228 return format; | 231 return format; |
| 229 } | 232 } |
| 230 | 233 |
| 231 void OpenSLESPlayer::AllocateDataBuffers() { | 234 void OpenSLESPlayer::AllocateDataBuffers() { |
| 232 ALOGD("AllocateDataBuffers"); | 235 ALOGD("AllocateDataBuffers"); |
| 233 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 236 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 234 RTC_DCHECK(!simple_buffer_queue_); | 237 RTC_DCHECK(!simple_buffer_queue_); |
| 235 RTC_CHECK(audio_device_buffer_); | 238 RTC_CHECK(audio_device_buffer_); |
| 236 bytes_per_buffer_ = audio_parameters_.GetBytesPerBuffer(); | 239 // Don't use the lowest possible size as native buffer size. Instead, |
| 240 // use 10ms to better match the frame size that WebRTC uses. It will result |
| 241 // in a reduced risk for audio glitches and also in a more "clean" sequence |
| 242 // of callbacks from the OpenSL ES thread in to WebRTC when asking for audio |
| 243 // to render. |
| 244 ALOGD("lowest possible buffer size: %" PRIuS, |
| 245 audio_parameters_.GetBytesPerBuffer()); |
| 246 bytes_per_buffer_ = audio_parameters_.GetBytesPerFrame() * |
| 247 audio_parameters_.frames_per_10ms_buffer(); |
| 248 RTC_DCHECK_GT(bytes_per_buffer_, audio_parameters_.GetBytesPerBuffer()); |
| 237 ALOGD("native buffer size: %" PRIuS, bytes_per_buffer_); | 249 ALOGD("native buffer size: %" PRIuS, bytes_per_buffer_); |
| 238 // Create a modified audio buffer class which allows us to ask for any number | 250 // Create a modified audio buffer class which allows us to ask for any number |
| 239 // of samples (and not only multiple of 10ms) to match the native OpenSL ES | 251 // of samples (and not only multiple of 10ms) to match the native OpenSL ES |
| 240 // buffer size. | 252 // buffer size. |
| 241 fine_buffer_.reset(new FineAudioBuffer(audio_device_buffer_, | 253 fine_buffer_.reset(new FineAudioBuffer(audio_device_buffer_, |
| 242 bytes_per_buffer_, | 254 bytes_per_buffer_, |
| 243 audio_parameters_.sample_rate())); | 255 audio_parameters_.sample_rate())); |
| 244 // Each buffer must be of this size to avoid unnecessary memcpy while caching | 256 // Each buffer must be of this size to avoid unnecessary memcpy while caching |
| 245 // data between successive callbacks. | 257 // data between successive callbacks. |
| 246 const size_t required_buffer_size = | 258 const size_t required_buffer_size = |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 RTC_DCHECK(thread_checker_opensles_.CalledOnValidThread()); | 423 RTC_DCHECK(thread_checker_opensles_.CalledOnValidThread()); |
| 412 SLuint32 state = GetPlayState(); | 424 SLuint32 state = GetPlayState(); |
| 413 if (state != SL_PLAYSTATE_PLAYING) { | 425 if (state != SL_PLAYSTATE_PLAYING) { |
| 414 ALOGW("Buffer callback in non-playing state!"); | 426 ALOGW("Buffer callback in non-playing state!"); |
| 415 return; | 427 return; |
| 416 } | 428 } |
| 417 EnqueuePlayoutData(); | 429 EnqueuePlayoutData(); |
| 418 } | 430 } |
| 419 | 431 |
| 420 void OpenSLESPlayer::EnqueuePlayoutData() { | 432 void OpenSLESPlayer::EnqueuePlayoutData() { |
| 433 // Check delta time between two successive callbacks and provide a warning |
| 434 // if it becomes very large. |
| 435 // TODO(henrika): using 100ms as upper limit but this value is rather random. |
| 436 const uint32_t current_time = rtc::Time(); |
| 437 const uint32_t diff = current_time - last_play_time_; |
| 438 if (diff > 100) { |
| 439 ALOGW("Bad OpenSL ES playout timing, dT=%u [ms]", diff); |
| 440 } |
| 441 last_play_time_ = current_time; |
| 421 // Read audio data from the WebRTC source using the FineAudioBuffer object | 442 // Read audio data from the WebRTC source using the FineAudioBuffer object |
| 422 // to adjust for differences in buffer size between WebRTC (10ms) and native | 443 // to adjust for differences in buffer size between WebRTC (10ms) and native |
| 423 // OpenSL ES. | 444 // OpenSL ES. |
| 424 SLint8* audio_ptr = audio_buffers_[buffer_index_].get(); | 445 SLint8* audio_ptr = audio_buffers_[buffer_index_].get(); |
| 425 fine_buffer_->GetPlayoutData(audio_ptr); | 446 fine_buffer_->GetPlayoutData(audio_ptr); |
| 426 // Enqueue the decoded audio buffer for playback. | 447 // Enqueue the decoded audio buffer for playback. |
| 427 SLresult err = | 448 SLresult err = |
| 428 (*simple_buffer_queue_) | 449 (*simple_buffer_queue_) |
| 429 ->Enqueue(simple_buffer_queue_, audio_ptr, bytes_per_buffer_); | 450 ->Enqueue(simple_buffer_queue_, audio_ptr, bytes_per_buffer_); |
| 430 if (SL_RESULT_SUCCESS != err) { | 451 if (SL_RESULT_SUCCESS != err) { |
| 431 ALOGE("Enqueue failed: %d", err); | 452 ALOGE("Enqueue failed: %d", err); |
| 432 } | 453 } |
| 433 buffer_index_ = (buffer_index_ + 1) % kNumOfOpenSLESBuffers; | 454 buffer_index_ = (buffer_index_ + 1) % kNumOfOpenSLESBuffers; |
| 434 } | 455 } |
| 435 | 456 |
| 436 SLuint32 OpenSLESPlayer::GetPlayState() const { | 457 SLuint32 OpenSLESPlayer::GetPlayState() const { |
| 437 RTC_DCHECK(player_); | 458 RTC_DCHECK(player_); |
| 438 SLuint32 state; | 459 SLuint32 state; |
| 439 SLresult err = (*player_)->GetPlayState(player_, &state); | 460 SLresult err = (*player_)->GetPlayState(player_, &state); |
| 440 if (SL_RESULT_SUCCESS != err) { | 461 if (SL_RESULT_SUCCESS != err) { |
| 441 ALOGE("GetPlayState failed: %d", err); | 462 ALOGE("GetPlayState failed: %d", err); |
| 442 } | 463 } |
| 443 return state; | 464 return state; |
| 444 } | 465 } |
| 445 | 466 |
| 446 } // namespace webrtc | 467 } // namespace webrtc |
| OLD | NEW |