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 
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 
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 
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 
612  format = av_mallocz(sizeof(FFAMediaFormat));
613  if (!format) {
614  return NULL;
615  }
616  format->class = &amediaformat_class;
617 
618  env = ff_jni_get_env(format);
619  if (!env) {
620  av_freep(&format);
621  return NULL;
622  }
623 
624  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
625  goto fail;
626  }
627 
628  format->object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
629  if (!format->object) {
630  goto fail;
631  }
632 
633  format->object = (*env)->NewGlobalRef(env, format->object);
634  if (!format->object) {
635  goto fail;
636  }
637 
638  return format;
639 fail:
640  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
641 
642  av_freep(&format);
643 
644  return NULL;
645 }
646 
648 {
649  JNIEnv *env = NULL;
651 
652  format = av_mallocz(sizeof(FFAMediaFormat));
653  if (!format) {
654  return NULL;
655  }
656  format->class = &amediaformat_class;
657 
658  env = ff_jni_get_env(format);
659  if (!env) {
660  av_freep(&format);
661  return NULL;
662  }
663 
664  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
665  goto fail;
666  }
667 
668  format->object = (*env)->NewGlobalRef(env, object);
669  if (!format->object) {
670  goto fail;
671  }
672 
673  return format;
674 fail:
675  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
676 
677  av_freep(&format);
678 
679  return NULL;
680 }
681 
683 {
684  int ret = 0;
685 
686  JNIEnv *env = NULL;
687 
688  if (!format) {
689  return 0;
690  }
691 
693 
694  (*env)->DeleteGlobalRef(env, format->object);
695  format->object = NULL;
696 
697  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
698 
699  av_freep(&format);
700 
701  return ret;
702 }
703 
705 {
706  char *ret = NULL;
707 
708  JNIEnv *env = NULL;
709  jstring description = NULL;
710 
711  av_assert0(format != NULL);
712 
713  JNI_GET_ENV_OR_RETURN(env, format, NULL);
714 
715  description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
716  if (ff_jni_exception_check(env, 1, NULL) < 0) {
717  goto fail;
718  }
719 
720  ret = ff_jni_jstring_to_utf_chars(env, description, format);
721 fail:
722  if (description) {
723  (*env)->DeleteLocalRef(env, description);
724  }
725 
726  return ret;
727 }
728 
730 {
731  int ret = 1;
732 
733  JNIEnv *env = NULL;
734  jstring key = NULL;
735 
736  av_assert0(format != NULL);
737 
738  JNI_GET_ENV_OR_RETURN(env, format, 0);
739 
740  key = ff_jni_utf_chars_to_jstring(env, name, format);
741  if (!key) {
742  ret = 0;
743  goto fail;
744  }
745 
746  *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
747  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
748  ret = 0;
749  goto fail;
750  }
751 
752  ret = 1;
753 fail:
754  if (key) {
755  (*env)->DeleteLocalRef(env, key);
756  }
757 
758  return ret;
759 }
760 
762 {
763  int ret = 1;
764 
765  JNIEnv *env = NULL;
766  jstring key = NULL;
767 
768  av_assert0(format != NULL);
769 
770  JNI_GET_ENV_OR_RETURN(env, format, 0);
771 
772  key = ff_jni_utf_chars_to_jstring(env, name, format);
773  if (!key) {
774  ret = 0;
775  goto fail;
776  }
777 
778  *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
779  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
780  ret = 0;
781  goto fail;
782  }
783 
784  ret = 1;
785 fail:
786  if (key) {
787  (*env)->DeleteLocalRef(env, key);
788  }
789 
790  return ret;
791 }
792 
794 {
795  int ret = 1;
796 
797  JNIEnv *env = NULL;
798  jstring key = NULL;
799 
800  av_assert0(format != NULL);
801 
802  JNI_GET_ENV_OR_RETURN(env, format, 0);
803 
804  key = ff_jni_utf_chars_to_jstring(env, name, format);
805  if (!key) {
806  ret = 0;
807  goto fail;
808  }
809 
810  *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
811  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
812  ret = 0;
813  goto fail;
814  }
815 
816  ret = 1;
817 fail:
818  if (key) {
819  (*env)->DeleteLocalRef(env, key);
820  }
821 
822  return ret;
823 }
824 
825 int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
826 {
827  int ret = 1;
828 
829  JNIEnv *env = NULL;
830  jstring key = NULL;
831  jobject result = NULL;
832 
833  av_assert0(format != NULL);
834 
835  JNI_GET_ENV_OR_RETURN(env, format, 0);
836 
837  key = ff_jni_utf_chars_to_jstring(env, name, format);
838  if (!key) {
839  ret = 0;
840  goto fail;
841  }
842 
843  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
844  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
845  ret = 0;
846  goto fail;
847  }
848 
849  *data = (*env)->GetDirectBufferAddress(env, result);
850  *size = (*env)->GetDirectBufferCapacity(env, result);
851 
852  if (*data && *size) {
853  void *src = *data;
854  *data = av_malloc(*size);
855  if (!*data) {
856  ret = 0;
857  goto fail;
858  }
859 
860  memcpy(*data, src, *size);
861  }
862 
863  ret = 1;
864 fail:
865  if (key) {
866  (*env)->DeleteLocalRef(env, key);
867  }
868 
869  if (result) {
870  (*env)->DeleteLocalRef(env, result);
871  }
872 
873  return ret;
874 }
875 
876 int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
877 {
878  int ret = 1;
879 
880  JNIEnv *env = NULL;
881  jstring key = NULL;
882  jstring result = NULL;
883 
884  av_assert0(format != NULL);
885 
886  JNI_GET_ENV_OR_RETURN(env, format, 0);
887 
888  key = ff_jni_utf_chars_to_jstring(env, name, format);
889  if (!key) {
890  ret = 0;
891  goto fail;
892  }
893 
894  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
895  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
896  ret = 0;
897  goto fail;
898  }
899 
900  *out = ff_jni_jstring_to_utf_chars(env, result, format);
901  if (!*out) {
902  ret = 0;
903  goto fail;
904  }
905 
906  ret = 1;
907 fail:
908  if (key) {
909  (*env)->DeleteLocalRef(env, key);
910  }
911 
912  if (result) {
913  (*env)->DeleteLocalRef(env, result);
914  }
915 
916  return ret;
917 }
918 
920 {
921  JNIEnv *env = NULL;
922  jstring key = NULL;
923 
924  av_assert0(format != NULL);
925 
926  JNI_GET_ENV_OR_RETURN_VOID(env, format);
927 
928  key = ff_jni_utf_chars_to_jstring(env, name, format);
929  if (!key) {
930  goto fail;
931  }
932 
933  (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
934  if (ff_jni_exception_check(env, 1, format) < 0) {
935  goto fail;
936  }
937 
938 fail:
939  if (key) {
940  (*env)->DeleteLocalRef(env, key);
941  }
942 }
943 
945 {
946  JNIEnv *env = NULL;
947  jstring key = NULL;
948 
949  av_assert0(format != NULL);
950 
951  JNI_GET_ENV_OR_RETURN_VOID(env, format);
952 
953  key = ff_jni_utf_chars_to_jstring(env, name, format);
954  if (!key) {
955  goto fail;
956  }
957 
958  (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
959  if (ff_jni_exception_check(env, 1, format) < 0) {
960  goto fail;
961  }
962 
963 fail:
964  if (key) {
965  (*env)->DeleteLocalRef(env, key);
966  }
967 }
968 
970 {
971  JNIEnv *env = NULL;
972  jstring key = NULL;
973 
974  av_assert0(format != NULL);
975 
976  JNI_GET_ENV_OR_RETURN_VOID(env, format);
977 
978  key = ff_jni_utf_chars_to_jstring(env, name, format);
979  if (!key) {
980  goto fail;
981  }
982 
983  (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
984  if (ff_jni_exception_check(env, 1, format) < 0) {
985  goto fail;
986  }
987 
988 fail:
989  if (key) {
990  (*env)->DeleteLocalRef(env, key);
991  }
992 }
993 
994 void ff_AMediaFormat_setString(FFAMediaFormat* format, const char* name, const char* value)
995 {
996  JNIEnv *env = NULL;
997  jstring key = NULL;
998  jstring string = NULL;
999 
1000  av_assert0(format != NULL);
1001 
1002  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1003 
1004  key = ff_jni_utf_chars_to_jstring(env, name, format);
1005  if (!key) {
1006  goto fail;
1007  }
1008 
1009  string = ff_jni_utf_chars_to_jstring(env, value, format);
1010  if (!string) {
1011  goto fail;
1012  }
1013 
1014  (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
1015  if (ff_jni_exception_check(env, 1, format) < 0) {
1016  goto fail;
1017  }
1018 
1019 fail:
1020  if (key) {
1021  (*env)->DeleteLocalRef(env, key);
1022  }
1023 
1024  if (string) {
1025  (*env)->DeleteLocalRef(env, string);
1026  }
1027 }
1028 
1029 void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
1030 {
1031  JNIEnv *env = NULL;
1032  jstring key = NULL;
1033  jobject buffer = NULL;
1034  void *buffer_data = NULL;
1035 
1036  av_assert0(format != NULL);
1037 
1038  JNI_GET_ENV_OR_RETURN_VOID(env, format);
1039 
1040  key = ff_jni_utf_chars_to_jstring(env, name, format);
1041  if (!key) {
1042  goto fail;
1043  }
1044 
1045  if (!data || !size) {
1046  goto fail;
1047  }
1048 
1049  buffer_data = av_malloc(size);
1050  if (!buffer_data) {
1051  goto fail;
1052  }
1053 
1054  memcpy(buffer_data, data, size);
1055 
1056  buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
1057  if (!buffer) {
1058  goto fail;
1059  }
1060 
1061  (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
1062  if (ff_jni_exception_check(env, 1, format) < 0) {
1063  goto fail;
1064  }
1065 
1066 fail:
1067  if (key) {
1068  (*env)->DeleteLocalRef(env, key);
1069  }
1070 
1071  if (buffer) {
1072  (*env)->DeleteLocalRef(env, buffer);
1073  }
1074 }
1075 
1077 {
1078  int ret = 0;
1079  JNIEnv *env = NULL;
1080 
1082 
1083  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1084  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1085  goto fail;
1086  }
1087 
1088  codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
1089  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1090  goto fail;
1091  }
1092 
1093  codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
1094  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1095  goto fail;
1096  }
1097 
1098  if (codec->jfields.buffer_flag_key_frame_id) {
1099  codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
1100  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1101  goto fail;
1102  }
1103  }
1104 
1105  codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
1106  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1107  goto fail;
1108  }
1109 
1110  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1111  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1112  goto fail;
1113  }
1114 
1115  codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
1116  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1117  goto fail;
1118  }
1119 
1120  codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
1121  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1122  goto fail;
1123  }
1124 
1125 fail:
1126 
1127  return ret;
1128 }
1129 
1131 {
1132  JNIEnv *env = NULL;
1133  FFAMediaCodec *codec = NULL;
1134  jstring codec_name = NULL;
1135 
1136  codec = av_mallocz(sizeof(FFAMediaCodec));
1137  if (!codec) {
1138  return NULL;
1139  }
1140  codec->class = &amediacodec_class;
1141 
1142  env = ff_jni_get_env(codec);
1143  if (!env) {
1144  av_freep(&codec);
1145  return NULL;
1146  }
1147 
1148  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1149  goto fail;
1150  }
1151 
1152  codec_name = ff_jni_utf_chars_to_jstring(env, name, codec);
1153  if (!codec_name) {
1154  goto fail;
1155  }
1156 
1157  codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_by_codec_name_id, codec_name);
1158  if (ff_jni_exception_check(env, 1, codec) < 0) {
1159  goto fail;
1160  }
1161 
1162  codec->object = (*env)->NewGlobalRef(env, codec->object);
1163  if (!codec->object) {
1164  goto fail;
1165  }
1166 
1167  if (codec_init_static_fields(codec) < 0) {
1168  goto fail;
1169  }
1170 
1172  codec->has_get_i_o_buffer = 1;
1173  }
1174 
1175  return codec;
1176 fail:
1177  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1178 
1179  if (codec_name) {
1180  (*env)->DeleteLocalRef(env, codec_name);
1181  }
1182 
1183  av_freep(&codec);
1184 
1185  return NULL;
1186 }
1187 
1189 {
1190  JNIEnv *env = NULL;
1191  FFAMediaCodec *codec = NULL;
1192  jstring mime_type = NULL;
1193 
1194  codec = av_mallocz(sizeof(FFAMediaCodec));
1195  if (!codec) {
1196  return NULL;
1197  }
1198  codec->class = &amediacodec_class;
1199 
1200  env = ff_jni_get_env(codec);
1201  if (!env) {
1202  av_freep(&codec);
1203  return NULL;
1204  }
1205 
1206  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1207  goto fail;
1208  }
1209 
1210  mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
1211  if (!mime_type) {
1212  goto fail;
1213  }
1214 
1215  codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type);
1216  if (ff_jni_exception_check(env, 1, codec) < 0) {
1217  goto fail;
1218  }
1219 
1220  codec->object = (*env)->NewGlobalRef(env, codec->object);
1221  if (!codec->object) {
1222  goto fail;
1223  }
1224 
1225  if (codec_init_static_fields(codec) < 0) {
1226  goto fail;
1227  }
1228 
1230  codec->has_get_i_o_buffer = 1;
1231  }
1232 
1233  return codec;
1234 fail:
1235  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1236 
1237  if (mime_type) {
1238  (*env)->DeleteLocalRef(env, mime_type);
1239  }
1240 
1241  av_freep(&codec);
1242 
1243  return NULL;
1244 }
1245 
1247 {
1248  JNIEnv *env = NULL;
1249  FFAMediaCodec *codec = NULL;
1250  jstring mime_type = NULL;
1251 
1252  codec = av_mallocz(sizeof(FFAMediaCodec));
1253  if (!codec) {
1254  return NULL;
1255  }
1256  codec->class = &amediacodec_class;
1257 
1258  env = ff_jni_get_env(codec);
1259  if (!env) {
1260  av_freep(&codec);
1261  return NULL;
1262  }
1263 
1264  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1265  goto fail;
1266  }
1267 
1268  mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
1269  if (!mime_type) {
1270  goto fail;
1271  }
1272 
1273  codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_encoder_by_type_id, mime_type);
1274  if (ff_jni_exception_check(env, 1, codec) < 0) {
1275  goto fail;
1276  }
1277 
1278  codec->object = (*env)->NewGlobalRef(env, codec->object);
1279  if (!codec->object) {
1280  goto fail;
1281  }
1282 
1283  if (codec_init_static_fields(codec) < 0) {
1284  goto fail;
1285  }
1286 
1288  codec->has_get_i_o_buffer = 1;
1289  }
1290 
1291  return codec;
1292 fail:
1293  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1294 
1295  if (mime_type) {
1296  (*env)->DeleteLocalRef(env, mime_type);
1297  }
1298 
1299  av_freep(&codec);
1300 
1301  return NULL;
1302 }
1303 
1305 {
1306  int ret = 0;
1307 
1308  JNIEnv *env = NULL;
1309 
1310  if (!codec) {
1311  return 0;
1312  }
1313 
1315 
1316  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
1317  if (ff_jni_exception_check(env, 1, codec) < 0) {
1318  ret = AVERROR_EXTERNAL;
1319  }
1320 
1321  (*env)->DeleteGlobalRef(env, codec->object);
1322  codec->object = NULL;
1323 
1324  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1325 
1326  av_freep(&codec);
1327 
1328  return ret;
1329 }
1330 
1332 {
1333  char *ret = NULL;
1334  JNIEnv *env = NULL;
1335  jobject *name = NULL;
1336 
1337  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1338 
1339  name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1340  if (ff_jni_exception_check(env, 1, codec) < 0) {
1341  goto fail;
1342  }
1343 
1344  ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1345 
1346 fail:
1347  return ret;
1348 }
1349 
1350 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
1351 {
1352  int ret = 0;
1353  JNIEnv *env = NULL;
1354 
1356 
1357  (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
1358  if (ff_jni_exception_check(env, 1, codec) < 0) {
1359  ret = AVERROR_EXTERNAL;
1360  goto fail;
1361  }
1362 
1363 fail:
1364  return ret;
1365 }
1366 
1368 {
1369  int ret = 0;
1370  JNIEnv *env = NULL;
1371 
1373 
1374  (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1375  if (ff_jni_exception_check(env, 1, codec) < 0) {
1376  ret = AVERROR_EXTERNAL;
1377  goto fail;
1378  }
1379 
1380 fail:
1381  return ret;
1382 }
1383 
1385 {
1386  int ret = 0;
1387  JNIEnv *env = NULL;
1388 
1390 
1391  (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1392  if (ff_jni_exception_check(env, 1, codec) < 0) {
1393  ret = AVERROR_EXTERNAL;
1394  goto fail;
1395  }
1396 
1397 fail:
1398  return ret;
1399 }
1400 
1402 {
1403  int ret = 0;
1404  JNIEnv *env = NULL;
1405 
1407 
1408  (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1409  if (ff_jni_exception_check(env, 1, codec) < 0) {
1410  ret = AVERROR_EXTERNAL;
1411  goto fail;
1412  }
1413 
1414 fail:
1415  return ret;
1416 }
1417 
1418 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
1419 {
1420  int ret = 0;
1421  JNIEnv *env = NULL;
1422 
1424 
1425  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, idx, render);
1426  if (ff_jni_exception_check(env, 1, codec) < 0) {
1427  ret = AVERROR_EXTERNAL;
1428  goto fail;
1429  }
1430 
1431 fail:
1432  return ret;
1433 }
1434 
1435 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
1436 {
1437  int ret = 0;
1438  JNIEnv *env = NULL;
1439 
1441 
1442  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, idx, timestampNs);
1443  if (ff_jni_exception_check(env, 1, codec) < 0) {
1444  ret = AVERROR_EXTERNAL;
1445  goto fail;
1446  }
1447 
1448 fail:
1449  return ret;
1450 }
1451 
1452 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
1453 {
1454  int ret = 0;
1455  JNIEnv *env = NULL;
1456 
1458 
1459  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1460  if (ff_jni_exception_check(env, 1, codec) < 0) {
1461  ret = AVERROR_EXTERNAL;
1462  goto fail;
1463  }
1464 
1465 fail:
1466  return ret;
1467 }
1468 
1469 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1470 {
1471  int ret = 0;
1472  JNIEnv *env = NULL;
1473 
1475 
1476  (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, idx, offset, size, time, flags);
1477  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1478  ret = AVERROR_EXTERNAL;
1479  goto fail;
1480  }
1481 
1482 fail:
1483  return ret;
1484 }
1485 
1487 {
1488  int ret = 0;
1489  JNIEnv *env = NULL;
1490 
1491  jobject mediainfo = NULL;
1492 
1494 
1495  mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
1496  if (ff_jni_exception_check(env, 1, codec) < 0) {
1497  ret = AVERROR_EXTERNAL;
1498  goto fail;
1499  }
1500 
1501  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, mediainfo, timeoutUs);
1502  if (ff_jni_exception_check(env, 1, codec) < 0) {
1503  ret = AVERROR_EXTERNAL;
1504  goto fail;
1505  }
1506 
1507  info->flags = (*env)->GetIntField(env, mediainfo, codec->jfields.flags_id);
1508  if (ff_jni_exception_check(env, 1, codec) < 0) {
1509  ret = AVERROR_EXTERNAL;
1510  goto fail;
1511  }
1512 
1513  info->offset = (*env)->GetIntField(env, mediainfo, codec->jfields.offset_id);
1514  if (ff_jni_exception_check(env, 1, codec) < 0) {
1515  ret = AVERROR_EXTERNAL;
1516  goto fail;
1517  }
1518 
1519  info->presentationTimeUs = (*env)->GetLongField(env, mediainfo, codec->jfields.presentation_time_us_id);
1520  if (ff_jni_exception_check(env, 1, codec) < 0) {
1521  ret = AVERROR_EXTERNAL;
1522  goto fail;
1523  }
1524 
1525  info->size = (*env)->GetIntField(env, mediainfo, codec->jfields.size_id);
1526  if (ff_jni_exception_check(env, 1, codec) < 0) {
1527  ret = AVERROR_EXTERNAL;
1528  goto fail;
1529  }
1530 fail:
1531  if (mediainfo) {
1532  (*env)->DeleteLocalRef(env, mediainfo);
1533  }
1534 
1535  return ret;
1536 }
1537 
1539 {
1540  uint8_t *ret = NULL;
1541  JNIEnv *env = NULL;
1542 
1543  jobject buffer = NULL;
1544 
1545  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1546 
1547  if (codec->has_get_i_o_buffer) {
1548  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, idx);
1549  if (ff_jni_exception_check(env, 1, codec) < 0) {
1550  goto fail;
1551  }
1552  } else {
1553  if (!codec->input_buffers) {
1554  codec->input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1555  if (ff_jni_exception_check(env, 1, codec) < 0) {
1556  goto fail;
1557  }
1558 
1559  codec->input_buffers = (*env)->NewGlobalRef(env, codec->input_buffers);
1560  if (ff_jni_exception_check(env, 1, codec) < 0) {
1561  goto fail;
1562  }
1563  }
1564 
1565  buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1566  if (ff_jni_exception_check(env, 1, codec) < 0) {
1567  goto fail;
1568  }
1569  }
1570 
1571  ret = (*env)->GetDirectBufferAddress(env, buffer);
1572  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1573 fail:
1574  if (buffer) {
1575  (*env)->DeleteLocalRef(env, buffer);
1576  }
1577 
1578  return ret;
1579 }
1580 
1582 {
1583  uint8_t *ret = NULL;
1584  JNIEnv *env = NULL;
1585 
1586  jobject buffer = NULL;
1587 
1588  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1589 
1590  if (codec->has_get_i_o_buffer) {
1591  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, idx);
1592  if (ff_jni_exception_check(env, 1, codec) < 0) {
1593  goto fail;
1594  }
1595  } else {
1596  if (!codec->output_buffers) {
1597  codec->output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1598  if (ff_jni_exception_check(env, 1, codec) < 0) {
1599  goto fail;
1600  }
1601 
1602  codec->output_buffers = (*env)->NewGlobalRef(env, codec->output_buffers);
1603  if (ff_jni_exception_check(env, 1, codec) < 0) {
1604  goto fail;
1605  }
1606  }
1607 
1608  buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1609  if (ff_jni_exception_check(env, 1, codec) < 0) {
1610  goto fail;
1611  }
1612  }
1613 
1614  ret = (*env)->GetDirectBufferAddress(env, buffer);
1615  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1616 fail:
1617  if (buffer) {
1618  (*env)->DeleteLocalRef(env, buffer);
1619  }
1620 
1621  return ret;
1622 }
1623 
1625 {
1626  FFAMediaFormat *ret = NULL;
1627  JNIEnv *env = NULL;
1628 
1629  jobject mediaformat = NULL;
1630 
1631  JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1632 
1633  mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1634  if (ff_jni_exception_check(env, 1, codec) < 0) {
1635  goto fail;
1636  }
1637 
1638  ret = ff_AMediaFormat_newFromObject(mediaformat);
1639 fail:
1640  if (mediaformat) {
1641  (*env)->DeleteLocalRef(env, mediaformat);
1642  }
1643 
1644  return ret;
1645 }
1646 
1648 {
1649  return idx == codec->INFO_TRY_AGAIN_LATER;
1650 }
1651 
1653 {
1654  return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1655 }
1656 
1658 {
1659  return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1660 }
1661 
1663 {
1664  return codec->BUFFER_FLAG_CODEC_CONFIG;
1665 }
1666 
1668 {
1669  return codec->BUFFER_FLAG_END_OF_STREAM;
1670 }
1671 
1673 {
1674  return codec->BUFFER_FLAG_KEY_FRAME;
1675 }
1676 
1678 {
1679  return codec->CONFIGURE_FLAG_ENCODE;
1680 }
1681 
1683 {
1684  int ret = 0;
1685 
1686  if (!codec->has_get_i_o_buffer) {
1687  if (codec->output_buffers) {
1688  JNIEnv *env = NULL;
1689 
1690  env = ff_jni_get_env(codec);
1691  if (!env) {
1692  ret = AVERROR_EXTERNAL;
1693  goto fail;
1694  }
1695 
1696  (*env)->DeleteGlobalRef(env, codec->output_buffers);
1697  codec->output_buffers = NULL;
1698  }
1699  }
1700 
1701 fail:
1702  return ret;
1703 }
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:3222
#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:369
char * ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
Memory handling functions.
FFAMediaCodec * ff_AMediaCodec_createCodecByName(const char *name)
void ff_AMediaFormat_setBuffer(FFAMediaFormat *format, const char *name, void *data, size_t size)
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
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:252
static const struct FFJniField jni_amediacodeclist_mapping[]
int profile
profile
Definition: avcodec.h:3181
static const struct FFJniField jni_amediacodec_mapping[]
static const AVClass amediacodec_class
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE
Definition: avcodec.h:3232
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 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:3220
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:3269
#define LIBAVCODEC_VERSION_INT
Definition: version.h:34
int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
FFAMediaCodec * ff_AMediaCodec_createEncoderByType(const char *mime)
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:3223
char * ff_AMediaFormat_toString(FFAMediaFormat *format)
ptrdiff_t size
Definition: opengl_enc.c:101
#define FF_PROFILE_HEVC_MAIN_10
Definition: avcodec.h:3270
struct JNIAMediaCodecFields JNIAMediaCodecFields
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)
av_default_item_name
struct JNIAMediaCodecListFields JNIAMediaCodecListFields
jfieldID info_output_format_changed_id
uint8_t * ff_AMediaCodec_getInputBuffer(FFAMediaCodec *codec, size_t idx, size_t *out_size)
#define FF_PROFILE_H264_HIGH_422
Definition: avcodec.h:3228
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:3224
#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:83
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:3271
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
#define src
Definition: vp9dsp.c:530
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)
struct JNIAMediaFormatFields JNIAMediaFormatFields
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:3229
enum AVCodecID codec_id
Definition: avcodec.h:1693
main external API structure.
Definition: avcodec.h:1676
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:3226
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:3231
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:42
jmethodID release_output_buffer_at_time_id
static int flags
Definition: cpu.c:47
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:3233
FILE * out
Definition: movenc.c:54
int ff_AMediaFormat_getInt64(FFAMediaFormat *format, const char *name, int64_t *out)
#define av_freep(p)
FFAMediaCodec * ff_AMediaCodec_createDecoderByType(const char *mime)
#define FF_PROFILE_H264_CONSTRAINED_BASELINE
Definition: avcodec.h:3221
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:3225
#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