android_audiotrack.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*****************************************************************************
  2. * 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 "android_audiotrack.h"
  25. #include <assert.h>
  26. #include "j4au/class/android/media/AudioTrack.util.h"
  27. #include "ijksdl_android_jni.h"
  28. #include "../ijksdl_inc_internal.h"
  29. #include "../ijksdl_audio.h"
  30. #ifdef SDLTRACE
  31. #undef SDLTRACE
  32. #define SDLTRACE(...)
  33. #endif
  34. typedef struct AudioChannelMapEntry {
  35. Uint8 sdl_channel;
  36. int android_channel;
  37. const char *sdl_name;
  38. const char *android_name;
  39. } AudioChannelMapEntry;
  40. static AudioChannelMapEntry g_audio_channel_map[] = {
  41. { 2, CHANNEL_OUT_STEREO, "2-chan", "CHANNEL_OUT_STEREO" },
  42. { 1, CHANNEL_OUT_MONO, "1-chan", "CHANNEL_OUT_MONO" },
  43. };
  44. typedef struct AudioFormatMapEntry {
  45. SDL_AudioFormat sdl_format;
  46. int android_format;
  47. const char *sdl_name;
  48. const char *android_name;
  49. } AudioFormatMapEntry;
  50. static AudioFormatMapEntry g_audio_format_map[] = {
  51. { AUDIO_S16SYS, ENCODING_PCM_16BIT, "AUDIO_S16SYS", "ENCODING_PCM_16BIT" },
  52. { AUDIO_U8, ENCODING_PCM_8BIT, "AUDIO_U8", "ENCODING_PCM_8BIT" },
  53. { AUDIO_F32, ENCODING_PCM_FLOAT, "AUDIO_F32", "ENCODING_PCM_FLOAT" },
  54. };
  55. static Uint8 find_sdl_channel(int android_channel)
  56. {
  57. for (int i = 0; i < NELEM(g_audio_channel_map); ++i) {
  58. AudioChannelMapEntry *entry = &g_audio_channel_map[i];
  59. if (entry->android_channel == android_channel)
  60. return entry->sdl_channel;
  61. }
  62. return 0;
  63. }
  64. static int find_android_channel(int sdl_channel)
  65. {
  66. for (int i = 0; i < NELEM(g_audio_channel_map); ++i) {
  67. AudioChannelMapEntry *entry = &g_audio_channel_map[i];
  68. if (entry->sdl_channel == sdl_channel)
  69. return entry->android_channel;
  70. }
  71. return CHANNEL_OUT_INVALID;
  72. }
  73. static SDL_AudioFormat find_sdl_format(int android_format)
  74. {
  75. for (int i = 0; i < NELEM(g_audio_format_map); ++i) {
  76. AudioFormatMapEntry *entry = &g_audio_format_map[i];
  77. if (entry->android_format == android_format)
  78. return entry->sdl_format;
  79. }
  80. return AUDIO_INVALID;
  81. }
  82. static int find_android_format(int sdl_format)
  83. {
  84. for (int i = 0; i < NELEM(g_audio_format_map); ++i) {
  85. AudioFormatMapEntry *entry = &g_audio_format_map[i];
  86. if (entry->sdl_format == sdl_format)
  87. return entry->android_format;
  88. }
  89. return ENCODING_INVALID;
  90. }
  91. typedef struct SDL_Android_AudioTrack {
  92. jobject thiz;
  93. SDL_Android_AudioTrack_Spec spec;
  94. jbyteArray byte_buffer;
  95. int byte_buffer_capacity;
  96. int min_buffer_size;
  97. float max_volume;
  98. float min_volume;
  99. } SDL_Android_AudioTrack;
  100. static void SDL_Android_AudioTrack_get_default_spec(SDL_Android_AudioTrack_Spec *spec)
  101. {
  102. assert(spec);
  103. spec->stream_type = STREAM_MUSIC;
  104. spec->sample_rate_in_hz = 0;
  105. spec->channel_config = CHANNEL_OUT_STEREO;
  106. spec->audio_format = ENCODING_PCM_16BIT;
  107. spec->buffer_size_in_bytes = 0;
  108. spec->mode = MODE_STREAM;
  109. }
  110. #define STREAM_MUSIC 3
  111. int audiotrack_get_native_output_sample_rate(JNIEnv *env)
  112. {
  113. if (!env) {
  114. if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
  115. ALOGE("%s: SetupThreadEnv failed", __func__);
  116. return -1;
  117. }
  118. }
  119. jint retval = J4AC_AudioTrack__getNativeOutputSampleRate(env, STREAM_MUSIC);
  120. if (J4A_ExceptionCheck__catchAll(env) || retval <= 0)
  121. return -1;
  122. return retval;
  123. }
  124. void SDL_Android_AudioTrack_set_volume(JNIEnv *env, SDL_Android_AudioTrack *atrack, float left_volume, float right_volume)
  125. {
  126. J4AC_AudioTrack__setStereoVolume__catchAll(env, atrack->thiz, left_volume, right_volume);
  127. }
  128. SDL_Android_AudioTrack *SDL_Android_AudioTrack_new_from_spec(JNIEnv *env, SDL_Android_AudioTrack_Spec *spec)
  129. {
  130. assert(spec);
  131. switch (spec->channel_config) {
  132. case CHANNEL_OUT_MONO:
  133. ALOGI("SDL_Android_AudioTrack: %s", "CHANNEL_OUT_MONO");
  134. break;
  135. case CHANNEL_OUT_STEREO:
  136. ALOGI("SDL_Android_AudioTrack: %s", "CHANNEL_OUT_STEREO");
  137. break;
  138. default:
  139. ALOGE("%s: invalid channel %d", __func__, spec->channel_config);
  140. return NULL;
  141. }
  142. switch (spec->audio_format) {
  143. case ENCODING_PCM_16BIT:
  144. ALOGI("SDL_Android_AudioTrack: %s", "ENCODING_PCM_16BIT");
  145. break;
  146. case ENCODING_PCM_8BIT:
  147. ALOGI("SDL_Android_AudioTrack: %s", "ENCODING_PCM_8BIT");
  148. break;
  149. #if 0
  150. case ENCODING_PCM_FLOAT:
  151. ALOGI("SDL_Android_AudioTrack: %s", "ENCODING_PCM_FLOAT");
  152. if (sdk_int < IJK_API_21_LOLLIPOP) {
  153. ALOGI("SDL_Android_AudioTrack: %s need API 21 or above", "ENCODING_PCM_FLOAT");
  154. return NULL;
  155. }
  156. break;
  157. #endif
  158. default:
  159. ALOGE("%s: invalid format %d", __func__, spec->audio_format);
  160. return NULL;
  161. }
  162. if (spec->sample_rate_in_hz <= 0) {
  163. ALOGE("%s: invalid sample rate %d", __func__, spec->sample_rate_in_hz);
  164. return NULL;
  165. }
  166. SDL_Android_AudioTrack *atrack = (SDL_Android_AudioTrack*) mallocz(sizeof(SDL_Android_AudioTrack));
  167. if (!atrack) {
  168. ALOGE("%s: mallocz faild.\n", __func__);
  169. return NULL;
  170. }
  171. atrack->spec = *spec;
  172. // libswresample is ugly, depending on native resampler
  173. while (atrack->spec.sample_rate_in_hz < 4000) {
  174. atrack->spec.sample_rate_in_hz *= 2;
  175. }
  176. while (atrack->spec.sample_rate_in_hz > 48000) {
  177. atrack->spec.sample_rate_in_hz /= 2;
  178. }
  179. int min_buffer_size = J4AC_AudioTrack__getMinBufferSize(env,
  180. atrack->spec.sample_rate_in_hz,
  181. atrack->spec.channel_config,
  182. atrack->spec.audio_format);
  183. if (J4A_ExceptionCheck__catchAll(env) || min_buffer_size <= 0) {
  184. ALOGE("%s: J4AC_AudioTrack__getMinBufferSize: return %d:", __func__, min_buffer_size);
  185. free(atrack);
  186. return NULL;
  187. }
  188. // for fast playback
  189. min_buffer_size *= AUDIOTRACK_PLAYBACK_MAXSPEED;
  190. atrack->thiz = J4AC_AudioTrack__AudioTrack__asGlobalRef__catchAll(env,
  191. atrack->spec.stream_type,
  192. atrack->spec.sample_rate_in_hz,
  193. atrack->spec.channel_config,
  194. atrack->spec.audio_format,
  195. min_buffer_size,
  196. atrack->spec.mode);
  197. if (!atrack->thiz) {
  198. free(atrack);
  199. return NULL;
  200. }
  201. atrack->min_buffer_size = min_buffer_size;
  202. atrack->spec.buffer_size_in_bytes = min_buffer_size;
  203. // atrack->max_volume = J4AC_AudioTrack__getMaxVolume__catchAll(env);
  204. // atrack->min_volume = J4AC_AudioTrack__getMinVolume__catchAll(env);
  205. atrack->max_volume = 1.0f;
  206. atrack->min_volume = 0.0f;
  207. // extra init
  208. float init_volume = 1.0f;
  209. init_volume = IJKMIN(init_volume, atrack->max_volume);
  210. init_volume = IJKMAX(init_volume, atrack->min_volume);
  211. ALOGI("%s: init volume as %f/(%f,%f)", __func__, init_volume, atrack->min_volume, atrack->max_volume);
  212. J4AC_AudioTrack__setStereoVolume__catchAll(env, atrack->thiz, init_volume, init_volume);
  213. return atrack;
  214. }
  215. SDL_Android_AudioTrack *SDL_Android_AudioTrack_new_from_sdl_spec(JNIEnv *env, const SDL_AudioSpec *sdl_spec)
  216. {
  217. SDL_Android_AudioTrack_Spec atrack_spec;
  218. SDL_Android_AudioTrack_get_default_spec(&atrack_spec);
  219. atrack_spec.sample_rate_in_hz = sdl_spec->freq;
  220. atrack_spec.channel_config = find_android_channel(sdl_spec->channels);
  221. atrack_spec.audio_format = find_android_format(sdl_spec->format);
  222. atrack_spec.buffer_size_in_bytes = sdl_spec->size;
  223. return SDL_Android_AudioTrack_new_from_spec(env, &atrack_spec);
  224. }
  225. void SDL_Android_AudioTrack_free(JNIEnv *env, SDL_Android_AudioTrack* atrack)
  226. {
  227. J4A_DeleteGlobalRef__p(env, &atrack->byte_buffer);
  228. atrack->byte_buffer_capacity = 0;
  229. if (atrack->thiz) {
  230. J4AC_AudioTrack__release(env, atrack->thiz);
  231. J4A_DeleteGlobalRef__p(env, &atrack->thiz);
  232. }
  233. free(atrack);
  234. }
  235. void SDL_Android_AudioTrack_get_target_spec(SDL_Android_AudioTrack *atrack, SDL_AudioSpec *sdl_spec)
  236. {
  237. SDL_Android_AudioTrack_Spec *atrack_spec = &atrack->spec;
  238. sdl_spec->freq = atrack_spec->sample_rate_in_hz;
  239. sdl_spec->channels = find_sdl_channel(atrack_spec->channel_config);
  240. sdl_spec->format = find_sdl_format(atrack_spec->audio_format);
  241. sdl_spec->size = atrack_spec->buffer_size_in_bytes;
  242. sdl_spec->silence = 0;
  243. sdl_spec->padding = 0;
  244. }
  245. int SDL_Android_AudioTrack_get_min_buffer_size(SDL_Android_AudioTrack* atrack)
  246. {
  247. return atrack->min_buffer_size;
  248. }
  249. void SDL_Android_AudioTrack_play(JNIEnv *env, SDL_Android_AudioTrack *atrack)
  250. {
  251. SDLTRACE("%s", __func__);
  252. J4AC_AudioTrack__play__catchAll(env, atrack->thiz);
  253. }
  254. void SDL_Android_AudioTrack_pause(JNIEnv *env, SDL_Android_AudioTrack *atrack)
  255. {
  256. SDLTRACE("%s", __func__);
  257. J4AC_AudioTrack__pause__catchAll(env, atrack->thiz);
  258. }
  259. void SDL_Android_AudioTrack_flush(JNIEnv *env, SDL_Android_AudioTrack *atrack)
  260. {
  261. SDLTRACE("%s", __func__);
  262. J4AC_AudioTrack__flush__catchAll(env, atrack->thiz);
  263. }
  264. void SDL_Android_AudioTrack_stop(JNIEnv *env, SDL_Android_AudioTrack *atrack)
  265. {
  266. SDLTRACE("%s", __func__);
  267. J4AC_AudioTrack__stop__catchAll(env, atrack->thiz);
  268. }
  269. int SDL_Android_AudioTrack_reserve_byte_buffer(JNIEnv *env, SDL_Android_AudioTrack *atrack, int size_in_byte)
  270. {
  271. if (atrack->byte_buffer && size_in_byte <= atrack->byte_buffer_capacity)
  272. return size_in_byte;
  273. J4A_DeleteGlobalRef__p(env, &atrack->byte_buffer);
  274. atrack->byte_buffer_capacity = 0;
  275. int capacity = IJKMAX(size_in_byte, atrack->min_buffer_size);
  276. atrack->byte_buffer = J4A_NewByteArray__asGlobalRef__catchAll(env, capacity);
  277. if (!atrack->byte_buffer)
  278. return -1;
  279. atrack->byte_buffer_capacity = capacity;
  280. return capacity;
  281. }
  282. int SDL_Android_AudioTrack_write(JNIEnv *env, SDL_Android_AudioTrack *atrack, uint8_t *data, int size_in_byte)
  283. {
  284. if (size_in_byte <= 0)
  285. return size_in_byte;
  286. int reserved = SDL_Android_AudioTrack_reserve_byte_buffer(env, atrack, size_in_byte);
  287. if (reserved < size_in_byte) {
  288. ALOGE("%s failed %d < %d\n", __func__, reserved, size_in_byte);
  289. return -1;
  290. }
  291. (*env)->SetByteArrayRegion(env, atrack->byte_buffer, 0, (int)size_in_byte, (jbyte*) data);
  292. if (J4A_ExceptionCheck__catchAll(env))
  293. return -1;
  294. int retval = J4AC_AudioTrack__write(env, atrack->thiz, atrack->byte_buffer, 0, (int)size_in_byte);
  295. if (J4A_ExceptionCheck__catchAll(env))
  296. return -1;
  297. return retval;
  298. }
  299. int SDL_Android_AudioTrack_getAudioSessionId(JNIEnv *env, SDL_Android_AudioTrack *atrack)
  300. {
  301. SDLTRACE("%s", __func__);
  302. int audioSessionId = J4AC_AudioTrack__getAudioSessionId(env, atrack->thiz);
  303. if (J4A_ExceptionCheck__catchAll(env))
  304. return 0;
  305. return audioSessionId;
  306. }
  307. void SDL_Android_AudioTrack_setSpeed(JNIEnv *env, SDL_Android_AudioTrack *atrack, float speed)
  308. {
  309. J4AC_AudioTrack__setSpeed(env, atrack->thiz, speed);
  310. if (J4A_ExceptionCheck__catchAll(env))
  311. return;
  312. return;
  313. }