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