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