FFmpeg
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;
165  struct JNIAMediaFormatFields jfields;
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 
278  struct JNIAMediaCodecFields jfields;
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:2939
#define NULL
Definition: coverity.c:32
const AVClass * class
int ff_AMediaFormat_getBuffer(FFAMediaFormat *format, const char *name, void **data, size_t *size)
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
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)
GLint GLenum type
Definition: opengl_enc.c:104
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:2898
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
static const struct FFJniField jni_amediacodec_mapping[]
static const AVClass amediacodec_class
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE
Definition: avcodec.h:2949
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:2937
int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec *codec, size_t idx, int render)
uint8_t
#define av_malloc(s)
FFAMediaFormat * ff_AMediaFormat_new(void)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec *codec, ssize_t idx)
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
#define FF_PROFILE_HEVC_MAIN
Definition: avcodec.h:2986
int ff_Build_SDK_INT(AVCodecContext *avctx)
int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:2940
char * ff_AMediaFormat_toString(FFAMediaFormat *format)
ptrdiff_t size
Definition: opengl_enc.c:100
#define FF_PROFILE_HEVC_MAIN_10
Definition: avcodec.h:2987
int ff_AMediaFormat_getFloat(FFAMediaFormat *format, const char *name, float *out)
Libavcodec version macros.
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
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:2945
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:2941
#define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx)
Tag description
Definition: snow.txt:206
simple assert() macros that are a bit more flexible than ISO C assert().
#define fail()
Definition: checkasm.h:120
#define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method)
MIPS optimizations info
Definition: mips.txt:2
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)
#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE
Definition: avcodec.h:2988
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:2946
enum AVCodecID codec_id
Definition: avcodec.h:1575
#define CREATE_ENCODER_BY_TYPE
main external API structure.
Definition: avcodec.h:1565
int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
The following API around MediaCodec and MediaFormat is based on the NDK one provided by Google since ...
#define FF_PROFILE_H264_HIGH_10_INTRA
Definition: avcodec.h:2943
Describe the class of an AVClass context structure.
Definition: log.h:67
#define FF_PROFILE_H264_HIGH_444
Definition: avcodec.h:2948
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:561
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:2950
and forward the result(frame or status change) to the corresponding input.If nothing is possible
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:2938
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:2942
#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:101
const char * name
Definition: opengl_enc.c:102