slesTestPlayUri.cpp revision 7126c25d7c037e5086216cf540ecf40779c3585a
12c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* 22c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2010 The Android Open Source Project 32c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 42c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 52c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * you may not use this file except in compliance with the License. 62c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * You may obtain a copy of the License at 72c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 82c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * http://www.apache.org/licenses/LICENSE-2.0 92c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Unless required by applicable law or agreed to in writing, software 112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * See the License for the specific language governing permissions and 142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * limitations under the License. 152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* 182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (c) 2009 The Khronos Group Inc. 192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Permission is hereby granted, free of charge, to any person obtaining a copy of this 212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * software and /or associated documentation files (the "Materials "), to deal in the 222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Materials without restriction, including without limitation the rights to use, copy, 232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials, 242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * and to permit persons to whom the Materials are furnished to do so, subject to 252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * the following conditions: 262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * The above copyright notice and this permission notice shall be included 282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * in all copies or substantial portions of the Materials. 292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE 372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * MATERIALS. 382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include <stdlib.h> 412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include <stdio.h> 422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent//#include <string.h> 432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include <unistd.h> 442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent//#include <sys/time.h> 452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "SLES/OpenSLES.h" 472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#define MAX_NUMBER_INTERFACES 2 502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#define PREFETCHEVENT_ERROR_CANDIDATE \ 522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE) 532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent//----------------------------------------------------------------- 552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent//* Exits the application if an error is encountered */ 562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#define CheckErr(x) ExitOnErrorFunc(x,__LINE__) 572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurentvoid ExitOnErrorFunc( SLresult result , int line) 592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{ 602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (SL_RESULT_SUCCESS != result) { 612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent fprintf(stderr, "%lu error code encountered at line %d, exiting\n", result, line); 622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent exit(EXIT_FAILURE); 632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent} 652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurentbool prefetchError = false; 672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent//----------------------------------------------------------------- 692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PrefetchStatusItf callback for an audio player */ 702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurentvoid PrefetchEventCallback( SLPrefetchStatusItf caller, void *pContext, SLuint32 event) 712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{ 722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLpermille level = 0; 732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent (*caller)->GetFillLevel(caller, &level); 742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLuint32 status; 752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent //fprintf(stdout, "PrefetchEventCallback: received event %lu\n", event); 762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent (*caller)->GetPrefetchStatus(caller, &status); 772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE)) 782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) { 792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent fprintf(stdout, "PrefetchEventCallback: Error while prefetching data, exiting\n"); 802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent prefetchError = true; 812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) { 832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent fprintf(stdout, "PrefetchEventCallback: Buffer fill level is = %d\n", level); 842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (event & SL_PREFETCHEVENT_STATUSCHANGE) { 862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent fprintf(stdout, "PrefetchEventCallback: Prefetch Status is = %lu\n", status); 872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent} 902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent//----------------------------------------------------------------- 932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Play some music from a URI */ 952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurentvoid TestPlayUri( SLObjectItf sl, const char* path) 962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{ 972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLEngineItf EngineItf; 982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLint32 numOutputs = 0; 1002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLuint32 deviceID = 0; 1012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLresult res; 1032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLDataSource audioSource; 1052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLDataLocator_URI uri; 1062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLDataFormat_MIME mime; 1072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLDataSink audioSink; 1092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLDataLocator_OutputMix locator_outputmix; 1102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLObjectItf player; 1122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLPlayItf playItf; 1132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLVolumeItf volItf; 1142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLPrefetchStatusItf prefetchItf; 1152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLObjectItf OutputMix; 1172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLboolean required[MAX_NUMBER_INTERFACES]; 1192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent SLInterfaceID iidArray[MAX_NUMBER_INTERFACES]; 1202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* Get the SL Engine Interface which is implicit */ 1222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 1232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent CheckErr(res); 1242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* Initialize arrays required[] and iidArray[] */ 1262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) { 1272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent required[i] = SL_BOOLEAN_FALSE; 1282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent iidArray[i] = SL_IID_NULL; 129 } 130 131 // Set arrays required[] and iidArray[] for VOLUME and PREFETCHSTATUS interface 132 required[0] = SL_BOOLEAN_TRUE; 133 iidArray[0] = SL_IID_VOLUME; 134 required[1] = SL_BOOLEAN_TRUE; 135 iidArray[1] = SL_IID_PREFETCHSTATUS; 136 // Create Output Mix object to be used by player 137 res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0, 138 iidArray, required); CheckErr(res); 139 140 // Realizing the Output Mix object in synchronous mode. 141 res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); 142 CheckErr(res); 143 144 /* Setup the data source structure for the URI */ 145 uri.locatorType = SL_DATALOCATOR_URI; 146 uri.URI = (SLchar*) path; 147 mime.formatType = SL_DATAFORMAT_MIME; 148 mime.mimeType = (SLchar*)NULL; 149 mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED; 150 151 audioSource.pFormat = (void *)&mime; 152 audioSource.pLocator = (void *)&uri; 153 154 /* Setup the data sink structure */ 155 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 156 locator_outputmix.outputMix = OutputMix; 157 audioSink.pLocator = (void *)&locator_outputmix; 158 audioSink.pFormat = NULL; 159 160 /* Create the audio player */ 161 res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 162 MAX_NUMBER_INTERFACES, iidArray, required); CheckErr(res); 163 164 /* Realizing the player in synchronous mode. */ 165 res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res); 166 fprintf(stdout, "URI example: after Realize\n"); 167 168 /* Get interfaces */ 169 res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 170 CheckErr(res); 171 172 res = (*player)->GetInterface(player, SL_IID_VOLUME, (void*)&volItf); 173 CheckErr(res); 174 175 res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf); 176 CheckErr(res); 177 res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, &prefetchItf); 178 CheckErr(res); 179 res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf, 180 SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE); 181 CheckErr(res); 182 183 /* Configure fill level updates every 5 percent */ 184 (*prefetchItf)->SetFillUpdatePeriod(prefetchItf, 50); 185 186 /* Display duration */ 187 SLmillisecond durationInMsec = SL_TIME_UNKNOWN; 188 res = (*playItf)->GetDuration(playItf, &durationInMsec); 189 CheckErr(res); 190 if (durationInMsec == SL_TIME_UNKNOWN) { 191 fprintf(stdout, "Content duration is unknown (before starting to prefetch)\n"); 192 } else { 193 fprintf(stdout, "Content duration is %lu ms (before starting to prefetch)\n", 194 durationInMsec); 195 } 196 197 /* Set the player volume */ 198 res = (*volItf)->SetVolumeLevel( volItf, -300); 199 CheckErr(res); 200 201 /* Play the URI */ 202 /* first cause the player to prefetch the data */ 203 fprintf(stdout, "Before set to PAUSED\n"); 204 res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED ); 205 fprintf(stdout, "After set to PAUSED\n"); 206 CheckErr(res); 207 208 /* wait until there's data to play */ 209 //SLpermille fillLevel = 0; 210 SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW; 211 SLuint32 timeOutIndex = 100; // 10s 212 while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0) && 213 !prefetchError) { 214 usleep(100 * 1000); 215 (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus); 216 timeOutIndex--; 217 } 218 219 if (timeOutIndex == 0 || prefetchError) { 220 fprintf(stderr, "We\'re done waiting, failed to prefetch data in time, exiting\n"); 221 goto destroyRes; 222 } 223 224 /* Display duration again, */ 225 res = (*playItf)->GetDuration(playItf, &durationInMsec); 226 CheckErr(res); 227 if (durationInMsec == SL_TIME_UNKNOWN) { 228 fprintf(stdout, "Content duration is unknown (after prefetch completed)\n"); 229 } else { 230 fprintf(stdout, "Content duration is %lu ms (after prefetch completed)\n", durationInMsec); 231 } 232 233 fprintf(stdout, "URI example: starting to play\n"); 234 res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); 235 CheckErr(res); 236 237 /* Wait as long as the duration of the content before stopping */ 238 usleep(durationInMsec * 1000); 239 240 /* Make sure player is stopped */ 241 fprintf(stdout, "URI example: stopping playback\n"); 242 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); 243 CheckErr(res); 244 245destroyRes: 246 247 /* Destroy the player */ 248 (*player)->Destroy(player); 249 250 /* Destroy Output Mix object */ 251 (*OutputMix)->Destroy(OutputMix); 252} 253 254//----------------------------------------------------------------- 255int main(int argc, char* const argv[]) 256{ 257 SLresult res; 258 SLObjectItf sl; 259 260 fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLVolumeItf ", argv[0]); 261 fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n"); 262 fprintf(stdout, "Plays a sound and stops after its reported duration\n\n"); 263 264 if (argc == 1) { 265 fprintf(stdout, "Usage: %s path \n\t%s url\n", argv[0], argv[0]); 266 fprintf(stdout, "Example: \"%s /sdcard/my.mp3\" or \"%s file:///sdcard/my.mp3\"\n", 267 argv[0], argv[0]); 268 exit(EXIT_FAILURE); 269 } 270 271 SLEngineOption EngineOption[] = { 272 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, 273 (SLuint32) SL_BOOLEAN_TRUE}}; 274 275 res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 276 CheckErr(res); 277 /* Realizing the SL Engine in synchronous mode. */ 278 res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 279 CheckErr(res); 280 281 TestPlayUri(sl, argv[1]); 282 283 /* Shutdown OpenSL ES */ 284 (*sl)->Destroy(sl); 285 286 return EXIT_SUCCESS; 287} 288