ijksdl_aout_android_audiotrack.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*****************************************************************************
  2. * ijksdl_aout_android_audiotrack.c
  3. *****************************************************************************
  4. *
  5. * Copyright (c) 2013 Bilibili
  6. * copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
  7. *
  8. * This file is part of ijkPlayer.
  9. *
  10. * ijkPlayer is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * ijkPlayer is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with ijkPlayer; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. #include "ijksdl_aout_android_audiotrack.h"
  25. #include <stdbool.h>
  26. #include <assert.h>
  27. #include <jni.h>
  28. #include "../ijksdl_inc_internal.h"
  29. #include "../ijksdl_thread.h"
  30. #include "../ijksdl_aout_internal.h"
  31. #include "ijksdl_android_jni.h"
  32. #include "android_audiotrack.h"
  33. #ifdef SDLTRACE
  34. #undef SDLTRACE
  35. #define SDLTRACE(...)
  36. //#define SDLTRACE ALOGE
  37. #endif
  38. static SDL_Class g_audiotrack_class = {
  39. .name = "AudioTrack",
  40. };
  41. typedef struct SDL_Aout_Opaque {
  42. SDL_cond *wakeup_cond;
  43. SDL_mutex *wakeup_mutex;
  44. SDL_AudioSpec spec;
  45. SDL_Android_AudioTrack* atrack;
  46. uint8_t *buffer;
  47. int buffer_size;
  48. volatile bool need_flush;
  49. volatile bool pause_on;
  50. volatile bool abort_request;
  51. volatile bool need_set_volume;
  52. volatile float left_volume;
  53. volatile float right_volume;
  54. SDL_Thread *audio_tid;
  55. SDL_Thread _audio_tid;
  56. int audio_session_id;
  57. volatile float speed;
  58. volatile bool speed_changed;
  59. } SDL_Aout_Opaque;
  60. static int aout_thread_n(JNIEnv *env, SDL_Aout *aout)
  61. {
  62. SDL_Aout_Opaque *opaque = aout->opaque;
  63. SDL_Android_AudioTrack *atrack = opaque->atrack;
  64. SDL_AudioCallback audio_cblk = opaque->spec.callback;
  65. void *userdata = opaque->spec.userdata;
  66. uint8_t *buffer = opaque->buffer;
  67. int copy_size = 256;
  68. assert(atrack);
  69. assert(buffer);
  70. SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
  71. if (!opaque->abort_request && !opaque->pause_on)
  72. SDL_Android_AudioTrack_play(env, atrack);
  73. while (!opaque->abort_request) {
  74. SDL_LockMutex(opaque->wakeup_mutex);
  75. if (!opaque->abort_request && opaque->pause_on) {
  76. SDL_Android_AudioTrack_pause(env, atrack);
  77. while (!opaque->abort_request && opaque->pause_on) {
  78. SDL_CondWaitTimeout(opaque->wakeup_cond, opaque->wakeup_mutex, 1000);
  79. }
  80. if (!opaque->abort_request && !opaque->pause_on) {
  81. if (opaque->need_flush) {
  82. opaque->need_flush = 0;
  83. SDL_Android_AudioTrack_flush(env, atrack);
  84. }
  85. SDL_Android_AudioTrack_play(env, atrack);
  86. }
  87. }
  88. if (opaque->need_flush) {
  89. opaque->need_flush = 0;
  90. SDL_Android_AudioTrack_flush(env, atrack);
  91. }
  92. if (opaque->need_set_volume) {
  93. opaque->need_set_volume = 0;
  94. SDL_Android_AudioTrack_set_volume(env, atrack, opaque->left_volume, opaque->right_volume);
  95. }
  96. if (opaque->speed_changed) {
  97. opaque->speed_changed = 0;
  98. SDL_Android_AudioTrack_setSpeed(env, atrack, opaque->speed);
  99. }
  100. SDL_UnlockMutex(opaque->wakeup_mutex);
  101. audio_cblk(userdata, buffer, copy_size);
  102. if (opaque->need_flush) {
  103. SDL_Android_AudioTrack_flush(env, atrack);
  104. opaque->need_flush = false;
  105. }
  106. if (opaque->need_flush) {
  107. opaque->need_flush = 0;
  108. SDL_Android_AudioTrack_flush(env, atrack);
  109. } else {
  110. int written = SDL_Android_AudioTrack_write(env, atrack, buffer, copy_size);
  111. if (written != copy_size) {
  112. ALOGW("AudioTrack: not all data copied %d/%d", (int)written, (int)copy_size);
  113. }
  114. }
  115. // TODO: 1 if callback return -1 or 0
  116. }
  117. SDL_Android_AudioTrack_free(env, atrack);
  118. return 0;
  119. }
  120. static int aout_thread(void *arg)
  121. {
  122. SDL_Aout *aout = arg;
  123. // SDL_Aout_Opaque *opaque = aout->opaque;
  124. JNIEnv *env = NULL;
  125. if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
  126. ALOGE("aout_thread: SDL_AndroidJni_SetupEnv: failed");
  127. return -1;
  128. }
  129. return aout_thread_n(env, aout);
  130. }
  131. static int aout_open_audio_n(JNIEnv *env, SDL_Aout *aout, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
  132. {
  133. assert(desired);
  134. SDL_Aout_Opaque *opaque = aout->opaque;
  135. opaque->spec = *desired;
  136. opaque->atrack = SDL_Android_AudioTrack_new_from_sdl_spec(env, desired);
  137. if (!opaque->atrack) {
  138. ALOGE("aout_open_audio_n: failed to new AudioTrcak()");
  139. return -1;
  140. }
  141. opaque->buffer_size = SDL_Android_AudioTrack_get_min_buffer_size(opaque->atrack);
  142. if (opaque->buffer_size <= 0) {
  143. ALOGE("aout_open_audio_n: failed to getMinBufferSize()");
  144. SDL_Android_AudioTrack_free(env, opaque->atrack);
  145. opaque->atrack = NULL;
  146. return -1;
  147. }
  148. opaque->buffer = malloc(opaque->buffer_size);
  149. if (!opaque->buffer) {
  150. ALOGE("aout_open_audio_n: failed to allocate buffer");
  151. SDL_Android_AudioTrack_free(env, opaque->atrack);
  152. opaque->atrack = NULL;
  153. return -1;
  154. }
  155. if (obtained) {
  156. SDL_Android_AudioTrack_get_target_spec(opaque->atrack, obtained);
  157. SDLTRACE("audio target format fmt:0x%x, channel:0x%x", (int)obtained->format, (int)obtained->channels);
  158. }
  159. opaque->audio_session_id = SDL_Android_AudioTrack_getAudioSessionId(env, opaque->atrack);
  160. ALOGI("audio_session_id = %d\n", opaque->audio_session_id);
  161. opaque->pause_on = 1;
  162. opaque->abort_request = 0;
  163. opaque->audio_tid = SDL_CreateThreadEx(&opaque->_audio_tid, aout_thread, aout, "ff_aout_android");
  164. if (!opaque->audio_tid) {
  165. ALOGE("aout_open_audio_n: failed to create audio thread");
  166. SDL_Android_AudioTrack_free(env, opaque->atrack);
  167. opaque->atrack = NULL;
  168. return -1;
  169. }
  170. return 0;
  171. }
  172. static int aout_open_audio(SDL_Aout *aout, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
  173. {
  174. // SDL_Aout_Opaque *opaque = aout->opaque;
  175. JNIEnv *env = NULL;
  176. if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
  177. ALOGE("aout_open_audio: AttachCurrentThread: failed");
  178. return -1;
  179. }
  180. return aout_open_audio_n(env, aout, desired, obtained);
  181. }
  182. static void aout_pause_audio(SDL_Aout *aout, int pause_on)
  183. {
  184. SDL_Aout_Opaque *opaque = aout->opaque;
  185. SDL_LockMutex(opaque->wakeup_mutex);
  186. SDLTRACE("aout_pause_audio(%d)", pause_on);
  187. opaque->pause_on = pause_on;
  188. if (!pause_on)
  189. SDL_CondSignal(opaque->wakeup_cond);
  190. SDL_UnlockMutex(opaque->wakeup_mutex);
  191. }
  192. static void aout_flush_audio(SDL_Aout *aout)
  193. {
  194. SDL_Aout_Opaque *opaque = aout->opaque;
  195. SDL_LockMutex(opaque->wakeup_mutex);
  196. SDLTRACE("aout_flush_audio()");
  197. opaque->need_flush = 1;
  198. SDL_CondSignal(opaque->wakeup_cond);
  199. SDL_UnlockMutex(opaque->wakeup_mutex);
  200. }
  201. static void aout_set_volume(SDL_Aout *aout, float left_volume, float right_volume)
  202. {
  203. SDL_Aout_Opaque *opaque = aout->opaque;
  204. SDL_LockMutex(opaque->wakeup_mutex);
  205. SDLTRACE("aout_flush_audio()");
  206. opaque->left_volume = left_volume;
  207. opaque->right_volume = right_volume;
  208. opaque->need_set_volume = 1;
  209. SDL_CondSignal(opaque->wakeup_cond);
  210. SDL_UnlockMutex(opaque->wakeup_mutex);
  211. }
  212. static void aout_close_audio(SDL_Aout *aout)
  213. {
  214. SDL_Aout_Opaque *opaque = aout->opaque;
  215. SDL_LockMutex(opaque->wakeup_mutex);
  216. opaque->abort_request = true;
  217. SDL_CondSignal(opaque->wakeup_cond);
  218. SDL_UnlockMutex(opaque->wakeup_mutex);
  219. SDL_WaitThread(opaque->audio_tid, NULL);
  220. opaque->audio_tid = NULL;
  221. }
  222. static int aout_get_audio_session_id(SDL_Aout *aout)
  223. {
  224. SDL_Aout_Opaque *opaque = aout->opaque;
  225. return opaque->audio_session_id;
  226. }
  227. static void aout_free_l(SDL_Aout *aout)
  228. {
  229. if (!aout)
  230. return;
  231. aout_close_audio(aout);
  232. SDL_Aout_Opaque *opaque = aout->opaque;
  233. if (opaque) {
  234. free(opaque->buffer);
  235. opaque->buffer = NULL;
  236. opaque->buffer_size = 0;
  237. SDL_DestroyCond(opaque->wakeup_cond);
  238. SDL_DestroyMutex(opaque->wakeup_mutex);
  239. }
  240. SDL_Aout_FreeInternal(aout);
  241. }
  242. static void func_set_playback_rate(SDL_Aout *aout, float speed)
  243. {
  244. if (!aout)
  245. return;
  246. SDL_Aout_Opaque *opaque = aout->opaque;
  247. SDL_LockMutex(opaque->wakeup_mutex);
  248. SDLTRACE("%s %f", __func__, (double)speed);
  249. opaque->speed = speed;
  250. opaque->speed_changed = 1;
  251. SDL_CondSignal(opaque->wakeup_cond);
  252. SDL_UnlockMutex(opaque->wakeup_mutex);
  253. }
  254. SDL_Aout *SDL_AoutAndroid_CreateForAudioTrack()
  255. {
  256. SDL_Aout *aout = SDL_Aout_CreateInternal(sizeof(SDL_Aout_Opaque));
  257. if (!aout)
  258. return NULL;
  259. SDL_Aout_Opaque *opaque = aout->opaque;
  260. opaque->wakeup_cond = SDL_CreateCond();
  261. opaque->wakeup_mutex = SDL_CreateMutex();
  262. opaque->speed = 1.0f;
  263. aout->opaque_class = &g_audiotrack_class;
  264. aout->free_l = aout_free_l;
  265. aout->open_audio = aout_open_audio;
  266. aout->pause_audio = aout_pause_audio;
  267. aout->flush_audio = aout_flush_audio;
  268. aout->set_volume = aout_set_volume;
  269. aout->close_audio = aout_close_audio;
  270. aout->func_get_audio_session_id = aout_get_audio_session_id;
  271. aout->func_set_playback_rate = func_set_playback_rate;
  272. return aout;
  273. }
  274. bool SDL_AoutAndroid_IsObjectOfAudioTrack(SDL_Aout *aout)
  275. {
  276. if (aout)
  277. return false;
  278. return aout->opaque_class == &g_audiotrack_class;
  279. }
  280. void SDL_Init_AoutAndroid(JNIEnv *env)
  281. {
  282. }