mimeUri_test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. * Copyright (c) 2009 The Khronos Group Inc.
  18. *
  19. * Permission is hereby granted, free of charge, to any person obtaining a copy of this
  20. * software and /or associated documentation files (the "Materials "), to deal in the
  21. * Materials without restriction, including without limitation the rights to use, copy,
  22. * modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials,
  23. * and to permit persons to whom the Materials are furnished to do so, subject to
  24. * the following conditions:
  25. *
  26. * The above copyright notice and this permission notice shall be included
  27. * in all copies or substantial portions of the Materials.
  28. *
  29. * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  30. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  31. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  32. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  33. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  34. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  35. * CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE
  36. * MATERIALS.
  37. */
  38. #define LOG_NDEBUG 0
  39. #define LOG_TAG "slesTestPlayUri"
  40. #include <utils/Log.h>
  41. #include <getopt.h>
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <unistd.h>
  46. #include <sys/time.h>
  47. #include <gtest/gtest.h>
  48. #include <SLES/OpenSLES.h>
  49. #define MAX_NUMBER_INTERFACES 3
  50. #define MAX_NUMBER_OUTPUT_DEVICES 6
  51. //The expected playback duration
  52. const int MP3_DURATION = 71030; //71 secs
  53. //-----------------------------------------------------------------
  54. /* Checks for error. If any errors exit the application! */
  55. void CheckErr( SLresult res )
  56. {
  57. if ( res != SL_RESULT_SUCCESS ) {
  58. fprintf(stderr, "%u SL failure, exiting\n", res);
  59. //Fail the test case
  60. ASSERT_TRUE(false);
  61. }
  62. }
  63. //-----------------------------------------------------------------
  64. /* PrefetchStatusItf callback for an audio player */
  65. void PrefetchEventCallback( SLPrefetchStatusItf caller, void *pContext __unused, SLuint32 event)
  66. {
  67. SLpermille level = 0;
  68. (*caller)->GetFillLevel(caller, &level);
  69. SLuint32 status;
  70. fprintf(stdout, "\t\tPrefetchEventCallback: received event %u\n", event);
  71. (*caller)->GetPrefetchStatus(caller, &status);
  72. if ((event & (SL_PREFETCHEVENT_STATUSCHANGE|SL_PREFETCHEVENT_FILLLEVELCHANGE))
  73. && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
  74. fprintf(stderr, "\t\tPrefetchEventCallback: Error while prefetching data, exiting\n");
  75. ASSERT_TRUE(false);
  76. }
  77. if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) {
  78. fprintf(stdout, "\t\tPrefetchEventCallback: Buffer fill level is = %d\n", level);
  79. }
  80. if (event & SL_PREFETCHEVENT_STATUSCHANGE) {
  81. fprintf(stdout, "\t\tPrefetchEventCallback: Prefetch Status is = %u\n", status);
  82. }
  83. }
  84. //-----------------------------------------------------------------
  85. /* Play some music from a URI */
  86. void TestPlayUri( SLObjectItf sl, const char* path)
  87. {
  88. SLEngineItf EngineItf;
  89. SLresult res;
  90. SLDataSource audioSource;
  91. SLDataLocator_URI uri;
  92. SLDataFormat_MIME mime;
  93. SLDataSink audioSink;
  94. SLDataLocator_OutputMix locator_outputmix;
  95. SLObjectItf player;
  96. SLPlayItf playItf;
  97. SLVolumeItf volItf;
  98. SLPrefetchStatusItf prefetchItf;
  99. SLObjectItf OutputMix;
  100. SLboolean required[MAX_NUMBER_INTERFACES];
  101. SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
  102. /* Get the SL Engine Interface which is implicit */
  103. res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
  104. CheckErr(res);
  105. /* Initialize arrays required[] and iidArray[] */
  106. for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
  107. required[i] = SL_BOOLEAN_FALSE;
  108. iidArray[i] = SL_IID_NULL;
  109. }
  110. // Set arrays required[] and iidArray[] for VOLUME and PREFETCHSTATUS interface
  111. required[0] = SL_BOOLEAN_TRUE;
  112. iidArray[0] = SL_IID_VOLUME;
  113. required[1] = SL_BOOLEAN_TRUE;
  114. iidArray[1] = SL_IID_PREFETCHSTATUS;
  115. // Create Output Mix object to be used by player
  116. res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0,
  117. iidArray, required); CheckErr(res);
  118. // Realizing the Output Mix object in synchronous mode.
  119. res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);
  120. CheckErr(res);
  121. /* Setup the data source structure for the URI */
  122. uri.locatorType = SL_DATALOCATOR_URI;
  123. uri.URI = (SLchar*) path;
  124. mime.formatType = SL_DATAFORMAT_MIME;
  125. mime.mimeType = (SLchar*)NULL;
  126. mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
  127. audioSource.pFormat = (void *)&mime;
  128. audioSource.pLocator = (void *)&uri;
  129. /* Setup the data sink structure */
  130. locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
  131. locator_outputmix.outputMix = OutputMix;
  132. audioSink.pLocator = (void *)&locator_outputmix;
  133. audioSink.pFormat = NULL;
  134. /* Create the audio player */
  135. res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player,
  136. &audioSource, &audioSink, 2, iidArray, required); CheckErr(res);
  137. /* Realizing the player in synchronous mode. */
  138. res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res);
  139. /* Get interfaces */
  140. res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
  141. CheckErr(res);
  142. res = (*player)->GetInterface(player, SL_IID_VOLUME, (void*)&volItf);
  143. CheckErr(res);
  144. res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
  145. CheckErr(res);
  146. res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, &prefetchItf);
  147. CheckErr(res);
  148. res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
  149. SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE);
  150. /* Display duration */
  151. SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
  152. res = (*playItf)->GetDuration(playItf, &durationInMsec);
  153. CheckErr(res);
  154. /* Set the player volume */
  155. res = (*volItf)->SetVolumeLevel( volItf, -300);
  156. CheckErr(res);
  157. /* Play the URI */
  158. /* first cause the player to prefetch the data */
  159. res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
  160. CheckErr(res);
  161. /* wait until there's data to play */
  162. //SLpermille fillLevel = 0;
  163. SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
  164. SLuint32 timeOutIndex = 100; // 10s
  165. while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0)) {
  166. usleep(100 * 1000);
  167. (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
  168. timeOutIndex--;
  169. }
  170. if (timeOutIndex == 0) {
  171. fprintf(stderr, "Error: Failed to prefetch data in time, exiting\n");
  172. ASSERT_TRUE(false);
  173. // goto destroyRes;
  174. }
  175. /* Display duration again, */
  176. res = (*playItf)->GetDuration(playItf, &durationInMsec);
  177. CheckErr(res);
  178. if (durationInMsec == SL_TIME_UNKNOWN) {
  179. fprintf(stderr, "Error: GetDuration returned SL_TIME_UNKNOWN (after prefetch completed)\n");
  180. ASSERT_TRUE(false);
  181. }
  182. SLint32 durationDiffMsec = durationInMsec - MP3_DURATION;
  183. if (durationDiffMsec < 0) { durationDiffMsec *= -1; }
  184. if (durationDiffMsec > (MP3_DURATION/20)) {
  185. fprintf(stderr, "Error: GetDuration returned %d, more than 5percent off from expected %d\n",
  186. durationInMsec, MP3_DURATION);
  187. ASSERT_TRUE(false);
  188. }
  189. res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
  190. CheckErr(res);
  191. /* Play for the song duration*/
  192. usleep(MP3_DURATION * 1000);
  193. /* Validate the play position*/
  194. SLmillisecond currentPositionInMsec = SL_TIME_UNKNOWN;
  195. res = (*playItf)->GetPosition(playItf, &currentPositionInMsec);
  196. CheckErr(res);
  197. if (currentPositionInMsec == SL_TIME_UNKNOWN) {
  198. fprintf(stderr, "Error: GetPosition returns SL_TIME_UNKNOWN after expected duration\n");
  199. ASSERT_TRUE(false);
  200. } else if ( currentPositionInMsec <= 0 ||
  201. currentPositionInMsec > (MP3_DURATION * 1.1) ){
  202. fprintf(stderr, "Error: GetPosition returns %i, should be expected duration for test\n",
  203. (int) currentPositionInMsec);
  204. ASSERT_TRUE(false);
  205. }
  206. /* Make sure player is stopped */
  207. res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
  208. CheckErr(res);
  209. //destroyRes:
  210. /* Destroy the player */
  211. (*player)->Destroy(player);
  212. /* Destroy Output Mix object */
  213. (*OutputMix)->Destroy(OutputMix);
  214. fprintf(stdout, "End of test reached\n");
  215. }
  216. // The fixture for testing class MimeUri
  217. class MimeUri: public ::testing::Test {
  218. public:
  219. SLresult res;
  220. SLObjectItf sl;
  221. protected:
  222. MimeUri() {
  223. // You can do set-up work for each test here.
  224. SLEngineOption EngineOption[] = { { (SLuint32) SL_ENGINEOPTION_THREADSAFE,
  225. (SLuint32) SL_BOOLEAN_TRUE } };
  226. res = slCreateEngine(&sl, 1, EngineOption, 0, NULL, NULL);
  227. CheckErr(res);
  228. /* Realizing the SL Engine in synchronous mode. */
  229. res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
  230. CheckErr(res);
  231. }
  232. virtual ~MimeUri() {
  233. // You can do clean-up work that doesn't throw exceptions here.
  234. (*sl)->Destroy(sl);
  235. }
  236. virtual void SetUp() {
  237. // Code here will be called immediately after the constructor (right
  238. // before each test).
  239. }
  240. virtual void TearDown() {
  241. // Code here will be called immediately after each test (right
  242. // before the destructor).
  243. }
  244. };
  245. TEST_F(MimeUri, testPlayAbsPath){
  246. TestPlayUri(sl, "/sdcard/media_api/music/MP3_256kbps_2ch.mp3");
  247. }
  248. TEST_F(MimeUri, testPlayfilePath){
  249. TestPlayUri(sl, "file:///sdcard/media_api/music/MP3_256kbps_2ch.mp3");
  250. }
  251. //-----------------------------------------------------------------
  252. int main(int argc, char **argv)
  253. {
  254. testing::InitGoogleTest(&argc, argv);
  255. return RUN_ALL_TESTS();
  256. }