]> git.sesse.net Git - ffmpeg/blob - libavcodec/mediacodec_wrapper.c
Merge commit '58640fe89ec4f2a3d67c0a2585fca8de34440857'
[ffmpeg] / libavcodec / mediacodec_wrapper.c
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
34 struct JNIAMediaCodecListFields {
35
36     jclass mediacodec_list_class;
37     jmethodID init_id;
38     jmethodID find_decoder_for_format_id;
39
40     jmethodID get_codec_count_id;
41     jmethodID get_codec_info_at_id;
42
43     jclass mediacodec_info_class;
44     jmethodID get_name_id;
45     jmethodID get_codec_capabilities_id;
46     jmethodID get_supported_types_id;
47     jmethodID is_encoder_id;
48
49     jclass codec_capabilities_class;
50     jfieldID color_formats_id;
51     jfieldID profile_levels_id;
52
53     jclass codec_profile_level_class;
54     jfieldID profile_id;
55     jfieldID level_id;
56
57     jfieldID avc_profile_baseline_id;
58     jfieldID avc_profile_main_id;
59     jfieldID avc_profile_extended_id;
60     jfieldID avc_profile_high_id;
61     jfieldID avc_profile_high10_id;
62     jfieldID avc_profile_high422_id;
63     jfieldID avc_profile_high444_id;
64
65 } JNIAMediaCodecListFields;
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
100 struct JNIAMediaFormatFields {
101
102     jclass mediaformat_class;
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
120 } JNIAMediaFormatFields;
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
150 struct FFAMediaFormat {
151
152     const AVClass *class;
153     struct JNIAMediaFormatFields jfields;
154     jobject object;
155 };
156
157 struct JNIAMediaCodecFields {
158
159     jclass mediacodec_class;
160
161     jfieldID info_try_again_later_id;
162     jfieldID info_output_buffers_changed_id;
163     jfieldID info_output_format_changed_id;
164
165     jfieldID buffer_flag_codec_config_id;
166     jfieldID buffer_flag_end_of_stream_id;
167     jfieldID buffer_flag_key_frame_id;
168
169     jfieldID configure_flag_encode_id;
170
171     jmethodID create_by_codec_name_id;
172     jmethodID create_decoder_by_type_id;
173     jmethodID create_encoder_by_type_id;
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
183     jmethodID get_output_format_id;
184
185     jmethodID dequeue_input_buffer_id;
186     jmethodID queue_input_buffer_id;
187     jmethodID get_input_buffer_id;
188     jmethodID get_input_buffers_id;
189
190     jmethodID dequeue_output_buffer_id;
191     jmethodID get_output_buffer_id;
192     jmethodID get_output_buffers_id;
193     jmethodID release_output_buffer_id;
194     jmethodID release_output_buffer_at_time_id;
195
196     jclass mediainfo_class;
197
198     jmethodID init_id;
199
200     jfieldID flags_id;
201     jfieldID offset_id;
202     jfieldID presentation_time_us_id;
203     jfieldID size_id;
204
205 } JNIAMediaCodecFields;
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
262 struct FFAMediaCodec {
263
264     const AVClass *class;
265
266     struct JNIAMediaCodecFields jfields;
267
268     jobject object;
269
270     jobject input_buffers;
271     jobject output_buffers;
272
273     int INFO_TRY_AGAIN_LATER;
274     int INFO_OUTPUT_BUFFERS_CHANGED;
275     int INFO_OUTPUT_FORMAT_CHANGED;
276
277     int BUFFER_FLAG_CODEC_CONFIG;
278     int BUFFER_FLAG_END_OF_STREAM;
279     int BUFFER_FLAG_KEY_FRAME;
280
281     int CONFIGURE_FLAG_ENCODE;
282
283     int has_get_i_o_buffer;
284 };
285
286 #define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do {              \
287     (env) = ff_jni_get_env(log_ctx);                               \
288     if (!(env)) {                                                  \
289         return ret;                                                \
290     }                                                              \
291 } while (0)
292
293 #define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do {              \
294     (env) = ff_jni_get_env(log_ctx);                               \
295     if (!(env)) {                                                  \
296         return;                                                    \
297     }                                                              \
298 } while (0)
299
300 int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
301 {
302     int ret = -1;
303
304     JNIEnv *env = NULL;
305     struct JNIAMediaCodecListFields jfields = { 0 };
306
307     JNI_GET_ENV_OR_RETURN(env, avctx, -1);
308
309     if (ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx) < 0) {
310         goto done;
311     }
312
313     if (avctx->codec_id == AV_CODEC_ID_H264) {
314         jfieldID field_id = 0;
315
316         switch(avctx->profile) {
317         case FF_PROFILE_H264_BASELINE:
318         case FF_PROFILE_H264_CONSTRAINED_BASELINE:
319             field_id = jfields.avc_profile_baseline_id;
320             break;
321         case FF_PROFILE_H264_MAIN:
322             field_id = jfields.avc_profile_main_id;
323             break;
324         case FF_PROFILE_H264_EXTENDED:
325             field_id = jfields.avc_profile_extended_id;
326             break;
327         case FF_PROFILE_H264_HIGH:
328             field_id = jfields.avc_profile_high_id;
329             break;
330         case FF_PROFILE_H264_HIGH_10:
331         case FF_PROFILE_H264_HIGH_10_INTRA:
332             field_id = jfields.avc_profile_high10_id;
333             break;
334         case FF_PROFILE_H264_HIGH_422:
335         case FF_PROFILE_H264_HIGH_422_INTRA:
336             field_id = jfields.avc_profile_high422_id;
337             break;
338         case FF_PROFILE_H264_HIGH_444:
339         case FF_PROFILE_H264_HIGH_444_INTRA:
340         case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
341             field_id = jfields.avc_profile_high444_id;
342             break;
343         }
344
345         if (field_id) {
346             ret = (*env)->GetStaticIntField(env, jfields.codec_profile_level_class, field_id);
347             if (ff_jni_exception_check(env, 1, avctx) < 0) {
348                 ret = -1;
349                 goto done;
350             }
351         }
352     }
353
354 done:
355     ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx);
356
357     return ret;
358 }
359
360 char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
361 {
362     int ret;
363     int i;
364     int codec_count;
365     int found_codec = 0;
366     char *name = NULL;
367     char *supported_type = NULL;
368
369     JNIEnv *env = NULL;
370     struct JNIAMediaCodecListFields jfields = { 0 };
371     struct JNIAMediaFormatFields mediaformat_jfields = { 0 };
372
373     jobject format = NULL;
374     jobject codec = NULL;
375     jobject codec_name = NULL;
376
377     jobject info = NULL;
378     jobject type = NULL;
379     jobjectArray types = NULL;
380
381     jobject capabilities = NULL;
382     jobject profile_level = NULL;
383     jobjectArray profile_levels = NULL;
384
385     JNI_GET_ENV_OR_RETURN(env, log_ctx, NULL);
386
387     if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
388         goto done;
389     }
390
391     if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) {
392         goto done;
393     }
394
395     codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
396     if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
397         goto done;
398     }
399
400     for(i = 0; i < codec_count; i++) {
401         int j;
402         int type_count;
403         int is_encoder;
404
405         info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
406         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
407             goto done;
408         }
409
410         types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
411         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
412             goto done;
413         }
414
415         is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
416         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
417             goto done;
418         }
419
420         if (is_encoder != encoder) {
421             goto done_with_info;
422         }
423
424         type_count = (*env)->GetArrayLength(env, types);
425         for (j = 0; j < type_count; j++) {
426             int k;
427             int profile_count;
428
429             type = (*env)->GetObjectArrayElement(env, types, j);
430             if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
431                 goto done;
432             }
433
434             supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
435             if (!supported_type) {
436                 goto done;
437             }
438
439             if (!av_strcasecmp(supported_type, mime)) {
440                 codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
441                 if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
442                     goto done;
443                 }
444
445                 name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
446                 if (!name) {
447                     goto done;
448                 }
449
450                 if (strstr(name, "OMX.google")) {
451                     av_freep(&name);
452                     goto done_with_type;
453                 }
454
455                 capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type);
456                 if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
457                     goto done;
458                 }
459
460                 profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id);
461                 if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
462                     goto done;
463                 }
464
465                 profile_count = (*env)->GetArrayLength(env, profile_levels);
466                 for (k = 0; k < profile_count; k++) {
467                     int supported_profile = 0;
468
469                     if (profile < 0) {
470                         found_codec = 1;
471                         break;
472                     }
473
474                     profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k);
475                     if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
476                         goto done;
477                     }
478
479                     supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id);
480                     if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
481                         goto done;
482                     }
483
484                     found_codec = profile == supported_profile;
485
486                     if (profile_level) {
487                         (*env)->DeleteLocalRef(env, profile_level);
488                         profile_level = NULL;
489                     }
490
491                     if (found_codec) {
492                         break;
493                     }
494                 }
495             }
496
497 done_with_type:
498             if (profile_levels) {
499                 (*env)->DeleteLocalRef(env, profile_levels);
500                 profile_levels = NULL;
501             }
502
503             if (capabilities) {
504                 (*env)->DeleteLocalRef(env, capabilities);
505                 capabilities = NULL;
506             }
507
508             if (type) {
509                 (*env)->DeleteLocalRef(env, type);
510                 type = NULL;
511             }
512
513             av_freep(&supported_type);
514
515             if (found_codec) {
516                 break;
517             }
518
519             av_freep(&name);
520         }
521
522 done_with_info:
523         if (info) {
524             (*env)->DeleteLocalRef(env, info);
525             info = NULL;
526         }
527
528         if (types) {
529             (*env)->DeleteLocalRef(env, types);
530             types = NULL;
531         }
532
533         if (found_codec) {
534             break;
535         }
536     }
537
538 done:
539     if (format) {
540         (*env)->DeleteLocalRef(env, format);
541     }
542
543     if (codec) {
544         (*env)->DeleteLocalRef(env, codec);
545     }
546
547     if (codec_name) {
548         (*env)->DeleteLocalRef(env, codec_name);
549     }
550
551     if (info) {
552         (*env)->DeleteLocalRef(env, info);
553     }
554
555     if (type) {
556         (*env)->DeleteLocalRef(env, type);
557     }
558
559     if (types) {
560         (*env)->DeleteLocalRef(env, types);
561     }
562
563     if (capabilities) {
564         (*env)->DeleteLocalRef(env, capabilities);
565     }
566
567     if (profile_level) {
568         (*env)->DeleteLocalRef(env, profile_level);
569     }
570
571     if (profile_levels) {
572         (*env)->DeleteLocalRef(env, profile_levels);
573     }
574
575     av_freep(&supported_type);
576
577     ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
578     ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
579
580     if (!found_codec) {
581         av_freep(&name);
582     }
583
584     return name;
585 }
586
587 FFAMediaFormat *ff_AMediaFormat_new(void)
588 {
589     JNIEnv *env = NULL;
590     FFAMediaFormat *format = NULL;
591
592     format = av_mallocz(sizeof(FFAMediaFormat));
593     if (!format) {
594         return NULL;
595     }
596     format->class = &amediaformat_class;
597
598     env = ff_jni_get_env(format);
599     if (!env) {
600         av_freep(&format);
601         return NULL;
602     }
603
604     if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
605         goto fail;
606     }
607
608     format->object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
609     if (!format->object) {
610         goto fail;
611     }
612
613     format->object = (*env)->NewGlobalRef(env, format->object);
614     if (!format->object) {
615         goto fail;
616     }
617
618     return format;
619 fail:
620     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
621
622     av_freep(&format);
623
624     return NULL;
625 }
626
627 static FFAMediaFormat *ff_AMediaFormat_newFromObject(void *object)
628 {
629     JNIEnv *env = NULL;
630     FFAMediaFormat *format = NULL;
631
632     format = av_mallocz(sizeof(FFAMediaFormat));
633     if (!format) {
634         return NULL;
635     }
636     format->class = &amediaformat_class;
637
638     env = ff_jni_get_env(format);
639     if (!env) {
640         av_freep(&format);
641         return NULL;
642     }
643
644     if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
645         goto fail;
646     }
647
648     format->object = (*env)->NewGlobalRef(env, object);
649     if (!format->object) {
650         goto fail;
651     }
652
653     return format;
654 fail:
655     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
656
657     av_freep(&format);
658
659     return NULL;
660 }
661
662 int ff_AMediaFormat_delete(FFAMediaFormat* format)
663 {
664     int ret = 0;
665
666     JNIEnv *env = NULL;
667
668     if (!format) {
669         return 0;
670     }
671
672     JNI_GET_ENV_OR_RETURN(env, format, AVERROR_EXTERNAL);
673
674     (*env)->DeleteGlobalRef(env, format->object);
675     format->object = NULL;
676
677     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
678
679     av_freep(&format);
680
681     return ret;
682 }
683
684 char* ff_AMediaFormat_toString(FFAMediaFormat* format)
685 {
686     char *ret = NULL;
687
688     JNIEnv *env = NULL;
689     jstring description = NULL;
690
691     av_assert0(format != NULL);
692
693     JNI_GET_ENV_OR_RETURN(env, format, NULL);
694
695     description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
696     if (ff_jni_exception_check(env, 1, NULL) < 0) {
697         goto fail;
698     }
699
700     ret = ff_jni_jstring_to_utf_chars(env, description, format);
701 fail:
702     if (description) {
703         (*env)->DeleteLocalRef(env, description);
704     }
705
706     return ret;
707 }
708
709 int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t *out)
710 {
711     int ret = 1;
712
713     JNIEnv *env = NULL;
714     jstring key = NULL;
715
716     av_assert0(format != NULL);
717
718     JNI_GET_ENV_OR_RETURN(env, format, 0);
719
720     key = ff_jni_utf_chars_to_jstring(env, name, format);
721     if (!key) {
722         ret = 0;
723         goto fail;
724     }
725
726     *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
727     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
728         ret = 0;
729         goto fail;
730     }
731
732     ret = 1;
733 fail:
734     if (key) {
735         (*env)->DeleteLocalRef(env, key);
736     }
737
738     return ret;
739 }
740
741 int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t *out)
742 {
743     int ret = 1;
744
745     JNIEnv *env = NULL;
746     jstring key = NULL;
747
748     av_assert0(format != NULL);
749
750     JNI_GET_ENV_OR_RETURN(env, format, 0);
751
752     key = ff_jni_utf_chars_to_jstring(env, name, format);
753     if (!key) {
754         ret = 0;
755         goto fail;
756     }
757
758     *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
759     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
760         ret = 0;
761         goto fail;
762     }
763
764     ret = 1;
765 fail:
766     if (key) {
767         (*env)->DeleteLocalRef(env, key);
768     }
769
770     return ret;
771 }
772
773 int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *out)
774 {
775     int ret = 1;
776
777     JNIEnv *env = NULL;
778     jstring key = NULL;
779
780     av_assert0(format != NULL);
781
782     JNI_GET_ENV_OR_RETURN(env, format, 0);
783
784     key = ff_jni_utf_chars_to_jstring(env, name, format);
785     if (!key) {
786         ret = 0;
787         goto fail;
788     }
789
790     *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
791     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
792         ret = 0;
793         goto fail;
794     }
795
796     ret = 1;
797 fail:
798     if (key) {
799         (*env)->DeleteLocalRef(env, key);
800     }
801
802     return ret;
803 }
804
805 int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
806 {
807     int ret = 1;
808
809     JNIEnv *env = NULL;
810     jstring key = NULL;
811     jobject result = NULL;
812
813     av_assert0(format != NULL);
814
815     JNI_GET_ENV_OR_RETURN(env, format, 0);
816
817     key = ff_jni_utf_chars_to_jstring(env, name, format);
818     if (!key) {
819         ret = 0;
820         goto fail;
821     }
822
823     result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
824     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
825         ret = 0;
826         goto fail;
827     }
828
829     *data = (*env)->GetDirectBufferAddress(env, result);
830     *size = (*env)->GetDirectBufferCapacity(env, result);
831
832     if (*data && *size) {
833         void *src = *data;
834         *data = av_malloc(*size);
835         if (!*data) {
836             ret = 0;
837             goto fail;
838         }
839
840         memcpy(*data, src, *size);
841     }
842
843     ret = 1;
844 fail:
845     if (key) {
846         (*env)->DeleteLocalRef(env, key);
847     }
848
849     if (result) {
850         (*env)->DeleteLocalRef(env, result);
851     }
852
853     return ret;
854 }
855
856 int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
857 {
858     int ret = 1;
859
860     JNIEnv *env = NULL;
861     jstring key = NULL;
862     jstring result = NULL;
863
864     av_assert0(format != NULL);
865
866     JNI_GET_ENV_OR_RETURN(env, format, 0);
867
868     key = ff_jni_utf_chars_to_jstring(env, name, format);
869     if (!key) {
870         ret = 0;
871         goto fail;
872     }
873
874     result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
875     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
876         ret = 0;
877         goto fail;
878     }
879
880     *out = ff_jni_jstring_to_utf_chars(env, result, format);
881     if (!*out) {
882         ret = 0;
883         goto fail;
884     }
885
886     ret = 1;
887 fail:
888     if (key) {
889         (*env)->DeleteLocalRef(env, key);
890     }
891
892     if (result) {
893         (*env)->DeleteLocalRef(env, result);
894     }
895
896     return ret;
897 }
898
899 void ff_AMediaFormat_setInt32(FFAMediaFormat* format, const char* name, int32_t value)
900 {
901     JNIEnv *env = NULL;
902     jstring key = NULL;
903
904     av_assert0(format != NULL);
905
906     JNI_GET_ENV_OR_RETURN_VOID(env, format);
907
908     key = ff_jni_utf_chars_to_jstring(env, name, format);
909     if (!key) {
910         goto fail;
911     }
912
913     (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
914     if (ff_jni_exception_check(env, 1, format) < 0) {
915         goto fail;
916     }
917
918 fail:
919     if (key) {
920         (*env)->DeleteLocalRef(env, key);
921     }
922 }
923
924 void ff_AMediaFormat_setInt64(FFAMediaFormat* format, const char* name, int64_t value)
925 {
926     JNIEnv *env = NULL;
927     jstring key = NULL;
928
929     av_assert0(format != NULL);
930
931     JNI_GET_ENV_OR_RETURN_VOID(env, format);
932
933     key = ff_jni_utf_chars_to_jstring(env, name, format);
934     if (!key) {
935         goto fail;
936     }
937
938     (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
939     if (ff_jni_exception_check(env, 1, format) < 0) {
940         goto fail;
941     }
942
943 fail:
944     if (key) {
945         (*env)->DeleteLocalRef(env, key);
946     }
947 }
948
949 void ff_AMediaFormat_setFloat(FFAMediaFormat* format, const char* name, float value)
950 {
951     JNIEnv *env = NULL;
952     jstring key = NULL;
953
954     av_assert0(format != NULL);
955
956     JNI_GET_ENV_OR_RETURN_VOID(env, format);
957
958     key = ff_jni_utf_chars_to_jstring(env, name, format);
959     if (!key) {
960         goto fail;
961     }
962
963     (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
964     if (ff_jni_exception_check(env, 1, format) < 0) {
965         goto fail;
966     }
967
968 fail:
969     if (key) {
970         (*env)->DeleteLocalRef(env, key);
971     }
972 }
973
974 void ff_AMediaFormat_setString(FFAMediaFormat* format, const char* name, const char* value)
975 {
976     JNIEnv *env = NULL;
977     jstring key = NULL;
978     jstring string = NULL;
979
980     av_assert0(format != NULL);
981
982     JNI_GET_ENV_OR_RETURN_VOID(env, format);
983
984     key = ff_jni_utf_chars_to_jstring(env, name, format);
985     if (!key) {
986         goto fail;
987     }
988
989     string = ff_jni_utf_chars_to_jstring(env, value, format);
990     if (!string) {
991         goto fail;
992     }
993
994     (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
995     if (ff_jni_exception_check(env, 1, format) < 0) {
996         goto fail;
997     }
998
999 fail:
1000     if (key) {
1001         (*env)->DeleteLocalRef(env, key);
1002     }
1003
1004     if (string) {
1005         (*env)->DeleteLocalRef(env, string);
1006     }
1007 }
1008
1009 void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
1010 {
1011     JNIEnv *env = NULL;
1012     jstring key = NULL;
1013     jobject buffer = NULL;
1014     void *buffer_data = NULL;
1015
1016     av_assert0(format != NULL);
1017
1018     JNI_GET_ENV_OR_RETURN_VOID(env, format);
1019
1020     key = ff_jni_utf_chars_to_jstring(env, name, format);
1021     if (!key) {
1022         goto fail;
1023     }
1024
1025     if (!data || !size) {
1026         goto fail;
1027     }
1028
1029     buffer_data = av_malloc(size);
1030     if (!buffer_data) {
1031         goto fail;
1032     }
1033
1034     memcpy(buffer_data, data, size);
1035
1036     buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
1037     if (!buffer) {
1038         goto fail;
1039     }
1040
1041     (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
1042     if (ff_jni_exception_check(env, 1, format) < 0) {
1043         goto fail;
1044     }
1045
1046 fail:
1047     if (key) {
1048         (*env)->DeleteLocalRef(env, key);
1049     }
1050
1051     if (buffer) {
1052         (*env)->DeleteLocalRef(env, buffer);
1053     }
1054 }
1055
1056 static int codec_init_static_fields(FFAMediaCodec *codec)
1057 {
1058     int ret = 0;
1059     JNIEnv *env = NULL;
1060
1061     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1062
1063     codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1064     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1065         goto fail;
1066     }
1067
1068     codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
1069     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1070         goto fail;
1071     }
1072
1073     codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
1074     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1075         goto fail;
1076     }
1077
1078     if (codec->jfields.buffer_flag_key_frame_id) {
1079         codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
1080         if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1081             goto fail;
1082         }
1083     }
1084
1085     codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
1086     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1087         goto fail;
1088     }
1089
1090     codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1091     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1092         goto fail;
1093     }
1094
1095     codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
1096     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1097         goto fail;
1098     }
1099
1100     codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
1101     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1102         goto fail;
1103     }
1104
1105 fail:
1106
1107     return ret;
1108 }
1109
1110 FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name)
1111 {
1112     JNIEnv *env = NULL;
1113     FFAMediaCodec *codec = NULL;
1114     jstring codec_name = NULL;
1115
1116     codec = av_mallocz(sizeof(FFAMediaCodec));
1117     if (!codec) {
1118         return NULL;
1119     }
1120     codec->class = &amediacodec_class;
1121
1122     env = ff_jni_get_env(codec);
1123     if (!env) {
1124         av_freep(&codec);
1125         return NULL;
1126     }
1127
1128     if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1129         goto fail;
1130     }
1131
1132     codec_name = ff_jni_utf_chars_to_jstring(env, name, codec);
1133     if (!codec_name) {
1134         goto fail;
1135     }
1136
1137     codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_by_codec_name_id, codec_name);
1138     if (ff_jni_exception_check(env, 1, codec) < 0) {
1139         goto fail;
1140     }
1141
1142     codec->object = (*env)->NewGlobalRef(env, codec->object);
1143     if (!codec->object) {
1144         goto fail;
1145     }
1146
1147     if (codec_init_static_fields(codec) < 0) {
1148         goto fail;
1149     }
1150
1151     if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
1152         codec->has_get_i_o_buffer = 1;
1153     }
1154
1155     return codec;
1156 fail:
1157     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1158
1159     if (codec_name) {
1160         (*env)->DeleteLocalRef(env, codec_name);
1161     }
1162
1163     av_freep(&codec);
1164
1165     return NULL;
1166 }
1167
1168 FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)
1169 {
1170     JNIEnv *env = NULL;
1171     FFAMediaCodec *codec = NULL;
1172     jstring mime_type = NULL;
1173
1174     codec = av_mallocz(sizeof(FFAMediaCodec));
1175     if (!codec) {
1176         return NULL;
1177     }
1178     codec->class = &amediacodec_class;
1179
1180     env = ff_jni_get_env(codec);
1181     if (!env) {
1182         av_freep(&codec);
1183         return NULL;
1184     }
1185
1186     if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1187         goto fail;
1188     }
1189
1190     mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
1191     if (!mime_type) {
1192         goto fail;
1193     }
1194
1195     codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type);
1196     if (ff_jni_exception_check(env, 1, codec) < 0) {
1197         goto fail;
1198     }
1199
1200     codec->object = (*env)->NewGlobalRef(env, codec->object);
1201     if (!codec->object) {
1202         goto fail;
1203     }
1204
1205     if (codec_init_static_fields(codec) < 0) {
1206         goto fail;
1207     }
1208
1209     if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
1210         codec->has_get_i_o_buffer = 1;
1211     }
1212
1213     return codec;
1214 fail:
1215     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1216
1217     if (mime_type) {
1218         (*env)->DeleteLocalRef(env, mime_type);
1219     }
1220
1221     av_freep(&codec);
1222
1223     return NULL;
1224 }
1225
1226 FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime)
1227 {
1228     JNIEnv *env = NULL;
1229     FFAMediaCodec *codec = NULL;
1230     jstring mime_type = NULL;
1231
1232     codec = av_mallocz(sizeof(FFAMediaCodec));
1233     if (!codec) {
1234         return NULL;
1235     }
1236     codec->class = &amediacodec_class;
1237
1238     env = ff_jni_get_env(codec);
1239     if (!env) {
1240         av_freep(&codec);
1241         return NULL;
1242     }
1243
1244     if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1245         goto fail;
1246     }
1247
1248     mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
1249     if (!mime_type) {
1250         goto fail;
1251     }
1252
1253     codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_encoder_by_type_id, mime_type);
1254     if (ff_jni_exception_check(env, 1, codec) < 0) {
1255         goto fail;
1256     }
1257
1258     codec->object = (*env)->NewGlobalRef(env, codec->object);
1259     if (!codec->object) {
1260         goto fail;
1261     }
1262
1263     if (codec_init_static_fields(codec) < 0) {
1264         goto fail;
1265     }
1266
1267     if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
1268         codec->has_get_i_o_buffer = 1;
1269     }
1270
1271     return codec;
1272 fail:
1273     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1274
1275     if (mime_type) {
1276         (*env)->DeleteLocalRef(env, mime_type);
1277     }
1278
1279     av_freep(&codec);
1280
1281     return NULL;
1282 }
1283
1284 int ff_AMediaCodec_delete(FFAMediaCodec* codec)
1285 {
1286     int ret = 0;
1287
1288     JNIEnv *env = NULL;
1289
1290     if (!codec) {
1291         return 0;
1292     }
1293
1294     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1295
1296     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
1297     if (ff_jni_exception_check(env, 1, codec) < 0) {
1298         ret = AVERROR_EXTERNAL;
1299     }
1300
1301     (*env)->DeleteGlobalRef(env, codec->object);
1302     codec->object = NULL;
1303
1304     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1305
1306     av_freep(&codec);
1307
1308     return ret;
1309 }
1310
1311 char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
1312 {
1313     char *ret = NULL;
1314     JNIEnv *env = NULL;
1315     jobject *name = NULL;
1316
1317     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1318
1319     name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1320     if (ff_jni_exception_check(env, 1, codec) < 0) {
1321         goto fail;
1322     }
1323
1324     ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1325
1326 fail:
1327     return ret;
1328 }
1329
1330 int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
1331 {
1332     int ret = 0;
1333     JNIEnv *env = NULL;
1334
1335     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1336
1337     (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
1338     if (ff_jni_exception_check(env, 1, codec) < 0) {
1339         ret = AVERROR_EXTERNAL;
1340         goto fail;
1341     }
1342
1343 fail:
1344     return ret;
1345 }
1346
1347 int ff_AMediaCodec_start(FFAMediaCodec* codec)
1348 {
1349     int ret = 0;
1350     JNIEnv *env = NULL;
1351
1352     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1353
1354     (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1355     if (ff_jni_exception_check(env, 1, codec) < 0) {
1356         ret = AVERROR_EXTERNAL;
1357         goto fail;
1358     }
1359
1360 fail:
1361     return ret;
1362 }
1363
1364 int ff_AMediaCodec_stop(FFAMediaCodec* codec)
1365 {
1366     int ret = 0;
1367     JNIEnv *env = NULL;
1368
1369     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1370
1371     (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1372     if (ff_jni_exception_check(env, 1, codec) < 0) {
1373         ret = AVERROR_EXTERNAL;
1374         goto fail;
1375     }
1376
1377 fail:
1378     return ret;
1379 }
1380
1381 int ff_AMediaCodec_flush(FFAMediaCodec* codec)
1382 {
1383     int ret = 0;
1384     JNIEnv *env = NULL;
1385
1386     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1387
1388     (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1389     if (ff_jni_exception_check(env, 1, codec) < 0) {
1390         ret = AVERROR_EXTERNAL;
1391         goto fail;
1392     }
1393
1394 fail:
1395     return ret;
1396 }
1397
1398 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
1399 {
1400     int ret = 0;
1401     JNIEnv *env = NULL;
1402
1403     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1404
1405     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, idx, render);
1406     if (ff_jni_exception_check(env, 1, codec) < 0) {
1407         ret = AVERROR_EXTERNAL;
1408         goto fail;
1409     }
1410
1411 fail:
1412     return ret;
1413 }
1414
1415 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
1416 {
1417     int ret = 0;
1418     JNIEnv *env = NULL;
1419
1420     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1421
1422     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, idx, timestampNs);
1423     if (ff_jni_exception_check(env, 1, codec) < 0) {
1424         ret = AVERROR_EXTERNAL;
1425         goto fail;
1426     }
1427
1428 fail:
1429     return ret;
1430 }
1431
1432 ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
1433 {
1434     int ret = 0;
1435     JNIEnv *env = NULL;
1436
1437     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1438
1439     ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1440     if (ff_jni_exception_check(env, 1, codec) < 0) {
1441         ret = AVERROR_EXTERNAL;
1442         goto fail;
1443     }
1444
1445 fail:
1446     return ret;
1447 }
1448
1449 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1450 {
1451     int ret = 0;
1452     JNIEnv *env = NULL;
1453
1454     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1455
1456     (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, idx, offset, size, time, flags);
1457     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1458         ret = AVERROR_EXTERNAL;
1459         goto fail;
1460     }
1461
1462 fail:
1463     return ret;
1464 }
1465
1466 ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec* codec, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
1467 {
1468     int ret = 0;
1469     JNIEnv *env = NULL;
1470
1471     jobject mediainfo = NULL;
1472
1473     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1474
1475     mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
1476     if (ff_jni_exception_check(env, 1, codec) < 0) {
1477         ret = AVERROR_EXTERNAL;
1478         goto fail;
1479     }
1480
1481     ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, mediainfo, timeoutUs);
1482     if (ff_jni_exception_check(env, 1, codec) < 0) {
1483         ret = AVERROR_EXTERNAL;
1484         goto fail;
1485     }
1486
1487     info->flags = (*env)->GetIntField(env, mediainfo, codec->jfields.flags_id);
1488     if (ff_jni_exception_check(env, 1, codec) < 0) {
1489         ret = AVERROR_EXTERNAL;
1490         goto fail;
1491     }
1492
1493     info->offset = (*env)->GetIntField(env, mediainfo, codec->jfields.offset_id);
1494     if (ff_jni_exception_check(env, 1, codec) < 0) {
1495         ret = AVERROR_EXTERNAL;
1496         goto fail;
1497     }
1498
1499     info->presentationTimeUs = (*env)->GetLongField(env, mediainfo, codec->jfields.presentation_time_us_id);
1500     if (ff_jni_exception_check(env, 1, codec) < 0) {
1501         ret = AVERROR_EXTERNAL;
1502         goto fail;
1503     }
1504
1505     info->size = (*env)->GetIntField(env, mediainfo, codec->jfields.size_id);
1506     if (ff_jni_exception_check(env, 1, codec) < 0) {
1507         ret = AVERROR_EXTERNAL;
1508         goto fail;
1509     }
1510 fail:
1511     if (mediainfo) {
1512         (*env)->DeleteLocalRef(env, mediainfo);
1513     }
1514
1515     return ret;
1516 }
1517
1518 uint8_t* ff_AMediaCodec_getInputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
1519 {
1520     uint8_t *ret = NULL;
1521     JNIEnv *env = NULL;
1522
1523     jobject buffer = NULL;
1524
1525     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1526
1527     if (codec->has_get_i_o_buffer) {
1528         buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, idx);
1529         if (ff_jni_exception_check(env, 1, codec) < 0) {
1530             goto fail;
1531         }
1532     } else {
1533         if (!codec->input_buffers) {
1534             codec->input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1535             if (ff_jni_exception_check(env, 1, codec) < 0) {
1536                 goto fail;
1537             }
1538
1539             codec->input_buffers = (*env)->NewGlobalRef(env, codec->input_buffers);
1540             if (ff_jni_exception_check(env, 1, codec) < 0) {
1541                 goto fail;
1542             }
1543         }
1544
1545         buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1546         if (ff_jni_exception_check(env, 1, codec) < 0) {
1547             goto fail;
1548         }
1549     }
1550
1551     ret = (*env)->GetDirectBufferAddress(env, buffer);
1552     *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1553 fail:
1554     if (buffer) {
1555         (*env)->DeleteLocalRef(env, buffer);
1556     }
1557
1558     return ret;
1559 }
1560
1561 uint8_t* ff_AMediaCodec_getOutputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
1562 {
1563     uint8_t *ret = NULL;
1564     JNIEnv *env = NULL;
1565
1566     jobject buffer = NULL;
1567
1568     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1569
1570     if (codec->has_get_i_o_buffer) {
1571         buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, idx);
1572         if (ff_jni_exception_check(env, 1, codec) < 0) {
1573             goto fail;
1574         }
1575     } else {
1576         if (!codec->output_buffers) {
1577             codec->output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1578             if (ff_jni_exception_check(env, 1, codec) < 0) {
1579                 goto fail;
1580             }
1581
1582             codec->output_buffers = (*env)->NewGlobalRef(env, codec->output_buffers);
1583             if (ff_jni_exception_check(env, 1, codec) < 0) {
1584                 goto fail;
1585             }
1586         }
1587
1588         buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1589         if (ff_jni_exception_check(env, 1, codec) < 0) {
1590             goto fail;
1591         }
1592     }
1593
1594     ret = (*env)->GetDirectBufferAddress(env, buffer);
1595     *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1596 fail:
1597     if (buffer) {
1598         (*env)->DeleteLocalRef(env, buffer);
1599     }
1600
1601     return ret;
1602 }
1603
1604 FFAMediaFormat* ff_AMediaCodec_getOutputFormat(FFAMediaCodec* codec)
1605 {
1606     FFAMediaFormat *ret = NULL;
1607     JNIEnv *env = NULL;
1608
1609     jobject mediaformat = NULL;
1610
1611     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1612
1613     mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1614     if (ff_jni_exception_check(env, 1, codec) < 0) {
1615         goto fail;
1616     }
1617
1618     ret = ff_AMediaFormat_newFromObject(mediaformat);
1619 fail:
1620     if (mediaformat) {
1621         (*env)->DeleteLocalRef(env, mediaformat);
1622     }
1623
1624     return ret;
1625 }
1626
1627 int ff_AMediaCodec_infoTryAgainLater(FFAMediaCodec *codec, ssize_t idx)
1628 {
1629     return idx == codec->INFO_TRY_AGAIN_LATER;
1630 }
1631
1632 int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec *codec, ssize_t idx)
1633 {
1634     return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1635 }
1636
1637 int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
1638 {
1639     return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1640 }
1641
1642 int ff_AMediaCodec_getBufferFlagCodecConfig(FFAMediaCodec *codec)
1643 {
1644     return codec->BUFFER_FLAG_CODEC_CONFIG;
1645 }
1646
1647 int ff_AMediaCodec_getBufferFlagEndOfStream(FFAMediaCodec *codec)
1648 {
1649     return codec->BUFFER_FLAG_END_OF_STREAM;
1650 }
1651
1652 int ff_AMediaCodec_getBufferFlagKeyFrame(FFAMediaCodec *codec)
1653 {
1654     return codec->BUFFER_FLAG_KEY_FRAME;
1655 }
1656
1657 int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec)
1658 {
1659     return codec->CONFIGURE_FLAG_ENCODE;
1660 }
1661
1662 int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
1663 {
1664     int ret = 0;
1665
1666     if (!codec->has_get_i_o_buffer) {
1667         if (codec->output_buffers) {
1668             JNIEnv *env = NULL;
1669
1670             env = ff_jni_get_env(codec);
1671             if (!env) {
1672                 ret = AVERROR_EXTERNAL;
1673                 goto fail;
1674             }
1675
1676             (*env)->DeleteGlobalRef(env, codec->output_buffers);
1677             codec->output_buffers = NULL;
1678         }
1679     }
1680
1681 fail:
1682     return ret;
1683 }