BufferQueue_test.cpp revision 104c000a6f36b871ca11e0394db1e5217f374caf
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/** \file BufferQueue_test.cpp */ 18 19#define LOG_NDEBUG 0 20#define LOG_TAG "BufferQueue_test" 21 22#ifdef ANDROID 23#include <utils/Log.h> 24#else 25#define LOGV printf 26#endif 27 28#include <assert.h> 29#include <math.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <unistd.h> 33#include "SLES/OpenSLES.h" 34#include "SLES/OpenSLESUT.h" 35#include <gtest/gtest.h> 36 37typedef struct { 38 short left; 39 short right; 40} stereo; 41 42// volume of sine wave in range 0.0 to 1.0 43static float gVolume = 1.0f; 44 45// 1 second of stereo audio at 44.1 kHz 46static stereo stereoBuffer1[44100 * 1]; 47static const SLuint32 invalidNumBuffers[] = { 0, 0xFFFFFFFF, 0x80000000, 0x10002, 0x102, 48 0x101, 0x100 }; 49static const SLuint32 validNumBuffers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 255 }; 50 51//----------------------------------------------------------------- 52/* Checks for error. If any errors exit the application! */ 53void CheckErr(SLresult res) { 54 if (SL_RESULT_SUCCESS != res) { 55 fprintf(stderr, "CheckErr failure: %s (0x%x), exiting\n", slesutResultToString(res), 56 (unsigned) res); 57 //Fail the test case 58 FAIL(); 59 } 60} 61 62static const SLInterfaceID ids[1] = { SL_IID_BUFFERQUEUE }; 63static const SLboolean flags[1] = { SL_BOOLEAN_TRUE }; 64static const SLInterfaceID ids_mutesolo[2] = { SL_IID_BUFFERQUEUE, SL_IID_MUTESOLO }; 65static const SLboolean flags_mutesolo[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; 66static const SLInterfaceID ids_seek[2] = { SL_IID_BUFFERQUEUE, SL_IID_SEEK }; 67static const SLboolean flags_seek[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; 68 69// The fixture for testing class BufferQueue 70class TestBufferQueue: public ::testing::Test { 71public: 72 SLresult res; 73 SLObjectItf outputmixObject; 74 SLObjectItf engineObject; 75 76 SLDataSource audiosrc; 77 SLDataSink audiosnk; 78 SLDataFormat_PCM pcm; 79 SLDataLocator_OutputMix locator_outputmix; 80 SLDataLocator_BufferQueue locator_bufferqueue; 81 SLBufferQueueItf playerBufferQueue; 82 SLBufferQueueState bufferqueueState; 83 SLPlayItf playerPlay; 84 SLObjectItf playerObject; 85 SLEngineItf engineEngine; 86 SLuint32 playerState; 87 88protected: 89 TestBufferQueue() { 90 } 91 92 virtual ~TestBufferQueue() { 93 94 } 95 96 /*Test setup*/ 97 virtual void SetUp() { 98 99 // create engine 100 res = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 101 CheckErr(res); 102 res = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 103 CheckErr(res); 104 res = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 105 CheckErr(res); 106 107 // create output mix 108 res = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL); 109 CheckErr(res); 110 res = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE); 111 CheckErr(res); 112 113 locator_bufferqueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 114 locator_bufferqueue.numBuffers = 0; 115 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 116 locator_outputmix.outputMix = outputmixObject; 117 118 pcm.formatType = SL_DATAFORMAT_PCM; 119 pcm.numChannels = 2; 120 pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; 121 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 122 pcm.containerSize = 16; 123 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 124 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 125 126 audiosrc.pLocator = &locator_bufferqueue; 127 audiosrc.pFormat = &pcm; 128 audiosnk.pLocator = &locator_outputmix; 129 audiosnk.pFormat = NULL; 130 131 // initialize the test tone to be a sine sweep from 441 Hz to 882 Hz 132 unsigned nframes = sizeof(stereoBuffer1) / sizeof(stereoBuffer1[0]); 133 float nframes_ = (float) nframes; 134 SLuint32 i; 135 for (i = 0; i < nframes; ++i) { 136 float i_ = (float) i; 137 float pcm_ = sin((i_ * (1.0f + 0.5f * (i_ / nframes_)) * 0.01 * M_PI * 2.0)); 138 int pcm = (int) (pcm_ * 32766.0 * gVolume); 139 ASSERT_TRUE(-32768 <= pcm && pcm <= 32767) << "pcm out of bound " << pcm; 140 stereoBuffer1[i].left = pcm; 141 stereoBuffer1[nframes - 1 - i].right = pcm; 142 } 143 } 144 145 virtual void TearDown() { 146 // Clean up the mixer and the engine 147 // (must be done in that order, and after player destroyed) 148 if (outputmixObject){ 149 (*outputmixObject)->Destroy(outputmixObject); 150 outputmixObject = NULL; 151 } 152 if (engineObject){ 153 (*engineObject)->Destroy(engineObject); 154 engineObject = NULL; 155 } 156 } 157 158 void DestroyPlayer() { 159 if (playerObject){ 160 //printf("destroy player\n"); 161 (*playerObject)->Destroy(playerObject); 162 playerObject = NULL; 163 } 164 } 165 166 /* Test case for creating audio player with various invalid values for numBuffers*/ 167 void InvalidBuffer() { 168 169 for (unsigned i = 0; i < sizeof(invalidNumBuffers) / sizeof(invalidNumBuffers[0]); ++i) { 170 SLuint32 numBuffers = invalidNumBuffers[i]; 171 172 locator_bufferqueue.numBuffers = numBuffers; 173 //printf("create audio player - invalid\n"); 174 SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, 175 &audiosrc, &audiosnk, 1, ids, flags); 176 ASSERT_EQ(SL_RESULT_PARAMETER_INVALID, result); 177 ASSERT_EQ(NULL, playerObject); 178 179 } 180 } 181 182 /*Prepare the buffer*/ 183 void PrepareValidBuffer(SLuint32 numBuffers) { 184 185 locator_bufferqueue.numBuffers = numBuffers; 186 //printf("create audio player - valid\n"); 187 res = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 188 1, ids, flags); 189 CheckErr(res); 190 res = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 191 CheckErr(res); 192 // get the play interface 193 res = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 194 CheckErr(res); 195 // verify that player is initially stopped 196 res = (*playerPlay)->GetPlayState(playerPlay, &playerState); 197 CheckErr(res); 198 ASSERT_EQ(SL_PLAYSTATE_STOPPED, playerState); 199 200 // get the buffer queue interface 201 res = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue); 202 CheckErr(res); 203 204 // verify that buffer queue is initially empty 205 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 206 CheckErr(res); 207 ASSERT_EQ((SLuint32) 0, bufferqueueState.count); 208 ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex); 209 } 210 211 void EnqueueMaxBuffer(SLuint32 numBuffers) { 212 SLuint32 j; 213 214 for (j = 0; j < numBuffers; ++j) { 215 res = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4); 216 CheckErr(res); 217 // verify that each buffer is enqueued properly and increments the buffer count 218 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 219 CheckErr(res); 220 ASSERT_EQ(j + 1, bufferqueueState.count); 221 ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex); 222 } 223 } 224 225 void EnqueueExtraBuffer(SLuint32 numBuffers) { 226 // enqueue one more buffer and make sure it fails 227 res = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4); 228 ASSERT_EQ(SL_RESULT_BUFFER_INSUFFICIENT, res); 229 // verify that the failed enqueue did not affect the buffer count 230 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 231 CheckErr(res); 232 ASSERT_EQ(numBuffers, bufferqueueState.count); 233 ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex); 234 } 235 236 void SetPlayerState(SLuint32 state) { 237 res = (*playerPlay)->SetPlayState(playerPlay, state); 238 CheckErr(res); 239 //verify the state can set correctly 240 GetPlayerState(state); 241 } 242 243 void GetPlayerState(SLuint32 state) { 244 res = (*playerPlay)->GetPlayState(playerPlay, &playerState); 245 CheckErr(res); 246 ASSERT_EQ(state, playerState); 247 } 248 249 void ClearQueue() { 250 // now clear the buffer queue 251 res = (*playerBufferQueue)->Clear(playerBufferQueue); 252 CheckErr(res); 253 // make sure the clear works 254 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 255 CheckErr(res); 256 ASSERT_EQ((SLuint32) 0, bufferqueueState.count); 257 ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex); 258 } 259 260 void CheckBufferCount(SLuint32 ExpectedCount, SLuint32 ExpectedPlayIndex) { 261 // changing the play state should not affect the buffer count 262 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 263 CheckErr(res); 264 ASSERT_EQ(ExpectedCount, bufferqueueState.count); 265 ASSERT_EQ(ExpectedPlayIndex, bufferqueueState.playIndex); 266 } 267 268 void PlayBufferQueue() { 269 // enqueue a buffer 270 res = (*playerBufferQueue)->Enqueue(playerBufferQueue, stereoBuffer1, 271 sizeof(stereoBuffer1)); 272 CheckErr(res); 273 // set play state to playing 274 res = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 275 CheckErr(res); 276 // state should be playing immediately after enqueue 277 res = (*playerPlay)->GetPlayState(playerPlay, &playerState); 278 CheckErr(res); 279 ASSERT_EQ(SL_PLAYSTATE_PLAYING, playerState); 280 // buffer should still be on the queue 281 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 282 CheckErr(res); 283 ASSERT_EQ((SLuint32) 1, bufferqueueState.count); 284 ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex); 285 //LOGV("Before 1.5 sec"); 286 // wait 1.5 seconds 287 usleep(1500000); 288 //LOGV("After 1.5 sec"); 289 // state should still be playing 290 res = (*playerPlay)->GetPlayState(playerPlay, &playerState); 291 //LOGV("GetPlayState"); 292 CheckErr(res); 293 ASSERT_EQ(SL_PLAYSTATE_PLAYING, playerState); 294 // buffer should be removed from the queue 295 res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState); 296 CheckErr(res); 297 ASSERT_EQ((SLuint32) 0, bufferqueueState.count); 298 ASSERT_EQ((SLuint32) 1, bufferqueueState.playIndex); 299 //LOGV("TestEnd"); 300 } 301}; 302 303TEST_F(TestBufferQueue, testInvalidBuffer){ 304 //LOGV("Test Fixture: InvalidBuffer"); 305 InvalidBuffer(); 306} 307 308TEST_F(TestBufferQueue, testMuteSolo) { 309 // create audio player with buffer queue data source in stereo PCM format and ask for mute solo 310 locator_bufferqueue.numBuffers = 1; 311 SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, 312 &audiosnk, 2, ids_mutesolo, flags_mutesolo); 313 ASSERT_EQ(SL_RESULT_SUCCESS, result); 314 ASSERT_TRUE(NULL != playerObject); 315 DestroyPlayer(); 316 // create audio player with buffer queue data source in mono PCM format and ask for mute solo 317 pcm.numChannels = 1; 318 pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 319 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 320 2, ids_mutesolo, flags_mutesolo); 321 ASSERT_EQ(SL_RESULT_FEATURE_UNSUPPORTED, result); 322 ASSERT_EQ(NULL, playerObject); 323 DestroyPlayer(); 324} 325 326TEST_F(TestBufferQueue, testSeek) { 327 // can create audio player with buffer queue data source and ask for seek 328 locator_bufferqueue.numBuffers = 1; 329 SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, 330 &audiosrc, &audiosnk, 2, ids_seek, flags_seek); 331 ASSERT_EQ(SL_RESULT_FEATURE_UNSUPPORTED, result); 332 ASSERT_EQ(NULL, playerObject); 333 DestroyPlayer(); 334} 335 336TEST_F(TestBufferQueue, testValidBuffer) { 337 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 338 SLuint32 numBuffers = validNumBuffers[i]; 339 PrepareValidBuffer(numBuffers); 340 DestroyPlayer(); 341 } 342} 343 344TEST_F(TestBufferQueue, testEnqueueMaxBuffer) { 345 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 346 SLuint32 numBuffers = validNumBuffers[i]; 347 PrepareValidBuffer(numBuffers); 348 EnqueueMaxBuffer(numBuffers); 349 DestroyPlayer(); 350 } 351} 352 353TEST_F(TestBufferQueue, testEnqueueExtraBuffer) { 354 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 355 SLuint32 numBuffers = validNumBuffers[i]; 356 PrepareValidBuffer(numBuffers); 357 EnqueueMaxBuffer(numBuffers); 358 EnqueueExtraBuffer(numBuffers); 359 GetPlayerState(SL_PLAYSTATE_STOPPED); 360 DestroyPlayer(); 361 } 362} 363 364TEST_F(TestBufferQueue, testEnqueueAtStopped) { 365 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 366 SLuint32 numBuffers = validNumBuffers[i]; 367 PrepareValidBuffer(numBuffers); 368 SetPlayerState(SL_PLAYSTATE_STOPPED); 369 EnqueueMaxBuffer(numBuffers); 370 CheckBufferCount(numBuffers, (SLuint32) 0); 371 DestroyPlayer(); 372 } 373} 374 375TEST_F(TestBufferQueue, testEnqueueAtPaused) { 376 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 377 SLuint32 numBuffers = validNumBuffers[i]; 378 PrepareValidBuffer(numBuffers); 379 SetPlayerState(SL_PLAYSTATE_PAUSED); 380 EnqueueMaxBuffer(numBuffers); 381 CheckBufferCount(numBuffers, (SLuint32) 0); 382 DestroyPlayer(); 383 } 384} 385 386TEST_F(TestBufferQueue, testClearQueue) { 387 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 388 SLuint32 numBuffers = validNumBuffers[i]; 389 PrepareValidBuffer(numBuffers); 390 EnqueueMaxBuffer(numBuffers); 391 ClearQueue(); 392 DestroyPlayer(); 393 } 394} 395 396TEST_F(TestBufferQueue, testStateTransitionEmptyQueue) { 397 static const SLuint32 newStates[] = { 398 SL_PLAYSTATE_PAUSED, // paused -> paused 399 SL_PLAYSTATE_STOPPED, // paused -> stopped 400 SL_PLAYSTATE_PAUSED, // stopped -> paused 401 SL_PLAYSTATE_PLAYING, // paused -> playing 402 SL_PLAYSTATE_PLAYING, // playing -> playing 403 SL_PLAYSTATE_STOPPED, // playing -> stopped 404 SL_PLAYSTATE_STOPPED, // stopped -> stopped 405 SL_PLAYSTATE_PLAYING, // stopped -> playing 406 SL_PLAYSTATE_PAUSED // playing -> paused 407 }; 408 409 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 410 SLuint32 numBuffers = validNumBuffers[i]; 411 SLuint32 j; 412 413 PrepareValidBuffer(numBuffers); 414 /* Set initial state to paused*/ 415 SetPlayerState(SL_PLAYSTATE_PAUSED); 416 417 for (j = 0; j < sizeof(newStates) / sizeof(newStates[0]); ++j) { 418 SetPlayerState(newStates[j]); 419 CheckBufferCount((SLuint32) 0, (SLuint32) 0); 420 } 421 DestroyPlayer(); 422 } 423} 424 425TEST_F(TestBufferQueue, testStateTransitionNonEmptyQueue) { 426 static const SLuint32 newStates[] = { 427 SL_PLAYSTATE_PAUSED, // paused -> paused 428 SL_PLAYSTATE_STOPPED, // paused -> stopped 429 SL_PLAYSTATE_STOPPED, // stopped -> stopped 430 SL_PLAYSTATE_PAUSED // stopped -> paused 431 }; 432 433 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 434 SLuint32 numBuffers = validNumBuffers[i]; 435 SLuint32 j; 436 437 /* Prepare the player */ 438 PrepareValidBuffer(numBuffers); 439 EnqueueMaxBuffer(numBuffers); 440 SetPlayerState(SL_PLAYSTATE_PAUSED); 441 442 for (j = 0; j < sizeof(newStates) / sizeof(newStates[0]); ++j) { 443 SetPlayerState(newStates[j]); 444 CheckBufferCount(numBuffers, (SLuint32) 0); 445 } 446 DestroyPlayer(); 447 } 448} 449 450TEST_F(TestBufferQueue, testStatePlayBuffer){ 451 for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { 452 SLuint32 numBuffers = validNumBuffers[i]; 453 PrepareValidBuffer(numBuffers); 454 PlayBufferQueue(); 455 DestroyPlayer(); 456 } 457} 458 459int main(int argc, char **argv) { 460 testing::InitGoogleTest(&argc, argv); 461#if 1 // temporary workaround if hardware volume control is not working 462 const char *VOLUME = getenv("BufferQueue_test_VOLUME"); 463 if (NULL != VOLUME) { 464 float volume = atof(VOLUME); 465 if (volume >= 0.0f && volume <= 1.0f) { 466 gVolume = volume; 467 } 468 } 469#endif 470 return RUN_ALL_TESTS(); 471} 472