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.

1714 lines
53KB

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