BufferQueue_test.cpp revision a15af1c45c3ad1d96e3012f1613a79a86c0b2547
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#include <assert.h>
20#include <math.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include "SLES/OpenSLES.h"
25
26#ifdef ANDROID
27#include "gtest/gtest.h"
28#else
29#define ASSERT_EQ(x, y) assert((x) == (y))
30#endif
31
32typedef struct {
33    short left;
34    short right;
35} stereo;
36
37// 1 second of stereo audio at 44.1 kHz
38static stereo stereoBuffer1[44100 * 1];
39
40static void do_my_testing()
41{
42    SLresult result;
43
44    // initialize the test tone to be a sine sweep from 441 Hz to 882 Hz
45    unsigned nframes = sizeof(stereoBuffer1) / sizeof(stereoBuffer1[0]);
46    float nframes_ = (float) nframes;
47    SLuint32 i;
48    for (i = 0; i < nframes; ++i) {
49        float i_ = (float) i;
50        float pcm_ = sin((i_*(1.0f+0.5f*(i_/nframes_))*0.01 * M_PI * 2.0));
51        int pcm = (int) (pcm_ * 32766.0);
52        assert(-32768 <= pcm && pcm <= 32767);
53        stereoBuffer1[i].left = pcm;
54        stereoBuffer1[nframes - 1 - i].right = pcm;
55    }
56
57    // create engine
58    SLObjectItf engineObject;
59    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
60    ASSERT_EQ(SL_RESULT_SUCCESS, result);
61    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
62    ASSERT_EQ(SL_RESULT_SUCCESS, result);
63    SLEngineItf engineEngine;
64    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
65    ASSERT_EQ(SL_RESULT_SUCCESS, result);
66
67    // create output mix
68    SLObjectItf outputmixObject;
69    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL);
70    ASSERT_EQ(SL_RESULT_SUCCESS, result);
71    result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE);
72    ASSERT_EQ(SL_RESULT_SUCCESS, result);
73
74    // set up data structures to create an audio player with buffer queue source and output mix sink
75    SLDataSource audiosrc;
76    SLDataSink audiosnk;
77    SLDataFormat_PCM pcm;
78    SLDataLocator_OutputMix locator_outputmix;
79    SLDataLocator_BufferQueue locator_bufferqueue;
80    locator_bufferqueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
81    locator_bufferqueue.numBuffers = 0;
82    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
83    locator_outputmix.outputMix = outputmixObject;
84    pcm.formatType = SL_DATAFORMAT_PCM;
85    pcm.numChannels = 2;
86    pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
87    pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
88    pcm.containerSize = 16;
89    pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
90    pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
91    audiosrc.pLocator = &locator_bufferqueue;
92    audiosrc.pFormat = &pcm;
93    audiosnk.pLocator = &locator_outputmix;
94    audiosnk.pFormat = NULL;
95    SLObjectItf playerObject;
96    SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
97    SLboolean flags[1] = {SL_BOOLEAN_TRUE};
98
99    // try creating audio player with various invalid values for numBuffers
100    static const SLuint32 invalidNumBuffers[] = {0, 0xFFFFFFFF, 0x80000000, 0x10002, 0x102, 0x101, 0x100};
101    for (i = 0; i < sizeof(invalidNumBuffers) / sizeof(invalidNumBuffers[0]); ++i) {
102        locator_bufferqueue.numBuffers = invalidNumBuffers[i];
103        result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 1, ids, flags);
104        ASSERT_EQ(SL_RESULT_PARAMETER_INVALID, result);
105    }
106
107    // now try some valid values for numBuffers */
108    static const SLuint32 validNumBuffers[] = {1, 2, 3, 4, 5, 6, 7, 8, 255};
109    for (i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) {
110        locator_bufferqueue.numBuffers = validNumBuffers[i];
111        result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 1, ids, flags);
112        ASSERT_EQ(SL_RESULT_SUCCESS, result);
113        result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
114        ASSERT_EQ(SL_RESULT_SUCCESS, result);
115        // get the play interface
116        SLPlayItf playerPlay;
117        result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
118        ASSERT_EQ(SL_RESULT_SUCCESS, result);
119        SLuint32 playerState;
120        // verify that player is initially stopped
121        result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
122        ASSERT_EQ(SL_RESULT_SUCCESS, result);
123        ASSERT_EQ(SL_PLAYSTATE_STOPPED, playerState);
124        // get the buffer queue interface
125        SLBufferQueueItf playerBufferQueue;
126        result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue);
127        ASSERT_EQ(SL_RESULT_SUCCESS, result);
128        // verify that buffer queue is initially empty
129        SLBufferQueueState bufferqueueState;
130        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
131        ASSERT_EQ(SL_RESULT_SUCCESS, result);
132        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
133        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
134        // try enqueuing the maximum number of buffers while stopped
135        SLuint32 j;
136        for (j = 0; j < validNumBuffers[i]; ++j) {
137            result = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
138            ASSERT_EQ(SL_RESULT_SUCCESS, result);
139            // verify that each buffer is enqueued properly and increments the buffer count
140            result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
141            ASSERT_EQ(SL_RESULT_SUCCESS, result);
142            ASSERT_EQ(j + 1, bufferqueueState.count);
143            ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
144            // verify that player is still stopped; enqueue should not affect play state
145            result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
146            ASSERT_EQ(SL_RESULT_SUCCESS, result);
147            ASSERT_EQ(SL_PLAYSTATE_STOPPED, playerState);
148        }
149        // enqueue one more buffer and make sure it fails
150        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
151        ASSERT_EQ(SL_RESULT_BUFFER_INSUFFICIENT, result);
152        // verify that the failed enqueue did not affect the buffer count
153        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
154        ASSERT_EQ(SL_RESULT_SUCCESS, result);
155        ASSERT_EQ(validNumBuffers[i], bufferqueueState.count);
156        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
157        // now clear the buffer queue
158        result = (*playerBufferQueue)->Clear(playerBufferQueue);
159        ASSERT_EQ(SL_RESULT_SUCCESS, result);
160        // make sure the clear works
161        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
162        ASSERT_EQ(SL_RESULT_SUCCESS, result);
163        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
164        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
165        // change play state from paused to stopped
166        result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
167        ASSERT_EQ(SL_RESULT_SUCCESS, result);
168        // verify that player is really paused
169        result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
170        ASSERT_EQ(SL_RESULT_SUCCESS, result);
171        ASSERT_EQ(SL_PLAYSTATE_PAUSED, playerState);
172        // try enqueuing the maximum number of buffers while paused
173        for (j = 0; j < validNumBuffers[i]; ++j) {
174            result = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
175            ASSERT_EQ(SL_RESULT_SUCCESS, result);
176            // verify that each buffer is enqueued properly and increments the buffer count
177            result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
178            ASSERT_EQ(SL_RESULT_SUCCESS, result);
179            ASSERT_EQ(j + 1, bufferqueueState.count);
180            ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
181            // verify that player is still paused; enqueue should not affect play state
182            result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
183            ASSERT_EQ(SL_RESULT_SUCCESS, result);
184            ASSERT_EQ(SL_PLAYSTATE_PAUSED, playerState);
185        }
186        // enqueue one more buffer and make sure it fails
187        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
188        ASSERT_EQ(SL_RESULT_BUFFER_INSUFFICIENT, result);
189        // verify that the failed enqueue did not affect the buffer count
190        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
191        ASSERT_EQ(SL_RESULT_SUCCESS, result);
192        ASSERT_EQ(validNumBuffers[i], bufferqueueState.count);
193        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
194        // now clear the buffer queue
195        result = (*playerBufferQueue)->Clear(playerBufferQueue);
196        ASSERT_EQ(SL_RESULT_SUCCESS, result);
197        // make sure the clear works
198        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
199        ASSERT_EQ(SL_RESULT_SUCCESS, result);
200        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
201        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
202        // try every possible play state transition while buffer queue is empty
203        static const SLuint32 newStates1[] = {
204            SL_PLAYSTATE_PAUSED,    // paused -> paused
205            SL_PLAYSTATE_STOPPED,   // paused -> stopped
206            SL_PLAYSTATE_PAUSED,    // stopped -> paused, also done earlier
207            SL_PLAYSTATE_PLAYING,   // paused -> playing
208            SL_PLAYSTATE_PLAYING,   // playing -> playing
209            SL_PLAYSTATE_STOPPED,   // playing -> stopped
210            SL_PLAYSTATE_STOPPED,   // stopped -> stopped
211            SL_PLAYSTATE_PLAYING,   // stopped -> playing
212            SL_PLAYSTATE_PAUSED     // playing -> paused
213        };
214        // initially the play state is (still) paused
215        result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
216        ASSERT_EQ(SL_RESULT_SUCCESS, result);
217        ASSERT_EQ(SL_PLAYSTATE_PAUSED, playerState);
218        for (j = 0; j < sizeof(newStates1) / sizeof(newStates1[0]); ++j) {
219            // change play state
220            result = (*playerPlay)->SetPlayState(playerPlay, newStates1[j]);
221            ASSERT_EQ(SL_RESULT_SUCCESS, result);
222            // make sure the new play state is taken
223            result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
224            ASSERT_EQ(SL_RESULT_SUCCESS, result);
225            ASSERT_EQ(newStates1[j], playerState);
226            // changing the play state should not affect the buffer count
227            result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
228            ASSERT_EQ(SL_RESULT_SUCCESS, result);
229            ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
230            ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
231        }
232        // finally the play state is (again) paused
233        result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
234        ASSERT_EQ(SL_RESULT_SUCCESS, result);
235        ASSERT_EQ(SL_PLAYSTATE_PAUSED, playerState);
236        // enqueue a buffer
237        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, "test", 4);
238        ASSERT_EQ(SL_RESULT_SUCCESS, result);
239        // try several inaudible play state transitions while buffer queue is non-empty
240        static const SLuint32 newStates2[] = {
241            SL_PLAYSTATE_PAUSED,    // paused -> paused
242            SL_PLAYSTATE_STOPPED,   // paused -> stopped
243            SL_PLAYSTATE_STOPPED,   // stopped -> stopped
244            SL_PLAYSTATE_PAUSED    // stopped -> paused
245        };
246        for (j = 0; j < sizeof(newStates2) / sizeof(newStates2[0]); ++j) {
247            // change play state
248            result = (*playerPlay)->SetPlayState(playerPlay, newStates2[j]);
249            ASSERT_EQ(SL_RESULT_SUCCESS, result);
250            // make sure the new play state is taken
251            result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
252            ASSERT_EQ(SL_RESULT_SUCCESS, result);
253            ASSERT_EQ(newStates2[j], playerState);
254            // changing the play state should not affect the buffer count
255            result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
256            ASSERT_EQ(SL_RESULT_SUCCESS, result);
257            ASSERT_EQ((SLuint32) 1, bufferqueueState.count);
258            ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
259        }
260        // clear the buffer queue
261        result = (*playerBufferQueue)->Clear(playerBufferQueue);
262        ASSERT_EQ(SL_RESULT_SUCCESS, result);
263
264        // now we're finally ready to make some noise
265
266        // enqueue a buffer
267        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, stereoBuffer1, sizeof(stereoBuffer1));
268        ASSERT_EQ(SL_RESULT_SUCCESS, result);
269        // set play state to playing
270        result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
271        ASSERT_EQ(SL_RESULT_SUCCESS, result);
272        // state should be playing immediately after enqueue
273        result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
274        ASSERT_EQ(SL_RESULT_SUCCESS, result);
275        ASSERT_EQ(SL_PLAYSTATE_PLAYING, playerState);
276        // buffer should still be on the queue
277        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
278        ASSERT_EQ(SL_RESULT_SUCCESS, result);
279        ASSERT_EQ((SLuint32) 1, bufferqueueState.count);
280        ASSERT_EQ((SLuint32) 0, bufferqueueState.playIndex);
281        // wait 1.5 seconds
282        usleep(1500000);
283        // state should still be playing
284        result = (*playerPlay)->GetPlayState(playerPlay, &playerState);
285        ASSERT_EQ(SL_RESULT_SUCCESS, result);
286        ASSERT_EQ(SL_PLAYSTATE_PLAYING, playerState);
287        // buffer should be removed from the queue
288        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufferqueueState);
289        ASSERT_EQ(SL_RESULT_SUCCESS, result);
290        ASSERT_EQ((SLuint32) 0, bufferqueueState.count);
291        ASSERT_EQ((SLuint32) 1, bufferqueueState.playIndex);
292        // destroy the player
293        (*playerObject)->Destroy(playerObject);
294    }
295
296    // destroy the output mix
297    (*outputmixObject)->Destroy(outputmixObject);
298    // destroy the engine
299    (*engineObject)->Destroy(engineObject);
300
301}
302
303int main(int argc, char **argv)
304{
305    do_my_testing();
306    return EXIT_SUCCESS;
307}
308