FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mediacodec_wrapper.c
Go to the documentation of this file.
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 
23 #include <jni.h>
24 
25 #include "libavutil/avassert.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/avstring.h"
28 
29 #include "avcodec.h"
30 #include "ffjni.h"
31 #include "version.h"
32 #include "mediacodec_wrapper.h"
33 
35 
37  jmethodID init_id;
39 
40  jmethodID get_codec_count_id;
42 
44  jmethodID get_name_id;
47  jmethodID is_encoder_id;
48 
50  jfieldID color_formats_id;
52 
54  jfieldID profile_id;
55  jfieldID level_id;
56 
64 
68 
69 };
70 
71 static const struct FFJniField jni_amediacodeclist_mapping[] = {
72  { "android/media/MediaCodecList", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_list_class), 1 },
73  { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, init_id), 0 },
74  { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, find_decoder_for_format_id), 0 },
75 
76  { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_count_id), 1 },
77  { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_info_at_id), 1 },
78 
79  { "android/media/MediaCodecInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_info_class), 1 },
80  { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_name_id), 1 },
81  { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_capabilities_id), 1 },
82  { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_supported_types_id), 1 },
83  { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_encoder_id), 1 },
84 
85  { "android/media/MediaCodecInfo$CodecCapabilities", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_capabilities_class), 1 },
86  { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, color_formats_id), 1 },
87  { "android/media/MediaCodecInfo$CodecCapabilities", "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_levels_id), 1 },
88 
89  { "android/media/MediaCodecInfo$CodecProfileLevel", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_profile_level_class), 1 },
90  { "android/media/MediaCodecInfo$CodecProfileLevel", "profile", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_id), 1 },
91  { "android/media/MediaCodecInfo$CodecProfileLevel", "level", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, level_id), 1 },
92 
93  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileBaseline", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_baseline_id), 1 },
94  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileMain", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_main_id), 1 },
95  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileExtended", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_extended_id), 1 },
96  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high_id), 1 },
97  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high10_id), 1 },
98  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh422", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high422_id), 1 },
99  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh444", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high444_id), 1 },
100 
101  { "android/media/MediaCodecInfo$CodecProfileLevel", "HEVCProfileMain", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, hevc_profile_main_id), 0 },
102  { "android/media/MediaCodecInfo$CodecProfileLevel", "HEVCProfileMain10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, hevc_profile_main10_id), 0 },
103  { "android/media/MediaCodecInfo$CodecProfileLevel", "HEVCProfileMain10HDR10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, hevc_profile_main10_hdr10_id), 0 },
104 
105  { NULL }
106 };
107 
109 
111 
112  jmethodID init_id;
113 
114  jmethodID contains_key_id;
115 
116  jmethodID get_integer_id;
117  jmethodID get_long_id;
118  jmethodID get_float_id;
119  jmethodID get_bytebuffer_id;
120  jmethodID get_string_id;
121 
122  jmethodID set_integer_id;
123  jmethodID set_long_id;
124  jmethodID set_float_id;
125  jmethodID set_bytebuffer_id;
126  jmethodID set_string_id;
127 
128  jmethodID to_string_id;
129 
130 };
131 
132 static const struct FFJniField jni_amediaformat_mapping[] = {
133  { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaFormatFields, mediaformat_class), 1 },
134 
135  { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, init_id), 1 },
136 
137  { "android/media/MediaFormat", "containsKey", "(Ljava/lang/String;)Z", FF_JNI_METHOD,offsetof(struct JNIAMediaFormatFields, contains_key_id), 1 },
138 
139  { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_integer_id), 1 },
140  { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_long_id), 1 },
141  { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_float_id), 1 },
142  { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_bytebuffer_id), 1 },
143  { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_string_id), 1 },
144 
145  { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_integer_id), 1 },
146  { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_long_id), 1 },
147  { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_float_id), 1 },
148  { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_bytebuffer_id), 1 },
149  { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_string_id), 1 },
150 
151  { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, to_string_id), 1 },
152 
153  { NULL }
154 };
155 
156 static const AVClass amediaformat_class = {
157  .class_name = "amediaformat",
158  .item_name = av_default_item_name,
159  .version = LIBAVUTIL_VERSION_INT,
160 };
161 
163 
164  const AVClass *class;
166  jobject object;
167 };
168 
170 
172 
176 
180 
182 
186 
187  jmethodID get_name_id;
188 
189  jmethodID configure_id;
190  jmethodID start_id;
191  jmethodID flush_id;
192  jmethodID stop_id;
193  jmethodID release_id;
194 
196 
201 
207 
209 
210  jmethodID init_id;
211 
212  jfieldID flags_id;
213  jfieldID offset_id;
215  jfieldID size_id;
216 
217 };
218 
219 static const struct FFJniField jni_amediacodec_mapping[] = {
220  { "android/media/MediaCodec", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediacodec_class), 1 },
221 
222  { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_try_again_later_id), 1 },
223  { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_buffers_changed_id), 1 },
224  { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_format_changed_id), 1 },
225 
226  { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_codec_config_id), 1 },
227  { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_end_of_stream_id), 1 },
228  { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_key_frame_id), 0 },
229 
230  { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, configure_flag_encode_id), 1 },
231 
232  { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_by_codec_name_id), 1 },
233  { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_decoder_by_type_id), 1 },
234  { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_encoder_by_type_id), 1 },
235 
236  { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_name_id), 1 },
237 
238  { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, configure_id), 1 },
239  { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, start_id), 1 },
240  { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, flush_id), 1 },
241  { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, stop_id), 1 },
242  { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_id), 1 },
243 
244  { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_format_id), 1 },
245 
246  { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_input_buffer_id), 1 },
247  { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, queue_input_buffer_id), 1 },
248  { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffer_id), 0 },
249  { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffers_id), 1 },
250 
251  { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_output_buffer_id), 1 },
252  { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffer_id), 0 },
253  { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffers_id), 1 },
254  { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_id), 1 },
255  { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_at_time_id), 0 },
256 
257  { "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediainfo_class), 1 },
258 
259  { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, init_id), 1 },
260  { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, flags_id), 1 },
261  { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, offset_id), 1 },
262  { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, presentation_time_us_id), 1 },
263  { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, size_id), 1 },
264 
265  { NULL }
266 };
267 
268 static const AVClass amediacodec_class = {
269  .class_name = "amediacodec",
270  .item_name = av_default_item_name,
271  .version = LIBAVUTIL_VERSION_INT,
272 };
273 
275 
276  const AVClass *class;
277 
279 
280  jobject object;
281  jobject buffer_info;
282 
283  jobject input_buffers;
284  jobject output_buffers;
285 
289 
293 
295 
297 };
298 
299 #define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do { \
300  (env) = ff_jni_get_env(log_ctx); \
301  if (!(env)) { \
302  return ret; \
303  } \
304 } while (0)
305 
306 #define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do { \
307  (env) = ff_jni_get_env(log_ctx); \
308  if (!(env)) { \
309  return; \
310  } \
311 } while (0)
312 
314 {
315  int ret = -1;
316 
317  JNIEnv *env = NULL;
318  struct JNIAMediaCodecListFields jfields = { 0 };
319  jfieldID field_id = 0;
320 
321  JNI_GET_ENV_OR_RETURN(env, avctx, -1);
322 
323  if (ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx) < 0) {
324  goto done;
325  }
326 
327  if (avctx->codec_id == AV_CODEC_ID_H264) {
328  switch(avctx->profile) {
331  field_id = jfields.avc_profile_baseline_id;
332  break;
334  field_id = jfields.avc_profile_main_id;
335  break;
337  field_id = jfields.avc_profile_extended_id;
338  break;
340  field_id = jfields.avc_profile_high_id;
341  break;
344  field_id = jfields.avc_profile_high10_id;
345  break;
348  field_id = jfields.avc_profile_high422_id;
349  break;
353  field_id = jfields.avc_profile_high444_id;
354  break;
355  }
356  } else if (avctx->codec_id == AV_CODEC_ID_HEVC) {
357  switch (avctx->profile) {
360  field_id = jfields.hevc_profile_main_id;
361  break;
363  field_id = jfields.hevc_profile_main10_id;
364  break;
365  }
366  }
367 
368  if (field_id) {
369  ret = (*env)->GetStaticIntField(env, jfields.codec_profile_level_class, field_id);
370  if (ff_jni_exception_check(env, 1, avctx) < 0) {
371  ret = -1;
372  goto done;
373  }
374  }
375 
376 done:
377  ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx);
378 
379  return ret;
380 }
381 
382 char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
383 {
384  int ret;
385  int i;
386  int codec_count;
387  int found_codec = 0;
388  char *name = NULL;
389  char *supported_type = NULL;
390 
391  JNIEnv *env = NULL;
392  struct JNIAMediaCodecListFields jfields = { 0 };
393  struct JNIAMediaFormatFields mediaformat_jfields = { 0 };
394 
395  jobject format = NULL;
396  jobject codec = NULL;
397  jobject codec_name = NULL;
398 
399  jobject info = NULL;
400  jobject type = NULL;
401  jobjectArray types = NULL;
402 
403  jobject capabilities = NULL;
404  jobject profile_level = NULL;
405  jobjectArray profile_levels = NULL;
406 
407  JNI_GET_ENV_OR_RETURN(env, log_ctx, NULL);
408 
409  if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
410  goto done;
411  }
412 
413  if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) {
414  goto done;
415  }
416 
417  codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
418  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
419  goto done;
420  }
421 
422  for(i = 0; i < codec_count; i++) {
423  int j;
424  int type_count;
425  int is_encoder;
426 
427  info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
428  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
429  goto done;
430  }
431 
432  types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
433  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
434  goto done;
435  }
436 
437  is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
438  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
439  goto done;
440  }
441 
442  if (is_encoder != encoder) {
443  goto done_with_info;
444  }
445 
446  type_count = (*env)->GetArrayLength(env, types);
447  for (j = 0; j < type_count; j++) {
448  int k;
449  int profile_count;
450 
451  type = (*env)->GetObjectArrayElement(env, types, j);
452  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
453  goto done;
454  }
455 
456  supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
457  if (!supported_type) {
458  goto done;
459  }
460 
461  if (!av_strcasecmp(supported_type, mime)) {
462  codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
463  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
464  goto done;
465  }
466 
467  name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
468  if (!name) {
469  goto done;
470  }
471 
472  /* Skip software decoders */
473  if (
474  strstr(name, "OMX.google") ||
475  strstr(name, "OMX.ffmpeg") ||
476  (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) ||
477  !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) {
478  av_freep(&name);
479  goto done_with_type;
480  }
481 
482  capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type);
483  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
484  goto done;
485  }
486 
487  profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id);
488  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
489  goto done;
490  }
491 
492  profile_count = (*env)->GetArrayLength(env, profile_levels);
493  if (!profile_count) {
494  found_codec = 1;
495  }
496  for (k = 0; k < profile_count; k++) {
497  int supported_profile = 0;
498 
499  if (profile < 0) {
500  found_codec = 1;
501  break;
502  }
503 
504  profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k);
505  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
506  goto done;
507  }
508 
509  supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id);
510  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
511  goto done;
512  }
513 
514  found_codec = profile == supported_profile;
515 
516  if (profile_level) {
517  (*env)->DeleteLocalRef(env, profile_level);
518  profile_level = NULL;
519  }
520 
521  if (found_codec) {
522  break;
523  }
524  }
525  }
526 
527 done_with_type:
528  if (profile_levels) {
529  (*env)->DeleteLocalRef(env, profile_levels);
530  profile_levels = NULL;
531  }
532 
533  if (capabilities) {
534  (*env)->DeleteLocalRef(env, capabilities);
535  capabilities = NULL;
536  }
537 
538  if (type) {
539  (*env)->DeleteLocalRef(env, type);
540  type = NULL;
541  }
542 
543  av_freep(&supported_type);
544 
545  if (found_codec) {
546  break;
547  }
548 
549  av_freep(&name);
550  }
551 
552 done_with_info:
553  if (info) {
554  (*env)->DeleteLocalRef(env, info);
555  info = NULL;
556  }
557 
558  if (types) {
559  (*env)->DeleteLocalRef(env, types);
560  types = NULL;
561  }
562 
563  if (found_codec) {
564  break;
565  }
566  }
567 
568 done:
569  if (format) {
570  (*env)->DeleteLocalRef(env, format);
571  }
572 
573  if (codec) {
574  (*env)->DeleteLocalRef(env, codec);
575  }
576 
577  if (codec_name) {
578  (*env)->DeleteLocalRef(env, codec_name);
579  }
580 
581  if (info) {
582  (*env)->DeleteLocalRef(env, info);
583  }
584 
585  if (type) {
586  (*env)->DeleteLocalRef(env, type);
587  }
588 
589  if (types) {
590  (*env)->DeleteLocalRef(env, types);
591  }
592 
593  if (capabilities) {
594  (*env)->DeleteLocalRef(env, capabilities);
595  }
596 
597  if (profile_level) {
598  (*env)->DeleteLocalRef(env, profile_level);
599  }
600 
601  if (profile_levels) {
602  (*env)->DeleteLocalRef(env, profile_levels);
603  }
604 
605  av_freep(&supported_type);
606 
607  ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
608  ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
609 
610  if (!found_codec) {
611  av_freep(&name);
612  }
613 
614  return name;
615 }
616 
618 {
619  JNIEnv *env = NULL;
621  jobject object = NULL;
622 
623  format = av_mallocz(sizeof(FFAMediaFormat));
624  if (!format) {
625  return NULL;
626  }
627  format->class = &amediaformat_class;
628 
629  env = ff_jni_get_env(format);
630  if (!env) {
631  av_freep(&format);
632  return NULL;
633  }
634 
635  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
636  goto fail;
637  }
638 
639  object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
640  if (!object) {
641  goto fail;
642  }
643 
644  format->object = (*env)->NewGlobalRef(env, object);
645  if (!format->object) {
646  goto fail;
647  }
648 
649 fail:
650  if (object) {
651  (*env)->DeleteLocalRef(env, object);
652  }
653 
654  if (!format->object) {
655  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
656  av_freep(&format);
657  }
658 
659  return format;
660 }
661 
663 {
664  JNIEnv *env = NULL;
666 
667  format = av_mallocz(sizeof(FFAMediaFormat));
668  if (!format) {
669  return NULL;
670  }
671  format->class = &amediaformat_class;
672 
673  env = ff_jni_get_env(format);
674  if (!env) {
675  av_freep(&format);
676  return NULL;
677  }
678 
679  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
680  goto fail;
681  }
682 
683  format->object = (*env)->NewGlobalRef(env, object);
684  if (!format->object) {
685  goto fail;
686  }
687 
688  return format;
689 fail:
690  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
691 
692  av_freep(&format);
693 
694  return NULL;
695 }
696 
698 {
699  int ret = 0;
700 
701  JNIEnv *env = NULL;
702 
703  if (!format) {
704  return 0;
705  }
706 
708 
709  (*env)->DeleteGlobalRef(env, format->object);
710  format->object = NULL;
711 
712  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
713 
714  av_freep(&format);
715 
716  return ret;
717 }
718 
720 {
721  char *ret = NULL;
722 
723  JNIEnv *env = NULL;
724  jstring description = NULL;
725 
726  av_assert0(format != NULL);
727 
728  JNI_GET_ENV_OR_RETURN(env, format, NULL);
729 
730  description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
731  if (ff_jni_exception_check(env, 1, NULL) < 0) {
732  goto fail;
733  }
734 
735  ret = ff_jni_jstring_to_utf_chars(env, description, format);
736 fail:
737  if (description) {
738  (*env)->DeleteLocalRef(env, description);
739  }
740 
741  return ret;
742 }
743 
745 {
746  int ret = 1;
747 
748  JNIEnv *env = NULL;
749  jstring key = NULL;
750  jboolean contains_key;
751 
752  av_assert0(format != NULL);
753 
754  JNI_GET_ENV_OR_RETURN(env, format, 0);
755 
756  key = ff_jni_utf_chars_to_jstring(env, name, format);
757  if (!key) {
758  ret = 0;
759  goto fail;
760  }
761 
762  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
763  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
764  ret = 0;
765  goto fail;
766  }
767 
768  *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
769  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
770  ret = 0;
771  goto fail;
772  }
773 
774  ret = 1;
775 fail:
776  if (key) {
777  (*env)->DeleteLocalRef(env, key);
778  }
779 
780  return ret;
781 }
782 
784 {
785  int ret = 1;
786 
787  JNIEnv *env = NULL;
788  jstring key = NULL;
789  jboolean contains_key;
790 
791  av_assert0(format != NULL);
792 
793  JNI_GET_ENV_OR_RETURN(env, format, 0);
794 
795  key = ff_jni_utf_chars_to_jstring(env, name, format);
796  if (!key) {
797  ret = 0;
798  goto fail;
799  }
800 
801  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
802  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
803  ret = 0;
804  goto fail;
805  }
806 
807  *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
808  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
809  ret = 0;
810  goto fail;
811  }
812 
813  ret = 1;
814 fail:
815  if (key) {
816  (*env)->DeleteLocalRef(env, key);
817  }
818 
819  return ret;
820 }
821 
823 {
824  int ret = 1;
825 
826  JNIEnv *env = NULL;
827  jstring key = NULL;
828  jboolean contains_key;
829 
830  av_assert0(format != NULL);
831 
832  JNI_GET_ENV_OR_RETURN(env, format, 0);
833 
834  key = ff_jni_utf_chars_to_jstring(env, name, format);
835  if (!key) {
836  ret = 0;
837  goto fail;
838  }
839 
840  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
841  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
842  ret = 0;
843  goto fail;
844  }
845 
846  *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
847  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
848  ret = 0;
849  goto fail;
850  }
851 
852  ret = 1;
853 fail:
854  if (key) {
855  (*env)->DeleteLocalRef(env, key);
856  }
857 
858  return ret;
859 }
860 
861 int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
862 {
863  int ret = 1;
864 
865  JNIEnv *env = NULL;
866  jstring key = NULL;
867  jboolean contains_key;
868  jobject result = NULL;
869 
870  av_assert0(format != NULL);
871 
872  JNI_GET_ENV_OR_RETURN(env, format, 0);
873 
874  key = ff_jni_utf_chars_to_jstring(env, name, format);
875  if (!key) {
876  ret = 0;
877  goto fail;
878  }
879 
880  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
881  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
882  ret = 0;
883  goto fail;
884  }
885 
886  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
887  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
888  ret = 0;
889  goto fail;
890  }
891 
892  *data = (*env)->GetDirectBufferAddress(env, result);
893  *size = (*env)->GetDirectBufferCapacity(env, result);
894 
895  if (*data && *size) {
896  void *src = *data;
897  *data = av_malloc(*size);
898  if (!*data) {
899  ret = 0;
900  goto fail;
901  }
902 
903  memcpy(*data, src, *size);
904  }
905 
906  ret = 1;
907 fail:
908  if (key) {
909  (*env)->DeleteLocalRef(env, key);
910  }
911 
912  if (result) {
913  (*env)->DeleteLocalRef(env, result);
914  }
915 
916  return ret;
917 }
918 
919 int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
920 {
921  int ret = 1;
922 
923  JNIEnv *env = NULL;
924  jstring key = NULL;
925  jboolean contains_key;
926  jstring result = NULL;
927 
928  av_assert0(format != NULL);
929 
930  JNI_GET_ENV_OR_RETURN(env, format, 0);
931 
932  key = ff_jni_utf_chars_to_jstring(env, name, format);
933  if (!key) {
934  ret = 0;
935  goto fail;
936  }
937 
938  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
939  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
940  ret = 0;
941  goto fail;
942  }
943 
944  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
945  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
946  ret = 0;
947  goto fail;
948  }
949 
950  *out = ff_jni_jstring_to_utf_chars(env, result, format);
951  if (!*out) {
952  ret = 0;
953  goto fail;
954  }
955 
956  ret = 1;
957 fail:
958  if (key) {
959  (*env)->DeleteLocalRef(env, key);
960  }
961 
962  if (result) {
963  (*env)->DeleteLocalRef(env, result);
964  }
965 
966  return ret;
967 }
968 
970 {
971  JNIEnv *env = NULL;
972  jstring key = NULL;
973 
974  av_assert0(format != NULL);
975 
976  JNI_GET_ENV_OR_RETURN_VOID(env, format);
977 
978  key = ff_jni_utf_chars_to_jstring(env, name, format);
979  if (!key) {
980  goto fail;
981  }
982 
983  (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
984  if (ff_jni_exception_check(env, 1, format) < 0) {
985  goto fail;
986  }
987 
988 fail:
989  if (key) {
990  (*env)->DeleteLocalRef(env, key);
991  }
992 }
993 
995 {
996  JNIEnv *env = NULL;
997  jstring key = NULL;
998 
999  av_assert0(format != NULL);
1000 
1001  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1002 
1003  key = ff_jni_utf_chars_to_jstring(env, name, format);
1004  if (!key) {
1005  goto fail;
1006  }
1007 
1008  (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
1009  if (ff_jni_exception_check(env, 1, format) < 0) {
1010  goto fail;
1011  }
1012 
1013 fail:
1014  if (key) {
1015  (*env)->DeleteLocalRef(env, key);
1016  }
1017 }
1018 
1020 {
1021  JNIEnv *env = NULL;
1022  jstring key = NULL;
1023 
1024  av_assert0(format != NULL);
1025 
1026  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1027 
1028  key = ff_jni_utf_chars_to_jstring(env, name, format);
1029  if (!key) {
1030  goto fail;
1031  }
1032 
1033  (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
1034  if (ff_jni_exception_check(env, 1, format) < 0) {
1035  goto fail;
1036  }
1037 
1038 fail:
1039  if (key) {
1040  (*env)->DeleteLocalRef(env, key);
1041  }
1042 }
1043 
1045 {
1046  JNIEnv *env = NULL;
1047  jstring key = NULL;
1048  jstring string = NULL;
1049 
1050  av_assert0(format != NULL);
1051 
1052  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1053 
1054  key = ff_jni_utf_chars_to_jstring(env, name, format);
1055  if (!key) {
1056  goto fail;
1057  }
1058 
1059  string = ff_jni_utf_chars_to_jstring(env, value, format);
1060  if (!string) {
1061  goto fail;
1062  }
1063 
1064  (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
1065  if (ff_jni_exception_check(env, 1, format) < 0) {
1066  goto fail;
1067  }
1068 
1069 fail:
1070  if (key) {
1071  (*env)->DeleteLocalRef(env, key);
1072  }
1073 
1074  if (string) {
1075  (*env)->DeleteLocalRef(env, string);
1076  }
1077 }
1078 
1079 void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
1080 {
1081  JNIEnv *env = NULL;
1082  jstring key = NULL;
1083  jobject buffer = NULL;
1084  void *buffer_data = NULL;
1085 
1086  av_assert0(format != NULL);
1087 
1088  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1089 
1090  key = ff_jni_utf_chars_to_jstring(env, name, format);
1091  if (!key) {
1092  goto fail;
1093  }
1094 
1095  if (!data || !size) {
1096  goto fail;
1097  }
1098 
1099  buffer_data = av_malloc(size);
1100  if (!buffer_data) {
1101  goto fail;
1102  }
1103 
1104  memcpy(buffer_data, data, size);
1105 
1106  buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
1107  if (!buffer) {
1108  goto fail;
1109  }
1110 
1111  (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
1112  if (ff_jni_exception_check(env, 1, format) < 0) {
1113  goto fail;
1114  }
1115 
1116 fail:
1117  if (key) {
1118  (*env)->DeleteLocalRef(env, key);
1119  }
1120 
1121  if (buffer) {
1122  (*env)->DeleteLocalRef(env, buffer);
1123  }
1124 }
1125 
1127 {
1128  int ret = 0;
1129  JNIEnv *env = NULL;
1130 
1132 
1133  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1134  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1135  goto fail;
1136  }
1137 
1138  codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
1139  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1140  goto fail;
1141  }
1142 
1143  codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
1144  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1145  goto fail;
1146  }
1147 
1148  if (codec->jfields.buffer_flag_key_frame_id) {
1149  codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
1150  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1151  goto fail;
1152  }
1153  }
1154 
1155  codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
1156  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1157  goto fail;
1158  }
1159 
1160  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1161  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1162  goto fail;
1163  }
1164 
1165  codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
1166  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1167  goto fail;
1168  }
1169 
1170  codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
1171  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1172  goto fail;
1173  }
1174 
1175 fail:
1176 
1177  return ret;
1178 }
1179 
1180 #define CREATE_CODEC_BY_NAME 0
1181 #define CREATE_DECODER_BY_TYPE 1
1182 #define CREATE_ENCODER_BY_TYPE 2
1183 
1184 static inline FFAMediaCodec *codec_create(int method, const char *arg)
1185 {
1186  int ret = -1;
1187  JNIEnv *env = NULL;
1188  FFAMediaCodec *codec = NULL;
1189  jstring jarg = NULL;
1190  jobject object = NULL;
1191  jobject buffer_info = NULL;
1192  jmethodID create_id = NULL;
1193 
1194  codec = av_mallocz(sizeof(FFAMediaCodec));
1195  if (!codec) {
1196  return NULL;
1197  }
1198  codec->class = &amediacodec_class;
1199 
1200  env = ff_jni_get_env(codec);
1201  if (!env) {
1202  av_freep(&codec);
1203  return NULL;
1204  }
1205 
1206  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1207  goto fail;
1208  }
1209 
1210  jarg = ff_jni_utf_chars_to_jstring(env, arg, codec);
1211  if (!jarg) {
1212  goto fail;
1213  }
1214 
1215  switch (method) {
1216  case CREATE_CODEC_BY_NAME: create_id = codec->jfields.create_by_codec_name_id; break;
1217  case CREATE_DECODER_BY_TYPE: create_id = codec->jfields.create_decoder_by_type_id; break;
1218  case CREATE_ENCODER_BY_TYPE: create_id = codec->jfields.create_encoder_by_type_id; break;
1219  default:
1220  av_assert0(0);
1221  }
1222 
1223  object = (*env)->CallStaticObjectMethod(env,
1224  codec->jfields.mediacodec_class,
1225  create_id,
1226  jarg);
1227  if (ff_jni_exception_check(env, 1, codec) < 0) {
1228  goto fail;
1229  }
1230 
1231  codec->object = (*env)->NewGlobalRef(env, object);
1232  if (!codec->object) {
1233  goto fail;
1234  }
1235 
1236  if (codec_init_static_fields(codec) < 0) {
1237  goto fail;
1238  }
1239 
1241  codec->has_get_i_o_buffer = 1;
1242  }
1243 
1244  buffer_info = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
1245  if (ff_jni_exception_check(env, 1, codec) < 0) {
1246  goto fail;
1247  }
1248 
1249  codec->buffer_info = (*env)->NewGlobalRef(env, buffer_info);
1250  if (!codec->buffer_info) {
1251  goto fail;
1252  }
1253 
1254  ret = 0;
1255 fail:
1256  if (jarg) {
1257  (*env)->DeleteLocalRef(env, jarg);
1258  }
1259 
1260  if (object) {
1261  (*env)->DeleteLocalRef(env, object);
1262  }
1263 
1264  if (buffer_info) {
1265  (*env)->DeleteLocalRef(env, buffer_info);
1266  }
1267 
1268  if (ret < 0) {
1269  if (codec->object) {
1270  (*env)->DeleteGlobalRef(env, codec->object);
1271  }
1272 
1273  if (codec->buffer_info) {
1274  (*env)->DeleteGlobalRef(env, codec->buffer_info);
1275  }
1276 
1277  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1278  av_freep(&codec);
1279  }
1280 
1281  return codec;
1282 }
1283 
1284 #define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \
1285 FFAMediaCodec *ff_AMediaCodec_##name(const char *arg) \
1286 { \
1287  return codec_create(method, arg); \
1288 } \
1289 
1293 
1295 {
1296  int ret = 0;
1297 
1298  JNIEnv *env = NULL;
1299 
1300  if (!codec) {
1301  return 0;
1302  }
1303 
1305 
1306  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
1307  if (ff_jni_exception_check(env, 1, codec) < 0) {
1308  ret = AVERROR_EXTERNAL;
1309  }
1310 
1311  (*env)->DeleteGlobalRef(env, codec->object);
1312  codec->object = NULL;
1313 
1314  (*env)->DeleteGlobalRef(env, codec->buffer_info);
1315  codec->buffer_info = NULL;
1316 
1317  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1318 
1319  av_freep(&codec);
1320 
1321  return ret;
1322 }
1323 
1325 {
1326  char *ret = NULL;
1327  JNIEnv *env = NULL;
1328  jobject *name = NULL;
1329 
1330  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1331 
1332  name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1333  if (ff_jni_exception_check(env, 1, codec) < 0) {
1334  goto fail;
1335  }
1336 
1337  ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1338 
1339 fail:
1340  return ret;
1341 }
1342 
1343 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
1344 {
1345  int ret = 0;
1346  JNIEnv *env = NULL;
1347 
1349 
1350  (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
1351  if (ff_jni_exception_check(env, 1, codec) < 0) {
1352  ret = AVERROR_EXTERNAL;
1353  goto fail;
1354  }
1355 
1356 fail:
1357  return ret;
1358 }
1359 
1361 {
1362  int ret = 0;
1363  JNIEnv *env = NULL;
1364 
1366 
1367  (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1368  if (ff_jni_exception_check(env, 1, codec) < 0) {
1369  ret = AVERROR_EXTERNAL;
1370  goto fail;
1371  }
1372 
1373 fail:
1374  return ret;
1375 }
1376 
1378 {
1379  int ret = 0;
1380  JNIEnv *env = NULL;
1381 
1383 
1384  (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1385  if (ff_jni_exception_check(env, 1, codec) < 0) {
1386  ret = AVERROR_EXTERNAL;
1387  goto fail;
1388  }
1389 
1390 fail:
1391  return ret;
1392 }
1393 
1395 {
1396  int ret = 0;
1397  JNIEnv *env = NULL;
1398 
1400 
1401  (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1402  if (ff_jni_exception_check(env, 1, codec) < 0) {
1403  ret = AVERROR_EXTERNAL;
1404  goto fail;
1405  }
1406 
1407 fail:
1408  return ret;
1409 }
1410 
1411 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
1412 {
1413  int ret = 0;
1414  JNIEnv *env = NULL;
1415 
1417 
1418  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, (jint)idx, (jboolean)render);
1419  if (ff_jni_exception_check(env, 1, codec) < 0) {
1420  ret = AVERROR_EXTERNAL;
1421  goto fail;
1422  }
1423 
1424 fail:
1425  return ret;
1426 }
1427 
1428 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
1429 {
1430  int ret = 0;
1431  JNIEnv *env = NULL;
1432 
1434 
1435  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs);
1436  if (ff_jni_exception_check(env, 1, codec) < 0) {
1437  ret = AVERROR_EXTERNAL;
1438  goto fail;
1439  }
1440 
1441 fail:
1442  return ret;
1443 }
1444 
1445 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
1446 {
1447  int ret = 0;
1448  JNIEnv *env = NULL;
1449 
1451 
1452  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1453  if (ff_jni_exception_check(env, 1, codec) < 0) {
1454  ret = AVERROR_EXTERNAL;
1455  goto fail;
1456  }
1457 
1458 fail:
1459  return ret;
1460 }
1461 
1462 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1463 {
1464  int ret = 0;
1465  JNIEnv *env = NULL;
1466 
1468 
1469  (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, (jint)idx, (jint)offset, (jint)size, time, flags);
1470  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1471  ret = AVERROR_EXTERNAL;
1472  goto fail;
1473  }
1474 
1475 fail:
1476  return ret;
1477 }
1478 
1480 {
1481  int ret = 0;
1482  JNIEnv *env = NULL;
1483 
1485 
1486  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs);
1487  if (ff_jni_exception_check(env, 1, codec) < 0) {
1488  return AVERROR_EXTERNAL;
1489  }
1490 
1491  info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id);
1492  if (ff_jni_exception_check(env, 1, codec) < 0) {
1493  return AVERROR_EXTERNAL;
1494  }
1495 
1496  info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id);
1497  if (ff_jni_exception_check(env, 1, codec) < 0) {
1498  return AVERROR_EXTERNAL;
1499  }
1500 
1501  info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id);
1502  if (ff_jni_exception_check(env, 1, codec) < 0) {
1503  return AVERROR_EXTERNAL;
1504  }
1505 
1506  info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id);
1507  if (ff_jni_exception_check(env, 1, codec) < 0) {
1508  return AVERROR_EXTERNAL;
1509  }
1510 
1511  return ret;
1512 }
1513 
1515 {
1516  uint8_t *ret = NULL;
1517  JNIEnv *env = NULL;
1518 
1519  jobject buffer = NULL;
1520  jobject input_buffers = NULL;
1521 
1522  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1523 
1524  if (codec->has_get_i_o_buffer) {
1525  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, (jint)idx);
1526  if (ff_jni_exception_check(env, 1, codec) < 0) {
1527  goto fail;
1528  }
1529  } else {
1530  if (!codec->input_buffers) {
1531  input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1532  if (ff_jni_exception_check(env, 1, codec) < 0) {
1533  goto fail;
1534  }
1535 
1536  codec->input_buffers = (*env)->NewGlobalRef(env, input_buffers);
1537  if (ff_jni_exception_check(env, 1, codec) < 0) {
1538  goto fail;
1539  }
1540  }
1541 
1542  buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1543  if (ff_jni_exception_check(env, 1, codec) < 0) {
1544  goto fail;
1545  }
1546  }
1547 
1548  ret = (*env)->GetDirectBufferAddress(env, buffer);
1549  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1550 fail:
1551  if (buffer) {
1552  (*env)->DeleteLocalRef(env, buffer);
1553  }
1554 
1555  if (input_buffers) {
1556  (*env)->DeleteLocalRef(env, input_buffers);
1557  }
1558 
1559  return ret;
1560 }
1561 
1563 {
1564  uint8_t *ret = NULL;
1565  JNIEnv *env = NULL;
1566 
1567  jobject buffer = NULL;
1568  jobject output_buffers = NULL;
1569 
1570  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1571 
1572  if (codec->has_get_i_o_buffer) {
1573  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, (jint)idx);
1574  if (ff_jni_exception_check(env, 1, codec) < 0) {
1575  goto fail;
1576  }
1577  } else {
1578  if (!codec->output_buffers) {
1579  output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1580  if (ff_jni_exception_check(env, 1, codec) < 0) {
1581  goto fail;
1582  }
1583 
1584  codec->output_buffers = (*env)->NewGlobalRef(env, output_buffers);
1585  if (ff_jni_exception_check(env, 1, codec) < 0) {
1586  goto fail;
1587  }
1588  }
1589 
1590  buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1591  if (ff_jni_exception_check(env, 1, codec) < 0) {
1592  goto fail;
1593  }
1594  }
1595 
1596  ret = (*env)->GetDirectBufferAddress(env, buffer);
1597  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1598 fail:
1599  if (buffer) {
1600  (*env)->DeleteLocalRef(env, buffer);
1601  }
1602 
1603  if (output_buffers) {
1604  (*env)->DeleteLocalRef(env, output_buffers);
1605  }
1606 
1607  return ret;
1608 }
1609 
1611 {
1612  FFAMediaFormat *ret = NULL;
1613  JNIEnv *env = NULL;
1614 
1615  jobject mediaformat = NULL;
1616 
1617  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1618 
1619  mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1620  if (ff_jni_exception_check(env, 1, codec) < 0) {
1621  goto fail;
1622  }
1623 
1624  ret = ff_AMediaFormat_newFromObject(mediaformat);
1625 fail:
1626  if (mediaformat) {
1627  (*env)->DeleteLocalRef(env, mediaformat);
1628  }
1629 
1630  return ret;
1631 }
1632 
1634 {
1635  return idx == codec->INFO_TRY_AGAIN_LATER;
1636 }
1637 
1639 {
1640  return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1641 }
1642 
1644 {
1645  return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1646 }
1647 
1649 {
1650  return codec->BUFFER_FLAG_CODEC_CONFIG;
1651 }
1652 
1654 {
1655  return codec->BUFFER_FLAG_END_OF_STREAM;
1656 }
1657 
1659 {
1660  return codec->BUFFER_FLAG_KEY_FRAME;
1661 }
1662 
1664 {
1665  return codec->CONFIGURE_FLAG_ENCODE;
1666 }
1667 
1669 {
1670  int ret = 0;
1671 
1672  if (!codec->has_get_i_o_buffer) {
1673  if (codec->output_buffers) {
1674  JNIEnv *env = NULL;
1675 
1676  env = ff_jni_get_env(codec);
1677  if (!env) {
1678  ret = AVERROR_EXTERNAL;
1679  goto fail;
1680  }
1681 
1682  (*env)->DeleteGlobalRef(env, codec->output_buffers);
1683  codec->output_buffers = NULL;
1684  }
1685  }
1686 
1687 fail:
1688  return ret;
1689 }
1690 
1692 {
1693  int ret = -1;
1694  JNIEnv *env = NULL;
1695  jclass versionClass;
1696  jfieldID sdkIntFieldID;
1697  JNI_GET_ENV_OR_RETURN(env, avctx, -1);
1698 
1699  versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
1700  sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I");
1701  ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
1702  (*env)->DeleteLocalRef(env, versionClass);
1703  return ret;
1704 }
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:2900
#define NULL
Definition: coverity.c:32
const AVClass * class
int ff_AMediaFormat_getBuffer(FFAMediaFormat *format, const char *name, void **data, size_t *size)
static const char * format[]
Definition: af_aiir.c:330
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
int ff_jni_reset_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx)
Definition: ffjni.c:374
char * ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
Memory handling functions.
void ff_AMediaFormat_setBuffer(FFAMediaFormat *format, const char *name, void *data, size_t size)
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
static FFAMediaFormat * ff_AMediaFormat_newFromObject(void *object)
struct JNIAMediaFormatFields jfields
int out_size
Definition: movenc.c:55
jstring ff_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, void *log_ctx)
Definition: ffjni.c:127
const char * key
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
static const struct FFJniField jni_amediacodeclist_mapping[]
#define src
Definition: vp8dsp.c:254
int profile
profile
Definition: avcodec.h:2859
static const struct FFJniField jni_amediacodec_mapping[]
static const AVClass amediacodec_class
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE
Definition: avcodec.h:2910
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
#define CREATE_CODEC_BY_NAME
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_AMediaCodec_flush(FFAMediaCodec *codec)
#define FF_PROFILE_H264_BASELINE
Definition: avcodec.h:2898
int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec *codec, size_t idx, int render)
uint8_t
#define av_malloc(s)
FFAMediaFormat * ff_AMediaFormat_new(void)
int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec *codec, ssize_t idx)
#define FF_PROFILE_HEVC_MAIN
Definition: avcodec.h:2947
int ff_Build_SDK_INT(AVCodecContext *avctx)
int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:2901
char * ff_AMediaFormat_toString(FFAMediaFormat *format)
ptrdiff_t size
Definition: opengl_enc.c:101
#define FF_PROFILE_HEVC_MAIN_10
Definition: avcodec.h:2948
int ff_AMediaFormat_getFloat(FFAMediaFormat *format, const char *name, float *out)
Libavcodec version macros.
static const struct FFJniField jni_amediaformat_mapping[]
char * ff_AMediaCodec_getName(FFAMediaCodec *codec)
jfieldID info_output_format_changed_id
uint8_t * ff_AMediaCodec_getInputBuffer(FFAMediaCodec *codec, size_t idx, size_t *out_size)
const char * arg
Definition: jacosubdec.c:66
#define FF_PROFILE_H264_HIGH_422
Definition: avcodec.h:2906
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:2902
#define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx)
simple assert() macros that are a bit more flexible than ISO C assert().
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
#define fail()
Definition: checkasm.h:117
#define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method)
int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec *codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec *codec, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
void ff_AMediaFormat_setInt32(FFAMediaFormat *format, const char *name, int32_t value)
char * ff_jni_jstring_to_utf_chars(JNIEnv *env, jstring string, void *log_ctx)
Definition: ffjni.c:97
int ff_AMediaCodec_delete(FFAMediaCodec *codec)
int ff_AMediaFormat_getString(FFAMediaFormat *format, const char *name, const char **out)
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE
Definition: avcodec.h:2949
int32_t
void ff_AMediaFormat_setInt64(FFAMediaFormat *format, const char *name, int64_t value)
int ff_AMediaCodec_getBufferFlagEndOfStream(FFAMediaCodec *codec)
int ff_jni_init_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx)
Definition: ffjni.c:285
void ff_AMediaFormat_setFloat(FFAMediaFormat *format, const char *name, float value)
int ff_jni_exception_check(JNIEnv *env, int log, void *log_ctx)
Definition: ffjni.c:252
int ff_AMediaCodec_getBufferFlagKeyFrame(FFAMediaCodec *codec)
void ff_AMediaFormat_setString(FFAMediaFormat *format, const char *name, const char *value)
ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec *codec, int64_t timeoutUs)
#define CREATE_DECODER_BY_TYPE
int ff_AMediaFormat_getInt32(FFAMediaFormat *format, const char *name, int32_t *out)
struct JNIAMediaCodecFields jfields
int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
int ff_AMediaCodec_start(FFAMediaCodec *codec)
Libavcodec external API header.
int ff_AMediaCodec_getBufferFlagCodecConfig(FFAMediaCodec *codec)
#define FF_PROFILE_H264_HIGH_422_INTRA
Definition: avcodec.h:2907
enum AVCodecID codec_id
Definition: avcodec.h:1543
#define CREATE_ENCODER_BY_TYPE
main external API structure.
Definition: avcodec.h:1533
int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
The following API around MediaCodec and MediaFormat is based on the NDK one provided by Google since ...
GLint GLenum type
Definition: opengl_enc.c:105
#define FF_PROFILE_H264_HIGH_10_INTRA
Definition: avcodec.h:2904
Describe the class of an AVClass context structure.
Definition: log.h:67
#define FF_PROFILE_H264_HIGH_444
Definition: avcodec.h:2909
jfieldID info_output_buffers_changed_id
int ff_AMediaCodec_stop(FFAMediaCodec *codec)
int ff_AMediaCodec_infoTryAgainLater(FFAMediaCodec *codec, ssize_t idx)
int ff_AMediaFormat_delete(FFAMediaFormat *format)
mfxU16 profile
Definition: qsvenc.c:44
jmethodID release_output_buffer_at_time_id
#define flags(name, subs,...)
Definition: cbs_av1.c:596
uint8_t * ff_AMediaCodec_getOutputBuffer(FFAMediaCodec *codec, size_t idx, size_t *out_size)
int ff_AMediaCodec_configure(FFAMediaCodec *codec, const FFAMediaFormat *format, void *surface, void *crypto, uint32_t flags)
JNIEnv * ff_jni_get_env(void *log_ctx)
Definition: ffjni.c:51
static const AVClass amediaformat_class
const AVClass * class
#define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret)
int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec)
static int codec_init_static_fields(FFAMediaCodec *codec)
FFAMediaFormat * ff_AMediaCodec_getOutputFormat(FFAMediaCodec *codec)
#define FF_PROFILE_H264_HIGH_444_INTRA
Definition: avcodec.h:2911
FILE * out
Definition: movenc.c:54
int ff_AMediaFormat_getInt64(FFAMediaFormat *format, const char *name, int64_t *out)
#define av_freep(p)
static FFAMediaCodec * codec_create(int method, const char *arg)
#define FF_PROFILE_H264_CONSTRAINED_BASELINE
Definition: avcodec.h:2899
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:2903
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
GLuint buffer
Definition: opengl_enc.c:102
const char * name
Definition: opengl_enc.c:103