BufferQueue_test.cpp revision 7126c25d7c037e5086216cf540ecf40779c3585a
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        const char *str = slesutResultToString(res);
56        if (NULL == str)
57            str = "unknown";
58        fprintf(stderr, "CheckErr failure: %s (0x%lx), exiting\n", str, res);
59        //Fail the test case
60        FAIL();
61    }
62}
63
64static const SLInterfaceID ids[1] = { SL_IID_BUFFERQUEUE };
65static const SLboolean flags[1] = { SL_BOOLEAN_TRUE };
66static const SLInterfaceID ids_mutesolo[2] = { SL_IID_BUFFERQUEUE, SL_IID_MUTESOLO };
67static const SLboolean flags_mutesolo[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
68static const SLInterfaceID ids_seek[2] = { SL_IID_BUFFERQUEUE, SL_IID_SEEK };
69static const SLboolean flags_seek[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
70
71// The fixture for testing class BufferQueue
72class TestBufferQueue: public ::testing::Test {
73public:
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
90protected:
91    TestBufferQueue() {
92    }
93
94    virtual ~TestBufferQueue() {
95
96    }
97
98    /*Test 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
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
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*/
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*/
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
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
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
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
245    void GetPlayerState(SLuint32 state) {
246        res = (*playerPlay)->GetPlayState(playerPlay, &playerState);
247        CheckErr(res);
248        ASSERT_EQ(state, playerState);
249    }
250
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
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
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        //LOGV("Before 1.5 sec");
288        // wait 1.5 seconds
289        usleep(1500000);
290        //LOGV("After 1.5 sec");
291        // state should still be playing
292        res = (*playerPlay)->GetPlayState(playerPlay, &playerState);
293        //LOGV("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        //LOGV("TestEnd");
302    }
303};
304
305TEST_F(TestBufferQueue, testInvalidBuffer){
306    //LOGV("Test Fixture: InvalidBuffer");
307    InvalidBuffer();
308}
309
310TEST_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
328TEST_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
338TEST_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
346TEST_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
355TEST_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
366TEST_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
377TEST_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
388TEST_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
398TEST_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
427TEST_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
452TEST_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
461int 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