Blame channels/rdpsnd/client/opensles/opensl_io.c

Packit Service fa4841
/*
Packit Service fa4841
opensl_io.c:
Packit Service fa4841
Android OpenSL input/output module
Packit Service fa4841
Copyright (c) 2012, Victor Lazzarini
Packit Service fa4841
All rights reserved.
Packit Service fa4841
Packit Service fa4841
Redistribution and use in source and binary forms, with or without
Packit Service fa4841
modification, are permitted provided that the following conditions are met:
Packit Service fa4841
    * Redistributions of source code must retain the above copyright
Packit Service fa4841
      notice, this list of conditions and the following disclaimer.
Packit Service fa4841
    * Redistributions in binary form must reproduce the above copyright
Packit Service fa4841
      notice, this list of conditions and the following disclaimer in the
Packit Service fa4841
      documentation and/or other materials provided with the distribution.
Packit Service fa4841
    * Neither the name of the <organization> nor the
Packit Service fa4841
      names of its contributors may be used to endorse or promote products
Packit Service fa4841
      derived from this software without specific prior written permission.
Packit Service fa4841
Packit Service fa4841
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Packit Service fa4841
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Packit Service fa4841
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit Service fa4841
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
Packit Service fa4841
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit Service fa4841
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Packit Service fa4841
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Packit Service fa4841
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service fa4841
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit Service fa4841
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service fa4841
*/
Packit Service fa4841
Packit Service fa4841
#include <assert.h>
Packit Service fa4841
Packit Service fa4841
#include "rdpsnd_main.h"
Packit Service fa4841
#include "opensl_io.h"
Packit Service fa4841
#define CONV16BIT 32768
Packit Service fa4841
#define CONVMYFLT (1. / 32768.)
Packit Service fa4841
Packit Service fa4841
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
Packit Service fa4841
Packit Service fa4841
// creates the OpenSL ES audio engine
Packit Service fa4841
static SLresult openSLCreateEngine(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	SLresult result;
Packit Service fa4841
	// create engine
Packit Service fa4841
	result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
Packit Service fa4841
	DEBUG_SND("engineObject=%p", (void*)p->engineObject);
Packit Service fa4841
Packit Service fa4841
	if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
		goto engine_end;
Packit Service fa4841
Packit Service fa4841
	// realize the engine
Packit Service fa4841
	result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
Packit Service fa4841
	DEBUG_SND("Realize=%" PRIu32 "", result);
Packit Service fa4841
Packit Service fa4841
	if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
		goto engine_end;
Packit Service fa4841
Packit Service fa4841
	// get the engine interface, which is needed in order to create other objects
Packit Service fa4841
	result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
Packit Service fa4841
	DEBUG_SND("engineEngine=%p", (void*)p->engineEngine);
Packit Service fa4841
Packit Service fa4841
	if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
		goto engine_end;
Packit Service fa4841
Packit Service fa4841
engine_end:
Packit Service fa4841
	return result;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
// opens the OpenSL ES device for output
Packit Service fa4841
static SLresult openSLPlayOpen(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	SLresult result;
Packit Service fa4841
	SLuint32 sr = p->sr;
Packit Service fa4841
	SLuint32 channels = p->outchannels;
Packit Service fa4841
	assert(p->engineObject);
Packit Service fa4841
	assert(p->engineEngine);
Packit Service fa4841
Packit Service fa4841
	if (channels)
Packit Service fa4841
	{
Packit Service fa4841
		// configure audio source
Packit Service fa4841
		SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
Packit Service fa4841
			                                                p->queuesize };
Packit Service fa4841
Packit Service fa4841
		switch (sr)
Packit Service fa4841
		{
Packit Service fa4841
			case 8000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_8;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 11025:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_11_025;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 16000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_16;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 22050:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_22_05;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 24000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_24;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 32000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_32;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 44100:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_44_1;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 48000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_48;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 64000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_64;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 88200:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_88_2;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 96000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_96;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case 192000:
Packit Service fa4841
				sr = SL_SAMPLINGRATE_192;
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			default:
Packit Service fa4841
				return -1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		const SLInterfaceID ids[] = { SL_IID_VOLUME };
Packit Service fa4841
		const SLboolean req[] = { SL_BOOLEAN_FALSE };
Packit Service fa4841
		result = (*p->engineEngine)
Packit Service fa4841
		             ->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req);
Packit Service fa4841
		DEBUG_SND("engineEngine=%p", (void*)p->engineEngine);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// realize the output mix
Packit Service fa4841
		result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
Packit Service fa4841
		DEBUG_SND("Realize=%" PRIu32 "", result);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		int speakers;
Packit Service fa4841
Packit Service fa4841
		if (channels > 1)
Packit Service fa4841
			speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
Packit Service fa4841
		else
Packit Service fa4841
			speakers = SL_SPEAKER_FRONT_CENTER;
Packit Service fa4841
Packit Service fa4841
		SLDataFormat_PCM format_pcm = { SL_DATAFORMAT_PCM,
Packit Service fa4841
			                            channels,
Packit Service fa4841
			                            sr,
Packit Service fa4841
			                            SL_PCMSAMPLEFORMAT_FIXED_16,
Packit Service fa4841
			                            SL_PCMSAMPLEFORMAT_FIXED_16,
Packit Service fa4841
			                            speakers,
Packit Service fa4841
			                            SL_BYTEORDER_LITTLEENDIAN };
Packit Service fa4841
		SLDataSource audioSrc = { &loc_bufq, &format_pcm };
Packit Service fa4841
		// configure audio sink
Packit Service fa4841
		SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject };
Packit Service fa4841
		SLDataSink audioSnk = { &loc_outmix, NULL };
Packit Service fa4841
		// create audio player
Packit Service fa4841
		const SLInterfaceID ids1[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };
Packit Service fa4841
		const SLboolean req1[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
Packit Service fa4841
		result = (*p->engineEngine)
Packit Service fa4841
		             ->CreateAudioPlayer(p->engineEngine, &(p->bqPlayerObject), &audioSrc,
Packit Service fa4841
		                                 &audioSnk, 2, ids1, req1);
Packit Service fa4841
		DEBUG_SND("bqPlayerObject=%p", (void*)p->bqPlayerObject);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// realize the player
Packit Service fa4841
		result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
Packit Service fa4841
		DEBUG_SND("Realize=%" PRIu32 "", result);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// get the play interface
Packit Service fa4841
		result =
Packit Service fa4841
		    (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay));
Packit Service fa4841
		DEBUG_SND("bqPlayerPlay=%p", (void*)p->bqPlayerPlay);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// get the volume interface
Packit Service fa4841
		result = (*p->bqPlayerObject)
Packit Service fa4841
		             ->GetInterface(p->bqPlayerObject, SL_IID_VOLUME, &(p->bqPlayerVolume));
Packit Service fa4841
		DEBUG_SND("bqPlayerVolume=%p", (void*)p->bqPlayerVolume);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// get the buffer queue interface
Packit Service fa4841
		result = (*p->bqPlayerObject)
Packit Service fa4841
		             ->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
Packit Service fa4841
		                            &(p->bqPlayerBufferQueue));
Packit Service fa4841
		DEBUG_SND("bqPlayerBufferQueue=%p", (void*)p->bqPlayerBufferQueue);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// register callback on the buffer queue
Packit Service fa4841
		result = (*p->bqPlayerBufferQueue)
Packit Service fa4841
		             ->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p);
Packit Service fa4841
		DEBUG_SND("bqPlayerCallback=%p", (void*)p->bqPlayerCallback);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
Packit Service fa4841
		if (result != SL_RESULT_SUCCESS)
Packit Service fa4841
			goto end_openaudio;
Packit Service fa4841
Packit Service fa4841
		// set the player's state to playing
Packit Service fa4841
		result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
Packit Service fa4841
		DEBUG_SND("SetPlayState=%" PRIu32 "", result);
Packit Service fa4841
		assert(!result);
Packit Service fa4841
	end_openaudio:
Packit Service fa4841
		assert(!result);
Packit Service fa4841
		return result;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return SL_RESULT_SUCCESS;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
// close the OpenSL IO and destroy the audio engine
Packit Service fa4841
static void openSLDestroyEngine(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	// destroy buffer queue audio player object, and invalidate all associated interfaces
Packit Service fa4841
	if (p->bqPlayerObject != NULL)
Packit Service fa4841
	{
Packit Service fa4841
		(*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
Packit Service fa4841
		p->bqPlayerObject = NULL;
Packit Service fa4841
		p->bqPlayerVolume = NULL;
Packit Service fa4841
		p->bqPlayerPlay = NULL;
Packit Service fa4841
		p->bqPlayerBufferQueue = NULL;
Packit Service fa4841
		p->bqPlayerEffectSend = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	// destroy output mix object, and invalidate all associated interfaces
Packit Service fa4841
	if (p->outputMixObject != NULL)
Packit Service fa4841
	{
Packit Service fa4841
		(*p->outputMixObject)->Destroy(p->outputMixObject);
Packit Service fa4841
		p->outputMixObject = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	// destroy engine object, and invalidate all associated interfaces
Packit Service fa4841
	if (p->engineObject != NULL)
Packit Service fa4841
	{
Packit Service fa4841
		(*p->engineObject)->Destroy(p->engineObject);
Packit Service fa4841
		p->engineObject = NULL;
Packit Service fa4841
		p->engineEngine = NULL;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
// open the android audio device for and/or output
Packit Service fa4841
OPENSL_STREAM* android_OpenAudioDevice(int sr, int outchannels, int bufferframes)
Packit Service fa4841
{
Packit Service fa4841
	OPENSL_STREAM* p;
Packit Service fa4841
	p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
Packit Service fa4841
Packit Service fa4841
	if (!p)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	p->queuesize = bufferframes;
Packit Service fa4841
	p->outchannels = outchannels;
Packit Service fa4841
	p->sr = sr;
Packit Service fa4841
Packit Service fa4841
	if (openSLCreateEngine(p) != SL_RESULT_SUCCESS)
Packit Service fa4841
	{
Packit Service fa4841
		android_CloseAudioDevice(p);
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (openSLPlayOpen(p) != SL_RESULT_SUCCESS)
Packit Service fa4841
	{
Packit Service fa4841
		android_CloseAudioDevice(p);
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	p->queue = Queue_New(TRUE, -1, -1);
Packit Service fa4841
Packit Service fa4841
	if (!p->queue)
Packit Service fa4841
	{
Packit Service fa4841
		android_CloseAudioDevice(p);
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return p;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
// close the android audio device
Packit Service fa4841
void android_CloseAudioDevice(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	if (p == NULL)
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	openSLDestroyEngine(p);
Packit Service fa4841
Packit Service fa4841
	if (p->queue)
Packit Service fa4841
		Queue_Free(p->queue);
Packit Service fa4841
Packit Service fa4841
	free(p);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
// this callback handler is called every time a buffer finishes playing
Packit Service fa4841
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
Packit Service fa4841
{
Packit Service fa4841
	OPENSL_STREAM* p = (OPENSL_STREAM*)context;
Packit Service fa4841
	assert(p);
Packit Service fa4841
	assert(p->queue);
Packit Service fa4841
	void* data = Queue_Dequeue(p->queue);
Packit Service fa4841
	free(data);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
// puts a buffer of size samples to the device
Packit Service fa4841
int android_AudioOut(OPENSL_STREAM* p, const short* buffer, int size)
Packit Service fa4841
{
Packit Service fa4841
	assert(p);
Packit Service fa4841
	assert(buffer);
Packit Service fa4841
	assert(size > 0);
Packit Service fa4841
Packit Service fa4841
	/* Assure, that the queue is not full. */
Packit Service fa4841
	if (p->queuesize <= Queue_Count(p->queue) &&
Packit Service fa4841
	    WaitForSingleObject(p->queue->event, INFINITE) == WAIT_FAILED)
Packit Service fa4841
	{
Packit Service fa4841
		DEBUG_SND("WaitForSingleObject failed!");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	void* data = calloc(size, sizeof(short));
Packit Service fa4841
Packit Service fa4841
	if (!data)
Packit Service fa4841
	{
Packit Service fa4841
		DEBUG_SND("unable to allocate a buffer");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	memcpy(data, buffer, size * sizeof(short));
Packit Service fa4841
	Queue_Enqueue(p->queue, data);
Packit Service fa4841
	(*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue, data, sizeof(short) * size);
Packit Service fa4841
	return size;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int android_GetOutputMute(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	SLboolean mute;
Packit Service fa4841
	assert(p);
Packit Service fa4841
	assert(p->bqPlayerVolume);
Packit Service fa4841
	SLresult rc = (*p->bqPlayerVolume)->GetMute(p->bqPlayerVolume, &mute);
Packit Service fa4841
Packit Service fa4841
	if (SL_RESULT_SUCCESS != rc)
Packit Service fa4841
		return SL_BOOLEAN_FALSE;
Packit Service fa4841
Packit Service fa4841
	return mute;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL android_SetOutputMute(OPENSL_STREAM* p, BOOL _mute)
Packit Service fa4841
{
Packit Service fa4841
	SLboolean mute = _mute;
Packit Service fa4841
	assert(p);
Packit Service fa4841
	assert(p->bqPlayerVolume);
Packit Service fa4841
	SLresult rc = (*p->bqPlayerVolume)->SetMute(p->bqPlayerVolume, mute);
Packit Service fa4841
Packit Service fa4841
	if (SL_RESULT_SUCCESS != rc)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int android_GetOutputVolume(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	SLmillibel level;
Packit Service fa4841
	assert(p);
Packit Service fa4841
	assert(p->bqPlayerVolume);
Packit Service fa4841
	SLresult rc = (*p->bqPlayerVolume)->GetVolumeLevel(p->bqPlayerVolume, &level);
Packit Service fa4841
Packit Service fa4841
	if (SL_RESULT_SUCCESS != rc)
Packit Service fa4841
		return 0;
Packit Service fa4841
Packit Service fa4841
	return level;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int android_GetOutputVolumeMax(OPENSL_STREAM* p)
Packit Service fa4841
{
Packit Service fa4841
	SLmillibel level;
Packit Service fa4841
	assert(p);
Packit Service fa4841
	assert(p->bqPlayerVolume);
Packit Service fa4841
	SLresult rc = (*p->bqPlayerVolume)->GetMaxVolumeLevel(p->bqPlayerVolume, &level);
Packit Service fa4841
Packit Service fa4841
	if (SL_RESULT_SUCCESS != rc)
Packit Service fa4841
		return 0;
Packit Service fa4841
Packit Service fa4841
	return level;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL android_SetOutputVolume(OPENSL_STREAM* p, int level)
Packit Service fa4841
{
Packit Service fa4841
	SLresult rc = (*p->bqPlayerVolume)->SetVolumeLevel(p->bqPlayerVolume, level);
Packit Service fa4841
Packit Service fa4841
	if (SL_RESULT_SUCCESS != rc)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}