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