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->object);
1307  codec->object = NULL;
1308 
1309  (*env)->DeleteGlobalRef(env, codec->buffer_info);
1310  codec->buffer_info = NULL;
1311 
1312  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1313 
1314  av_freep(&codec);
1315 
1316  return ret;
1317 }
1318 
1320 {
1321  char *ret = NULL;
1322  JNIEnv *env = NULL;
1323  jobject *name = NULL;
1324 
1325  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1326 
1327  name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1328  if (ff_jni_exception_check(env, 1, codec) < 0) {
1329  goto fail;
1330  }
1331 
1332  ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1333 
1334 fail:
1335  if (name) {
1336  (*env)->DeleteLocalRef(env, name);
1337  }
1338 
1339  return ret;
1340 }
1341 
1342 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
1343 {
1344  int ret = 0;
1345  JNIEnv *env = NULL;
1346 
1348 
1349  (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
1350  if (ff_jni_exception_check(env, 1, codec) < 0) {
1351  ret = AVERROR_EXTERNAL;
1352  goto fail;
1353  }
1354 
1355 fail:
1356  return ret;
1357 }
1358 
1360 {
1361  int ret = 0;
1362  JNIEnv *env = NULL;
1363 
1365 
1366  (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1367  if (ff_jni_exception_check(env, 1, codec) < 0) {
1368  ret = AVERROR_EXTERNAL;
1369  goto fail;
1370  }
1371 
1372 fail:
1373  return ret;
1374 }
1375 
1377 {
1378  int ret = 0;
1379  JNIEnv *env = NULL;
1380 
1382 
1383  (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1384  if (ff_jni_exception_check(env, 1, codec) < 0) {
1385  ret = AVERROR_EXTERNAL;
1386  goto fail;
1387  }
1388 
1389 fail:
1390  return ret;
1391 }
1392 
1394 {
1395  int ret = 0;
1396  JNIEnv *env = NULL;
1397 
1399 
1400  (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1401  if (ff_jni_exception_check(env, 1, codec) < 0) {
1402  ret = AVERROR_EXTERNAL;
1403  goto fail;
1404  }
1405 
1406 fail:
1407  return ret;
1408 }
1409 
1410 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
1411 {
1412  int ret = 0;
1413  JNIEnv *env = NULL;
1414 
1416 
1417  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, (jint)idx, (jboolean)render);
1418  if (ff_jni_exception_check(env, 1, codec) < 0) {
1419  ret = AVERROR_EXTERNAL;
1420  goto fail;
1421  }
1422 
1423 fail:
1424  return ret;
1425 }
1426 
1427 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
1428 {
1429  int ret = 0;
1430  JNIEnv *env = NULL;
1431 
1433 
1434  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs);
1435  if (ff_jni_exception_check(env, 1, codec) < 0) {
1436  ret = AVERROR_EXTERNAL;
1437  goto fail;
1438  }
1439 
1440 fail:
1441  return ret;
1442 }
1443 
1444 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
1445 {
1446  int ret = 0;
1447  JNIEnv *env = NULL;
1448 
1450 
1451  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1452  if (ff_jni_exception_check(env, 1, codec) < 0) {
1453  ret = AVERROR_EXTERNAL;
1454  goto fail;
1455  }
1456 
1457 fail:
1458  return ret;
1459 }
1460 
1461 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1462 {
1463  int ret = 0;
1464  JNIEnv *env = NULL;
1465 
1467 
1468  (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, (jint)idx, (jint)offset, (jint)size, time, flags);
1469  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1470  ret = AVERROR_EXTERNAL;
1471  goto fail;
1472  }
1473 
1474 fail:
1475  return ret;
1476 }
1477 
1479 {
1480  int ret = 0;
1481  JNIEnv *env = NULL;
1482 
1484 
1485  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs);
1486  if (ff_jni_exception_check(env, 1, codec) < 0) {
1487  return AVERROR_EXTERNAL;
1488  }
1489 
1490  info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id);
1491  if (ff_jni_exception_check(env, 1, codec) < 0) {
1492  return AVERROR_EXTERNAL;
1493  }
1494 
1495  info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id);
1496  if (ff_jni_exception_check(env, 1, codec) < 0) {
1497  return AVERROR_EXTERNAL;
1498  }
1499 
1500  info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id);
1501  if (ff_jni_exception_check(env, 1, codec) < 0) {
1502  return AVERROR_EXTERNAL;
1503  }
1504 
1505  info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id);
1506  if (ff_jni_exception_check(env, 1, codec) < 0) {
1507  return AVERROR_EXTERNAL;
1508  }
1509 
1510  return ret;
1511 }
1512 
1514 {
1515  uint8_t *ret = NULL;
1516  JNIEnv *env = NULL;
1517 
1518  jobject buffer = NULL;
1519  jobject input_buffers = NULL;
1520 
1521  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1522 
1523  if (codec->has_get_i_o_buffer) {
1524  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, (jint)idx);
1525  if (ff_jni_exception_check(env, 1, codec) < 0) {
1526  goto fail;
1527  }
1528  } else {
1529  if (!codec->input_buffers) {
1530  input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1531  if (ff_jni_exception_check(env, 1, codec) < 0) {
1532  goto fail;
1533  }
1534 
1535  codec->input_buffers = (*env)->NewGlobalRef(env, input_buffers);
1536  if (ff_jni_exception_check(env, 1, codec) < 0) {
1537  goto fail;
1538  }
1539  }
1540 
1541  buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1542  if (ff_jni_exception_check(env, 1, codec) < 0) {
1543  goto fail;
1544  }
1545  }
1546 
1547  ret = (*env)->GetDirectBufferAddress(env, buffer);
1548  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1549 fail:
1550  if (buffer) {
1551  (*env)->DeleteLocalRef(env, buffer);
1552  }
1553 
1554  if (input_buffers) {
1555  (*env)->DeleteLocalRef(env, input_buffers);
1556  }
1557 
1558  return ret;
1559 }
1560 
1562 {
1563  uint8_t *ret = NULL;
1564  JNIEnv *env = NULL;
1565 
1566  jobject buffer = NULL;
1567  jobject output_buffers = NULL;
1568 
1569  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1570 
1571  if (codec->has_get_i_o_buffer) {
1572  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, (jint)idx);
1573  if (ff_jni_exception_check(env, 1, codec) < 0) {
1574  goto fail;
1575  }
1576  } else {
1577  if (!codec->output_buffers) {
1578  output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1579  if (ff_jni_exception_check(env, 1, codec) < 0) {
1580  goto fail;
1581  }
1582 
1583  codec->output_buffers = (*env)->NewGlobalRef(env, output_buffers);
1584  if (ff_jni_exception_check(env, 1, codec) < 0) {
1585  goto fail;
1586  }
1587  }
1588 
1589  buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1590  if (ff_jni_exception_check(env, 1, codec) < 0) {
1591  goto fail;
1592  }
1593  }
1594 
1595  ret = (*env)->GetDirectBufferAddress(env, buffer);
1596  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1597 fail:
1598  if (buffer) {
1599  (*env)->DeleteLocalRef(env, buffer);
1600  }
1601 
1602  if (output_buffers) {
1603  (*env)->DeleteLocalRef(env, output_buffers);
1604  }
1605 
1606  return ret;
1607 }
1608 
1610 {
1611  FFAMediaFormat *ret = NULL;
1612  JNIEnv *env = NULL;
1613 
1614  jobject mediaformat = NULL;
1615 
1616  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1617 
1618  mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1619  if (ff_jni_exception_check(env, 1, codec) < 0) {
1620  goto fail;
1621  }
1622 
1623  ret = ff_AMediaFormat_newFromObject(mediaformat);
1624 fail:
1625  if (mediaformat) {
1626  (*env)->DeleteLocalRef(env, mediaformat);
1627  }
1628 
1629  return ret;
1630 }
1631 
1633 {
1634  return idx == codec->INFO_TRY_AGAIN_LATER;
1635 }
1636 
1638 {
1639  return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1640 }
1641 
1643 {
1644  return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1645 }
1646 
1648 {
1649  return codec->BUFFER_FLAG_CODEC_CONFIG;
1650 }
1651 
1653 {
1654  return codec->BUFFER_FLAG_END_OF_STREAM;
1655 }
1656 
1658 {
1659  return codec->BUFFER_FLAG_KEY_FRAME;
1660 }
1661 
1663 {
1664  return codec->CONFIGURE_FLAG_ENCODE;
1665 }
1666 
1668 {
1669  int ret = 0;
1670 
1671  if (!codec->has_get_i_o_buffer) {
1672  if (codec->output_buffers) {
1673  JNIEnv *env = NULL;
1674 
1675  env = ff_jni_get_env(codec);
1676  if (!env) {
1677  ret = AVERROR_EXTERNAL;
1678  goto fail;
1679  }
1680 
1681  (*env)->DeleteGlobalRef(env, codec->output_buffers);
1682  codec->output_buffers = NULL;
1683  }
1684  }
1685 
1686 fail:
1687  return ret;
1688 }
1689 
1691 {
1692  int ret = -1;
1693  JNIEnv *env = NULL;
1694  jclass versionClass;
1695  jfieldID sdkIntFieldID;
1696  JNI_GET_ENV_OR_RETURN(env, avctx, -1);
1697 
1698  versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
1699  sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I");
1700  ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
1701  (*env)->DeleteLocalRef(env, versionClass);
1702  return ret;
1703 }
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:2942
#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:2901
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:2952
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:2940
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:2989
int ff_Build_SDK_INT(AVCodecContext *avctx)
int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:2943
char * ff_AMediaFormat_toString(FFAMediaFormat *format)
ptrdiff_t size
Definition: opengl_enc.c:100
#define FF_PROFILE_HEVC_MAIN_10
Definition: avcodec.h:2990
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:2948
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:2944
#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:121
#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:2991
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:2949
enum AVCodecID codec_id
Definition: avcodec.h:1578
#define CREATE_ENCODER_BY_TYPE
main external API structure.
Definition: avcodec.h:1568
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:2946
Describe the class of an AVClass context structure.
Definition: log.h:67
#define FF_PROFILE_H264_HIGH_444
Definition: avcodec.h:2951
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:2953
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:2941
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:2945
#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