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 
66 
67 static const struct FFJniField jni_amediacodeclist_mapping[] = {
68  { "android/media/MediaCodecList", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_list_class), 1 },
69  { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, init_id), 0 },
70  { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, find_decoder_for_format_id), 0 },
71 
72  { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_count_id), 1 },
73  { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_info_at_id), 1 },
74 
75  { "android/media/MediaCodecInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_info_class), 1 },
76  { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_name_id), 1 },
77  { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_capabilities_id), 1 },
78  { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_supported_types_id), 1 },
79  { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_encoder_id), 1 },
80 
81  { "android/media/MediaCodecInfo$CodecCapabilities", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_capabilities_class), 1 },
82  { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, color_formats_id), 1 },
83  { "android/media/MediaCodecInfo$CodecCapabilities", "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_levels_id), 1 },
84 
85  { "android/media/MediaCodecInfo$CodecProfileLevel", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_profile_level_class), 1 },
86  { "android/media/MediaCodecInfo$CodecProfileLevel", "profile", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_id), 1 },
87  { "android/media/MediaCodecInfo$CodecProfileLevel", "level", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, level_id), 1 },
88 
89  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileBaseline", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_baseline_id), 1 },
90  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileMain", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_main_id), 1 },
91  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileExtended", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_extended_id), 1 },
92  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high_id), 1 },
93  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high10_id), 1 },
94  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh422", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high422_id), 1 },
95  { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh444", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high444_id), 1 },
96 
97  { NULL }
98 };
99 
101 
103 
104  jmethodID init_id;
105 
106  jmethodID get_integer_id;
107  jmethodID get_long_id;
108  jmethodID get_float_id;
109  jmethodID get_bytebuffer_id;
110  jmethodID get_string_id;
111 
112  jmethodID set_integer_id;
113  jmethodID set_long_id;
114  jmethodID set_float_id;
115  jmethodID set_bytebuffer_id;
116  jmethodID set_string_id;
117 
118  jmethodID to_string_id;
119 
121 
122 static const struct FFJniField jni_amediaformat_mapping[] = {
123  { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaFormatFields, mediaformat_class), 1 },
124 
125  { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, init_id), 1 },
126 
127  { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_integer_id), 1 },
128  { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_long_id), 1 },
129  { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_float_id), 1 },
130  { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_bytebuffer_id), 1 },
131  { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_string_id), 1 },
132 
133  { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_integer_id), 1 },
134  { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_long_id), 1 },
135  { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_float_id), 1 },
136  { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_bytebuffer_id), 1 },
137  { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_string_id), 1 },
138 
139  { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, to_string_id), 1 },
140 
141  { NULL }
142 };
143 
144 static const AVClass amediaformat_class = {
145  .class_name = "amediaformat",
146  .item_name = av_default_item_name,
147  .version = LIBAVCODEC_VERSION_INT,
148 };
149 
151 
152  const AVClass *class;
154  jobject object;
155 };
156 
158 
160 
164 
168 
170 
174 
175  jmethodID get_name_id;
176 
177  jmethodID configure_id;
178  jmethodID start_id;
179  jmethodID flush_id;
180  jmethodID stop_id;
181  jmethodID release_id;
182 
184 
189 
195 
197 
198  jmethodID init_id;
199 
200  jfieldID flags_id;
201  jfieldID offset_id;
203  jfieldID size_id;
204 
206 
207 static const struct FFJniField jni_amediacodec_mapping[] = {
208  { "android/media/MediaCodec", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediacodec_class), 1 },
209 
210  { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_try_again_later_id), 1 },
211  { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_buffers_changed_id), 1 },
212  { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_format_changed_id), 1 },
213 
214  { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_codec_config_id), 1 },
215  { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_end_of_stream_id), 1 },
216  { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_key_frame_id), 0 },
217 
218  { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, configure_flag_encode_id), 1 },
219 
220  { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_by_codec_name_id), 1 },
221  { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_decoder_by_type_id), 1 },
222  { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_encoder_by_type_id), 1 },
223 
224  { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_name_id), 1 },
225 
226  { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, configure_id), 1 },
227  { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, start_id), 1 },
228  { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, flush_id), 1 },
229  { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, stop_id), 1 },
230  { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_id), 1 },
231 
232  { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_format_id), 1 },
233 
234  { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_input_buffer_id), 1 },
235  { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, queue_input_buffer_id), 1 },
236  { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffer_id), 0 },
237  { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffers_id), 1 },
238 
239  { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_output_buffer_id), 1 },
240  { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffer_id), 0 },
241  { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffers_id), 1 },
242  { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_id), 1 },
243  { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_at_time_id), 0 },
244 
245  { "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediainfo_class), 1 },
246 
247  { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, init_id), 1 },
248  { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, flags_id), 1 },
249  { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, offset_id), 1 },
250  { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, presentation_time_us_id), 1 },
251  { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, size_id), 1 },
252 
253  { NULL }
254 };
255 
256 static const AVClass amediacodec_class = {
257  .class_name = "amediacodec",
258  .item_name = av_default_item_name,
259  .version = LIBAVCODEC_VERSION_INT,
260 };
261 
263 
264  const AVClass *class;
265 
267 
268  jobject object;
269 
270  jobject input_buffers;
271  jobject output_buffers;
272 
276 
280 
282 
284 };
285 
286 #define JNI_ATTACH_ENV_OR_RETURN(env, attached, log_ctx, ret) do { \
287  (env) = ff_jni_attach_env(attached, log_ctx); \
288  if (!(env)) { \
289  return ret; \
290  } \
291 } while (0)
292 
293 #define JNI_ATTACH_ENV_OR_RETURN_VOID(env, attached, log_ctx) do { \
294  (env) = ff_jni_attach_env(attached, log_ctx); \
295  if (!(env)) { \
296  return; \
297  } \
298 } while (0)
299 
300 #define JNI_DETACH_ENV(attached, log_ctx) do { \
301  if (attached) \
302  ff_jni_detach_env(log_ctx); \
303 } while (0)
304 
305 
306 
308 {
309  int ret = -1;
310 
311  int attached = 0;
312  JNIEnv *env = NULL;
313  struct JNIAMediaCodecListFields jfields = { 0 };
314 
315  JNI_ATTACH_ENV_OR_RETURN(env, &attached, avctx, -1);
316 
317  if (ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx) < 0) {
318  goto done;
319  }
320 
321  if (avctx->codec_id == AV_CODEC_ID_H264) {
322  jfieldID field_id = 0;
323 
324  switch(avctx->profile) {
327  field_id = jfields.avc_profile_baseline_id;
328  break;
330  field_id = jfields.avc_profile_main_id;
331  break;
333  field_id = jfields.avc_profile_extended_id;
334  break;
336  field_id = jfields.avc_profile_high_id;
337  break;
340  field_id = jfields.avc_profile_high10_id;
341  break;
344  field_id = jfields.avc_profile_high422_id;
345  break;
349  field_id = jfields.avc_profile_high444_id;
350  break;
351  }
352 
353  if (field_id) {
354  ret = (*env)->GetStaticIntField(env, jfields.codec_profile_level_class, field_id);
355  if (ff_jni_exception_check(env, 1, avctx) < 0) {
356  ret = -1;
357  goto done;
358  }
359  }
360  }
361 
362 done:
363  ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx);
364 
365  JNI_DETACH_ENV(attached, avctx);
366 
367  return ret;
368 }
369 
370 char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
371 {
372  int ret;
373  int i;
374  int codec_count;
375  int found_codec = 0;
376  char *name = NULL;
377  char *supported_type = NULL;
378 
379  int attached = 0;
380  JNIEnv *env = NULL;
381  struct JNIAMediaCodecListFields jfields = { 0 };
382  struct JNIAMediaFormatFields mediaformat_jfields = { 0 };
383 
384  jobject format = NULL;
385  jobject codec = NULL;
386  jobject codec_name = NULL;
387 
388  jobject info = NULL;
389  jobject type = NULL;
390  jobjectArray types = NULL;
391 
392  jobject capabilities = NULL;
393  jobject profile_level = NULL;
394  jobjectArray profile_levels = NULL;
395 
396  JNI_ATTACH_ENV_OR_RETURN(env, &attached, log_ctx, NULL);
397 
398  if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
399  goto done;
400  }
401 
402  if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) {
403  goto done;
404  }
405 
406  codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
407  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
408  goto done;
409  }
410 
411  for(i = 0; i < codec_count; i++) {
412  int j;
413  int type_count;
414  int is_encoder;
415 
416  info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
417  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
418  goto done;
419  }
420 
421  types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
422  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
423  goto done;
424  }
425 
426  is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
427  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
428  goto done;
429  }
430 
431  if (is_encoder != encoder) {
432  goto done_with_info;
433  }
434 
435  type_count = (*env)->GetArrayLength(env, types);
436  for (j = 0; j < type_count; j++) {
437  int k;
438  int profile_count;
439 
440  type = (*env)->GetObjectArrayElement(env, types, j);
441  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
442  goto done;
443  }
444 
445  supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
446  if (!supported_type) {
447  goto done;
448  }
449 
450  if (!av_strcasecmp(supported_type, mime)) {
451  codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
452  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
453  goto done;
454  }
455 
456  name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
457  if (!name) {
458  goto done;
459  }
460 
461  if (strstr(name, "OMX.google")) {
462  av_freep(&name);
463  goto done_with_type;
464  }
465 
466  capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type);
467  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
468  goto done;
469  }
470 
471  profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id);
472  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
473  goto done;
474  }
475 
476  profile_count = (*env)->GetArrayLength(env, profile_levels);
477  for (k = 0; k < profile_count; k++) {
478  int supported_profile = 0;
479 
480  if (profile < 0) {
481  found_codec = 1;
482  break;
483  }
484 
485  profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k);
486  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
487  goto done;
488  }
489 
490  supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id);
491  if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
492  goto done;
493  }
494 
495  found_codec = profile == supported_profile;
496 
497  if (profile_level) {
498  (*env)->DeleteLocalRef(env, profile_level);
499  profile_level = NULL;
500  }
501 
502  if (found_codec) {
503  break;
504  }
505  }
506  }
507 
508 done_with_type:
509  if (profile_levels) {
510  (*env)->DeleteLocalRef(env, profile_levels);
511  profile_levels = NULL;
512  }
513 
514  if (capabilities) {
515  (*env)->DeleteLocalRef(env, capabilities);
516  capabilities = NULL;
517  }
518 
519  if (type) {
520  (*env)->DeleteLocalRef(env, type);
521  type = NULL;
522  }
523 
524  av_freep(&supported_type);
525 
526  if (found_codec) {
527  break;
528  }
529 
530  av_freep(&name);
531  }
532 
533 done_with_info:
534  if (info) {
535  (*env)->DeleteLocalRef(env, info);
536  info = NULL;
537  }
538 
539  if (types) {
540  (*env)->DeleteLocalRef(env, types);
541  types = NULL;
542  }
543 
544  if (found_codec) {
545  break;
546  }
547  }
548 
549 done:
550  if (format) {
551  (*env)->DeleteLocalRef(env, format);
552  }
553 
554  if (codec) {
555  (*env)->DeleteLocalRef(env, codec);
556  }
557 
558  if (codec_name) {
559  (*env)->DeleteLocalRef(env, codec_name);
560  }
561 
562  if (info) {
563  (*env)->DeleteLocalRef(env, info);
564  }
565 
566  if (type) {
567  (*env)->DeleteLocalRef(env, type);
568  }
569 
570  if (types) {
571  (*env)->DeleteLocalRef(env, types);
572  }
573 
574  if (capabilities) {
575  (*env)->DeleteLocalRef(env, capabilities);
576  }
577 
578  if (profile_level) {
579  (*env)->DeleteLocalRef(env, profile_level);
580  }
581 
582  if (profile_levels) {
583  (*env)->DeleteLocalRef(env, profile_levels);
584  }
585 
586  av_freep(&supported_type);
587 
588  ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
589  ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
590 
591  JNI_DETACH_ENV(attached, log_ctx);
592 
593  if (!found_codec) {
594  av_freep(&name);
595  }
596 
597  return name;
598 }
599 
601 {
602  int attached = 0;
603  JNIEnv *env = NULL;
605 
606  format = av_mallocz(sizeof(FFAMediaFormat));
607  if (!format) {
608  return NULL;
609  }
610  format->class = &amediaformat_class;
611 
612  env = ff_jni_attach_env(&attached, format);
613  if (!env) {
614  av_freep(&format);
615  return NULL;
616  }
617 
618  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
619  goto fail;
620  }
621 
622  format->object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
623  if (!format->object) {
624  goto fail;
625  }
626 
627  format->object = (*env)->NewGlobalRef(env, format->object);
628  if (!format->object) {
629  goto fail;
630  }
631 
632  JNI_DETACH_ENV(attached, format);
633 
634  return format;
635 fail:
636  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
637 
638  JNI_DETACH_ENV(attached, format);
639 
640  av_freep(&format);
641 
642  return NULL;
643 }
644 
646 {
647  int attached = 0;
648  JNIEnv *env = NULL;
650 
651  format = av_mallocz(sizeof(FFAMediaFormat));
652  if (!format) {
653  return NULL;
654  }
655  format->class = &amediaformat_class;
656 
657  env = ff_jni_attach_env(&attached, format);
658  if (!env) {
659  av_freep(&format);
660  return NULL;
661  }
662 
663  if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
664  goto fail;
665  }
666 
667  format->object = (*env)->NewGlobalRef(env, object);
668  if (!format->object) {
669  goto fail;
670  }
671 
672  JNI_DETACH_ENV(attached, format);
673 
674  return format;
675 fail:
676  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
677 
678  JNI_DETACH_ENV(attached, format);
679 
680  av_freep(&format);
681 
682  return NULL;
683 }
684 
686 {
687  int ret = 0;
688 
689  int attached = 0;
690  JNIEnv *env = NULL;
691 
692  if (!format) {
693  return 0;
694  }
695 
696  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, AVERROR_EXTERNAL);
697 
698  (*env)->DeleteGlobalRef(env, format->object);
699  format->object = NULL;
700 
701  ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
702 
703  JNI_DETACH_ENV(attached, format);
704 
705  av_freep(&format);
706 
707  return ret;
708 }
709 
711 {
712  char *ret = NULL;
713 
714  int attached = 0;
715  JNIEnv *env = NULL;
716  jstring description = NULL;
717 
718  av_assert0(format != NULL);
719 
720  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, NULL);
721 
722  description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
723  if (ff_jni_exception_check(env, 1, NULL) < 0) {
724  goto fail;
725  }
726 
727  ret = ff_jni_jstring_to_utf_chars(env, description, format);
728 fail:
729 
730  if (description) {
731  (*env)->DeleteLocalRef(env, description);
732  }
733 
734  JNI_DETACH_ENV(attached, format);
735 
736  return ret;
737 }
738 
740 {
741  int ret = 1;
742 
743  int attached = 0;
744  JNIEnv *env = NULL;
745  jstring key = NULL;
746 
747  av_assert0(format != NULL);
748 
749  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
750 
751  key = ff_jni_utf_chars_to_jstring(env, name, format);
752  if (!key) {
753  ret = 0;
754  goto fail;
755  }
756 
757  *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
758  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
759  ret = 0;
760  goto fail;
761  }
762 
763  ret = 1;
764 fail:
765  if (key) {
766  (*env)->DeleteLocalRef(env, key);
767  }
768 
769  JNI_DETACH_ENV(attached, format);
770 
771  return ret;
772 }
773 
775 {
776  int ret = 1;
777 
778  int attached = 0;
779  JNIEnv *env = NULL;
780  jstring key = NULL;
781 
782  av_assert0(format != NULL);
783 
784  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
785 
786  key = ff_jni_utf_chars_to_jstring(env, name, format);
787  if (!key) {
788  ret = 0;
789  goto fail;
790  }
791 
792  *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
793  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
794  ret = 0;
795  goto fail;
796  }
797 
798  ret = 1;
799 fail:
800  if (key) {
801  (*env)->DeleteLocalRef(env, key);
802  }
803 
804  JNI_DETACH_ENV(attached, format);
805 
806  return ret;
807 }
808 
810 {
811  int ret = 1;
812 
813  int attached = 0;
814  JNIEnv *env = NULL;
815  jstring key = NULL;
816 
817  av_assert0(format != NULL);
818 
819  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
820 
821  key = ff_jni_utf_chars_to_jstring(env, name, format);
822  if (!key) {
823  ret = 0;
824  goto fail;
825  }
826 
827  *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
828  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
829  ret = 0;
830  goto fail;
831  }
832 
833  ret = 1;
834 fail:
835  if (key) {
836  (*env)->DeleteLocalRef(env, key);
837  }
838 
839  JNI_DETACH_ENV(attached, format);
840 
841  return ret;
842 }
843 
844 int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
845 {
846  int ret = 1;
847 
848  int attached = 0;
849  JNIEnv *env = NULL;
850  jstring key = NULL;
851  jobject result = NULL;
852 
853  av_assert0(format != NULL);
854 
855  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
856 
857  key = ff_jni_utf_chars_to_jstring(env, name, format);
858  if (!key) {
859  ret = 0;
860  goto fail;
861  }
862 
863  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
864  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
865  ret = 0;
866  goto fail;
867  }
868 
869  *data = (*env)->GetDirectBufferAddress(env, result);
870  *size = (*env)->GetDirectBufferCapacity(env, result);
871 
872  if (*data && *size) {
873  void *src = *data;
874  *data = av_malloc(*size);
875  if (!*data) {
876  ret = 0;
877  goto fail;
878  }
879 
880  memcpy(*data, src, *size);
881  }
882 
883  ret = 1;
884 fail:
885  if (key) {
886  (*env)->DeleteLocalRef(env, key);
887  }
888 
889  if (result) {
890  (*env)->DeleteLocalRef(env, result);
891  }
892 
893  JNI_DETACH_ENV(attached, format);
894 
895  return ret;
896 }
897 
898 int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
899 {
900  int ret = 1;
901 
902  int attached = 0;
903  JNIEnv *env = NULL;
904  jstring key = NULL;
905  jstring result = NULL;
906 
907  av_assert0(format != NULL);
908 
909  JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
910 
911  key = ff_jni_utf_chars_to_jstring(env, name, format);
912  if (!key) {
913  ret = 0;
914  goto fail;
915  }
916 
917  result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
918  if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
919  ret = 0;
920  goto fail;
921  }
922 
923  *out = ff_jni_jstring_to_utf_chars(env, result, format);
924  if (!*out) {
925  ret = 0;
926  goto fail;
927  }
928 
929  ret = 1;
930 fail:
931  if (key) {
932  (*env)->DeleteLocalRef(env, key);
933  }
934 
935  if (result) {
936  (*env)->DeleteLocalRef(env, result);
937  }
938 
939  JNI_DETACH_ENV(attached, format);
940 
941  return ret;
942 }
943 
945 {
946  int attached = 0;
947  JNIEnv *env = NULL;
948  jstring key = NULL;
949 
950  av_assert0(format != NULL);
951 
952  JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
953 
954  key = ff_jni_utf_chars_to_jstring(env, name, format);
955  if (!key) {
956  goto fail;
957  }
958 
959  (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
960  if (ff_jni_exception_check(env, 1, format) < 0) {
961  goto fail;
962  }
963 
964 fail:
965  if (key) {
966  (*env)->DeleteLocalRef(env, key);
967  }
968 
969  JNI_DETACH_ENV(attached, format);
970 }
971 
973 {
974  int attached = 0;
975  JNIEnv *env = NULL;
976  jstring key = NULL;
977 
978  av_assert0(format != NULL);
979 
980  JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
981 
982  key = ff_jni_utf_chars_to_jstring(env, name, format);
983  if (!key) {
984  goto fail;
985  }
986 
987  (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
988  if (ff_jni_exception_check(env, 1, format) < 0) {
989  goto fail;
990  }
991 
992 fail:
993  if (key) {
994  (*env)->DeleteLocalRef(env, key);
995  }
996 
997  JNI_DETACH_ENV(attached, NULL);
998 }
999 
1001 {
1002  int attached = 0;
1003  JNIEnv *env = NULL;
1004  jstring key = NULL;
1005 
1006  av_assert0(format != NULL);
1007 
1008  JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
1009 
1010  key = ff_jni_utf_chars_to_jstring(env, name, format);
1011  if (!key) {
1012  goto fail;
1013  }
1014 
1015  (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
1016  if (ff_jni_exception_check(env, 1, format) < 0) {
1017  goto fail;
1018  }
1019 
1020 fail:
1021  if (key) {
1022  (*env)->DeleteLocalRef(env, key);
1023  }
1024 
1025  JNI_DETACH_ENV(attached, NULL);
1026 }
1027 
1029 {
1030  int attached = 0;
1031  JNIEnv *env = NULL;
1032  jstring key = NULL;
1033  jstring string = NULL;
1034 
1035  av_assert0(format != NULL);
1036 
1037  JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
1038 
1039  key = ff_jni_utf_chars_to_jstring(env, name, format);
1040  if (!key) {
1041  goto fail;
1042  }
1043 
1044  string = ff_jni_utf_chars_to_jstring(env, value, format);
1045  if (!string) {
1046  goto fail;
1047  }
1048 
1049  (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
1050  if (ff_jni_exception_check(env, 1, format) < 0) {
1051  goto fail;
1052  }
1053 
1054 fail:
1055  if (key) {
1056  (*env)->DeleteLocalRef(env, key);
1057  }
1058 
1059  if (string) {
1060  (*env)->DeleteLocalRef(env, string);
1061  }
1062 
1063  JNI_DETACH_ENV(attached, format);
1064 }
1065 
1066 void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
1067 {
1068  int attached = 0;
1069  JNIEnv *env = NULL;
1070  jstring key = NULL;
1071  jobject buffer = NULL;
1072  void *buffer_data = NULL;
1073 
1074  av_assert0(format != NULL);
1075 
1076  JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
1077 
1078  key = ff_jni_utf_chars_to_jstring(env, name, format);
1079  if (!key) {
1080  goto fail;
1081  }
1082 
1083  if (!data || !size) {
1084  goto fail;
1085  }
1086 
1087  buffer_data = av_malloc(size);
1088  if (!buffer_data) {
1089  goto fail;
1090  }
1091 
1092  memcpy(buffer_data, data, size);
1093 
1094  buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
1095  if (!buffer) {
1096  goto fail;
1097  }
1098 
1099  (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
1100  if (ff_jni_exception_check(env, 1, format) < 0) {
1101  goto fail;
1102  }
1103 
1104 fail:
1105  if (key) {
1106  (*env)->DeleteLocalRef(env, key);
1107  }
1108 
1109  if (buffer) {
1110  (*env)->DeleteLocalRef(env, buffer);
1111  }
1112 
1113  JNI_DETACH_ENV(attached, format);
1114 }
1115 
1117 {
1118  int ret = 0;
1119  int attached = 0;
1120  JNIEnv *env = NULL;
1121 
1122  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1123 
1124  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1125  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1126  goto fail;
1127  }
1128 
1129  codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
1130  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1131  goto fail;
1132  }
1133 
1134  codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
1135  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1136  goto fail;
1137  }
1138 
1139  if (codec->jfields.buffer_flag_key_frame_id) {
1140  codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
1141  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1142  goto fail;
1143  }
1144  }
1145 
1146  codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
1147  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1148  goto fail;
1149  }
1150 
1151  codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1152  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1153  goto fail;
1154  }
1155 
1156  codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
1157  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1158  goto fail;
1159  }
1160 
1161  codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
1162  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1163  goto fail;
1164  }
1165 
1166 fail:
1167  JNI_DETACH_ENV(attached, NULL);
1168 
1169  return ret;
1170 }
1171 
1173 {
1174  int attached = 0;
1175  JNIEnv *env = NULL;
1176  FFAMediaCodec *codec = NULL;
1177  jstring codec_name = NULL;
1178 
1179  codec = av_mallocz(sizeof(FFAMediaCodec));
1180  if (!codec) {
1181  return NULL;
1182  }
1183  codec->class = &amediacodec_class;
1184 
1185  env = ff_jni_attach_env(&attached, codec);
1186  if (!env) {
1187  av_freep(&codec);
1188  return NULL;
1189  }
1190 
1191  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1192  goto fail;
1193  }
1194 
1195  codec_name = ff_jni_utf_chars_to_jstring(env, name, codec);
1196  if (!codec_name) {
1197  goto fail;
1198  }
1199 
1200  codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_by_codec_name_id, codec_name);
1201  if (ff_jni_exception_check(env, 1, codec) < 0) {
1202  goto fail;
1203  }
1204 
1205  codec->object = (*env)->NewGlobalRef(env, codec->object);
1206  if (!codec->object) {
1207  goto fail;
1208  }
1209 
1210  if (codec_init_static_fields(codec) < 0) {
1211  goto fail;
1212  }
1213 
1215  codec->has_get_i_o_buffer = 1;
1216  }
1217 
1218  JNI_DETACH_ENV(attached, codec);
1219 
1220  return codec;
1221 fail:
1222  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1223 
1224  if (codec_name) {
1225  (*env)->DeleteLocalRef(env, codec_name);
1226  }
1227 
1228  JNI_DETACH_ENV(attached, codec);
1229 
1230  av_freep(&codec);
1231 
1232  return NULL;
1233 }
1234 
1236 {
1237  int attached = 0;
1238  JNIEnv *env = NULL;
1239  FFAMediaCodec *codec = NULL;
1240  jstring mime_type = NULL;
1241 
1242  codec = av_mallocz(sizeof(FFAMediaCodec));
1243  if (!codec) {
1244  return NULL;
1245  }
1246  codec->class = &amediacodec_class;
1247 
1248  env = ff_jni_attach_env(&attached, codec);
1249  if (!env) {
1250  av_freep(&codec);
1251  return NULL;
1252  }
1253 
1254  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1255  goto fail;
1256  }
1257 
1258  mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
1259  if (!mime_type) {
1260  goto fail;
1261  }
1262 
1263  codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type);
1264  if (ff_jni_exception_check(env, 1, codec) < 0) {
1265  goto fail;
1266  }
1267 
1268  codec->object = (*env)->NewGlobalRef(env, codec->object);
1269  if (!codec->object) {
1270  goto fail;
1271  }
1272 
1273  if (codec_init_static_fields(codec) < 0) {
1274  goto fail;
1275  }
1276 
1278  codec->has_get_i_o_buffer = 1;
1279  }
1280 
1281  JNI_DETACH_ENV(attached, codec);
1282 
1283  return codec;
1284 fail:
1285  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1286 
1287  if (mime_type) {
1288  (*env)->DeleteLocalRef(env, mime_type);
1289  }
1290 
1291  JNI_DETACH_ENV(attached, codec);
1292 
1293  av_freep(&codec);
1294 
1295  return NULL;
1296 }
1297 
1299 {
1300  int attached = 0;
1301  JNIEnv *env = NULL;
1302  FFAMediaCodec *codec = NULL;
1303  jstring mime_type = NULL;
1304 
1305  codec = av_mallocz(sizeof(FFAMediaCodec));
1306  if (!codec) {
1307  return NULL;
1308  }
1309  codec->class = &amediacodec_class;
1310 
1311  env = ff_jni_attach_env(&attached, codec);
1312  if (!env) {
1313  av_freep(&codec);
1314  return NULL;
1315  }
1316 
1317  if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1318  goto fail;
1319  }
1320 
1321  mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
1322  if (!mime_type) {
1323  goto fail;
1324  }
1325 
1326  codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_encoder_by_type_id, mime_type);
1327  if (ff_jni_exception_check(env, 1, codec) < 0) {
1328  goto fail;
1329  }
1330 
1331  codec->object = (*env)->NewGlobalRef(env, codec->object);
1332  if (!codec->object) {
1333  goto fail;
1334  }
1335 
1336  if (codec_init_static_fields(codec) < 0) {
1337  goto fail;
1338  }
1339 
1341  codec->has_get_i_o_buffer = 1;
1342  }
1343 
1344  JNI_DETACH_ENV(attached, NULL);
1345 
1346  return codec;
1347 fail:
1348  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1349 
1350  if (mime_type) {
1351  (*env)->DeleteLocalRef(env, mime_type);
1352  }
1353 
1354  JNI_DETACH_ENV(attached, codec);
1355 
1356  av_freep(&codec);
1357 
1358  return NULL;
1359 }
1360 
1362 {
1363  int ret = 0;
1364 
1365  int attached = 0;
1366  JNIEnv *env = NULL;
1367 
1368  if (!codec) {
1369  return 0;
1370  }
1371 
1372  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1373 
1374  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
1375  if (ff_jni_exception_check(env, 1, codec) < 0) {
1376  ret = AVERROR_EXTERNAL;
1377  }
1378 
1379  (*env)->DeleteGlobalRef(env, codec->object);
1380  codec->object = NULL;
1381 
1382  ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1383 
1384  JNI_DETACH_ENV(attached, codec);
1385 
1386  av_freep(&codec);
1387 
1388  return ret;
1389 }
1390 
1392 {
1393  char *ret = NULL;
1394  int attached = 0;
1395  JNIEnv *env = NULL;
1396  jobject *name = NULL;
1397 
1398  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
1399 
1400  name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1401  if (ff_jni_exception_check(env, 1, codec) < 0) {
1402  goto fail;
1403  }
1404 
1405  ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1406 
1407 fail:
1408  JNI_DETACH_ENV(attached, NULL);
1409 
1410  return ret;
1411 }
1412 
1413 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
1414 {
1415  int ret = 0;
1416  int attached = 0;
1417  JNIEnv *env = NULL;
1418 
1419  /* TODO: implement surface handling */
1420  av_assert0(surface == NULL);
1421 
1422  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1423 
1424  (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, NULL, NULL, flags);
1425  if (ff_jni_exception_check(env, 1, codec) < 0) {
1426  ret = AVERROR_EXTERNAL;
1427  goto fail;
1428  }
1429 
1430 fail:
1431  JNI_DETACH_ENV(attached, NULL);
1432 
1433  return ret;
1434 }
1435 
1437 {
1438  int ret = 0;
1439  int attached = 0;
1440  JNIEnv *env = NULL;
1441 
1442  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1443 
1444  (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1445  if (ff_jni_exception_check(env, 1, codec) < 0) {
1446  ret = AVERROR_EXTERNAL;
1447  goto fail;
1448  }
1449 
1450 fail:
1451  JNI_DETACH_ENV(attached, codec);
1452 
1453  return ret;
1454 }
1455 
1457 {
1458  int ret = 0;
1459  int attached = 0;
1460  JNIEnv *env = NULL;
1461 
1462  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1463 
1464  (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1465  if (ff_jni_exception_check(env, 1, codec) < 0) {
1466  ret = AVERROR_EXTERNAL;
1467  goto fail;
1468  }
1469 
1470 fail:
1471  JNI_DETACH_ENV(attached, codec);
1472 
1473  return ret;
1474 }
1475 
1477 {
1478  int ret = 0;
1479  int attached = 0;
1480  JNIEnv *env = NULL;
1481 
1482  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1483 
1484  (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1485  if (ff_jni_exception_check(env, 1, codec) < 0) {
1486  ret = AVERROR_EXTERNAL;
1487  goto fail;
1488  }
1489 
1490 fail:
1491  JNI_DETACH_ENV(attached, codec);
1492 
1493  return ret;
1494 }
1495 
1496 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
1497 {
1498  int ret = 0;
1499  int attached = 0;
1500  JNIEnv *env = NULL;
1501 
1502  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1503 
1504  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, idx, render);
1505  if (ff_jni_exception_check(env, 1, codec) < 0) {
1506  ret = AVERROR_EXTERNAL;
1507  goto fail;
1508  }
1509 
1510 fail:
1511  JNI_DETACH_ENV(attached, codec);
1512 
1513  return ret;
1514 }
1515 
1516 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
1517 {
1518  int ret = 0;
1519  int attached = 0;
1520  JNIEnv *env = NULL;
1521 
1522  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1523 
1524  (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, idx, timestampNs);
1525  if (ff_jni_exception_check(env, 1, codec) < 0) {
1526  ret = AVERROR_EXTERNAL;
1527  goto fail;
1528  }
1529 
1530 fail:
1531  JNI_DETACH_ENV(attached, codec);
1532 
1533  return ret;
1534 }
1535 
1536 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
1537 {
1538  int ret = 0;
1539  int attached = 0;
1540  JNIEnv *env = NULL;
1541 
1542  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1543 
1544  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1545  if (ff_jni_exception_check(env, 1, codec) < 0) {
1546  ret = AVERROR_EXTERNAL;
1547  goto fail;
1548  }
1549 
1550 fail:
1551  JNI_DETACH_ENV(attached, codec);
1552 
1553  return ret;
1554 }
1555 
1556 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1557 {
1558  int ret = 0;
1559  int attached = 0;
1560  JNIEnv *env = NULL;
1561 
1562  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1563 
1564  (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, idx, offset, size, time, flags);
1565  if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1566  ret = AVERROR_EXTERNAL;
1567  goto fail;
1568  }
1569 
1570 fail:
1571  JNI_DETACH_ENV(attached, codec);
1572 
1573  return ret;
1574 }
1575 
1577 {
1578  int ret = 0;
1579  int attached = 0;
1580  JNIEnv *env = NULL;
1581 
1582  jobject mediainfo = NULL;
1583 
1584  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
1585 
1586  mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
1587  if (ff_jni_exception_check(env, 1, codec) < 0) {
1588  ret = AVERROR_EXTERNAL;
1589  goto fail;
1590  }
1591 
1592  ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, mediainfo, timeoutUs);
1593  if (ff_jni_exception_check(env, 1, codec) < 0) {
1594  ret = AVERROR_EXTERNAL;
1595  goto fail;
1596  }
1597 
1598  info->flags = (*env)->GetIntField(env, mediainfo, codec->jfields.flags_id);
1599  if (ff_jni_exception_check(env, 1, codec) < 0) {
1600  ret = AVERROR_EXTERNAL;
1601  goto fail;
1602  }
1603 
1604  info->offset = (*env)->GetIntField(env, mediainfo, codec->jfields.offset_id);
1605  if (ff_jni_exception_check(env, 1, codec) < 0) {
1606  ret = AVERROR_EXTERNAL;
1607  goto fail;
1608  }
1609 
1610  info->presentationTimeUs = (*env)->GetLongField(env, mediainfo, codec->jfields.presentation_time_us_id);
1611  if (ff_jni_exception_check(env, 1, codec) < 0) {
1612  ret = AVERROR_EXTERNAL;
1613  goto fail;
1614  }
1615 
1616  info->size = (*env)->GetIntField(env, mediainfo, codec->jfields.size_id);
1617  if (ff_jni_exception_check(env, 1, codec) < 0) {
1618  ret = AVERROR_EXTERNAL;
1619  goto fail;
1620  }
1621 fail:
1622  if (mediainfo) {
1623  (*env)->DeleteLocalRef(env, mediainfo);
1624  }
1625 
1626  JNI_DETACH_ENV(attached, NULL);
1627 
1628  return ret;
1629 }
1630 
1632 {
1633  uint8_t *ret = NULL;
1634  int attached = 0;
1635  JNIEnv *env = NULL;
1636 
1637  jobject buffer = NULL;
1638 
1639  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
1640 
1641  if (codec->has_get_i_o_buffer) {
1642  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, idx);
1643  if (ff_jni_exception_check(env, 1, codec) < 0) {
1644  goto fail;
1645  }
1646  } else {
1647  if (!codec->input_buffers) {
1648  codec->input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1649  if (ff_jni_exception_check(env, 1, codec) < 0) {
1650  goto fail;
1651  }
1652 
1653  codec->input_buffers = (*env)->NewGlobalRef(env, codec->input_buffers);
1654  if (ff_jni_exception_check(env, 1, codec) < 0) {
1655  goto fail;
1656  }
1657  }
1658 
1659  buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1660  if (ff_jni_exception_check(env, 1, codec) < 0) {
1661  goto fail;
1662  }
1663  }
1664 
1665  ret = (*env)->GetDirectBufferAddress(env, buffer);
1666  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1667 fail:
1668  if (buffer) {
1669  (*env)->DeleteLocalRef(env, buffer);
1670  }
1671 
1672  JNI_DETACH_ENV(attached, codec);
1673 
1674  return ret;
1675 }
1676 
1678 {
1679  uint8_t *ret = NULL;
1680  int attached = 0;
1681  JNIEnv *env = NULL;
1682 
1683  jobject buffer = NULL;
1684 
1685  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
1686 
1687  if (codec->has_get_i_o_buffer) {
1688  buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, idx);
1689  if (ff_jni_exception_check(env, 1, codec) < 0) {
1690  goto fail;
1691  }
1692  } else {
1693  if (!codec->output_buffers) {
1694  codec->output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1695  if (ff_jni_exception_check(env, 1, codec) < 0) {
1696  goto fail;
1697  }
1698 
1699  codec->output_buffers = (*env)->NewGlobalRef(env, codec->output_buffers);
1700  if (ff_jni_exception_check(env, 1, codec) < 0) {
1701  goto fail;
1702  }
1703  }
1704 
1705  buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1706  if (ff_jni_exception_check(env, 1, codec) < 0) {
1707  goto fail;
1708  }
1709  }
1710 
1711  ret = (*env)->GetDirectBufferAddress(env, buffer);
1712  *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1713 fail:
1714  if (buffer) {
1715  (*env)->DeleteLocalRef(env, buffer);
1716  }
1717 
1718  JNI_DETACH_ENV(attached, codec);
1719 
1720  return ret;
1721 }
1722 
1724 {
1725  FFAMediaFormat *ret = NULL;
1726  int attached = 0;
1727  JNIEnv *env = NULL;
1728 
1729  jobject mediaformat = NULL;
1730 
1731  JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
1732 
1733  mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1734  if (ff_jni_exception_check(env, 1, codec) < 0) {
1735  goto fail;
1736  }
1737 
1738  ret = ff_AMediaFormat_newFromObject(mediaformat);
1739 fail:
1740  if (mediaformat) {
1741  (*env)->DeleteLocalRef(env, mediaformat);
1742  }
1743 
1744  JNI_DETACH_ENV(attached, codec);
1745 
1746  return ret;
1747 }
1748 
1750 {
1751  return idx == codec->INFO_TRY_AGAIN_LATER;
1752 }
1753 
1755 {
1756  return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1757 }
1758 
1760 {
1761  return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1762 }
1763 
1765 {
1766  return codec->BUFFER_FLAG_CODEC_CONFIG;
1767 }
1768 
1770 {
1771  return codec->BUFFER_FLAG_END_OF_STREAM;
1772 }
1773 
1775 {
1776  return codec->BUFFER_FLAG_KEY_FRAME;
1777 }
1778 
1780 {
1781  return codec->CONFIGURE_FLAG_ENCODE;
1782 }
1783 
1785 {
1786  int ret = 0;
1787 
1788  if (!codec->has_get_i_o_buffer) {
1789  if (codec->output_buffers) {
1790  int attached = 0;
1791  JNIEnv *env = NULL;
1792 
1793  env = ff_jni_attach_env(&attached, codec);
1794  if (!env) {
1795  ret = AVERROR_EXTERNAL;
1796  goto fail;
1797  }
1798 
1799  (*env)->DeleteGlobalRef(env, codec->output_buffers);
1800  codec->output_buffers = NULL;
1801 
1802  JNI_DETACH_ENV(attached, codec);
1803  }
1804  }
1805 
1806 fail:
1807  return ret;
1808 }
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:3187
JNIEnv * ff_jni_attach_env(int *attached, void *log_ctx)
Definition: ffjni.c:37
#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:358
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:118
static const struct FFJniField jni_amediacodeclist_mapping[]
int profile
profile
Definition: avcodec.h:3153
static const struct FFJniField jni_amediacodec_mapping[]
static const AVClass amediacodec_class
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE
Definition: avcodec.h:3195
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:3185
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 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:3188
char * ff_AMediaFormat_toString(FFAMediaFormat *format)
ptrdiff_t size
Definition: opengl_enc.c:101
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
#define JNI_DETACH_ENV(attached, log_ctx)
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:3192
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:3189
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:81
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:88
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
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:276
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:243
#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
#define JNI_ATTACH_ENV_OR_RETURN_VOID(env, attached, log_ctx)
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:3193
enum AVCodecID codec_id
Definition: avcodec.h:1666
main external API structure.
Definition: avcodec.h:1649
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:3191
static const char * format
Definition: movenc.c:47
Describe the class of an AVClass context structure.
Definition: log.h:67
#define JNI_ATTACH_ENV_OR_RETURN(env, attached, log_ctx, ret)
#define FF_PROFILE_H264_HIGH_444
Definition: avcodec.h:3194
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)
static const AVClass amediaformat_class
const AVClass * class
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:3196
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:3186
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:3190
#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)
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:252
GLuint buffer
Definition: opengl_enc.c:102
const char * name
Definition: opengl_enc.c:103