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/base/timeutils.h" |
| 19 #include "webrtc/modules/audio_device/android/audio_common.h" |
19 #include "webrtc/modules/audio_device/android/audio_manager.h" | 20 #include "webrtc/modules/audio_device/android/audio_manager.h" |
20 #include "webrtc/modules/audio_device/fine_audio_buffer.h" | 21 #include "webrtc/modules/audio_device/fine_audio_buffer.h" |
21 | 22 |
22 #define TAG "OpenSLESPlayer" | 23 #define TAG "OpenSLESPlayer" |
23 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) | 24 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) |
24 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) | 25 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) |
25 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) | 26 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) |
26 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) | 27 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) |
27 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) | 28 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) |
28 | 29 |
29 #define RETURN_ON_ERROR(op, ...) \ | 30 #define RETURN_ON_ERROR(op, ...) \ |
30 do { \ | 31 do { \ |
31 SLresult err = (op); \ | 32 SLresult err = (op); \ |
32 if (err != SL_RESULT_SUCCESS) { \ | 33 if (err != SL_RESULT_SUCCESS) { \ |
33 ALOGE("%s failed: %d", #op, err); \ | 34 ALOGE("%s failed: %s", #op, GetSLErrorString(err)); \ |
34 return __VA_ARGS__; \ | 35 return __VA_ARGS__; \ |
35 } \ | 36 } \ |
36 } while (0) | 37 } while (0) |
37 | 38 |
38 namespace webrtc { | 39 namespace webrtc { |
39 | 40 |
40 OpenSLESPlayer::OpenSLESPlayer(AudioManager* audio_manager) | 41 OpenSLESPlayer::OpenSLESPlayer(AudioManager* audio_manager) |
41 : audio_parameters_(audio_manager->GetPlayoutAudioParameters()), | 42 : audio_manager_(audio_manager), |
42 audio_device_buffer_(NULL), | 43 audio_parameters_(audio_manager->GetPlayoutAudioParameters()), |
| 44 audio_device_buffer_(nullptr), |
43 initialized_(false), | 45 initialized_(false), |
44 playing_(false), | 46 playing_(false), |
45 bytes_per_buffer_(0), | 47 bytes_per_buffer_(0), |
46 buffer_index_(0), | 48 buffer_index_(0), |
47 engine_(nullptr), | 49 engine_(nullptr), |
48 player_(nullptr), | 50 player_(nullptr), |
49 simple_buffer_queue_(nullptr), | 51 simple_buffer_queue_(nullptr), |
50 volume_(nullptr), | 52 volume_(nullptr), |
51 last_play_time_(0) { | 53 last_play_time_(0) { |
52 ALOGD("ctor%s", GetThreadInfo().c_str()); | 54 ALOGD("ctor%s", GetThreadInfo().c_str()); |
53 // Use native audio output parameters provided by the audio manager and | 55 // Use native audio output parameters provided by the audio manager and |
54 // define the PCM format structure. | 56 // define the PCM format structure. |
55 pcm_format_ = CreatePCMConfiguration(audio_parameters_.channels(), | 57 pcm_format_ = CreatePCMConfiguration(audio_parameters_.channels(), |
56 audio_parameters_.sample_rate(), | 58 audio_parameters_.sample_rate(), |
57 audio_parameters_.bits_per_sample()); | 59 audio_parameters_.bits_per_sample()); |
58 // Detach from this thread since we want to use the checker to verify calls | 60 // Detach from this thread since we want to use the checker to verify calls |
59 // from the internal audio thread. | 61 // from the internal audio thread. |
60 thread_checker_opensles_.DetachFromThread(); | 62 thread_checker_opensles_.DetachFromThread(); |
61 } | 63 } |
62 | 64 |
63 OpenSLESPlayer::~OpenSLESPlayer() { | 65 OpenSLESPlayer::~OpenSLESPlayer() { |
64 ALOGD("dtor%s", GetThreadInfo().c_str()); | 66 ALOGD("dtor%s", GetThreadInfo().c_str()); |
65 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 67 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
66 Terminate(); | 68 Terminate(); |
67 DestroyAudioPlayer(); | 69 DestroyAudioPlayer(); |
68 DestroyMix(); | 70 DestroyMix(); |
69 DestroyEngine(); | 71 engine_ = nullptr; |
70 RTC_DCHECK(!engine_object_.Get()); | |
71 RTC_DCHECK(!engine_); | 72 RTC_DCHECK(!engine_); |
72 RTC_DCHECK(!output_mix_.Get()); | 73 RTC_DCHECK(!output_mix_.Get()); |
73 RTC_DCHECK(!player_); | 74 RTC_DCHECK(!player_); |
74 RTC_DCHECK(!simple_buffer_queue_); | 75 RTC_DCHECK(!simple_buffer_queue_); |
75 RTC_DCHECK(!volume_); | 76 RTC_DCHECK(!volume_); |
76 } | 77 } |
77 | 78 |
78 int OpenSLESPlayer::Init() { | 79 int OpenSLESPlayer::Init() { |
79 ALOGD("Init%s", GetThreadInfo().c_str()); | 80 ALOGD("Init%s", GetThreadInfo().c_str()); |
80 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 81 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
81 return 0; | 82 return 0; |
82 } | 83 } |
83 | 84 |
84 int OpenSLESPlayer::Terminate() { | 85 int OpenSLESPlayer::Terminate() { |
85 ALOGD("Terminate%s", GetThreadInfo().c_str()); | 86 ALOGD("Terminate%s", GetThreadInfo().c_str()); |
86 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 87 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
87 StopPlayout(); | 88 StopPlayout(); |
88 return 0; | 89 return 0; |
89 } | 90 } |
90 | 91 |
91 int OpenSLESPlayer::InitPlayout() { | 92 int OpenSLESPlayer::InitPlayout() { |
92 ALOGD("InitPlayout%s", GetThreadInfo().c_str()); | 93 ALOGD("InitPlayout%s", GetThreadInfo().c_str()); |
93 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 94 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
94 RTC_DCHECK(!initialized_); | 95 RTC_DCHECK(!initialized_); |
95 RTC_DCHECK(!playing_); | 96 RTC_DCHECK(!playing_); |
96 CreateEngine(); | 97 GetEngineInterface(); |
97 CreateMix(); | 98 CreateMix(); |
98 initialized_ = true; | 99 initialized_ = true; |
99 buffer_index_ = 0; | 100 buffer_index_ = 0; |
100 last_play_time_ = rtc::Time(); | 101 last_play_time_ = rtc::Time(); |
101 return 0; | 102 return 0; |
102 } | 103 } |
103 | 104 |
104 int OpenSLESPlayer::StartPlayout() { | 105 int OpenSLESPlayer::StartPlayout() { |
105 ALOGD("StartPlayout%s", GetThreadInfo().c_str()); | 106 ALOGD("StartPlayout%s", GetThreadInfo().c_str()); |
106 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 107 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 // Each buffer must be of this size to avoid unnecessary memcpy while caching | 257 // Each buffer must be of this size to avoid unnecessary memcpy while caching |
257 // data between successive callbacks. | 258 // data between successive callbacks. |
258 const size_t required_buffer_size = | 259 const size_t required_buffer_size = |
259 fine_buffer_->RequiredPlayoutBufferSizeBytes(); | 260 fine_buffer_->RequiredPlayoutBufferSizeBytes(); |
260 ALOGD("required buffer size: %" PRIuS, required_buffer_size); | 261 ALOGD("required buffer size: %" PRIuS, required_buffer_size); |
261 for (int i = 0; i < kNumOfOpenSLESBuffers; ++i) { | 262 for (int i = 0; i < kNumOfOpenSLESBuffers; ++i) { |
262 audio_buffers_[i].reset(new SLint8[required_buffer_size]); | 263 audio_buffers_[i].reset(new SLint8[required_buffer_size]); |
263 } | 264 } |
264 } | 265 } |
265 | 266 |
266 bool OpenSLESPlayer::CreateEngine() { | 267 bool OpenSLESPlayer::GetEngineInterface() { |
267 ALOGD("CreateEngine"); | 268 ALOGD("GetEngineInterface"); |
268 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 269 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
269 if (engine_object_.Get()) | |
270 return true; | |
271 RTC_DCHECK(!engine_); | 270 RTC_DCHECK(!engine_); |
272 const SLEngineOption option[] = { | 271 // Get access to (or create if not already existing) the global OpenSL Engine |
273 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}}; | 272 // object. |
| 273 SLObjectItf engine_object = audio_manager_->GetOpenSLEngine(); |
| 274 if (engine_object == nullptr) { |
| 275 ALOGE("Failed to access the global OpenSL engine"); |
| 276 return false; |
| 277 } |
| 278 // Get the SL Engine Interface which is implicit. |
274 RETURN_ON_ERROR( | 279 RETURN_ON_ERROR( |
275 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), | 280 (*engine_object)->GetInterface(engine_object, SL_IID_ENGINE, &engine_), |
276 false); | 281 false); |
277 RETURN_ON_ERROR( | |
278 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false); | |
279 RETURN_ON_ERROR(engine_object_->GetInterface(engine_object_.Get(), | |
280 SL_IID_ENGINE, &engine_), | |
281 false); | |
282 return true; | 282 return true; |
283 } | 283 } |
284 | 284 |
285 void OpenSLESPlayer::DestroyEngine() { | |
286 ALOGD("DestroyEngine"); | |
287 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
288 if (!engine_object_.Get()) | |
289 return; | |
290 engine_ = nullptr; | |
291 engine_object_.Reset(); | |
292 } | |
293 | |
294 bool OpenSLESPlayer::CreateMix() { | 285 bool OpenSLESPlayer::CreateMix() { |
295 ALOGD("CreateMix"); | 286 ALOGD("CreateMix"); |
296 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 287 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
297 RTC_DCHECK(engine_); | 288 RTC_DCHECK(engine_); |
298 if (output_mix_.Get()) | 289 if (output_mix_.Get()) |
299 return true; | 290 return true; |
300 | 291 |
301 // Create the ouput mix on the engine object. No interfaces will be used. | 292 // Create the ouput mix on the engine object. No interfaces will be used. |
302 RETURN_ON_ERROR((*engine_)->CreateOutputMix(engine_, output_mix_.Receive(), 0, | 293 RETURN_ON_ERROR((*engine_)->CreateOutputMix(engine_, output_mix_.Receive(), 0, |
303 NULL, NULL), | 294 nullptr, nullptr), |
304 false); | 295 false); |
305 RETURN_ON_ERROR(output_mix_->Realize(output_mix_.Get(), SL_BOOLEAN_FALSE), | 296 RETURN_ON_ERROR(output_mix_->Realize(output_mix_.Get(), SL_BOOLEAN_FALSE), |
306 false); | 297 false); |
307 return true; | 298 return true; |
308 } | 299 } |
309 | 300 |
310 void OpenSLESPlayer::DestroyMix() { | 301 void OpenSLESPlayer::DestroyMix() { |
311 ALOGD("DestroyMix"); | 302 ALOGD("DestroyMix"); |
312 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 303 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
313 if (!output_mix_.Get()) | 304 if (!output_mix_.Get()) |
314 return; | 305 return; |
315 output_mix_.Reset(); | 306 output_mix_.Reset(); |
316 } | 307 } |
317 | 308 |
318 bool OpenSLESPlayer::CreateAudioPlayer() { | 309 bool OpenSLESPlayer::CreateAudioPlayer() { |
319 ALOGD("CreateAudioPlayer"); | 310 ALOGD("CreateAudioPlayer"); |
320 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 311 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
321 RTC_DCHECK(engine_object_.Get()); | |
322 RTC_DCHECK(output_mix_.Get()); | 312 RTC_DCHECK(output_mix_.Get()); |
323 if (player_object_.Get()) | 313 if (player_object_.Get()) |
324 return true; | 314 return true; |
325 RTC_DCHECK(!player_); | 315 RTC_DCHECK(!player_); |
326 RTC_DCHECK(!simple_buffer_queue_); | 316 RTC_DCHECK(!simple_buffer_queue_); |
327 RTC_DCHECK(!volume_); | 317 RTC_DCHECK(!volume_); |
328 | 318 |
329 // source: Android Simple Buffer Queue Data Locator is source. | 319 // source: Android Simple Buffer Queue Data Locator is source. |
330 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { | 320 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { |
331 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, | 321 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, |
332 static_cast<SLuint32>(kNumOfOpenSLESBuffers)}; | 322 static_cast<SLuint32>(kNumOfOpenSLESBuffers)}; |
333 SLDataSource audio_source = {&simple_buffer_queue, &pcm_format_}; | 323 SLDataSource audio_source = {&simple_buffer_queue, &pcm_format_}; |
334 | 324 |
335 // sink: OutputMix-based data is sink. | 325 // sink: OutputMix-based data is sink. |
336 SLDataLocator_OutputMix locator_output_mix = {SL_DATALOCATOR_OUTPUTMIX, | 326 SLDataLocator_OutputMix locator_output_mix = {SL_DATALOCATOR_OUTPUTMIX, |
337 output_mix_.Get()}; | 327 output_mix_.Get()}; |
338 SLDataSink audio_sink = {&locator_output_mix, NULL}; | 328 SLDataSink audio_sink = {&locator_output_mix, nullptr}; |
339 | 329 |
340 // Define interfaces that we indend to use and realize. | 330 // Define interfaces that we indend to use and realize. |
341 const SLInterfaceID interface_ids[] = { | 331 const SLInterfaceID interface_ids[] = { |
342 SL_IID_ANDROIDCONFIGURATION, SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; | 332 SL_IID_ANDROIDCONFIGURATION, SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; |
343 const SLboolean interface_required[] = { | 333 const SLboolean interface_required[] = { |
344 SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; | 334 SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; |
345 | 335 |
346 // Create the audio player on the engine interface. | 336 // Create the audio player on the engine interface. |
347 RETURN_ON_ERROR( | 337 RETURN_ON_ERROR( |
348 (*engine_)->CreateAudioPlayer( | 338 (*engine_)->CreateAudioPlayer( |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 RTC_DCHECK(player_); | 448 RTC_DCHECK(player_); |
459 SLuint32 state; | 449 SLuint32 state; |
460 SLresult err = (*player_)->GetPlayState(player_, &state); | 450 SLresult err = (*player_)->GetPlayState(player_, &state); |
461 if (SL_RESULT_SUCCESS != err) { | 451 if (SL_RESULT_SUCCESS != err) { |
462 ALOGE("GetPlayState failed: %d", err); | 452 ALOGE("GetPlayState failed: %d", err); |
463 } | 453 } |
464 return state; | 454 return state; |
465 } | 455 } |
466 | 456 |
467 } // namespace webrtc | 457 } // namespace webrtc |
OLD | NEW |