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