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