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