blob: d0b3be0c19192efc4d8b2d257a88dafcd9667d5e [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Test for testing the creation of OpenSL ES objects under various configurations (determined
* by their data source and sink types) that are expected to be supported.
* The tests verify the creation and completion of the call to Realize() for the following objects:
* - Engine
* - OutputMix
* - AudioPlayer:
* * source is URI
* * source is FD
* * source is BufferQueue of PCM buffers
* * source is AndroidBufferQueue of MP2TS buffers
* * source is URI, sink is BufferQueue of PCM buffers
* * source is FD, sink is BufferQueue of PCM buffers
* * source is AndroidBufferQueue of AAC ADTS buffers, sink is BufferQueue of PCM buffers
* - AudioRecorder
* * source is IO device, sink is BufferQueue of PCM buffers
*/
#define LOG_NDEBUG 0
#define LOG_TAG "SLObjectCreationTest"
#include <gtest/gtest.h>
#include <utils/Log.h>
#if !defined(BUILD_ONLY)
#include "SLES/OpenSLES.h"
#include "SLES/OpenSLES_Android.h"
#include "OpenSLESUT.h"
#endif
#if !defined(BUILD_ONLY)
//-----------------------------------------------------------------
/* Checks for error and displays the error code if any */
bool IsOk(SLresult res) {
if (SL_RESULT_SUCCESS != res) {
const char *str = slesutResultToString(res);
if (NULL == str)
str = "unknown";
fprintf(stderr, "IsOk failure: %s (0x%x), exiting\n", str, res);
return false;
}
return true;
}
//-----------------------------------------------------------------
class SLObjectCreationTest : public ::testing::Test {
protected:
SLresult res;
SLObjectItf engineObj, outputMixObj, audioPlayerObj;
SLEngineItf engineItf;
SLDataSource audioSource;
SLDataSink audioSink;
SLDataLocator_URI locatorUriSrc;
SLDataLocator_AndroidBufferQueue locatorAbqSrc;
SLDataLocator_AndroidFD locatorFdSrc;
SLDataFormat_MIME formatMimeSrc;
SLDataLocator_OutputMix locatorOutputmixSnk;
SLDataLocator_AndroidSimpleBufferQueue locatorBqSnk;
SLDataFormat_PCM formatPcmSnk;
SLObjectCreationTest() { }
virtual ~SLObjectCreationTest() { }
/* Test setup*/
virtual void SetUp() {
ALOGV("Test Setup()");
res = SL_RESULT_UNKNOWN_ERROR;
engineItf = NULL;
engineObj = NULL;
outputMixObj = NULL;
audioPlayerObj = NULL;
// Engine creation
res = slCreateEngine(&engineObj, 0, NULL, 0, NULL, NULL);
ASSERT_TRUE(IsOk(res));
res = (*engineObj)->Realize(engineObj, SL_BOOLEAN_FALSE);
ASSERT_TRUE(IsOk(res));
res = (*engineObj)->GetInterface(engineObj, SL_IID_ENGINE, &engineItf);
ASSERT_TRUE(IsOk(res));
ASSERT_TRUE(NULL != engineItf);
}
virtual void TearDown() {
ALOGV("Test TearDown()");
if (audioPlayerObj) {
(*audioPlayerObj)->Destroy(audioPlayerObj);
audioPlayerObj = NULL;
}
if (outputMixObj) {
(*outputMixObj)->Destroy(outputMixObj);
outputMixObj = NULL;
}
if (engineObj){
(*engineObj)->Destroy(engineObj);
engineObj = NULL;
}
}
//---------------------------------------------------------------------------------------------
// Test implementation convenience methods (to avoid code duplication)
void AudioPlayerCreation() {
res = (*engineItf)->CreateAudioPlayer(engineItf, &audioPlayerObj,
&audioSource, &audioSink, 0, NULL/*iidArray*/, NULL/*required*/);
ASSERT_TRUE(IsOk(res));
ASSERT_TRUE(NULL != audioPlayerObj);
res = (*audioPlayerObj)->Realize(audioPlayerObj, SL_BOOLEAN_FALSE);
ASSERT_TRUE(IsOk(res));
}
void OutputMixSinkInitialization() {
locatorOutputmixSnk.locatorType = SL_DATALOCATOR_OUTPUTMIX;
locatorOutputmixSnk.outputMix = outputMixObj; // created in OutputMixCreation()
audioSink.pLocator = &locatorOutputmixSnk;
audioSink.pFormat = NULL;
}
void UriSourceInitialization() {
locatorUriSrc.locatorType = SL_DATALOCATOR_URI;
locatorUriSrc.URI = (SLchar*) "/dummyPath/dummyFile.mp3";
formatMimeSrc.formatType = SL_DATAFORMAT_MIME;
formatMimeSrc.mimeType = (SLchar *) NULL;
formatMimeSrc.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
audioSource.pLocator = &locatorUriSrc;
audioSource.pFormat = &formatMimeSrc;
}
void FdSourceInitialization() {
locatorFdSrc.locatorType = SL_DATALOCATOR_ANDROIDFD;
locatorFdSrc.fd = (SLint32) 1;// a positive value to fake a valid FD
locatorFdSrc.length = 10;
locatorFdSrc.offset = 0;
formatMimeSrc.formatType = SL_DATAFORMAT_MIME;
formatMimeSrc.mimeType = (SLchar *) NULL;
formatMimeSrc.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
audioSource.pLocator = &locatorFdSrc;
audioSource.pFormat = &formatMimeSrc;
}
void PcmBqSinkInitialization() {
locatorBqSnk.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
locatorBqSnk.numBuffers = 16;
formatPcmSnk.formatType = SL_DATAFORMAT_PCM;
formatPcmSnk.numChannels = 1;
formatPcmSnk.samplesPerSec = SL_SAMPLINGRATE_8;
formatPcmSnk.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
formatPcmSnk.containerSize = 16;
formatPcmSnk.channelMask = SL_SPEAKER_FRONT_LEFT;
formatPcmSnk.endianness = SL_BYTEORDER_LITTLEENDIAN;
audioSink.pLocator = (void *) &locatorBqSnk;
audioSink.pFormat = (void *) &formatPcmSnk;
}
//---------------------------------------------------------------------------------------------
// Tests
/* Test case for creating an AudioPlayer object */
void OutputMixCreation() {
res = (*engineItf)->CreateOutputMix(engineItf, &outputMixObj,
0, NULL/*iidArray*/, NULL/*required*/);
ASSERT_TRUE(IsOk(res));
ASSERT_TRUE(NULL != outputMixObj);
res = (*outputMixObj)->Realize(outputMixObj, SL_BOOLEAN_FALSE);
ASSERT_TRUE(IsOk(res));
}
/* Test case for creating an AudioPlayer object that plays from a URI */
void AudioPlayerFromUriCreation() {
// source: URI
UriSourceInitialization();
// sink: OutputMix
OutputMixSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioPlayer object that plays from a FD */
void AudioPlayerFromFdCreation() {
// source: FD
FdSourceInitialization();
// sink: OutputMix
OutputMixSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioPlayer object that plays from a PCM BufferQueue */
void AudioPlayerFromPcmBqCreation() {
// source: PCM BufferQueue
SLDataLocator_BufferQueue locatorBufferQueue;
locatorBufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
locatorBufferQueue.numBuffers = 16;
SLDataFormat_PCM pcm;
pcm.formatType = SL_DATAFORMAT_PCM;
pcm.numChannels = 2;
pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
pcm.containerSize = 16;
pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
audioSource.pLocator = &locatorBufferQueue;
audioSource.pFormat = &pcm;
// sink: OutputMix
OutputMixSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioPlayer object that plays from Transport Stream ABQ */
void AudioPlayerFromTsAbqCreation() {
// source: transport stream in an AndroidBufferQueue
locatorAbqSrc.locatorType = SL_DATALOCATOR_ANDROIDBUFFERQUEUE;
locatorAbqSrc.numBuffers = 16;
formatMimeSrc.formatType = SL_DATAFORMAT_MIME;
formatMimeSrc.mimeType = (SLchar *) "video/mp2ts";
formatMimeSrc.containerType = SL_CONTAINERTYPE_MPEG_TS;
audioSource.pFormat = (void *)&formatMimeSrc;
audioSource.pLocator = (void *)&locatorAbqSrc;
// sink: OutputMix
OutputMixSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioPlayer object that decodes from a URI to a PCM BQ */
void AudioPlayerFromUriToPcmBqCreation() {
// source: URI
UriSourceInitialization();
// sink: PCM BufferQueue
PcmBqSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioPlayer object that decodes from a FD to a PCM BQ */
void AudioPlayerFromFdToPcmBqCreation() {
// source: FD
FdSourceInitialization();
// sink: PCM BufferQueue
PcmBqSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioPlayer object that decodes from a ADTS ABQ to a PCM BQ */
void AudioPlayerFromAdtsAbqToPcmBqCreation() {
// source: ADTS AndroidBufferQueue
locatorAbqSrc.locatorType = SL_DATALOCATOR_ANDROIDBUFFERQUEUE;
locatorAbqSrc.numBuffers = 16;
formatMimeSrc.formatType = SL_DATAFORMAT_MIME;
formatMimeSrc.mimeType = (SLchar *)"audio/aac-adts";
formatMimeSrc.containerType = SL_CONTAINERTYPE_RAW;
audioSource.pLocator = (void *) &locatorAbqSrc;
audioSource.pFormat = (void *) &formatMimeSrc;
// sink: PCM BufferQueue
PcmBqSinkInitialization();
// AudioPlayer creation
AudioPlayerCreation();
}
/* Test case for creating an AudioRecorder object */
void AudioRecorderCreation(bool doNotRealize = false) {
// source: IO device
SLDataLocator_IODevice locatorIoDeviceSrc;
locatorIoDeviceSrc.locatorType = SL_DATALOCATOR_IODEVICE;
locatorIoDeviceSrc.deviceType = SL_IODEVICE_AUDIOINPUT;
locatorIoDeviceSrc.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
locatorIoDeviceSrc.device = NULL;
audioSource.pLocator = (void *) &locatorIoDeviceSrc;
audioSource.pFormat = NULL;
// sink: PCM BufferQueue
PcmBqSinkInitialization();
// AudioRecorder creation
SLObjectItf audioRecorderObj = NULL;
res = (*engineItf)->CreateAudioRecorder(engineItf, &audioRecorderObj,
&audioSource, &audioSink, 0, NULL/*iidArray*/, NULL/*required*/);
ASSERT_TRUE(IsOk(res));
ASSERT_TRUE(NULL != audioRecorderObj);
if (!doNotRealize) {
res = (*audioRecorderObj)->Realize(audioRecorderObj, SL_BOOLEAN_FALSE);
ASSERT_TRUE(IsOk(res));
}
// AudioRecorder destruction
(*audioRecorderObj)->Destroy(audioRecorderObj);
}
};
#else
class SLObjectCreationTest : public ::testing::Test {
protected:
void OutputMixCreation() { }
void AudioPlayerFromUriCreation() { }
void AudioPlayerFromFdCreation() { }
void AudioPlayerFromPcmBqCreation() { }
void AudioPlayerFromTsAbqCreation() { }
void AudioPlayerFromUriToPcmBqCreation() { }
void AudioPlayerFromFdToPcmBqCreation() { }
void AudioPlayerFromAdtsAbqToPcmBqCreation() { }
void AudioRecorderCreation(bool) { }
};
#endif
//-------------------------------------------------------------------------------------------------
TEST_F(SLObjectCreationTest, testEngineCreation) {
ALOGV("Test Fixture: EngineCreation");
// nothing to do here that isn't done in SetUp()
}
TEST_F(SLObjectCreationTest, testOutputMixCreation) {
ALOGV("Test Fixture: OutputMixCreation");
OutputMixCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromUriCreation) {
ALOGV("Test Fixture: AudioPlayerFromUriCreation");
// required for AudioPlayer creation
OutputMixCreation();
AudioPlayerFromUriCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromFdCreation) {
ALOGV("Test Fixture: AudioPlayerFromFdCreation");
// required for AudioPlayer creation
OutputMixCreation();
AudioPlayerFromFdCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromPcmBqCreation) {
ALOGV("Test Fixture: AudioPlayerFromPcmBqCreation");
// required for AudioPlayer creation
OutputMixCreation();
AudioPlayerFromPcmBqCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromTsAbqCreation) {
ALOGV("Test Fixture: AudioPlayerFromTsAbqCreation");
// required for AudioPlayer creation
OutputMixCreation();
AudioPlayerFromTsAbqCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromUriToPcmBqCreation) {
ALOGV("Test Fixture: AudioPlayerFromUriToPcmBqCreation");
AudioPlayerFromUriToPcmBqCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromFdToPcmBqCreation) {
ALOGV("Test Fixture: AudioPlayerFromFdToPcmBqCreation");
AudioPlayerFromFdToPcmBqCreation();
}
TEST_F(SLObjectCreationTest, testAudioPlayerFromAdtsAbqToPcmBqCreation) {
ALOGV("Test Fixture: AudioPlayerFromAdtsAbqToPcmBqCreation");
AudioPlayerFromAdtsAbqToPcmBqCreation();
}
TEST_F(SLObjectCreationTest, testAudioRecorderCreation) {
ALOGV("Test Fixture: AudioRecorderCreation");
// cannot Realize as native test cannot have necessary permission.
AudioRecorderCreation(true);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}