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