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 codec_name = NULL;
396 
397  jobject info = NULL;
398  jobject type = NULL;
399  jobjectArray types = NULL;
400 
401  jobject capabilities = NULL;
402  jobject profile_level = NULL;
403  jobjectArray profile_levels = NULL;
404 
405  JNI_GET_ENV_OR_RETURN(env, log_ctx, NULL);
406 
407  if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
408  goto done;
409  }
410 
411  if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) {
412  goto done;
413  }
414 
415  codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
416  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
417  goto done;
418  }
419 
420  for(i = 0; i < codec_count; i++) {
421  int j;
422  int type_count;
423  int is_encoder;
424 
425  info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
426  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
427  goto done;
428  }
429 
430  types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
431  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
432  goto done;
433  }
434 
435  is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
436  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
437  goto done;
438  }
439 
440  if (is_encoder != encoder) {
441  goto done_with_info;
442  }
443 
444  type_count = (*env)->GetArrayLength(env, types);
445  for (j = 0; j < type_count; j++) {
446  int k;
447  int profile_count;
448 
449  type = (*env)->GetObjectArrayElement(env, types, j);
450  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
451  goto done;
452  }
453 
454  supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
455  if (!supported_type) {
456  goto done;
457  }
458 
459  if (!av_strcasecmp(supported_type, mime)) {
460  codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
461  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
462  goto done;
463  }
464 
465  name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
466  if (!name) {
467  goto done;
468  }
469 
470  if (codec_name) {
471  (*env)->DeleteLocalRef(env, codec_name);
472  codec_name = NULL;
473  }
474 
475  /* Skip software decoders */
476  if (
477  strstr(name, "OMX.google") ||
478  strstr(name, "OMX.ffmpeg") ||
479  (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) ||
480  !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) {
481  av_freep(&name);
482  goto done_with_type;
483  }
484 
485  capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type);
486  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
487  goto done;
488  }
489 
490  profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id);
491  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
492  goto done;
493  }
494 
495  profile_count = (*env)->GetArrayLength(env, profile_levels);
496  if (!profile_count) {
497  found_codec = 1;
498  }
499  for (k = 0; k < profile_count; k++) {
500  int supported_profile = 0;
501 
502  if (profile < 0) {
503  found_codec = 1;
504  break;
505  }
506 
507  profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k);
508  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
509  goto done;
510  }
511 
512  supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id);
513  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
514  goto done;
515  }
516 
517  found_codec = profile == supported_profile;
518 
519  if (profile_level) {
520  (*env)->DeleteLocalRef(env, profile_level);
521  profile_level = NULL;
522  }
523 
524  if (found_codec) {
525  break;
526  }
527  }
528  }
529 
530 done_with_type:
531  if (profile_levels) {
532  (*env)->DeleteLocalRef(env, profile_levels);
533  profile_levels = NULL;
534  }
535 
536  if (capabilities) {
537  (*env)->DeleteLocalRef(env, capabilities);
538  capabilities = NULL;
539  }
540 
541  if (type) {
542  (*env)->DeleteLocalRef(env, type);
543  type = NULL;
544  }
545 
546  av_freep(&supported_type);
547 
548  if (found_codec) {
549  break;
550  }
551 
552  av_freep(&name);
553  }
554 
555 done_with_info:
556  if (info) {
557  (*env)->DeleteLocalRef(env, info);
558  info = NULL;
559  }
560 
561  if (types) {
562  (*env)->DeleteLocalRef(env, types);
563  types = NULL;
564  }
565 
566  if (found_codec) {
567  break;
568  }
569  }
570 
571 done:
572  if (codec_name) {
573  (*env)->DeleteLocalRef(env, codec_name);
574  }
575 
576  if (info) {
577  (*env)->DeleteLocalRef(env, info);
578  }
579 
580  if (type) {
581  (*env)->DeleteLocalRef(env, type);
582  }
583 
584  if (types) {
585  (*env)->DeleteLocalRef(env, types);
586  }
587 
588  if (capabilities) {
589  (*env)->DeleteLocalRef(env, capabilities);
590  }
591 
592  if (profile_level) {
593  (*env)->DeleteLocalRef(env, profile_level);
594  }
595 
596  if (profile_levels) {
597  (*env)->DeleteLocalRef(env, profile_levels);
598  }
599 
600  av_freep(&supported_type);
601 
602  ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
603  ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
604 
605  if (!found_codec) {
606  av_freep(&name);
607  }
608 
609  return name;
610 }
611 
613 {
614  JNIEnv *env = NULL;
616  jobject object = NULL;
617 
618  format = av_mallocz(sizeof(FFAMediaFormat));
619  if (!format) {
620  return NULL;
621  }
622  format->class = &amediaformat_class;
623 
624  env = ff_jni_get_env(format);
625  if (!env) {
626  av_freep(&format);
627  return NULL;
628  }
629 
630  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
631  goto fail;
632  }
633 
634  object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
635  if (!object) {
636  goto fail;
637  }
638 
639  format->object = (*env)->NewGlobalRef(env, object);
640  if (!format->object) {
641  goto fail;
642  }
643 
644 fail:
645  if (object) {
646  (*env)->DeleteLocalRef(env, object);
647  }
648 
649  if (!format->object) {
650  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
651  av_freep(&format);
652  }
653 
654  return format;
655 }
656 
658 {
659  JNIEnv *env = NULL;
661 
662  format = av_mallocz(sizeof(FFAMediaFormat));
663  if (!format) {
664  return NULL;
665  }
666  format->class = &amediaformat_class;
667 
668  env = ff_jni_get_env(format);
669  if (!env) {
670  av_freep(&format);
671  return NULL;
672  }
673 
674  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
675  goto fail;
676  }
677 
678  format->object = (*env)->NewGlobalRef(env, object);
679  if (!format->object) {
680  goto fail;
681  }
682 
683  return format;
684 fail:
685  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
686 
687  av_freep(&format);
688 
689  return NULL;
690 }
691 
693 {
694  int ret = 0;
695 
696  JNIEnv *env = NULL;
697 
698  if (!format) {
699  return 0;
700  }
701 
703 
704  (*env)->DeleteGlobalRef(env, format->object);
705  format->object = NULL;
706 
707  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
708 
709  av_freep(&format);
710 
711  return ret;
712 }
713 
715 {
716  char *ret = NULL;
717 
718  JNIEnv *env = NULL;
719  jstring description = NULL;
720 
721  av_assert0(format != NULL);
722 
723  JNI_GET_ENV_OR_RETURN(env, format, NULL);
724 
725  description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
726  if (ff_jni_exception_check(env, 1, NULL) < 0) {
727  goto fail;
728  }
729 
730  ret = ff_jni_jstring_to_utf_chars(env, description, format);
731 fail:
732  if (description) {
733  (*env)->DeleteLocalRef(env, description);
734  }
735 
736  return ret;
737 }
738 
740 {
741  int ret = 1;
742 
743  JNIEnv *env = NULL;
744  jstring key = NULL;
745  jboolean contains_key;
746 
747  av_assert0(format != NULL);
748 
749  JNI_GET_ENV_OR_RETURN(env, format, 0);
750 
751  key = ff_jni_utf_chars_to_jstring(env, name, format);
752  if (!key) {
753  ret = 0;
754  goto fail;
755  }
756 
757  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
758  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
759  ret = 0;
760  goto fail;
761  }
762 
763  *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
764  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
765  ret = 0;
766  goto fail;
767  }
768 
769  ret = 1;
770 fail:
771  if (key) {
772  (*env)->DeleteLocalRef(env, key);
773  }
774 
775  return ret;
776 }
777 
779 {
780  int ret = 1;
781 
782  JNIEnv *env = NULL;
783  jstring key = NULL;
784  jboolean contains_key;
785 
786  av_assert0(format != NULL);
787 
788  JNI_GET_ENV_OR_RETURN(env, format, 0);
789 
790  key = ff_jni_utf_chars_to_jstring(env, name, format);
791  if (!key) {
792  ret = 0;
793  goto fail;
794  }
795 
796  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
797  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
798  ret = 0;
799  goto fail;
800  }
801 
802  *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
803  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
804  ret = 0;
805  goto fail;
806  }
807 
808  ret = 1;
809 fail:
810  if (key) {
811  (*env)->DeleteLocalRef(env, key);
812  }
813 
814  return ret;
815 }
816 
818 {
819  int ret = 1;
820 
821  JNIEnv *env = NULL;
822  jstring key = NULL;
823  jboolean contains_key;
824 
825  av_assert0(format != NULL);
826 
827  JNI_GET_ENV_OR_RETURN(env, format, 0);
828 
829  key = ff_jni_utf_chars_to_jstring(env, name, format);
830  if (!key) {
831  ret = 0;
832  goto fail;
833  }
834 
835  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
836  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
837  ret = 0;
838  goto fail;
839  }
840 
841  *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
842  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
843  ret = 0;
844  goto fail;
845  }
846 
847  ret = 1;
848 fail:
849  if (key) {
850  (*env)->DeleteLocalRef(env, key);
851  }
852 
853  return ret;
854 }
855 
856 int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
857 {
858  int ret = 1;
859 
860  JNIEnv *env = NULL;
861  jstring key = NULL;
862  jboolean contains_key;
863  jobject result = NULL;
864 
865  av_assert0(format != NULL);
866 
867  JNI_GET_ENV_OR_RETURN(env, format, 0);
868 
869  key = ff_jni_utf_chars_to_jstring(env, name, format);
870  if (!key) {
871  ret = 0;
872  goto fail;
873  }
874 
875  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
876  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
877  ret = 0;
878  goto fail;
879  }
880 
881  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
882  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
883  ret = 0;
884  goto fail;
885  }
886 
887  *data = (*env)->GetDirectBufferAddress(env, result);
888  *size = (*env)->GetDirectBufferCapacity(env, result);
889 
890  if (*data && *size) {
891  void *src = *data;
892  *data = av_malloc(*size);
893  if (!*data) {
894  ret = 0;
895  goto fail;
896  }
897 
898  memcpy(*data, src, *size);
899  }
900 
901  ret = 1;
902 fail:
903  if (key) {
904  (*env)->DeleteLocalRef(env, key);
905  }
906 
907  if (result) {
908  (*env)->DeleteLocalRef(env, result);
909  }
910 
911  return ret;
912 }
913 
914 int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
915 {
916  int ret = 1;
917 
918  JNIEnv *env = NULL;
919  jstring key = NULL;
920  jboolean contains_key;
921  jstring result = NULL;
922 
923  av_assert0(format != NULL);
924 
925  JNI_GET_ENV_OR_RETURN(env, format, 0);
926 
927  key = ff_jni_utf_chars_to_jstring(env, name, format);
928  if (!key) {
929  ret = 0;
930  goto fail;
931  }
932 
933  contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
934  if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
935  ret = 0;
936  goto fail;
937  }
938 
939  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
940  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
941  ret = 0;
942  goto fail;
943  }
944 
945  *out = ff_jni_jstring_to_utf_chars(env, result, format);
946  if (!*out) {
947  ret = 0;
948  goto fail;
949  }
950 
951  ret = 1;
952 fail:
953  if (key) {
954  (*env)->DeleteLocalRef(env, key);
955  }
956 
957  if (result) {
958  (*env)->DeleteLocalRef(env, result);
959  }
960 
961  return ret;
962 }
963 
965 {
966  JNIEnv *env = NULL;
967  jstring key = NULL;
968 
969  av_assert0(format != NULL);
970 
971  JNI_GET_ENV_OR_RETURN_VOID(env, format);
972 
973  key = ff_jni_utf_chars_to_jstring(env, name, format);
974  if (!key) {
975  goto fail;
976  }
977 
978  (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
979  if (ff_jni_exception_check(env, 1, format) < 0) {
980  goto fail;
981  }
982 
983 fail:
984  if (key) {
985  (*env)->DeleteLocalRef(env, key);
986  }
987 }
988 
990 {
991  JNIEnv *env = NULL;
992  jstring key = NULL;
993 
994  av_assert0(format != NULL);
995 
996  JNI_GET_ENV_OR_RETURN_VOID(env, format);
997 
998  key = ff_jni_utf_chars_to_jstring(env, name, format);
999  if (!key) {
1000  goto fail;
1001  }
1002 
1003  (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
1004  if (ff_jni_exception_check(env, 1, format) < 0) {
1005  goto fail;
1006  }
1007 
1008 fail:
1009  if (key) {
1010  (*env)->DeleteLocalRef(env, key);
1011  }
1012 }
1013 
1015 {
1016  JNIEnv *env = NULL;
1017  jstring key = NULL;
1018 
1019  av_assert0(format != NULL);
1020 
1021  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1022 
1023  key = ff_jni_utf_chars_to_jstring(env, name, format);
1024  if (!key) {
1025  goto fail;
1026  }
1027 
1028  (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
1029  if (ff_jni_exception_check(env, 1, format) < 0) {
1030  goto fail;
1031  }
1032 
1033 fail:
1034  if (key) {
1035  (*env)->DeleteLocalRef(env, key);
1036  }
1037 }
1038 
1040 {
1041  JNIEnv *env = NULL;
1042  jstring key = NULL;
1043  jstring string = NULL;
1044 
1045  av_assert0(format != NULL);
1046 
1047  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1048 
1049  key = ff_jni_utf_chars_to_jstring(env, name, format);
1050  if (!key) {
1051  goto fail;
1052  }
1053 
1054  string = ff_jni_utf_chars_to_jstring(env, value, format);
1055  if (!string) {
1056  goto fail;
1057  }
1058 
1059  (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
1060  if (ff_jni_exception_check(env, 1, format) < 0) {
1061  goto fail;
1062  }
1063 
1064 fail:
1065  if (key) {
1066  (*env)->DeleteLocalRef(env, key);
1067  }
1068 
1069  if (string) {
1070  (*env)->DeleteLocalRef(env, string);
1071  }
1072 }
1073 
1074 void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
1075 {
1076  JNIEnv *env = NULL;
1077  jstring key = NULL;
1078  jobject buffer = NULL;
1079  void *buffer_data = NULL;
1080 
1081  av_assert0(format != NULL);
1082 
1083  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1084 
1085  key = ff_jni_utf_chars_to_jstring(env, name, format);
1086  if (!key) {
1087  goto fail;
1088  }
1089 
1090  if (!data || !size) {
1091  goto fail;
1092  }
1093 
1094  buffer_data = av_malloc(size);
1095  if (!buffer_data) {
1096  goto fail;
1097  }
1098 
1099  memcpy(buffer_data, data, size);
1100 
1101  buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
1102  if (!buffer) {
1103  goto fail;
1104  }
1105 
1106  (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
1107  if (ff_jni_exception_check(env, 1, format) < 0) {
1108  goto fail;
1109  }
1110 
1111 fail:
1112  if (key) {
1113  (*env)->DeleteLocalRef(env, key);
1114  }
1115 
1116  if (buffer) {
1117  (*env)->DeleteLocalRef(env, buffer);
1118  }
1119 }
1120 
1122 {
1123  int ret = 0;
1124  JNIEnv *env = NULL;
1125 
1127 
1128  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1129  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1130  goto fail;
1131  }
1132 
1133  codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
1134  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1135  goto fail;
1136  }
1137 
1138  codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
1139  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1140  goto fail;
1141  }
1142 
1143  if (codec->jfields.buffer_flag_key_frame_id) {
1144  codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
1145  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1146  goto fail;
1147  }
1148  }
1149 
1150  codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
1151  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1152  goto fail;
1153  }
1154 
1155  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1156  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1157  goto fail;
1158  }
1159 
1160  codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
1161  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1162  goto fail;
1163  }
1164 
1165  codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
1166  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1167  goto fail;
1168  }
1169 
1170 fail:
1171 
1172  return ret;
1173 }
1174 
1175 #define CREATE_CODEC_BY_NAME 0
1176 #define CREATE_DECODER_BY_TYPE 1
1177 #define CREATE_ENCODER_BY_TYPE 2
1178 
1179 static inline FFAMediaCodec *codec_create(int method, const char *arg)
1180 {
1181  int ret = -1;
1182  JNIEnv *env = NULL;
1183  FFAMediaCodec *codec = NULL;
1184  jstring jarg = NULL;
1185  jobject object = NULL;
1186  jobject buffer_info = NULL;
1187  jmethodID create_id = NULL;
1188 
1189  codec = av_mallocz(sizeof(FFAMediaCodec));
1190  if (!codec) {
1191  return NULL;
1192  }
1193  codec->class = &amediacodec_class;
1194 
1195  env = ff_jni_get_env(codec);
1196  if (!env) {
1197  av_freep(&codec);
1198  return NULL;
1199  }
1200 
1201  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1202  goto fail;
1203  }
1204 
1205  jarg = ff_jni_utf_chars_to_jstring(env, arg, codec);
1206  if (!jarg) {
1207  goto fail;
1208  }
1209 
1210  switch (method) {
1211  case CREATE_CODEC_BY_NAME: create_id = codec->jfields.create_by_codec_name_id; break;
1212  case CREATE_DECODER_BY_TYPE: create_id = codec->jfields.create_decoder_by_type_id; break;
1213  case CREATE_ENCODER_BY_TYPE: create_id = codec->jfields.create_encoder_by_type_id; break;
1214  default:
1215  av_assert0(0);
1216  }
1217 
1218  object = (*env)->CallStaticObjectMethod(env,
1219  codec->jfields.mediacodec_class,
1220  create_id,
1221  jarg);
1222  if (ff_jni_exception_check(env, 1, codec) < 0) {
1223  goto fail;
1224  }
1225 
1226  codec->object = (*env)->NewGlobalRef(env, object);
1227  if (!codec->object) {
1228  goto fail;
1229  }
1230 
1231  if (codec_init_static_fields(codec) < 0) {
1232  goto fail;
1233  }
1234 
1236  codec->has_get_i_o_buffer = 1;
1237  }
1238 
1239  buffer_info = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
1240  if (ff_jni_exception_check(env, 1, codec) < 0) {
1241  goto fail;
1242  }
1243 
1244  codec->buffer_info = (*env)->NewGlobalRef(env, buffer_info);
1245  if (!codec->buffer_info) {
1246  goto fail;
1247  }
1248 
1249  ret = 0;
1250 fail:
1251  if (jarg) {
1252  (*env)->DeleteLocalRef(env, jarg);
1253  }
1254 
1255  if (object) {
1256  (*env)->DeleteLocalRef(env, object);
1257  }
1258 
1259  if (buffer_info) {
1260  (*env)->DeleteLocalRef(env, buffer_info);
1261  }
1262 
1263  if (ret < 0) {
1264  if (codec->object) {
1265  (*env)->DeleteGlobalRef(env, codec->object);
1266  }
1267 
1268  if (codec->buffer_info) {
1269  (*env)->DeleteGlobalRef(env, codec->buffer_info);
1270  }
1271 
1272  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1273  av_freep(&codec);
1274  }
1275 
1276  return codec;
1277 }
1278 
1279 #define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \
1280 FFAMediaCodec *ff_AMediaCodec_##name(const char *arg) \
1281 { \
1282  return codec_create(method, arg); \
1283 } \
1284 
1288 
1290 {
1291  int ret = 0;
1292 
1293  JNIEnv *env = NULL;
1294 
1295  if (!codec) {
1296  return 0;
1297  }
1298 
1300 
1301  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
1302  if (ff_jni_exception_check(env, 1, codec) < 0) {
1303  ret = AVERROR_EXTERNAL;
1304  }
1305 
1306  (*env)->DeleteGlobalRef(env, codec->input_buffers);
1307  codec->input_buffers = NULL;
1308 
1309  (*env)->DeleteGlobalRef(env, codec->output_buffers);
1310  codec->output_buffers = NULL;
1311 
1312  (*env)->DeleteGlobalRef(env, codec->object);
1313  codec->object = NULL;
1314 
1315  (*env)->DeleteGlobalRef(env, codec->buffer_info);
1316  codec->buffer_info = NULL;
1317 
1318  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1319 
1320  av_freep(&codec);
1321 
1322  return ret;
1323 }
1324 
1326 {
1327  char *ret = NULL;
1328  JNIEnv *env = NULL;
1329  jobject *name = NULL;
1330 
1331  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1332 
1333  name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1334  if (ff_jni_exception_check(env, 1, codec) < 0) {
1335  goto fail;
1336  }
1337 
1338  ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1339 
1340 fail:
1341  if (name) {
1342  (*env)->DeleteLocalRef(env, name);
1343  }
1344 
1345  return ret;
1346 }
1347 
1348 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
1349 {
1350  int ret = 0;
1351  JNIEnv *env = NULL;
1352 
1354 
1355  (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
1356  if (ff_jni_exception_check(env, 1, codec) < 0) {
1357  ret = AVERROR_EXTERNAL;
1358  goto fail;
1359  }
1360 
1361 fail:
1362  return ret;
1363 }
1364 
1366 {
1367  int ret = 0;
1368  JNIEnv *env = NULL;
1369 
1371 
1372  (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1373  if (ff_jni_exception_check(env, 1, codec) < 0) {
1374  ret = AVERROR_EXTERNAL;
1375  goto fail;
1376  }
1377 
1378 fail:
1379  return ret;
1380 }
1381 
1383 {
1384  int ret = 0;
1385  JNIEnv *env = NULL;
1386 
1388 
1389  (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1390  if (ff_jni_exception_check(env, 1, codec) < 0) {
1391  ret = AVERROR_EXTERNAL;
1392  goto fail;
1393  }
1394 
1395 fail:
1396  return ret;
1397 }
1398 
1400 {
1401  int ret = 0;
1402  JNIEnv *env = NULL;
1403 
1405 
1406  (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1407  if (ff_jni_exception_check(env, 1, codec) < 0) {
1408  ret = AVERROR_EXTERNAL;
1409  goto fail;
1410  }
1411 
1412 fail:
1413  return ret;
1414 }
1415 
1416 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
1417 {
1418  int ret = 0;
1419  JNIEnv *env = NULL;
1420 
1422 
1423  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, (jint)idx, (jboolean)render);
1424  if (ff_jni_exception_check(env, 1, codec) < 0) {
1425  ret = AVERROR_EXTERNAL;
1426  goto fail;
1427  }
1428 
1429 fail:
1430  return ret;
1431 }
1432 
1433 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
1434 {
1435  int ret = 0;
1436  JNIEnv *env = NULL;
1437 
1439 
1440  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs);
1441  if (ff_jni_exception_check(env, 1, codec) < 0) {
1442  ret = AVERROR_EXTERNAL;
1443  goto fail;
1444  }
1445 
1446 fail:
1447  return ret;
1448 }
1449 
1450 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
1451 {
1452  int ret = 0;
1453  JNIEnv *env = NULL;
1454 
1456 
1457  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1458  if (ff_jni_exception_check(env, 1, codec) < 0) {
1459  ret = AVERROR_EXTERNAL;
1460  goto fail;
1461  }
1462 
1463 fail:
1464  return ret;
1465 }
1466 
1467 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1468 {
1469  int ret = 0;
1470  JNIEnv *env = NULL;
1471 
1473 
1474  (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, (jint)idx, (jint)offset, (jint)size, time, flags);
1475  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1476  ret = AVERROR_EXTERNAL;
1477  goto fail;
1478  }
1479 
1480 fail:
1481  return ret;
1482 }
1483 
1485 {
1486  int ret = 0;
1487  JNIEnv *env = NULL;
1488 
1490 
1491  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs);
1492  if (ff_jni_exception_check(env, 1, codec) < 0) {
1493  return AVERROR_EXTERNAL;
1494  }
1495 
1496  info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id);
1497  if (ff_jni_exception_check(env, 1, codec) < 0) {
1498  return AVERROR_EXTERNAL;
1499  }
1500 
1501  info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id);
1502  if (ff_jni_exception_check(env, 1, codec) < 0) {
1503  return AVERROR_EXTERNAL;
1504  }
1505 
1506  info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id);
1507  if (ff_jni_exception_check(env, 1, codec) < 0) {
1508  return AVERROR_EXTERNAL;
1509  }
1510 
1511  info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id);
1512  if (ff_jni_exception_check(env, 1, codec) < 0) {
1513  return AVERROR_EXTERNAL;
1514  }
1515 
1516  return ret;
1517 }
1518 
1520 {
1521  uint8_t *ret = NULL;
1522  JNIEnv *env = NULL;
1523 
1524  jobject buffer = NULL;
1525  jobject input_buffers = NULL;
1526 
1527  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1528 
1529  if (codec->has_get_i_o_buffer) {
1530  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, (jint)idx);
1531  if (ff_jni_exception_check(env, 1, codec) < 0) {
1532  goto fail;
1533  }
1534  } else {
1535  if (!codec->input_buffers) {
1536  input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1537  if (ff_jni_exception_check(env, 1, codec) < 0) {
1538  goto fail;
1539  }
1540 
1541  codec->input_buffers = (*env)->NewGlobalRef(env, input_buffers);
1542  if (ff_jni_exception_check(env, 1, codec) < 0) {
1543  goto fail;
1544  }
1545  }
1546 
1547  buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1548  if (ff_jni_exception_check(env, 1, codec) < 0) {
1549  goto fail;
1550  }
1551  }
1552 
1553  ret = (*env)->GetDirectBufferAddress(env, buffer);
1554  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1555 fail:
1556  if (buffer) {
1557  (*env)->DeleteLocalRef(env, buffer);
1558  }
1559 
1560  if (input_buffers) {
1561  (*env)->DeleteLocalRef(env, input_buffers);
1562  }
1563 
1564  return ret;
1565 }
1566 
1568 {
1569  uint8_t *ret = NULL;
1570  JNIEnv *env = NULL;
1571 
1572  jobject buffer = NULL;
1573  jobject output_buffers = NULL;
1574 
1575  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1576 
1577  if (codec->has_get_i_o_buffer) {
1578  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, (jint)idx);
1579  if (ff_jni_exception_check(env, 1, codec) < 0) {
1580  goto fail;
1581  }
1582  } else {
1583  if (!codec->output_buffers) {
1584  output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1585  if (ff_jni_exception_check(env, 1, codec) < 0) {
1586  goto fail;
1587  }
1588 
1589  codec->output_buffers = (*env)->NewGlobalRef(env, output_buffers);
1590  if (ff_jni_exception_check(env, 1, codec) < 0) {
1591  goto fail;
1592  }
1593  }
1594 
1595  buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1596  if (ff_jni_exception_check(env, 1, codec) < 0) {
1597  goto fail;
1598  }
1599  }
1600 
1601  ret = (*env)->GetDirectBufferAddress(env, buffer);
1602  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1603 fail:
1604  if (buffer) {
1605  (*env)->DeleteLocalRef(env, buffer);
1606  }
1607 
1608  if (output_buffers) {
1609  (*env)->DeleteLocalRef(env, output_buffers);
1610  }
1611 
1612  return ret;
1613 }
1614 
1616 {
1617  FFAMediaFormat *ret = NULL;
1618  JNIEnv *env = NULL;
1619 
1620  jobject mediaformat = NULL;
1621 
1622  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1623 
1624  mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1625  if (ff_jni_exception_check(env, 1, codec) < 0) {
1626  goto fail;
1627  }
1628 
1629  ret = ff_AMediaFormat_newFromObject(mediaformat);
1630 fail:
1631  if (mediaformat) {
1632  (*env)->DeleteLocalRef(env, mediaformat);
1633  }
1634 
1635  return ret;
1636 }
1637 
1639 {
1640  return idx == codec->INFO_TRY_AGAIN_LATER;
1641 }
1642 
1644 {
1645  return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1646 }
1647 
1649 {
1650  return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1651 }
1652 
1654 {
1655  return codec->BUFFER_FLAG_CODEC_CONFIG;
1656 }
1657 
1659 {
1660  return codec->BUFFER_FLAG_END_OF_STREAM;
1661 }
1662 
1664 {
1665  return codec->BUFFER_FLAG_KEY_FRAME;
1666 }
1667 
1669 {
1670  return codec->CONFIGURE_FLAG_ENCODE;
1671 }
1672 
1674 {
1675  int ret = 0;
1676 
1677  if (!codec->has_get_i_o_buffer) {
1678  if (codec->output_buffers) {
1679  JNIEnv *env = NULL;
1680 
1681  env = ff_jni_get_env(codec);
1682  if (!env) {
1683  ret = AVERROR_EXTERNAL;
1684  goto fail;
1685  }
1686 
1687  (*env)->DeleteGlobalRef(env, codec->output_buffers);
1688  codec->output_buffers = NULL;
1689  }
1690  }
1691 
1692 fail:
1693  return ret;
1694 }
1695 
1697 {
1698  int ret = -1;
1699  JNIEnv *env = NULL;
1700  jclass versionClass;
1701  jfieldID sdkIntFieldID;
1702  JNI_GET_ENV_OR_RETURN(env, avctx, -1);
1703 
1704  versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
1705  sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I");
1706  ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
1707  (*env)->DeleteLocalRef(env, versionClass);
1708  return ret;
1709 }
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:1900
#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:235
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:237
static const struct FFJniField jni_amediacodeclist_mapping[]
int profile
profile
Definition: avcodec.h:1859
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:1910
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:1898
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:1947
int ff_Build_SDK_INT(AVCodecContext *avctx)
int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:1901
char * ff_AMediaFormat_toString(FFAMediaFormat *format)
ptrdiff_t size
Definition: opengl_enc.c:100
#define FF_PROFILE_HEVC_MAIN_10
Definition: avcodec.h:1948
int ff_AMediaFormat_getFloat(FFAMediaFormat *format, const char *name, float *out)
Libavcodec version macros.
#define src
Definition: vp8dsp.c:254
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:1906
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:1902
#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:123
#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:1949
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:1907
enum AVCodecID codec_id
Definition: avcodec.h:536
#define CREATE_ENCODER_BY_TYPE
main external API structure.
Definition: avcodec.h:526
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:1904
Describe the class of an AVClass context structure.
Definition: log.h:67
#define FF_PROFILE_H264_HIGH_444
Definition: avcodec.h:1909
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:45
jmethodID release_output_buffer_at_time_id
#define flags(name, subs,...)
Definition: cbs_av1.c:560
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:1911
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:1899
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:1903
#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)
int i
Definition: input.c:406
GLuint buffer
Definition: opengl_enc.c:101
const char * name
Definition: opengl_enc.c:102