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