14b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* 24b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * Copyright (C) 2011 The Android Open Source Project 34b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * 44b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 54b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * you may not use this file except in compliance with the License. 64b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * You may obtain a copy of the License at 74b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * 84b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 94b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * 104b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 114b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 124b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * See the License for the specific language governing permissions and 144b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * limitations under the License. 154b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi */ 164b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 174b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#include <stdlib.h> 184b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#include <stdio.h> 194b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#include <unistd.h> 204b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#include <utils/threads.h> 214b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 22c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h> 234b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 244b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* tolerance in ms for this test in time difference between reported position and time since 254b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * playback was requested to start. This is reasonable for a local file. 264b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi */ 274b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#define TIME_TOLERANCE_MS 600 284b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 294b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* explicitly requesting SL_IID_VOLUME and SL_IID_PREFETCHSTATUS 304b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * on the AudioPlayer object */ 314b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#define NUM_EXPLICIT_INTERFACES_FOR_PLAYER 2 324b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 334b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* used to detect errors likely to have occured when the OpenSL ES framework fails to open 344b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond. */ 354b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#define PREFETCHEVENT_ERROR_CANDIDATE \ 364b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE) 374b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 384b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* to signal to the test app the end of the stream to decode has been reached */ 394b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivibool eos = false; 404b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Triviandroid::Mutex eosLock; 414b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Triviandroid::Condition eosCondition; 424b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 434b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//----------------------------------------------------------------- 444b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//* Exits the application if an error is encountered */ 454b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#define CheckErr(x) ExitOnErrorFunc(x,__LINE__) 464b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 474b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line) 484b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi{ 494b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (SL_RESULT_SUCCESS != result) { 504b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line); 514b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi exit(EXIT_FAILURE); 524b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 534b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi} 544b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 554b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivibool prefetchError = false; 564b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 574b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//----------------------------------------------------------------- 584b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivivoid SignalEos() { 594b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi android::Mutex::Autolock autoLock(eosLock); 604b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi eos = true; 614b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi eosCondition.signal(); 624b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi} 634b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 644b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//----------------------------------------------------------------- 654b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* PrefetchStatusItf callback for an audio player */ 664b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivivoid PrefetchEventCallback( SLPrefetchStatusItf caller, void *pContext, SLuint32 event) 674b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi{ 684b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLpermille level = 0; 694b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLresult res = (*caller)->GetFillLevel(caller, &level); CheckErr(res); 704b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLuint32 status; 714b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi //fprintf(stdout, "PrefetchEventCallback: received event %u\n", event); 724b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*caller)->GetPrefetchStatus(caller, &status); CheckErr(res); 734b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE)) 744b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) { 754b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "PrefetchEventCallback: Error while prefetching data, exiting\n"); 764b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi prefetchError = true; 77089a7c63adb033aec7b3200753e66b30ec8932beGlenn Kasten return; 784b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 794b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) { 804b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "PrefetchEventCallback: Buffer fill level is = %d\n", level); 814b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 824b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (event & SL_PREFETCHEVENT_STATUSCHANGE) { 834b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "PrefetchEventCallback: Prefetch Status is = %u\n", status); 844b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 854b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi} 864b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 874b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 884b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//----------------------------------------------------------------- 894b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* PlayItf callback for playback events */ 904b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivivoid PlayEventCallback( 914b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLPlayItf caller, 924b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi void *pContext, 934b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLuint32 event) 944b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi{ 954b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLmillisecond posMsec = SL_TIME_UNKNOWN; 964b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLresult res; 974b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (SL_PLAYEVENT_HEADATEND & event) { 984b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "SL_PLAYEVENT_HEADATEND reached\n"); 994b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#if 0 1004b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*caller)->GetPosition(caller, &posMsec); CheckErr(res); 1014b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "after getPosition in SL_PLAYEVENT_HEADATEND handler\n"); 1024b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (posMsec == SL_TIME_UNKNOWN) { 1034b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "Error: position is SL_TIME_UNKNOWN at SL_PLAYEVENT_HEADATEND\n"); 1044b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } else { 1054b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "position is %d at SL_PLAYEVENT_HEADATEND\n", posMsec); 1064b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 1074b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // FIXME compare position against duration 1084b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi#endif 1094b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SignalEos(); 1104b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 1114b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1124b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (SL_PLAYEVENT_HEADATNEWPOS & event) { 1134b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*caller)->GetPosition(caller, &posMsec); CheckErr(res); 1144b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "SL_PLAYEVENT_HEADATNEWPOS current position=%ums\n", posMsec); 1154b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 1164b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1174b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (SL_PLAYEVENT_HEADATMARKER & event) { 1184b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*caller)->GetPosition(caller, &posMsec); CheckErr(res); 1194b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "SL_PLAYEVENT_HEADATMARKER current position=%ums\n", posMsec); 1204b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 1214b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi} 1224b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1234b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1244b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//----------------------------------------------------------------- 1254b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1264b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi/* Play some audio from a URI and regularly query the position */ 1274b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivivoid TestGetPositionUri( SLObjectItf sl, const char* path) 1284b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi{ 1294b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLEngineItf EngineItf; 1304b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1314b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLint32 numOutputs = 0; 1324b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLuint32 deviceID = 0; 1334b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1344b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLresult res; 1354b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1364b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLDataSource audioSource; 1374b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLDataLocator_URI uri; 1384b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLDataFormat_MIME mime; 1394b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1404b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLDataSink audioSink; 1414b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLDataLocator_OutputMix locator_outputmix; 1424b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1434b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLObjectItf player; 1444b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLPlayItf playItf; 1454b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLVolumeItf volItf; 1464b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLPrefetchStatusItf prefetchItf; 1474b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1484b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLObjectItf OutputMix; 1494b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1504b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* variables for the duration and position tests */ 1514b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLuint16 counter = 0; 1524b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLmillisecond posInMsec = SL_TIME_UNKNOWN; 1534b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLmillisecond durationInMsec = SL_TIME_UNKNOWN; 1544b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1554b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLboolean required[NUM_EXPLICIT_INTERFACES_FOR_PLAYER]; 1564b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLInterfaceID iidArray[NUM_EXPLICIT_INTERFACES_FOR_PLAYER]; 1574b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1584b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Get the SL Engine Interface which is implicit */ 1594b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 1604b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 1614b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1624b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Initialize arrays required[] and iidArray[] */ 1634b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi for (int i=0 ; i < NUM_EXPLICIT_INTERFACES_FOR_PLAYER ; i++) { 1644b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi required[i] = SL_BOOLEAN_FALSE; 1654b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi iidArray[i] = SL_IID_NULL; 1664b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 1674b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1684b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // Set arrays required[] and iidArray[] for VOLUME and PREFETCHSTATUS interface 1694b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi required[0] = SL_BOOLEAN_TRUE; 1704b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi iidArray[0] = SL_IID_VOLUME; 1714b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi required[1] = SL_BOOLEAN_TRUE; 1724b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi iidArray[1] = SL_IID_PREFETCHSTATUS; 1734b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // Create Output Mix object to be used by player 1744b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0, 1754b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi iidArray, required); CheckErr(res); 1764b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1774b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // Realizing the Output Mix object in synchronous mode. 1784b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); 1794b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 1804b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1814b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Setup the data source structure for the URI */ 1824b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi uri.locatorType = SL_DATALOCATOR_URI; 1834b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi uri.URI = (SLchar*) path; 1844b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi mime.formatType = SL_DATAFORMAT_MIME; 1854b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi mime.mimeType = (SLchar*)NULL; 1864b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED; 1874b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1884b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi audioSource.pFormat = (void *)&mime; 1894b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi audioSource.pLocator = (void *)&uri; 1904b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1914b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Setup the data sink structure */ 1924b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 1934b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi locator_outputmix.outputMix = OutputMix; 1944b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi audioSink.pLocator = (void *)&locator_outputmix; 1954b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi audioSink.pFormat = NULL; 1964b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 1974b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Create the audio player */ 1984b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 1994b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi NUM_EXPLICIT_INTERFACES_FOR_PLAYER, iidArray, required); CheckErr(res); 2004b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2014b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Realizing the player in synchronous mode. */ 2024b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res); 2034b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "URI example: after Realize\n"); 2044b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2054b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Get interfaces */ 2064b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 2074b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2084b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2094b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*player)->GetInterface(player, SL_IID_VOLUME, (void*)&volItf); 2104b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2114b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2124b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf); 2134b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2144b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, &prefetchItf); 2154b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2164b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf, 2174b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE); 2184b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2194b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2204b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Configure fill level updates every 5 percent */ 2214b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*prefetchItf)->SetFillUpdatePeriod(prefetchItf, 50); CheckErr(res); 2224b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2234b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Set up the player callback to get events during the decoding */ 2244b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->SetMarkerPosition(playItf, 2000); 2254b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2264b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->SetPositionUpdatePeriod(playItf, 500); 2274b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2284b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->SetCallbackEventsMask(playItf, 2294b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS | SL_PLAYEVENT_HEADATEND); 2304b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2314b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->RegisterCallback(playItf, PlayEventCallback, NULL); 2324b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2334b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2344b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Set the player volume */ 2354b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*volItf)->SetVolumeLevel( volItf, -300); 2364b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 2374b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2384b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Play the URI */ 2394b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* first cause the player to prefetch the data */ 2404b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Setting the player to PAUSED to cause it to prefetch the data\n"); 2414b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED ); CheckErr(res); 2424b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2434b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi usleep(100 * 1000); 2444b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* wait until there's data to play */ 2454b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW; 2464b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLuint32 timeOutIndex = 100; // 10s 2474b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0) && 2484b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi !prefetchError) { 2494b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi usleep(100 * 1000); 2504b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus); 2514b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi timeOutIndex--; 2524b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2534b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2544b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (timeOutIndex == 0 || prefetchError) { 2554b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "We're done waiting, failed to prefetch data in time, exiting\n"); 2564b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi goto destroyRes; 2574b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2584b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2594b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Display duration */ 2604b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->GetDuration(playItf, &durationInMsec); CheckErr(res); 2614b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (durationInMsec == SL_TIME_UNKNOWN) { 2624b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "Error: Content duration is unknown after prefetch completed, exiting\n"); 2634b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi goto destroyRes; 2644b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } else { 2654b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Content duration is %u ms (after prefetch completed)\n", durationInMsec); 2664b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2674b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2684b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Setting the player to PLAYING\n"); 2694b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); CheckErr(res); 2704b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2714b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Test GetPosition every second */ 2724b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi while ((counter*1000) < durationInMsec) { 2734b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi counter++; 2744b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi usleep(1 * 1000 * 1000); //1s 2754b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->GetPosition(playItf, &posInMsec); CheckErr(res); 2764b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (posInMsec == SL_TIME_UNKNOWN) { 2774b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "Error: position is SL_TIME_UNKNOWN %ds after start, exiting\n", 2784b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi counter); 2794b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi goto destroyRes; 2804b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } else { 2814b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "position is %dms %ds after start\n", posInMsec, counter); 2824b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2834b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // this test would probably deserve to be improved by relying on drift relative to 2844b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // a clock, as the operations between two consecutive sleep() are taking time as well 2854b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // and can add up 2864b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (((SLint32)posInMsec > (counter*1000 + TIME_TOLERANCE_MS)) || 2874b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi ((SLint32)posInMsec < (counter*1000 - TIME_TOLERANCE_MS))) { 2884b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stderr, "Error: position drifted too much, exiting\n"); 2894b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi goto destroyRes; 2904b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2914b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2924b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2934b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Play until the end of file is reached */ 2944b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi { 2954b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi android::Mutex::Autolock autoLock(eosLock); 2964b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi while (!eos) { 2974b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi eosCondition.wait(eosLock); 2984b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2994b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 3004b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "EOS signaled, stopping playback\n"); 3014b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); CheckErr(res); 3024b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3034b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel TrividestroyRes: 3044b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3054b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Destroy the player */ 3064b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Destroying the player\n"); 3074b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi (*player)->Destroy(player); 3084b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3094b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Destroy Output Mix object */ 3104b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi (*OutputMix)->Destroy(OutputMix); 3114b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi} 3124b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3134b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi//----------------------------------------------------------------- 3144b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Triviint main(int argc, char* const argv[]) 3154b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi{ 3164b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLresult res; 3174b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLObjectItf sl; 3184b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3194b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf", argv[0]); 3204b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n"); 3214b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Plays a sound and requests position at various times\n\n"); 3224b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3234b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (argc == 1) { 3244b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Usage: %s path \n\t%s url\n", argv[0], argv[0]); 3254b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi fprintf(stdout, "Example: \"%s /sdcard/my.mp3\" or \"%s file:///sdcard/my.mp3\"\n", 3264b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi argv[0], argv[0]); 3274b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi exit(EXIT_FAILURE); 3284b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 3294b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3304b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi SLEngineOption EngineOption[] = { 3314b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi {(SLuint32) SL_ENGINEOPTION_THREADSAFE, 3324b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi (SLuint32) SL_BOOLEAN_TRUE}}; 3334b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3344b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 3354b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 3364b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Realizing the SL Engine in synchronous mode. */ 3374b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 3384b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi CheckErr(res); 3394b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3404b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi TestGetPositionUri(sl, argv[1]); 3414b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3424b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /* Shutdown OpenSL ES */ 3434b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi (*sl)->Destroy(sl); 3444b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 3454b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi return EXIT_SUCCESS; 3464b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi} 347