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.

1740 lines
52KB

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