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