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.

1655 lines
47KB

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