You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			133 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
		
		
			
		
	
	
			133 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
| 
											10 years ago
										 | 
 | ||
|  | #include "AudioPlayer.h"
 | ||
|  | #include "EncodedAudioData.h"
 | ||
|  | 
 | ||
|  | #include <android/log.h>
 | ||
|  | 
 | ||
|  | #define TAG "AudioPlayer"
 | ||
|  | 
 | ||
|  | AudioPlayer::AudioPlayer(WebRtcJitterBuffer &webRtcJitterBuffer, AudioCodec &audioCodec) : | ||
|  |   webRtcJitterBuffer(webRtcJitterBuffer), audioCodec(audioCodec), | ||
|  |   bqPlayerObject(NULL), bqPlayerPlay(NULL), outputMixObject(NULL), bqPlayerBufferQueue(NULL) | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | AudioPlayer::~AudioPlayer() { | ||
|  | } | ||
|  | 
 | ||
|  | void AudioPlayer::playerCallback(SLAndroidSimpleBufferQueueItf bufferQueue, void *context) { | ||
|  |   AudioPlayer* audioPlayer = static_cast<AudioPlayer*>(context); | ||
|  |   audioPlayer->playerCallback(bufferQueue); | ||
|  | } | ||
|  | 
 | ||
|  | void AudioPlayer::playerCallback(SLAndroidSimpleBufferQueueItf bufferQueue) { | ||
|  |   int samples = webRtcJitterBuffer.getAudio(outputBuffer, FRAME_SIZE); | ||
|  | //  __android_log_print(ANDROID_LOG_WARN, TAG, "Jitter gave me: %d samples", samples);
 | ||
|  |   (*bufferQueue)->Enqueue(bufferQueue, outputBuffer, samples * sizeof(short)); | ||
|  | } | ||
|  | 
 | ||
|  | int AudioPlayer::start(SLEngineItf *engineEnginePtr) { | ||
|  |   SLEngineItf engineEngine = *engineEnginePtr; | ||
|  | 
 | ||
|  |   SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; | ||
|  | 
 | ||
|  |   SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_8, | ||
|  |                                  SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, | ||
|  |                                  SL_SPEAKER_FRONT_LEFT, SL_BYTEORDER_LITTLEENDIAN}; | ||
|  | 
 | ||
|  |   SLDataSource audioSrc = {&loc_bufq, &format_pcm}; | ||
|  | 
 | ||
|  |   const SLInterfaceID mixIds[] = {SL_IID_VOLUME}; | ||
|  |   const SLboolean    mixReq[]  = {SL_BOOLEAN_FALSE}; | ||
|  | 
 | ||
|  |   if ((*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, mixIds, mixReq) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "CreateOutputMix failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ((*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "Realize OutputMix failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; | ||
|  |   SLDataSink              audioSnk   = {&loc_outmix, NULL}; | ||
|  | 
 | ||
|  |   const SLInterfaceID ids[2] = {SL_IID_ANDROIDCONFIGURATION, SL_IID_BUFFERQUEUE}; | ||
|  |   const SLboolean     req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; | ||
|  | 
 | ||
|  |   if ((*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "CreateAudioPlayer failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   SLAndroidConfigurationItf playerConfig; | ||
|  | 
 | ||
|  |   if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDCONFIGURATION, &playerConfig) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "Get AndroidConfiguration interface failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   SLint32 streamType = SL_ANDROID_STREAM_VOICE; | ||
|  | 
 | ||
|  |   if ((*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32)) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "Setting SL_ANDROID_STREAM_VOICE failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ((*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "Realize PlayerObject failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "GetInterface PlayerObject failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "BufferQueue failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ((*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, &AudioPlayer::playerCallback, this) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "RegisterCallback failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   memset(outputBuffer, 0, FRAME_SIZE * sizeof(short)); | ||
|  | 
 | ||
|  |   if ((*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, outputBuffer, FRAME_SIZE * sizeof(short)) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "Player enqueue failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ((*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING) != SL_RESULT_SUCCESS) { | ||
|  |     __android_log_print(ANDROID_LOG_WARN, TAG, "Play state failed!"); | ||
|  |     return -1; | ||
|  |   } | ||
|  | 
 | ||
|  |   return 0; | ||
|  | } | ||
|  | 
 | ||
|  | void AudioPlayer::stop() { | ||
|  |   if (bqPlayerPlay != NULL) { | ||
|  |     (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); | ||
|  |   } | ||
|  | 
 | ||
|  |   if (bqPlayerBufferQueue != NULL) { | ||
|  |     (*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue); | ||
|  |   } | ||
|  | 
 | ||
|  |   if (bqPlayerObject != NULL) { | ||
|  |     (*bqPlayerObject)->Destroy(bqPlayerObject); | ||
|  |     bqPlayerPlay        = NULL; | ||
|  |     bqPlayerBufferQueue = NULL; | ||
|  |     bqPlayerObject      = NULL; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (outputMixObject != NULL) { | ||
|  |     (*outputMixObject)->Destroy(outputMixObject); | ||
|  |     outputMixObject = NULL; | ||
|  |   } | ||
|  | } |