15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/android/opensles_output.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/debug/trace_event.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/android/audio_manager_android.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#define LOG_ON_FAILURE_AND_RETURN(op, ...) \ 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) do { \ 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLresult err = (op); \ 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (err != SL_RESULT_SUCCESS) { \ 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DLOG(ERROR) << #op << " failed: " << err; \ 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return __VA_ARGS__; \ 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } \ 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } while (0) 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const AudioParameters& params, 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SLint32 stream_type) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : audio_manager_(manager), 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stream_type_(stream_type), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(NULL), 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) player_(NULL), 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) simple_buffer_queue_(NULL), 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) active_buffer_index_(0), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size_bytes_(0), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_(false), 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) muted_(false), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volume_(1.0) { 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream(" 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "stream_type=" << stream_type << ")"; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.formatType = SL_DATAFORMAT_PCM; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.numChannels = static_cast<SLuint32>(params.channels()); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provides sampling rate in milliHertz to OpenSLES. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.bitsPerSample = params.bits_per_sample(); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.containerSize = params.bits_per_sample(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.endianness = SL_BYTEORDER_LITTLEENDIAN; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format_.numChannels == 1) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.channelMask = SL_SPEAKER_FRONT_CENTER; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (format_.numChannels == 2) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size_bytes_ = params.GetBytesPerBuffer(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_ = AudioBus::Create(params); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&audio_data_, 0, sizeof(audio_data_)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OpenSLESOutputStream::~OpenSLESOutputStream() { 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()"; 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!engine_object_.Get()); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!player_object_.Get()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!output_mixer_.Get()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!player_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!simple_buffer_queue_); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!audio_data_[0]); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESOutputStream::Open() { 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::Open()"; 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (engine_object_.Get()) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreatePlayer()) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetupAudioBuffer(); 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) active_buffer_index_ = 0; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::Start(AudioSourceCallback* callback) { 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::Start()"; 85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(callback); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(player_); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(simple_buffer_queue_); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(callback_ == NULL || callback_ == callback); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Avoid start-up glitches by filling up one buffer queue before starting 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the stream. 98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FillBufferQueueNoLock(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING. 101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // For a player object, when the object is in the SL_PLAYSTATE_PLAYING 102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // state, adding buffers will implicitly start playback. 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); 105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_ = true; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::Stop() { 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::Stop()"; 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Stop playing by setting the play state to SL_PLAYSTATE_STOPPED. 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the buffer queue so that the old data won't be played when 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resuming playing. 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#ifndef NDEBUG 127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Verify that the buffer queue is in fact cleared as it should. 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLAndroidSimpleBufferQueueState buffer_queue_state; 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_)->GetState( 130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) simple_buffer_queue_, &buffer_queue_state)); 131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(0u, buffer_queue_state.count); 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(0u, buffer_queue_state.index); 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif 134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_ = NULL; 136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_ = false; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::Close() { 140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::Close()"; 141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop the stream if it is still playing. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Destroy the buffer queue player object and invalidate all associated 147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // interfaces. 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_object_.Reset(); 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) simple_buffer_queue_ = NULL; 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_ = NULL; 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Destroy the mixer object. We don't store any associated interface for 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // this object. 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_mixer_.Reset(); 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Destroy the engine object. We don't store any associated interface for 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // this object. 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine_object_.Reset(); 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ReleaseAudioBuffer(); 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_manager_->ReleaseOutputStream(this); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::SetVolume(double volume) { 166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume << ")"; 167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float volume_float = static_cast<float>(volume); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (volume_float < 0.0f || volume_float > 1.0f) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volume_ = volume_float; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::GetVolume(double* volume) { 176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *volume = static_cast<double>(volume_); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OpenSLESOutputStream::SetMute(bool muted) { 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << "OpenSLESOutputStream::SetMute(" << muted << ")"; 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) muted_ = muted; 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESOutputStream::CreatePlayer() { 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!engine_object_.Get()); 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!player_object_.Get()); 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!output_mixer_.Get()); 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!player_); 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!simple_buffer_queue_); 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes the engine object with specific option. After working with the 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object, we need to free the object and its resources. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLEngineOption option[] = { 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}}; 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Realize the SL engine object in synchronous mode. 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the SL engine interface which is implicit. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLEngineItf engine; 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface( 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine_object_.Get(), SL_IID_ENGINE, &engine), 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) false); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create ouput mixer object to be used by the player. 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG_ON_FAILURE_AND_RETURN((*engine)->CreateOutputMix( 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine, output_mixer_.Receive(), 0, NULL, NULL), 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) false); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Realizing the output mix object in synchronous mode. 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), false); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Audio source configuration. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<SLuint32>(kMaxNumOfBuffersInQueue)}; 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLDataSource audio_source = {&simple_buffer_queue, &format_}; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Audio sink configuration. 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLDataLocator_OutputMix locator_output_mix = {SL_DATALOCATOR_OUTPUTMIX, 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) output_mixer_.Get()}; 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLDataSink audio_sink = {&locator_output_mix, NULL}; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an audio player. 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SLInterfaceID interface_id[] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_IID_ANDROIDCONFIGURATION}; 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_BOOLEAN_TRUE}; 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*engine)->CreateAudioPlayer(engine, 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch player_object_.Receive(), 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &audio_source, 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &audio_sink, 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch arraysize(interface_id), 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch interface_id, 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch interface_required), 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION. 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SLAndroidConfigurationItf player_config; 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_object_->GetInterface( 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_object_.Get(), SL_IID_ANDROIDCONFIGURATION, &player_config), 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Set configuration using the stream type provided at construction. 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*player_config)->SetConfiguration(player_config, 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SL_ANDROID_KEY_STREAM_TYPE, 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &stream_type_, 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sizeof(SLint32)), 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Realize the player object in synchronous mode. 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), false); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get an implicit player interface. 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_), 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the simple buffer queue interface. 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_object_->GetInterface( 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) player_object_.Get(), SL_IID_BUFFERQUEUE, &simple_buffer_queue_), 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register the input callback for the simple buffer queue. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This callback will be called when the soundcard needs data. 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*simple_buffer_queue_)->RegisterCallback( 281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) simple_buffer_queue_, SimpleBufferQueueCallback, this), 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::SimpleBufferQueueCallback( 288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLAndroidSimpleBufferQueueItf buffer_queue, 289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void* instance) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSLESOutputStream* stream = 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<OpenSLESOutputStream*>(instance); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->FillBufferQueue(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::FillBufferQueue() { 296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue"); 301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Verify that we are in a playing state. 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLuint32 state; 304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLresult err = (*player_)->GetPlayState(player_, &state); 305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (SL_RESULT_SUCCESS != err) { 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) HandleError(err); 307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (state != SL_PLAYSTATE_PLAYING) { 310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DLOG(WARNING) << "Received callback in non-playing state"; 311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Fill up one buffer in the queue by asking the registered source for 315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // data using the OnMoreData() callback. 316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FillBufferQueueNoLock(); 317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void OpenSLESOutputStream::FillBufferQueueNoLock() { 320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Ensure that the calling thread has acquired the lock since it is not 321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // done in this method. 322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) lock_.AssertAcquired(); 323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read data from the registered client source. 325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(henrika): Investigate if it is possible to get a more accurate 326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // delay estimation. 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const uint32 hardware_delay = buffer_size_bytes_; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frames_filled = callback_->OnMoreData( 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_.get(), AudioBuffersState(0, hardware_delay)); 330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (frames_filled <= 0) { 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Audio source is shutting down, or halted on error. 332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Note: If the internal representation ever changes from 16-bit PCM to 336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // raw float, the data must be clipped and sanitized since it may come 337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // from an untrusted source such as NaCl. 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_bus_->Scale(muted_ ? 0.0f : volume_); 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_bus_->ToInterleaved(frames_filled, 340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) format_.bitsPerSample / 8, 341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_data_[active_buffer_index_]); 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int num_filled_bytes = 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enqueue the buffer for playback. 348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLresult err = 349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_, 350d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_data_[active_buffer_index_], 351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) num_filled_bytes); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SL_RESULT_SUCCESS != err) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(err); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::SetupAudioBuffer() { 359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!audio_data_[0]); 361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_data_[i] = new uint8[buffer_size_bytes_]; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::ReleaseAudioBuffer() { 367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (audio_data_[0]) { 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delete[] audio_data_[i]; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_data_[i] = NULL; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESOutputStream::HandleError(SLresult error) { 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DLOG(ERROR) << "OpenSLES Output error " << error; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback_) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_->OnError(this); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 383