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.

1655 lines
47KB

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