You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1706 lines
50KB

  1. /*
  2. * Android MediaCodec Wrapper
  3. *
  4. * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
  5. *
  6. * This file is part of FFmpeg.
  7. *
  8. * FFmpeg is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * FFmpeg is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with FFmpeg; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <jni.h>
  23. #include "libavutil/avassert.h"
  24. #include "libavutil/mem.h"
  25. #include "libavutil/avstring.h"
  26. #include "ffjni.h"
  27. #include "version.h"
  28. #include "mediacodec_wrapper.h"
  29. struct JNIAMediaCodecListFields {
  30. jclass mediaformat_class;
  31. jmethodID create_video_format_id;
  32. jclass mediacodec_list_class;
  33. jmethodID init_id;
  34. jmethodID find_decoder_for_format_id;
  35. jmethodID get_codec_count_id;
  36. jmethodID get_codec_info_at_id;
  37. jclass mediacodec_info_class;
  38. jmethodID get_name_id;
  39. jmethodID get_supported_types_id;
  40. jmethodID is_encoder_id;
  41. } JNIAMediaCodecListFields;
  42. static const struct FFJniField jfields_mapping[] = {
  43. { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediaformat_class), 1 },
  44. { "android/media/MediaFormat", "createVideoFormat", "(Ljava/lang/String;II)Landroid/media/MediaFormat;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, create_video_format_id), 1 },
  45. { "android/media/MediaCodecList", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_list_class), 1 },
  46. { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, init_id), 0 },
  47. { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, find_decoder_for_format_id), 0 },
  48. { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_count_id), 1 },
  49. { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_info_at_id), 1 },
  50. { "android/media/MediaCodecInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_info_class), 1 },
  51. { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_name_id), 1 },
  52. { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_supported_types_id), 1 },
  53. { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_encoder_id), 1 },
  54. { NULL }
  55. };
  56. #define JNI_ATTACH_ENV_OR_RETURN(env, attached, log_ctx, ret) do { \
  57. (env) = ff_jni_attach_env(attached, log_ctx); \
  58. if (!(env)) { \
  59. return ret; \
  60. } \
  61. } while (0)
  62. #define JNI_ATTACH_ENV_OR_RETURN_VOID(env, attached, log_ctx) do { \
  63. (env) = ff_jni_attach_env(attached, log_ctx); \
  64. if (!(env)) { \
  65. return; \
  66. } \
  67. } while (0)
  68. #define JNI_DETACH_ENV(attached, log_ctx) do { \
  69. if (attached) \
  70. ff_jni_detach_env(log_ctx); \
  71. } while (0)
  72. char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int width, int height, void *log_ctx)
  73. {
  74. int ret;
  75. char *name = NULL;
  76. char *supported_type = NULL;
  77. int attached = 0;
  78. JNIEnv *env = NULL;
  79. struct JNIAMediaCodecListFields jfields = { 0 };
  80. jobject format = NULL;
  81. jobject codec = NULL;
  82. jstring tmp = NULL;
  83. jobject info = NULL;
  84. jobject type = NULL;
  85. jobjectArray types = NULL;
  86. JNI_ATTACH_ENV_OR_RETURN(env, &attached, log_ctx, NULL);
  87. if ((ret = ff_jni_init_jfields(env, &jfields, jfields_mapping, 0, log_ctx)) < 0) {
  88. goto done;
  89. }
  90. if (jfields.init_id && jfields.find_decoder_for_format_id) {
  91. tmp = ff_jni_utf_chars_to_jstring(env, mime, log_ctx);
  92. if (!tmp) {
  93. goto done;
  94. }
  95. format = (*env)->CallStaticObjectMethod(env, jfields.mediaformat_class, jfields.create_video_format_id, tmp, width, height);
  96. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  97. goto done;
  98. }
  99. (*env)->DeleteLocalRef(env, tmp);
  100. codec = (*env)->NewObject(env, jfields.mediacodec_list_class, jfields.init_id, 0);
  101. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  102. goto done;
  103. }
  104. tmp = (*env)->CallObjectMethod(env, codec, jfields.find_decoder_for_format_id, format);
  105. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  106. goto done;
  107. }
  108. if (!tmp) {
  109. av_log(NULL, AV_LOG_ERROR, "Could not find decoder in media codec list "
  110. "for format { mime=%s width=%d height=%d }\n", mime, width, height);
  111. goto done;
  112. }
  113. name = ff_jni_jstring_to_utf_chars(env, tmp, log_ctx);
  114. if (!name) {
  115. goto done;
  116. }
  117. } else {
  118. int i;
  119. int codec_count;
  120. codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
  121. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  122. goto done;
  123. }
  124. for(i = 0; i < codec_count; i++) {
  125. int j;
  126. int type_count;
  127. int is_encoder;
  128. info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
  129. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  130. goto done;
  131. }
  132. types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
  133. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  134. goto done;
  135. }
  136. is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
  137. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  138. goto done;
  139. }
  140. if (is_encoder) {
  141. continue;
  142. }
  143. type_count = (*env)->GetArrayLength(env, types);
  144. for (j = 0; j < type_count; j++) {
  145. type = (*env)->GetObjectArrayElement(env, types, j);
  146. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  147. goto done;
  148. }
  149. supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
  150. if (!supported_type) {
  151. goto done;
  152. }
  153. if (!av_strcasecmp(supported_type, mime)) {
  154. jobject codec_name;
  155. codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
  156. if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
  157. goto done;
  158. }
  159. name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
  160. if (!name) {
  161. goto done;
  162. }
  163. if (strstr(name, "OMX.google")) {
  164. av_freep(&name);
  165. continue;
  166. }
  167. }
  168. av_freep(&supported_type);
  169. }
  170. (*env)->DeleteLocalRef(env, info);
  171. info = NULL;
  172. (*env)->DeleteLocalRef(env, types);
  173. types = NULL;
  174. if (name)
  175. break;
  176. }
  177. }
  178. done:
  179. if (format) {
  180. (*env)->DeleteLocalRef(env, format);
  181. }
  182. if (codec) {
  183. (*env)->DeleteLocalRef(env, codec);
  184. }
  185. if (tmp) {
  186. (*env)->DeleteLocalRef(env, tmp);
  187. }
  188. if (info) {
  189. (*env)->DeleteLocalRef(env, info);
  190. }
  191. if (type) {
  192. (*env)->DeleteLocalRef(env, type);
  193. }
  194. if (types) {
  195. (*env)->DeleteLocalRef(env, types);
  196. }
  197. av_freep(&supported_type);
  198. ff_jni_reset_jfields(env, &jfields, jfields_mapping, 0, log_ctx);
  199. JNI_DETACH_ENV(attached, log_ctx);
  200. return name;
  201. }
  202. struct JNIAMediaFormatFields {
  203. jclass clazz;
  204. jmethodID init_id;
  205. jmethodID get_integer_id;
  206. jmethodID get_long_id;
  207. jmethodID get_float_id;
  208. jmethodID get_bytebuffer_id;
  209. jmethodID get_string_id;
  210. jmethodID set_integer_id;
  211. jmethodID set_long_id;
  212. jmethodID set_float_id;
  213. jmethodID set_bytebuffer_id;
  214. jmethodID set_string_id;
  215. jmethodID to_string_id;
  216. } JNIAMediaFormatFields;
  217. static const struct FFJniField jni_amediaformat_mapping[] = {
  218. { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaFormatFields, clazz), 1 },
  219. { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, init_id), 1 },
  220. { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_integer_id), 1 },
  221. { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_long_id), 1 },
  222. { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_float_id), 1 },
  223. { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_bytebuffer_id), 1 },
  224. { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_string_id), 1 },
  225. { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_integer_id), 1 },
  226. { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_long_id), 1 },
  227. { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_float_id), 1 },
  228. { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_bytebuffer_id), 1 },
  229. { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_string_id), 1 },
  230. { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, to_string_id), 1 },
  231. { NULL }
  232. };
  233. static const AVClass amediaformat_class = {
  234. .class_name = "amediaformat",
  235. .item_name = av_default_item_name,
  236. .version = LIBAVCODEC_VERSION_INT,
  237. };
  238. struct FFAMediaFormat {
  239. const AVClass *class;
  240. struct JNIAMediaFormatFields jfields;
  241. jobject object;
  242. };
  243. FFAMediaFormat *ff_AMediaFormat_new(void)
  244. {
  245. int attached = 0;
  246. JNIEnv *env = NULL;
  247. FFAMediaFormat *format = NULL;
  248. format = av_mallocz(sizeof(FFAMediaFormat));
  249. if (!format) {
  250. return NULL;
  251. }
  252. format->class = &amediaformat_class;
  253. env = ff_jni_attach_env(&attached, format);
  254. if (!env) {
  255. av_freep(&format);
  256. return NULL;
  257. }
  258. if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
  259. goto fail;
  260. }
  261. format->object = (*env)->NewObject(env, format->jfields.clazz, format->jfields.init_id);
  262. if (!format->object) {
  263. goto fail;
  264. }
  265. format->object = (*env)->NewGlobalRef(env, format->object);
  266. if (!format->object) {
  267. goto fail;
  268. }
  269. JNI_DETACH_ENV(attached, format);
  270. return format;
  271. fail:
  272. ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
  273. JNI_DETACH_ENV(attached, format);
  274. av_freep(&format);
  275. return NULL;
  276. }
  277. static FFAMediaFormat *ff_AMediaFormat_newFromObject(void *object)
  278. {
  279. int attached = 0;
  280. JNIEnv *env = NULL;
  281. FFAMediaFormat *format = NULL;
  282. format = av_mallocz(sizeof(FFAMediaFormat));
  283. if (!format) {
  284. return NULL;
  285. }
  286. format->class = &amediaformat_class;
  287. env = ff_jni_attach_env(&attached, format);
  288. if (!env) {
  289. av_freep(&format);
  290. return NULL;
  291. }
  292. if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
  293. goto fail;
  294. }
  295. format->object = (*env)->NewGlobalRef(env, object);
  296. if (!format->object) {
  297. goto fail;
  298. }
  299. JNI_DETACH_ENV(attached, format);
  300. return format;
  301. fail:
  302. ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
  303. JNI_DETACH_ENV(attached, format);
  304. av_freep(&format);
  305. return NULL;
  306. }
  307. int ff_AMediaFormat_delete(FFAMediaFormat* format)
  308. {
  309. int ret = 0;
  310. int attached = 0;
  311. JNIEnv *env = NULL;
  312. if (!format) {
  313. return 0;
  314. }
  315. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, AVERROR_EXTERNAL);
  316. (*env)->DeleteGlobalRef(env, format->object);
  317. format->object = NULL;
  318. ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
  319. JNI_DETACH_ENV(attached, format);
  320. av_freep(&format);
  321. return ret;
  322. }
  323. char* ff_AMediaFormat_toString(FFAMediaFormat* format)
  324. {
  325. char *ret = NULL;
  326. int attached = 0;
  327. JNIEnv *env = NULL;
  328. jstring description = NULL;
  329. av_assert0(format != NULL);
  330. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, NULL);
  331. description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
  332. if (ff_jni_exception_check(env, 1, NULL) < 0) {
  333. goto fail;
  334. }
  335. ret = ff_jni_jstring_to_utf_chars(env, description, format);
  336. fail:
  337. if (description) {
  338. (*env)->DeleteLocalRef(env, description);
  339. }
  340. JNI_DETACH_ENV(attached, format);
  341. return ret;
  342. }
  343. int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t *out)
  344. {
  345. int ret = 1;
  346. int attached = 0;
  347. JNIEnv *env = NULL;
  348. jstring key = NULL;
  349. av_assert0(format != NULL);
  350. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
  351. key = ff_jni_utf_chars_to_jstring(env, name, format);
  352. if (!key) {
  353. ret = 0;
  354. goto fail;
  355. }
  356. *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
  357. if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
  358. ret = 0;
  359. goto fail;
  360. }
  361. ret = 1;
  362. fail:
  363. if (key) {
  364. (*env)->DeleteLocalRef(env, key);
  365. }
  366. JNI_DETACH_ENV(attached, format);
  367. return ret;
  368. }
  369. int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t *out)
  370. {
  371. int ret = 1;
  372. int attached = 0;
  373. JNIEnv *env = NULL;
  374. jstring key = NULL;
  375. av_assert0(format != NULL);
  376. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
  377. key = ff_jni_utf_chars_to_jstring(env, name, format);
  378. if (!key) {
  379. ret = 0;
  380. goto fail;
  381. }
  382. *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
  383. if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
  384. ret = 0;
  385. goto fail;
  386. }
  387. ret = 1;
  388. fail:
  389. if (key) {
  390. (*env)->DeleteLocalRef(env, key);
  391. }
  392. JNI_DETACH_ENV(attached, format);
  393. return ret;
  394. }
  395. int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *out)
  396. {
  397. int ret = 1;
  398. int attached = 0;
  399. JNIEnv *env = NULL;
  400. jstring key = NULL;
  401. av_assert0(format != NULL);
  402. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
  403. key = ff_jni_utf_chars_to_jstring(env, name, format);
  404. if (!key) {
  405. ret = 0;
  406. goto fail;
  407. }
  408. *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
  409. if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
  410. ret = 0;
  411. goto fail;
  412. }
  413. ret = 1;
  414. fail:
  415. if (key) {
  416. (*env)->DeleteLocalRef(env, key);
  417. }
  418. JNI_DETACH_ENV(attached, format);
  419. return ret;
  420. }
  421. int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
  422. {
  423. int ret = 1;
  424. int attached = 0;
  425. JNIEnv *env = NULL;
  426. jstring key = NULL;
  427. jobject result = NULL;
  428. av_assert0(format != NULL);
  429. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
  430. key = ff_jni_utf_chars_to_jstring(env, name, format);
  431. if (!key) {
  432. ret = 0;
  433. goto fail;
  434. }
  435. result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
  436. if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
  437. ret = 0;
  438. goto fail;
  439. }
  440. *data = (*env)->GetDirectBufferAddress(env, result);
  441. *size = (*env)->GetDirectBufferCapacity(env, result);
  442. if (*data && *size) {
  443. void *src = *data;
  444. *data = av_malloc(*size);
  445. if (!*data) {
  446. ret = 0;
  447. goto fail;
  448. }
  449. memcpy(*data, src, *size);
  450. }
  451. ret = 1;
  452. fail:
  453. if (key) {
  454. (*env)->DeleteLocalRef(env, key);
  455. }
  456. if (result) {
  457. (*env)->DeleteLocalRef(env, result);
  458. }
  459. JNI_DETACH_ENV(attached, format);
  460. return ret;
  461. }
  462. int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
  463. {
  464. int ret = 1;
  465. int attached = 0;
  466. JNIEnv *env = NULL;
  467. jstring key = NULL;
  468. jstring result = NULL;
  469. av_assert0(format != NULL);
  470. JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
  471. key = ff_jni_utf_chars_to_jstring(env, name, format);
  472. if (!key) {
  473. ret = 0;
  474. goto fail;
  475. }
  476. result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
  477. if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
  478. ret = 0;
  479. goto fail;
  480. }
  481. *out = ff_jni_jstring_to_utf_chars(env, result, format);
  482. if (!*out) {
  483. ret = 0;
  484. goto fail;
  485. }
  486. ret = 1;
  487. fail:
  488. if (key) {
  489. (*env)->DeleteLocalRef(env, key);
  490. }
  491. if (result) {
  492. (*env)->DeleteLocalRef(env, result);
  493. }
  494. JNI_DETACH_ENV(attached, format);
  495. return ret;
  496. }
  497. void ff_AMediaFormat_setInt32(FFAMediaFormat* format, const char* name, int32_t value)
  498. {
  499. int attached = 0;
  500. JNIEnv *env = NULL;
  501. jstring key = NULL;
  502. av_assert0(format != NULL);
  503. JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
  504. key = ff_jni_utf_chars_to_jstring(env, name, format);
  505. if (!key) {
  506. goto fail;
  507. }
  508. (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
  509. if (ff_jni_exception_check(env, 1, format) < 0) {
  510. goto fail;
  511. }
  512. fail:
  513. if (key) {
  514. (*env)->DeleteLocalRef(env, key);
  515. }
  516. JNI_DETACH_ENV(attached, format);
  517. }
  518. void ff_AMediaFormat_setInt64(FFAMediaFormat* format, const char* name, int64_t value)
  519. {
  520. int attached = 0;
  521. JNIEnv *env = NULL;
  522. jstring key = NULL;
  523. av_assert0(format != NULL);
  524. JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
  525. key = ff_jni_utf_chars_to_jstring(env, name, format);
  526. if (!key) {
  527. goto fail;
  528. }
  529. (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
  530. if (ff_jni_exception_check(env, 1, format) < 0) {
  531. goto fail;
  532. }
  533. fail:
  534. if (key) {
  535. (*env)->DeleteLocalRef(env, key);
  536. }
  537. JNI_DETACH_ENV(attached, NULL);
  538. }
  539. void ff_AMediaFormat_setFloat(FFAMediaFormat* format, const char* name, float value)
  540. {
  541. int attached = 0;
  542. JNIEnv *env = NULL;
  543. jstring key = NULL;
  544. av_assert0(format != NULL);
  545. JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
  546. key = ff_jni_utf_chars_to_jstring(env, name, format);
  547. if (!key) {
  548. goto fail;
  549. }
  550. (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
  551. if (ff_jni_exception_check(env, 1, format) < 0) {
  552. goto fail;
  553. }
  554. fail:
  555. if (key) {
  556. (*env)->DeleteLocalRef(env, key);
  557. }
  558. JNI_DETACH_ENV(attached, NULL);
  559. }
  560. void ff_AMediaFormat_setString(FFAMediaFormat* format, const char* name, const char* value)
  561. {
  562. int attached = 0;
  563. JNIEnv *env = NULL;
  564. jstring key = NULL;
  565. jstring string = NULL;
  566. av_assert0(format != NULL);
  567. JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
  568. key = ff_jni_utf_chars_to_jstring(env, name, format);
  569. if (!key) {
  570. goto fail;
  571. }
  572. string = ff_jni_utf_chars_to_jstring(env, value, format);
  573. if (!string) {
  574. goto fail;
  575. }
  576. (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
  577. if (ff_jni_exception_check(env, 1, format) < 0) {
  578. goto fail;
  579. }
  580. fail:
  581. if (key) {
  582. (*env)->DeleteLocalRef(env, key);
  583. }
  584. if (string) {
  585. (*env)->DeleteLocalRef(env, string);
  586. }
  587. JNI_DETACH_ENV(attached, format);
  588. }
  589. void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
  590. {
  591. int attached = 0;
  592. JNIEnv *env = NULL;
  593. jstring key = NULL;
  594. jobject buffer = NULL;
  595. void *buffer_data = NULL;
  596. av_assert0(format != NULL);
  597. JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
  598. key = ff_jni_utf_chars_to_jstring(env, name, format);
  599. if (!key) {
  600. goto fail;
  601. }
  602. if (!data || !size) {
  603. goto fail;
  604. }
  605. buffer_data = av_malloc(size);
  606. if (!buffer_data) {
  607. goto fail;
  608. }
  609. memcpy(buffer_data, data, size);
  610. buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
  611. if (!buffer) {
  612. goto fail;
  613. }
  614. (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
  615. if (ff_jni_exception_check(env, 1, format) < 0) {
  616. goto fail;
  617. }
  618. fail:
  619. if (key) {
  620. (*env)->DeleteLocalRef(env, key);
  621. }
  622. if (buffer) {
  623. (*env)->DeleteLocalRef(env, buffer);
  624. }
  625. JNI_DETACH_ENV(attached, format);
  626. }
  627. struct JNIAMediaCodecFields {
  628. jclass mediacodec_class;
  629. jfieldID info_try_again_later_id;
  630. jfieldID info_output_buffers_changed_id;
  631. jfieldID info_output_format_changed_id;
  632. jfieldID buffer_flag_codec_config_id;
  633. jfieldID buffer_flag_end_of_stream_id;
  634. jfieldID buffer_flag_key_frame_id;
  635. jfieldID configure_flag_encode_id;
  636. jmethodID create_by_codec_name_id;
  637. jmethodID create_decoder_by_type_id;
  638. jmethodID create_encoder_by_type_id;
  639. jmethodID get_name_id;
  640. jmethodID configure_id;
  641. jmethodID start_id;
  642. jmethodID flush_id;
  643. jmethodID stop_id;
  644. jmethodID release_id;
  645. jmethodID get_output_format_id;
  646. jmethodID dequeue_input_buffer_id;
  647. jmethodID queue_input_buffer_id;
  648. jmethodID get_input_buffer_id;
  649. jmethodID get_input_buffers_id;
  650. jmethodID dequeue_output_buffer_id;
  651. jmethodID get_output_buffer_id;
  652. jmethodID get_output_buffers_id;
  653. jmethodID release_output_buffer_id;
  654. jmethodID release_output_buffer_at_time_id;
  655. jclass mediainfo_class;
  656. jmethodID init_id;
  657. jfieldID flags_id;
  658. jfieldID offset_id;
  659. jfieldID presentation_time_us_id;
  660. jfieldID size_id;
  661. } JNIAMediaCodecFields;
  662. static const struct FFJniField jni_amediacodec_mapping[] = {
  663. { "android/media/MediaCodec", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediacodec_class), 1 },
  664. { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_try_again_later_id), 1 },
  665. { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_buffers_changed_id), 1 },
  666. { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_format_changed_id), 1 },
  667. { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_codec_config_id), 1 },
  668. { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_end_of_stream_id), 1 },
  669. { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_key_frame_id), 0 },
  670. { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, configure_flag_encode_id), 1 },
  671. { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_by_codec_name_id), 1 },
  672. { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_decoder_by_type_id), 1 },
  673. { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_encoder_by_type_id), 1 },
  674. { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_name_id), 1 },
  675. { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, configure_id), 1 },
  676. { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, start_id), 1 },
  677. { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, flush_id), 1 },
  678. { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, stop_id), 1 },
  679. { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_id), 1 },
  680. { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_format_id), 1 },
  681. { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_input_buffer_id), 1 },
  682. { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, queue_input_buffer_id), 1 },
  683. { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffer_id), 0 },
  684. { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffers_id), 1 },
  685. { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_output_buffer_id), 1 },
  686. { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffer_id), 0 },
  687. { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffers_id), 1 },
  688. { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_id), 1 },
  689. { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_at_time_id), 0 },
  690. { "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediainfo_class), 1 },
  691. { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, init_id), 1 },
  692. { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, flags_id), 1 },
  693. { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, offset_id), 1 },
  694. { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, presentation_time_us_id), 1 },
  695. { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, size_id), 1 },
  696. { NULL }
  697. };
  698. static const AVClass amediacodec_class = {
  699. .class_name = "amediacodec",
  700. .item_name = av_default_item_name,
  701. .version = LIBAVCODEC_VERSION_INT,
  702. };
  703. struct FFAMediaCodec {
  704. const AVClass *class;
  705. struct JNIAMediaCodecFields jfields;
  706. jobject object;
  707. jobject input_buffers;
  708. jobject output_buffers;
  709. int INFO_TRY_AGAIN_LATER;
  710. int INFO_OUTPUT_BUFFERS_CHANGED;
  711. int INFO_OUTPUT_FORMAT_CHANGED;
  712. int BUFFER_FLAG_CODEC_CONFIG;
  713. int BUFFER_FLAG_END_OF_STREAM;
  714. int BUFFER_FLAG_KEY_FRAME;
  715. int CONFIGURE_FLAG_ENCODE;
  716. int has_get_i_o_buffer;
  717. };
  718. FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name)
  719. {
  720. int attached = 0;
  721. JNIEnv *env = NULL;
  722. FFAMediaCodec *codec = NULL;
  723. jstring codec_name = NULL;
  724. codec = av_mallocz(sizeof(FFAMediaCodec));
  725. if (!codec) {
  726. return NULL;
  727. }
  728. codec->class = &amediacodec_class;
  729. env = ff_jni_attach_env(&attached, codec);
  730. if (!env) {
  731. av_freep(&codec);
  732. return NULL;
  733. }
  734. if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
  735. goto fail;
  736. }
  737. codec_name = ff_jni_utf_chars_to_jstring(env, name, codec);
  738. if (!codec_name) {
  739. goto fail;
  740. }
  741. codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_by_codec_name_id, codec_name);
  742. if (ff_jni_exception_check(env, 1, codec) < 0) {
  743. goto fail;
  744. }
  745. codec->object = (*env)->NewGlobalRef(env, codec->object);
  746. if (!codec->object) {
  747. goto fail;
  748. }
  749. codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
  750. if (ff_jni_exception_check(env, 1, codec) < 0) {
  751. goto fail;
  752. }
  753. codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
  754. if (ff_jni_exception_check(env, 1, codec) < 0) {
  755. goto fail;
  756. }
  757. codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
  758. if (ff_jni_exception_check(env, 1, codec) < 0) {
  759. goto fail;
  760. }
  761. if (codec->jfields.buffer_flag_key_frame_id) {
  762. codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
  763. if (ff_jni_exception_check(env, 1, codec) < 0) {
  764. goto fail;
  765. }
  766. }
  767. codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
  768. if (ff_jni_exception_check(env, 1, codec) < 0) {
  769. goto fail;
  770. }
  771. codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
  772. if (ff_jni_exception_check(env, 1, codec) < 0) {
  773. goto fail;
  774. }
  775. codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
  776. if (ff_jni_exception_check(env, 1, codec) < 0) {
  777. goto fail;
  778. }
  779. codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
  780. if (ff_jni_exception_check(env, 1, codec) < 0) {
  781. goto fail;
  782. }
  783. JNI_DETACH_ENV(attached, codec);
  784. return codec;
  785. fail:
  786. ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
  787. if (codec_name) {
  788. (*env)->DeleteLocalRef(env, codec_name);
  789. }
  790. JNI_DETACH_ENV(attached, codec);
  791. av_freep(&codec);
  792. return NULL;
  793. }
  794. FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)
  795. {
  796. int attached = 0;
  797. JNIEnv *env = NULL;
  798. FFAMediaCodec *codec = NULL;
  799. jstring mime_type = NULL;
  800. codec = av_mallocz(sizeof(FFAMediaCodec));
  801. if (!codec) {
  802. return NULL;
  803. }
  804. codec->class = &amediacodec_class;
  805. env = ff_jni_attach_env(&attached, codec);
  806. if (!env) {
  807. av_freep(&codec);
  808. return NULL;
  809. }
  810. if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
  811. goto fail;
  812. }
  813. mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
  814. if (!mime_type) {
  815. goto fail;
  816. }
  817. codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type);
  818. if (ff_jni_exception_check(env, 1, codec) < 0) {
  819. goto fail;
  820. }
  821. codec->object = (*env)->NewGlobalRef(env, codec->object);
  822. if (!codec->object) {
  823. goto fail;
  824. }
  825. codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
  826. if (ff_jni_exception_check(env, 1, codec) < 0) {
  827. goto fail;
  828. }
  829. codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
  830. if (ff_jni_exception_check(env, 1, codec) < 0) {
  831. goto fail;
  832. }
  833. if (codec->jfields.buffer_flag_key_frame_id) {
  834. codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
  835. if (ff_jni_exception_check(env, 1, codec) < 0) {
  836. goto fail;
  837. }
  838. }
  839. codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
  840. if (ff_jni_exception_check(env, 1, codec) < 0) {
  841. goto fail;
  842. }
  843. codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
  844. if (ff_jni_exception_check(env, 1, codec) < 0) {
  845. goto fail;
  846. }
  847. codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
  848. if (ff_jni_exception_check(env, 1, codec) < 0) {
  849. goto fail;
  850. }
  851. codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
  852. if (ff_jni_exception_check(env, 1, codec) < 0) {
  853. goto fail;
  854. }
  855. if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
  856. codec->has_get_i_o_buffer = 1;
  857. }
  858. JNI_DETACH_ENV(attached, codec);
  859. return codec;
  860. fail:
  861. ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
  862. if (mime_type) {
  863. (*env)->DeleteLocalRef(env, mime_type);
  864. }
  865. JNI_DETACH_ENV(attached, codec);
  866. av_freep(&codec);
  867. return NULL;
  868. }
  869. FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime)
  870. {
  871. int attached = 0;
  872. JNIEnv *env = NULL;
  873. FFAMediaCodec *codec = NULL;
  874. jstring mime_type = NULL;
  875. codec = av_mallocz(sizeof(FFAMediaCodec));
  876. if (!codec) {
  877. return NULL;
  878. }
  879. codec->class = &amediacodec_class;
  880. env = ff_jni_attach_env(&attached, codec);
  881. if (!env) {
  882. av_freep(&codec);
  883. return NULL;
  884. }
  885. if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
  886. goto fail;
  887. }
  888. mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
  889. if (!mime_type) {
  890. goto fail;
  891. }
  892. codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_encoder_by_type_id, mime_type);
  893. if (ff_jni_exception_check(env, 1, codec) < 0) {
  894. goto fail;
  895. }
  896. codec->object = (*env)->NewGlobalRef(env, codec->object);
  897. if (!codec->object) {
  898. goto fail;
  899. }
  900. codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
  901. if (ff_jni_exception_check(env, 1, codec) < 0) {
  902. goto fail;
  903. }
  904. codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
  905. if (ff_jni_exception_check(env, 1, codec) < 0) {
  906. goto fail;
  907. }
  908. codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
  909. if (ff_jni_exception_check(env, 1, codec) < 0) {
  910. goto fail;
  911. }
  912. if (codec->jfields.buffer_flag_key_frame_id) {
  913. codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
  914. if (ff_jni_exception_check(env, 1, codec) < 0) {
  915. goto fail;
  916. }
  917. }
  918. codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
  919. if (ff_jni_exception_check(env, 1, codec) < 0) {
  920. goto fail;
  921. }
  922. codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
  923. if (ff_jni_exception_check(env, 1, codec) < 0) {
  924. goto fail;
  925. }
  926. codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
  927. if (ff_jni_exception_check(env, 1, codec) < 0) {
  928. goto fail;
  929. }
  930. codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
  931. if (ff_jni_exception_check(env, 1, codec) < 0) {
  932. goto fail;
  933. }
  934. JNI_DETACH_ENV(attached, NULL);
  935. return codec;
  936. fail:
  937. ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
  938. if (mime_type) {
  939. (*env)->DeleteLocalRef(env, mime_type);
  940. }
  941. JNI_DETACH_ENV(attached, codec);
  942. av_freep(&codec);
  943. return NULL;
  944. }
  945. int ff_AMediaCodec_delete(FFAMediaCodec* codec)
  946. {
  947. int ret = 0;
  948. int attached = 0;
  949. JNIEnv *env = NULL;
  950. if (!codec) {
  951. return 0;
  952. }
  953. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  954. (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
  955. if (ff_jni_exception_check(env, 1, codec) < 0) {
  956. ret = AVERROR_EXTERNAL;
  957. }
  958. (*env)->DeleteGlobalRef(env, codec->object);
  959. codec->object = NULL;
  960. ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
  961. JNI_DETACH_ENV(attached, codec);
  962. av_freep(&codec);
  963. return ret;
  964. }
  965. char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
  966. {
  967. char *ret = NULL;
  968. int attached = 0;
  969. JNIEnv *env = NULL;
  970. jobject *name = NULL;
  971. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
  972. name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
  973. if (ff_jni_exception_check(env, 1, codec) < 0) {
  974. goto fail;
  975. }
  976. ret = ff_jni_jstring_to_utf_chars(env, name, codec);
  977. fail:
  978. JNI_DETACH_ENV(attached, NULL);
  979. return ret;
  980. }
  981. int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
  982. {
  983. int ret = 0;
  984. int attached = 0;
  985. JNIEnv *env = NULL;
  986. /* TODO: implement surface handling */
  987. av_assert0(surface == NULL);
  988. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  989. (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, NULL, NULL, flags);
  990. if (ff_jni_exception_check(env, 1, codec) < 0) {
  991. ret = AVERROR_EXTERNAL;
  992. goto fail;
  993. }
  994. fail:
  995. JNI_DETACH_ENV(attached, NULL);
  996. return ret;
  997. }
  998. int ff_AMediaCodec_start(FFAMediaCodec* codec)
  999. {
  1000. int ret = 0;
  1001. int attached = 0;
  1002. JNIEnv *env = NULL;
  1003. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1004. (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
  1005. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1006. ret = AVERROR_EXTERNAL;
  1007. goto fail;
  1008. }
  1009. fail:
  1010. JNI_DETACH_ENV(attached, codec);
  1011. return ret;
  1012. }
  1013. int ff_AMediaCodec_stop(FFAMediaCodec* codec)
  1014. {
  1015. int ret = 0;
  1016. int attached = 0;
  1017. JNIEnv *env = NULL;
  1018. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1019. (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
  1020. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1021. ret = AVERROR_EXTERNAL;
  1022. goto fail;
  1023. }
  1024. fail:
  1025. JNI_DETACH_ENV(attached, codec);
  1026. return ret;
  1027. }
  1028. int ff_AMediaCodec_flush(FFAMediaCodec* codec)
  1029. {
  1030. int ret = 0;
  1031. int attached = 0;
  1032. JNIEnv *env = NULL;
  1033. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1034. (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
  1035. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1036. ret = AVERROR_EXTERNAL;
  1037. goto fail;
  1038. }
  1039. fail:
  1040. JNI_DETACH_ENV(attached, codec);
  1041. return ret;
  1042. }
  1043. int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
  1044. {
  1045. int ret = 0;
  1046. int attached = 0;
  1047. JNIEnv *env = NULL;
  1048. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1049. (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, idx, render);
  1050. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1051. ret = AVERROR_EXTERNAL;
  1052. goto fail;
  1053. }
  1054. fail:
  1055. JNI_DETACH_ENV(attached, codec);
  1056. return ret;
  1057. }
  1058. int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
  1059. {
  1060. int ret = 0;
  1061. int attached = 0;
  1062. JNIEnv *env = NULL;
  1063. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1064. (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, idx, timestampNs);
  1065. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1066. ret = AVERROR_EXTERNAL;
  1067. goto fail;
  1068. }
  1069. fail:
  1070. JNI_DETACH_ENV(attached, codec);
  1071. return ret;
  1072. }
  1073. ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
  1074. {
  1075. int ret = 0;
  1076. int attached = 0;
  1077. JNIEnv *env = NULL;
  1078. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1079. ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
  1080. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1081. ret = AVERROR_EXTERNAL;
  1082. goto fail;
  1083. }
  1084. fail:
  1085. JNI_DETACH_ENV(attached, codec);
  1086. return ret;
  1087. }
  1088. int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
  1089. {
  1090. int ret = 0;
  1091. int attached = 0;
  1092. JNIEnv *env = NULL;
  1093. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1094. (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, idx, offset, size, time, flags);
  1095. if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
  1096. ret = AVERROR_EXTERNAL;
  1097. goto fail;
  1098. }
  1099. fail:
  1100. JNI_DETACH_ENV(attached, codec);
  1101. return ret;
  1102. }
  1103. ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec* codec, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
  1104. {
  1105. int ret = 0;
  1106. int attached = 0;
  1107. JNIEnv *env = NULL;
  1108. jobject mediainfo = NULL;
  1109. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
  1110. mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
  1111. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1112. ret = AVERROR_EXTERNAL;
  1113. goto fail;
  1114. }
  1115. ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, mediainfo, timeoutUs);
  1116. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1117. ret = AVERROR_EXTERNAL;
  1118. goto fail;
  1119. }
  1120. info->flags = (*env)->GetIntField(env, mediainfo, codec->jfields.flags_id);
  1121. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1122. ret = AVERROR_EXTERNAL;
  1123. goto fail;
  1124. }
  1125. info->offset = (*env)->GetIntField(env, mediainfo, codec->jfields.offset_id);
  1126. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1127. ret = AVERROR_EXTERNAL;
  1128. goto fail;
  1129. }
  1130. info->presentationTimeUs = (*env)->GetLongField(env, mediainfo, codec->jfields.presentation_time_us_id);
  1131. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1132. ret = AVERROR_EXTERNAL;
  1133. goto fail;
  1134. }
  1135. info->size = (*env)->GetIntField(env, mediainfo, codec->jfields.size_id);
  1136. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1137. ret = AVERROR_EXTERNAL;
  1138. goto fail;
  1139. }
  1140. fail:
  1141. if (mediainfo) {
  1142. (*env)->DeleteLocalRef(env, mediainfo);
  1143. }
  1144. JNI_DETACH_ENV(attached, NULL);
  1145. return ret;
  1146. }
  1147. uint8_t* ff_AMediaCodec_getInputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
  1148. {
  1149. uint8_t *ret = NULL;
  1150. int attached = 0;
  1151. JNIEnv *env = NULL;
  1152. jobject buffer = NULL;
  1153. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
  1154. if (codec->has_get_i_o_buffer) {
  1155. buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, idx);
  1156. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1157. goto fail;
  1158. }
  1159. } else {
  1160. if (!codec->input_buffers) {
  1161. codec->input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
  1162. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1163. goto fail;
  1164. }
  1165. codec->input_buffers = (*env)->NewGlobalRef(env, codec->input_buffers);
  1166. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1167. goto fail;
  1168. }
  1169. }
  1170. buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
  1171. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1172. goto fail;
  1173. }
  1174. }
  1175. ret = (*env)->GetDirectBufferAddress(env, buffer);
  1176. *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
  1177. fail:
  1178. if (buffer) {
  1179. (*env)->DeleteLocalRef(env, buffer);
  1180. }
  1181. JNI_DETACH_ENV(attached, codec);
  1182. return ret;
  1183. }
  1184. uint8_t* ff_AMediaCodec_getOutputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
  1185. {
  1186. uint8_t *ret = NULL;
  1187. int attached = 0;
  1188. JNIEnv *env = NULL;
  1189. jobject buffer = NULL;
  1190. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
  1191. if (codec->has_get_i_o_buffer) {
  1192. buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, idx);
  1193. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1194. goto fail;
  1195. }
  1196. } else {
  1197. if (!codec->output_buffers) {
  1198. codec->output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
  1199. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1200. goto fail;
  1201. }
  1202. codec->output_buffers = (*env)->NewGlobalRef(env, codec->output_buffers);
  1203. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1204. goto fail;
  1205. }
  1206. }
  1207. buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
  1208. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1209. goto fail;
  1210. }
  1211. }
  1212. ret = (*env)->GetDirectBufferAddress(env, buffer);
  1213. *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
  1214. fail:
  1215. if (buffer) {
  1216. (*env)->DeleteLocalRef(env, buffer);
  1217. }
  1218. JNI_DETACH_ENV(attached, codec);
  1219. return ret;
  1220. }
  1221. FFAMediaFormat* ff_AMediaCodec_getOutputFormat(FFAMediaCodec* codec)
  1222. {
  1223. FFAMediaFormat *ret = NULL;
  1224. int attached = 0;
  1225. JNIEnv *env = NULL;
  1226. jobject mediaformat = NULL;
  1227. JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
  1228. mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
  1229. if (ff_jni_exception_check(env, 1, codec) < 0) {
  1230. goto fail;
  1231. }
  1232. ret = ff_AMediaFormat_newFromObject(mediaformat);
  1233. fail:
  1234. if (mediaformat) {
  1235. (*env)->DeleteLocalRef(env, mediaformat);
  1236. }
  1237. JNI_DETACH_ENV(attached, codec);
  1238. return ret;
  1239. }
  1240. int ff_AMediaCodec_infoTryAgainLater(FFAMediaCodec *codec, ssize_t idx)
  1241. {
  1242. return idx == codec->INFO_TRY_AGAIN_LATER;
  1243. }
  1244. int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec *codec, ssize_t idx)
  1245. {
  1246. return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
  1247. }
  1248. int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
  1249. {
  1250. return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
  1251. }
  1252. int ff_AMediaCodec_getBufferFlagCodecConfig(FFAMediaCodec *codec)
  1253. {
  1254. return codec->BUFFER_FLAG_CODEC_CONFIG;
  1255. }
  1256. int ff_AMediaCodec_getBufferFlagEndOfStream(FFAMediaCodec *codec)
  1257. {
  1258. return codec->BUFFER_FLAG_END_OF_STREAM;
  1259. }
  1260. int ff_AMediaCodec_getBufferFlagKeyFrame(FFAMediaCodec *codec)
  1261. {
  1262. return codec->BUFFER_FLAG_KEY_FRAME;
  1263. }
  1264. int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec)
  1265. {
  1266. return codec->CONFIGURE_FLAG_ENCODE;
  1267. }
  1268. int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
  1269. {
  1270. int ret = 0;
  1271. if (!codec->has_get_i_o_buffer) {
  1272. if (codec->output_buffers) {
  1273. int attached = 0;
  1274. JNIEnv *env = NULL;
  1275. env = ff_jni_attach_env(&attached, codec);
  1276. if (!env) {
  1277. ret = AVERROR_EXTERNAL;
  1278. goto fail;
  1279. }
  1280. (*env)->DeleteGlobalRef(env, codec->output_buffers);
  1281. codec->output_buffers = NULL;
  1282. JNI_DETACH_ENV(attached, codec);
  1283. }
  1284. }
  1285. fail:
  1286. return ret;
  1287. }