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.

1809 lines
54KB

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