BufferQueue_test.cpp revision 4597a7427b697df31d0bbf4c2040806d0c27b6e0
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#define LOG_NDEBUG 0
19#define LOG_TAG "bufferQueue"
20
21#ifdef ANDROID
22#include <utils/Log.h>
23#else
24#define LOGV printf
25#endif
26
27#include <assert.h>
28#include <math.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include "SLES/OpenSLES.h"
33
34#include <gtest/gtest.h>
35
36#ifdef ANDROID
37#include "gtest/gtest.h"
38#else
39#define ASSERT_EQ(x, y) assert((x) == (y))
40#endif
41
42typedef struct {
43    short left;
44    short right;
45} stereo;
46
47// 1 second of stereo audio at 44.1 kHz
48static stereo stereoBuffer1[44100 * 1];
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 (res != SL_RESULT_SUCCESS) {
55        fprintf(stderr, "%lu SL failure, exiting\n", res);
56        //Fail the test case
57        ASSERT_TRUE(false);
58    }
59}
60
61// The fixture for testing class BufferQueue
62class TestBufferQueue: public ::testing::Test {
63public:
64    SLresult res;
65    SLObjectItf sl;
66    SLObjectItf outputmixObject;
67    SLObjectItf engineObject;
68
69    SLDataSource audiosrc;
70    SLDataSink audiosnk;
71    SLDataFormat_PCM pcm;
72    SLDataLocator_OutputMix locator_outputmix;
73    SLDataLocator_BufferQueue locator_bufferqueue;
74    SLBufferQueueItf playerBufferQueue;
75    SLBufferQueueState bufferqueueState;
76    SLPlayItf playerPlay;
77    SLObjectItf playerObject;
78    SLEngineItf engineEngine;
79    SLuint32 playerState;
80
81protected:
82    TestBufferQueue() {
83    }
84
85    virtual ~TestBufferQueue() {
86
87    }
88
89    virtual void SetUp() {
90        /*Test setup*/
91        res = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
92        CheckErr(res);
93        res = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
94        CheckErr(res);
95
96        res = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
97        CheckErr(res);
98
99        // create output mix
100        res = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL);
101        CheckErr(res);
102        res = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE);
103        CheckErr(res);
104
105        locator_bufferqueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
106        locator_bufferqueue.numBuffers = 0;
107        locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
108        locator_outputmix.outputMix = outputmixObject;
109
110        pcm.formatType = SL_DATAFORMAT_PCM;
111        pcm.numChannels = 2;
112        pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
113        pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
114        pcm.containerSize = 16;
115        pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
116        pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
117        audiosrc.pLocator = &locator_bufferqueue;
118        audiosrc.pFormat = &pcm;
119        audiosnk.pLocator = &locator_outputmix;
120        audiosnk.pFormat = NULL;
121
122        // initialize the test tone to be a sine sweep from 441 Hz to 882 Hz
123        unsigned nframes = sizeof(stereoBuffer1) / sizeof(stereoBuffer1[0]);
124        float nframes_ = (float) nframes;
125        SLuint32 i;
126        for (i = 0; i < nframes; ++i) {
127            float i_ = (float) i;
128            float pcm_ = sin((i_ * (1.0f + 0.5f * (i_ / nframes_)) * 0.01 * M_PI * 2.0));
129            int pcm = (int) (pcm_ * 32766.0);
130            ASSERT_TRUE(-32768 <= pcm && pcm <= 32767) << "pcm out of bound " << pcm;
131            stereoBuffer1[i].left = pcm;
132            stereoBuffer1[nframes - 1 - i].right = pcm;
133        }
134    }
135
136    virtual void TearDown() {
137        /* Clean up the player, mixer, and the engine (must be done in that order) */
138        if (playerObject){
139            (*playerObject)->Destroy(playerObject);
140            playerObject = NULL;
141        }
142        if (outputmixObject){
143            (*outputmixObject)->Destroy(outputmixObject);
144            outputmixObject = NULL;
145        }
146        if (engineObject){
147            (*engineObject)->Destroy(engineObject);
148            engineObject = NULL;
149        }
150    }
151
152    /* Test case for creating audio player with various invalid values for numBuffers*/
153    void InvalidBuffer() {
154        unsigned nframes = sizeof(stereoBuffer1) / sizeof(stereoBuffer1[0]);
155        float nframes_ = (float) nframes;
156        SLuint32 i;
157        SLInterfaceID ids[1] = { SL_IID_BUFFERQUEUE };
158        SLboolean flags[1] = { SL_BOOLEAN_TRUE };
159
160        static const SLuint32 invalidNumBuffers[] = { 0, 0xFFFFFFFF, 0x80000000, 0x10002, 0x102,
161                0x101, 0x100 };
162        for (i = 0; i < sizeof(invalidNumBuffers) / sizeof(invalidNumBuffers[0]); ++i) {
163            locator_bufferqueue.numBuffers = invalidNumBuffers[i];
164            LOGV("allocation buffer\n");
165            SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject,
166                                                            &audiosrc, &audiosnk, 1, ids, flags);
167            ASSERT_EQ(SL_RESULT_PARAMETER_INVALID, result);
168        }
169    }
170
171    /*Prepare the buffer*/
172    void PrepareValidBuffer(SLuint32 numbuffer) {
173        SLInterfaceID ids2[1] = { SL_IID_BUFFERQUEUE };
174        SLboolean flags2[1] = { SL_BOOLEAN_TRUE };
175
176        locator_bufferqueue.numBuffers = validNumBuffers[numbuffer];
177        res = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk,
178                                                1, ids2, flags2);
179        CheckErr(res);
180        res = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
181        CheckErr(res);
182        // get the play interface
183        res = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
184        CheckErr(res);
185        // verify that player is initially stopped
186        res = (*playerPlay)->GetPlayState(playerPlay, &playerState);
187        CheckErr(res);
188        ASSERT_EQ(SL_PLAYSTATE_STOPPED, playerState);
189
190        // get the buffer queue interface
191        res = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue);
192        CheckErr(res);
193
194        // verify that buffer queue is initially empty
195        res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
196        CheckErr(res);
197        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
198        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
199    }
200
201    void EnqueueMaxBuffer(SLuint32 i) {
202        SLuint32 j;
203
204        for (j = 0; j < validNumBuffers[i]; ++j) {
205            res = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
206            CheckErr(res);
207            // verify that each buffer is enqueued properly and increments the buffer count
208            res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
209            CheckErr(res);
210            ASSERT_EQ(j + 1, bufferqueueState.count);
211            ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
212        }
213    }
214
215    void EnqueueExtraBuffer(SLuint32 i) {
216        // enqueue one more buffer and make sure it fails
217        res = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
218        ASSERT_EQ(SL_RESULT_BUFFER_INSUFFICIENT, res);
219        // verify that the failed enqueue did not affect the buffer count
220        res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
221        CheckErr(res);
222        ASSERT_EQ(validNumBuffers[i], bufferqueueState.count);
223        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
224    }
225
226    void SetPlayerState(SLuint32 state) {
227        res = (*playerPlay)->SetPlayState(playerPlay, state);
228        CheckErr(res);
229        //verify the state can set correctly
230        GetPlayerState(state);
231    }
232
233    void GetPlayerState(SLuint32 state) {
234        res = (*playerPlay)->GetPlayState(playerPlay, &playerState);
235        CheckErr(res);
236        ASSERT_EQ(state, playerState);
237    }
238
239    void ClearQueue() {
240        // now clear the buffer queue
241        res = (*playerBufferQueue)->Clear(playerBufferQueue);
242        CheckErr(res);
243        // make sure the clear works
244        res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
245        CheckErr(res);
246        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
247        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
248    }
249
250    void CheckBufferCount(SLuint32 ExpectedCount, SLuint32 ExpectedPlayIndex) {
251        // changing the play state should not affect the buffer count
252        res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
253        CheckErr(res);
254        ASSERT_EQ(ExpectedCount, bufferqueueState.count);
255        ASSERT_EQ(ExpectedPlayIndex, bufferqueueState.playIndex);
256    }
257
258    void PlayBufferQueue() {
259        // enqueue a buffer
260        res = (*playerBufferQueue)->Enqueue(playerBufferQueue, stereoBuffer1,
261            sizeof(stereoBuffer1));
262        CheckErr(res);
263        // set play state to playing
264        res = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
265        CheckErr(res);
266        // state should be playing immediately after enqueue
267        res = (*playerPlay)->GetPlayState(playerPlay, &playerState);
268        CheckErr(res);
269        ASSERT_EQ(SL_PLAYSTATE_PLAYING, playerState);
270        // buffer should still be on the queue
271        res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
272        CheckErr(res);
273        ASSERT_EQ((SLuint32) 1, bufferqueueState.count);
274        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
275        LOGV("Before 1.5 sec");
276        // wait 1.5 seconds
277        usleep(1500000);
278        LOGV("After 1.5 sec");
279        // state should still be playing
280        res = (*playerPlay)->GetPlayState(playerPlay, &playerState);
281        LOGV("GetPlayState");
282        CheckErr(res);
283        ASSERT_EQ(SL_PLAYSTATE_PLAYING, playerState);
284        // buffer should be removed from the queue
285        res = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
286        CheckErr(res);
287        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
288        ASSERT_EQ((SLuint32) 1, bufferqueueState.playIndex);
289        LOGV("TestEnd");
290    }
291};
292
293TEST_F(TestBufferQueue, testInvalidBuffer){
294     LOGV("Test Fixture: InvalidBuffer\n");
295     InvalidBuffer();
296}
297
298TEST_F(TestBufferQueue, testValidBuffer) {
299    PrepareValidBuffer(1);
300}
301
302TEST_F(TestBufferQueue, testEnqueueMaxBuffer) {
303    PrepareValidBuffer(1);
304    EnqueueMaxBuffer(1);
305}
306
307TEST_F(TestBufferQueue, testEnqueExtraBuffer) {
308    PrepareValidBuffer(1);
309    EnqueueMaxBuffer(1);
310    EnqueueExtraBuffer(1);
311    GetPlayerState(SL_PLAYSTATE_STOPPED);
312}
313
314TEST_F(TestBufferQueue, testEnqueAtPause) {
315    PrepareValidBuffer(1);
316    SetPlayerState(SL_PLAYSTATE_PAUSED);
317    GetPlayerState(SL_PLAYSTATE_PAUSED);
318    EnqueueMaxBuffer(1);
319    CheckBufferCount((SLuint32) 2, (SLuint32) 0);
320}
321
322TEST_F(TestBufferQueue, testClearQueue) {
323    PrepareValidBuffer(1);
324    EnqueueMaxBuffer(1);
325    ClearQueue();
326}
327
328TEST_F(TestBufferQueue, testStateTransitionEmptyQueue) {
329    static const SLuint32 newStates[] = {
330        SL_PLAYSTATE_PAUSED,    // paused -> paused
331        SL_PLAYSTATE_STOPPED,   // paused -> stopped
332        SL_PLAYSTATE_PAUSED,    // stopped -> paused
333        SL_PLAYSTATE_PLAYING,   // paused -> playing
334        SL_PLAYSTATE_PLAYING,   // playing -> playing
335        SL_PLAYSTATE_STOPPED,   // playing -> stopped
336        SL_PLAYSTATE_STOPPED,   // stopped -> stopped
337        SL_PLAYSTATE_PLAYING,   // stopped -> playing
338        SL_PLAYSTATE_PAUSED     // playing -> paused
339    };
340    SLuint32 j;
341
342    PrepareValidBuffer(8);
343    /* Set inital state to pause*/
344    SetPlayerState(SL_PLAYSTATE_PAUSED);
345
346    for (j = 0; j < sizeof(newStates) / sizeof(newStates[0]); ++j) {
347        SetPlayerState(newStates[j]);
348        CheckBufferCount((SLuint32) 0, (SLuint32) 0);
349    }
350}
351
352TEST_F(TestBufferQueue, testStateTransitionNonEmptyQueue) {
353    static const SLuint32 newStates[] = {
354        SL_PLAYSTATE_PAUSED,    // paused -> paused
355        SL_PLAYSTATE_STOPPED,   // paused -> stopped
356        SL_PLAYSTATE_STOPPED,   // stopped -> stopped
357        SL_PLAYSTATE_PAUSED    // stopped -> paused
358    };
359    SLuint32 j;
360
361    /* Prepare the player */
362    PrepareValidBuffer(2);
363    EnqueueMaxBuffer(2);
364    SetPlayerState(SL_PLAYSTATE_PAUSED);
365
366    for (j = 0; j < sizeof(newStates) / sizeof(newStates[0]); ++j) {
367      SetPlayerState(newStates[j]);
368      CheckBufferCount((SLuint32) 3, (SLuint32) 0);
369    }
370}
371
372TEST_F(TestBufferQueue, testStatePlayBuffer){
373     PrepareValidBuffer(8);
374     PlayBufferQueue();
375}
376
377int main(int argc, char **argv) {
378    testing::InitGoogleTest(&argc, argv);
379    return RUN_ALL_TESTS();
380}
381