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.

1684 lines
50KB

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