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.

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