Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / 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 <dlfcn.h>
24 #include <jni.h>
25 #include <stdbool.h>
26 #include <media/NdkMediaFormat.h>
27 #include <media/NdkMediaCodec.h>
28 #include <android/native_window_jni.h>
29
30 #include "libavutil/avassert.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/avstring.h"
33
34 #include "avcodec.h"
35 #include "ffjni.h"
36 #include "mediacodec_wrapper.h"
37
38 struct JNIAMediaCodecListFields {
39
40     jclass mediacodec_list_class;
41     jmethodID init_id;
42     jmethodID find_decoder_for_format_id;
43
44     jmethodID get_codec_count_id;
45     jmethodID get_codec_info_at_id;
46
47     jclass mediacodec_info_class;
48     jmethodID get_name_id;
49     jmethodID get_codec_capabilities_id;
50     jmethodID get_supported_types_id;
51     jmethodID is_encoder_id;
52     jmethodID is_software_only_id;
53
54     jclass codec_capabilities_class;
55     jfieldID color_formats_id;
56     jfieldID profile_levels_id;
57
58     jclass codec_profile_level_class;
59     jfieldID profile_id;
60     jfieldID level_id;
61 };
62
63 static const struct FFJniField jni_amediacodeclist_mapping[] = {
64     { "android/media/MediaCodecList", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_list_class), 1 },
65         { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, init_id), 0 },
66         { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, find_decoder_for_format_id), 0 },
67
68         { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_count_id), 1 },
69         { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_info_at_id), 1 },
70
71     { "android/media/MediaCodecInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_info_class), 1 },
72         { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_name_id), 1 },
73         { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_capabilities_id), 1 },
74         { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_supported_types_id), 1 },
75         { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_encoder_id), 1 },
76         { "android/media/MediaCodecInfo", "isSoftwareOnly", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_software_only_id), 0 },
77
78     { "android/media/MediaCodecInfo$CodecCapabilities", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_capabilities_class), 1 },
79         { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, color_formats_id), 1 },
80         { "android/media/MediaCodecInfo$CodecCapabilities", "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_levels_id), 1 },
81
82     { "android/media/MediaCodecInfo$CodecProfileLevel", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_profile_level_class), 1 },
83         { "android/media/MediaCodecInfo$CodecProfileLevel", "profile", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_id), 1 },
84         { "android/media/MediaCodecInfo$CodecProfileLevel", "level", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, level_id), 1 },
85
86     { NULL }
87 };
88
89 struct JNIAMediaFormatFields {
90
91     jclass mediaformat_class;
92
93     jmethodID init_id;
94
95     jmethodID contains_key_id;
96
97     jmethodID get_integer_id;
98     jmethodID get_long_id;
99     jmethodID get_float_id;
100     jmethodID get_bytebuffer_id;
101     jmethodID get_string_id;
102
103     jmethodID set_integer_id;
104     jmethodID set_long_id;
105     jmethodID set_float_id;
106     jmethodID set_bytebuffer_id;
107     jmethodID set_string_id;
108
109     jmethodID to_string_id;
110
111 };
112
113 static const struct FFJniField jni_amediaformat_mapping[] = {
114     { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaFormatFields, mediaformat_class), 1 },
115
116         { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, init_id), 1 },
117
118         { "android/media/MediaFormat", "containsKey", "(Ljava/lang/String;)Z", FF_JNI_METHOD,offsetof(struct JNIAMediaFormatFields, contains_key_id), 1 },
119
120         { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_integer_id), 1 },
121         { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_long_id), 1 },
122         { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_float_id), 1 },
123         { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_bytebuffer_id), 1 },
124         { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_string_id), 1 },
125
126         { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_integer_id), 1 },
127         { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_long_id), 1 },
128         { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_float_id), 1 },
129         { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_bytebuffer_id), 1 },
130         { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_string_id), 1 },
131
132         { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, to_string_id), 1 },
133
134     { NULL }
135 };
136
137 static const AVClass amediaformat_class = {
138     .class_name = "amediaformat",
139     .item_name  = av_default_item_name,
140     .version    = LIBAVUTIL_VERSION_INT,
141 };
142
143 typedef struct FFAMediaFormatJni {
144     FFAMediaFormat api;
145
146     struct JNIAMediaFormatFields jfields;
147     jobject object;
148 } FFAMediaFormatJni;
149
150 static const FFAMediaFormat media_format_jni;
151
152 struct JNIAMediaCodecFields {
153
154     jclass mediacodec_class;
155
156     jfieldID info_try_again_later_id;
157     jfieldID info_output_buffers_changed_id;
158     jfieldID info_output_format_changed_id;
159
160     jfieldID buffer_flag_codec_config_id;
161     jfieldID buffer_flag_end_of_stream_id;
162     jfieldID buffer_flag_key_frame_id;
163
164     jfieldID configure_flag_encode_id;
165
166     jmethodID create_by_codec_name_id;
167     jmethodID create_decoder_by_type_id;
168     jmethodID create_encoder_by_type_id;
169
170     jmethodID get_name_id;
171
172     jmethodID configure_id;
173     jmethodID start_id;
174     jmethodID flush_id;
175     jmethodID stop_id;
176     jmethodID release_id;
177
178     jmethodID get_output_format_id;
179
180     jmethodID dequeue_input_buffer_id;
181     jmethodID queue_input_buffer_id;
182     jmethodID get_input_buffer_id;
183     jmethodID get_input_buffers_id;
184
185     jmethodID dequeue_output_buffer_id;
186     jmethodID get_output_buffer_id;
187     jmethodID get_output_buffers_id;
188     jmethodID release_output_buffer_id;
189     jmethodID release_output_buffer_at_time_id;
190
191     jmethodID set_input_surface_id;
192     jmethodID signal_end_of_input_stream_id;
193
194     jclass mediainfo_class;
195
196     jmethodID init_id;
197
198     jfieldID flags_id;
199     jfieldID offset_id;
200     jfieldID presentation_time_us_id;
201     jfieldID size_id;
202
203 };
204
205 static const struct FFJniField jni_amediacodec_mapping[] = {
206     { "android/media/MediaCodec", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediacodec_class), 1 },
207
208         { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_try_again_later_id), 1 },
209         { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_buffers_changed_id), 1 },
210         { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_format_changed_id), 1 },
211
212         { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_codec_config_id), 1 },
213         { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_end_of_stream_id), 1 },
214         { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_key_frame_id), 0 },
215
216         { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, configure_flag_encode_id), 1 },
217
218         { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_by_codec_name_id), 1 },
219         { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_decoder_by_type_id), 1 },
220         { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_encoder_by_type_id), 1 },
221
222         { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_name_id), 1 },
223
224         { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, configure_id), 1 },
225         { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, start_id), 1 },
226         { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, flush_id), 1 },
227         { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, stop_id), 1 },
228         { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_id), 1 },
229
230         { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_format_id), 1 },
231
232         { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_input_buffer_id), 1 },
233         { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, queue_input_buffer_id), 1 },
234         { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffer_id), 0 },
235         { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffers_id), 1 },
236
237         { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_output_buffer_id), 1 },
238         { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffer_id), 0 },
239         { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffers_id), 1 },
240         { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_id), 1 },
241         { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_at_time_id), 0 },
242
243         { "android/media/MediaCodec", "setInputSurface", "(Landroid/view/Surface;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, set_input_surface_id), 0 },
244         { "android/media/MediaCodec", "signalEndOfInputStream", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, signal_end_of_input_stream_id), 0 },
245
246     { "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediainfo_class), 1 },
247
248         { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, init_id), 1 },
249         { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, flags_id), 1 },
250         { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, offset_id), 1 },
251         { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, presentation_time_us_id), 1 },
252         { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, size_id), 1 },
253
254     { NULL }
255 };
256
257 static const AVClass amediacodec_class = {
258     .class_name = "amediacodec",
259     .item_name  = av_default_item_name,
260     .version    = LIBAVUTIL_VERSION_INT,
261 };
262
263 typedef struct FFAMediaCodecJni {
264     FFAMediaCodec api;
265
266     struct JNIAMediaCodecFields jfields;
267
268     jobject object;
269     jobject buffer_info;
270
271     jobject input_buffers;
272     jobject output_buffers;
273
274     int INFO_TRY_AGAIN_LATER;
275     int INFO_OUTPUT_BUFFERS_CHANGED;
276     int INFO_OUTPUT_FORMAT_CHANGED;
277
278     int BUFFER_FLAG_CODEC_CONFIG;
279     int BUFFER_FLAG_END_OF_STREAM;
280     int BUFFER_FLAG_KEY_FRAME;
281
282     int CONFIGURE_FLAG_ENCODE;
283
284     int has_get_i_o_buffer;
285 } FFAMediaCodecJni;
286
287 static const FFAMediaCodec media_codec_jni;
288
289 #define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do {              \
290     (env) = ff_jni_get_env(log_ctx);                               \
291     if (!(env)) {                                                  \
292         return ret;                                                \
293     }                                                              \
294 } while (0)
295
296 #define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do {              \
297     (env) = ff_jni_get_env(log_ctx);                               \
298     if (!(env)) {                                                  \
299         return;                                                    \
300     }                                                              \
301 } while (0)
302
303 int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
304 {
305     // Copy and modified from MediaCodecInfo.java
306     static const int AVCProfileBaseline = 0x01;
307     static const int AVCProfileMain     = 0x02;
308     static const int AVCProfileExtended = 0x04;
309     static const int AVCProfileHigh     = 0x08;
310     static const int AVCProfileHigh10   = 0x10;
311     static const int AVCProfileHigh422  = 0x20;
312     static const int AVCProfileHigh444  = 0x40;
313     static const int AVCProfileConstrainedBaseline = 0x10000;
314     static const int AVCProfileConstrainedHigh     = 0x80000;
315
316     static const int HEVCProfileMain        = 0x01;
317     static const int HEVCProfileMain10      = 0x02;
318     static const int HEVCProfileMainStill   = 0x04;
319     static const int HEVCProfileMain10HDR10 = 0x1000;
320     static const int HEVCProfileMain10HDR10Plus = 0x2000;
321
322     static const int VP9Profile0 = 0x01;
323     static const int VP9Profile1 = 0x02;
324     static const int VP9Profile2 = 0x04;
325     static const int VP9Profile3 = 0x08;
326     static const int VP9Profile2HDR = 0x1000;
327     static const int VP9Profile3HDR = 0x2000;
328     static const int VP9Profile2HDR10Plus = 0x4000;
329     static const int VP9Profile3HDR10Plus = 0x8000;
330
331     static const int MPEG4ProfileSimple           = 0x01;
332     static const int MPEG4ProfileSimpleScalable   = 0x02;
333     static const int MPEG4ProfileCore             = 0x04;
334     static const int MPEG4ProfileMain             = 0x08;
335     static const int MPEG4ProfileNbit             = 0x10;
336     static const int MPEG4ProfileScalableTexture  = 0x20;
337     static const int MPEG4ProfileSimpleFBA        = 0x80;
338     static const int MPEG4ProfileSimpleFace       = 0x40;
339     static const int MPEG4ProfileBasicAnimated    = 0x100;
340     static const int MPEG4ProfileHybrid           = 0x200;
341     static const int MPEG4ProfileAdvancedRealTime = 0x400;
342     static const int MPEG4ProfileCoreScalable     = 0x800;
343     static const int MPEG4ProfileAdvancedCoding   = 0x1000;
344     static const int MPEG4ProfileAdvancedCore     = 0x2000;
345     static const int MPEG4ProfileAdvancedScalable = 0x4000;
346     static const int MPEG4ProfileAdvancedSimple   = 0x8000;
347
348
349     static const int AV1ProfileMain8  = 0x1;
350     static const int AV1ProfileMain10 = 0x2;
351     static const int AV1ProfileMain10HDR10     = 0x1000;
352     static const int AV1ProfileMain10HDR10Plus = 0x2000;
353
354     // Unused yet.
355     (void)AVCProfileConstrainedHigh;
356     (void)HEVCProfileMain10HDR10;
357     (void)HEVCProfileMain10HDR10Plus;
358     (void)VP9Profile2HDR;
359     (void)VP9Profile3HDR;
360     (void)VP9Profile2HDR10Plus;
361     (void)VP9Profile3HDR10Plus;
362     (void)AV1ProfileMain10;
363     (void)AV1ProfileMain10HDR10;
364     (void)AV1ProfileMain10HDR10Plus;
365
366     if (avctx->codec_id == AV_CODEC_ID_H264) {
367         switch(avctx->profile) {
368         case AV_PROFILE_H264_BASELINE:
369             return AVCProfileBaseline;
370         case AV_PROFILE_H264_CONSTRAINED_BASELINE:
371             return AVCProfileConstrainedBaseline;
372         case AV_PROFILE_H264_MAIN:
373             return AVCProfileMain;
374             break;
375         case AV_PROFILE_H264_EXTENDED:
376             return AVCProfileExtended;
377         case AV_PROFILE_H264_HIGH:
378             return AVCProfileHigh;
379         case AV_PROFILE_H264_HIGH_10:
380         case AV_PROFILE_H264_HIGH_10_INTRA:
381             return AVCProfileHigh10;
382         case AV_PROFILE_H264_HIGH_422:
383         case AV_PROFILE_H264_HIGH_422_INTRA:
384             return AVCProfileHigh422;
385         case AV_PROFILE_H264_HIGH_444:
386         case AV_PROFILE_H264_HIGH_444_INTRA:
387         case AV_PROFILE_H264_HIGH_444_PREDICTIVE:
388             return AVCProfileHigh444;
389         }
390     } else if (avctx->codec_id == AV_CODEC_ID_HEVC) {
391         switch (avctx->profile) {
392         case AV_PROFILE_HEVC_MAIN:
393             return HEVCProfileMain;
394         case AV_PROFILE_HEVC_MAIN_STILL_PICTURE:
395             return HEVCProfileMainStill;
396         case AV_PROFILE_HEVC_MAIN_10:
397             return HEVCProfileMain10;
398         }
399     } else if (avctx->codec_id == AV_CODEC_ID_VP9) {
400         switch (avctx->profile) {
401         case AV_PROFILE_VP9_0:
402             return VP9Profile0;
403         case AV_PROFILE_VP9_1:
404             return VP9Profile1;
405         case AV_PROFILE_VP9_2:
406             return VP9Profile2;
407          case AV_PROFILE_VP9_3:
408             return VP9Profile3;
409         }
410     } else if(avctx->codec_id == AV_CODEC_ID_MPEG4) {
411         switch (avctx->profile)
412         {
413         case AV_PROFILE_MPEG4_SIMPLE:
414             return MPEG4ProfileSimple;
415         case AV_PROFILE_MPEG4_SIMPLE_SCALABLE:
416             return MPEG4ProfileSimpleScalable;
417         case AV_PROFILE_MPEG4_CORE:
418             return MPEG4ProfileCore;
419         case AV_PROFILE_MPEG4_MAIN:
420             return MPEG4ProfileMain;
421         case AV_PROFILE_MPEG4_N_BIT:
422             return MPEG4ProfileNbit;
423         case AV_PROFILE_MPEG4_SCALABLE_TEXTURE:
424             return MPEG4ProfileScalableTexture;
425         case AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION:
426             return MPEG4ProfileSimpleFBA;
427         case AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE:
428             return MPEG4ProfileBasicAnimated;
429         case AV_PROFILE_MPEG4_HYBRID:
430             return MPEG4ProfileHybrid;
431         case AV_PROFILE_MPEG4_ADVANCED_REAL_TIME:
432             return MPEG4ProfileAdvancedRealTime;
433         case AV_PROFILE_MPEG4_CORE_SCALABLE:
434             return MPEG4ProfileCoreScalable;
435         case AV_PROFILE_MPEG4_ADVANCED_CODING:
436             return MPEG4ProfileAdvancedCoding;
437         case AV_PROFILE_MPEG4_ADVANCED_CORE:
438             return MPEG4ProfileAdvancedCore;
439         case AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE:
440             return MPEG4ProfileAdvancedScalable;
441         case AV_PROFILE_MPEG4_ADVANCED_SIMPLE:
442             return MPEG4ProfileAdvancedSimple;
443         case AV_PROFILE_MPEG4_SIMPLE_STUDIO:
444             // Studio profiles are not supported by mediacodec.
445         default:
446             break;
447         }
448     } else if(avctx->codec_id == AV_CODEC_ID_AV1) {
449         switch (avctx->profile)
450         {
451         case AV_PROFILE_AV1_MAIN:
452             return AV1ProfileMain8;
453         case AV_PROFILE_AV1_HIGH:
454         case AV_PROFILE_AV1_PROFESSIONAL:
455         default:
456             break;
457         }
458     }
459
460     return -1;
461 }
462
463 char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
464 {
465     int ret;
466     int i;
467     int codec_count;
468     int found_codec = 0;
469     char *name = NULL;
470     char *supported_type = NULL;
471
472     JNIEnv *env = NULL;
473     struct JNIAMediaCodecListFields jfields = { 0 };
474     struct JNIAMediaFormatFields mediaformat_jfields = { 0 };
475
476     jobject codec_name = NULL;
477
478     jobject info = NULL;
479     jobject type = NULL;
480     jobjectArray types = NULL;
481
482     jobject capabilities = NULL;
483     jobject profile_level = NULL;
484     jobjectArray profile_levels = NULL;
485
486     JNI_GET_ENV_OR_RETURN(env, log_ctx, NULL);
487
488     if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
489         goto done;
490     }
491
492     if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) {
493         goto done;
494     }
495
496     codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
497     if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
498         goto done;
499     }
500
501     for(i = 0; i < codec_count; i++) {
502         int j;
503         int type_count;
504         int is_encoder;
505
506         info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
507         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
508             goto done;
509         }
510
511         types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
512         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
513             goto done;
514         }
515
516         is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
517         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
518             goto done;
519         }
520
521         if (is_encoder != encoder) {
522             goto done_with_info;
523         }
524
525         if (jfields.is_software_only_id) {
526             int is_software_only = (*env)->CallBooleanMethod(env, info, jfields.is_software_only_id);
527             if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
528                 goto done;
529             }
530
531             if (is_software_only) {
532                 goto done_with_info;
533             }
534         }
535
536         codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
537         if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
538             goto done;
539         }
540
541         name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
542         if (!name) {
543             goto done;
544         }
545
546         if (codec_name) {
547             (*env)->DeleteLocalRef(env, codec_name);
548             codec_name = NULL;
549         }
550
551         /* Skip software decoders */
552         if (
553             strstr(name, "OMX.google") ||
554             strstr(name, "OMX.ffmpeg") ||
555             (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) ||
556             !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) {
557             goto done_with_info;
558         }
559
560         type_count = (*env)->GetArrayLength(env, types);
561         for (j = 0; j < type_count; j++) {
562             int k;
563             int profile_count;
564
565             type = (*env)->GetObjectArrayElement(env, types, j);
566             if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
567                 goto done;
568             }
569
570             supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
571             if (!supported_type) {
572                 goto done;
573             }
574
575             if (av_strcasecmp(supported_type, mime)) {
576                 goto done_with_type;
577             }
578
579             capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type);
580             if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
581                 goto done;
582             }
583
584             profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id);
585             if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
586                 goto done;
587             }
588
589             profile_count = (*env)->GetArrayLength(env, profile_levels);
590             if (!profile_count) {
591                 found_codec = 1;
592             }
593             for (k = 0; k < profile_count; k++) {
594                 int supported_profile = 0;
595
596                 if (profile < 0) {
597                     found_codec = 1;
598                     break;
599                 }
600
601                 profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k);
602                 if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
603                     goto done;
604                 }
605
606                 supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id);
607                 if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
608                     goto done;
609                 }
610
611                 found_codec = profile == supported_profile;
612
613                 if (profile_level) {
614                     (*env)->DeleteLocalRef(env, profile_level);
615                     profile_level = NULL;
616                 }
617
618                 if (found_codec) {
619                     break;
620                 }
621             }
622
623 done_with_type:
624             if (profile_levels) {
625                 (*env)->DeleteLocalRef(env, profile_levels);
626                 profile_levels = NULL;
627             }
628
629             if (capabilities) {
630                 (*env)->DeleteLocalRef(env, capabilities);
631                 capabilities = NULL;
632             }
633
634             if (type) {
635                 (*env)->DeleteLocalRef(env, type);
636                 type = NULL;
637             }
638
639             av_freep(&supported_type);
640
641             if (found_codec) {
642                 break;
643             }
644         }
645
646 done_with_info:
647         if (info) {
648             (*env)->DeleteLocalRef(env, info);
649             info = NULL;
650         }
651
652         if (types) {
653             (*env)->DeleteLocalRef(env, types);
654             types = NULL;
655         }
656
657         if (found_codec) {
658             break;
659         }
660
661         av_freep(&name);
662     }
663
664 done:
665     if (codec_name) {
666         (*env)->DeleteLocalRef(env, codec_name);
667     }
668
669     if (info) {
670         (*env)->DeleteLocalRef(env, info);
671     }
672
673     if (type) {
674         (*env)->DeleteLocalRef(env, type);
675     }
676
677     if (types) {
678         (*env)->DeleteLocalRef(env, types);
679     }
680
681     if (capabilities) {
682         (*env)->DeleteLocalRef(env, capabilities);
683     }
684
685     if (profile_level) {
686         (*env)->DeleteLocalRef(env, profile_level);
687     }
688
689     if (profile_levels) {
690         (*env)->DeleteLocalRef(env, profile_levels);
691     }
692
693     av_freep(&supported_type);
694
695     ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
696     ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
697
698     if (!found_codec) {
699         av_freep(&name);
700     }
701
702     return name;
703 }
704
705 static FFAMediaFormat *mediaformat_jni_new(void)
706 {
707     JNIEnv *env = NULL;
708     FFAMediaFormatJni *format = NULL;
709     jobject object = NULL;
710
711     format = av_mallocz(sizeof(*format));
712     if (!format) {
713         return NULL;
714     }
715     format->api = media_format_jni;
716
717     env = ff_jni_get_env(format);
718     if (!env) {
719         av_freep(&format);
720         return NULL;
721     }
722
723     if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
724         goto fail;
725     }
726
727     object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
728     if (!object) {
729         goto fail;
730     }
731
732     format->object = (*env)->NewGlobalRef(env, object);
733     if (!format->object) {
734         goto fail;
735     }
736
737 fail:
738     if (object) {
739         (*env)->DeleteLocalRef(env, object);
740     }
741
742     if (!format->object) {
743         ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
744         av_freep(&format);
745     }
746
747     return (FFAMediaFormat *)format;
748 }
749
750 static FFAMediaFormat *mediaformat_jni_newFromObject(void *object)
751 {
752     JNIEnv *env = NULL;
753     FFAMediaFormatJni *format = NULL;
754
755     format = av_mallocz(sizeof(*format));
756     if (!format) {
757         return NULL;
758     }
759     format->api = media_format_jni;
760
761     env = ff_jni_get_env(format);
762     if (!env) {
763         av_freep(&format);
764         return NULL;
765     }
766
767     if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
768         goto fail;
769     }
770
771     format->object = (*env)->NewGlobalRef(env, object);
772     if (!format->object) {
773         goto fail;
774     }
775
776     return (FFAMediaFormat *)format;
777 fail:
778     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
779
780     av_freep(&format);
781
782     return NULL;
783 }
784
785 static int mediaformat_jni_delete(FFAMediaFormat* ctx)
786 {
787     int ret = 0;
788     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
789     JNIEnv *env = NULL;
790
791     if (!format) {
792         return 0;
793     }
794
795     JNI_GET_ENV_OR_RETURN(env, format, AVERROR_EXTERNAL);
796
797     (*env)->DeleteGlobalRef(env, format->object);
798     format->object = NULL;
799
800     ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
801
802     av_freep(&format);
803
804     return ret;
805 }
806
807 static char* mediaformat_jni_toString(FFAMediaFormat* ctx)
808 {
809     char *ret = NULL;
810     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
811     JNIEnv *env = NULL;
812     jstring description = NULL;
813
814     av_assert0(format != NULL);
815
816     JNI_GET_ENV_OR_RETURN(env, format, NULL);
817
818     description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
819     if (ff_jni_exception_check(env, 1, NULL) < 0) {
820         goto fail;
821     }
822
823     ret = ff_jni_jstring_to_utf_chars(env, description, format);
824 fail:
825     if (description) {
826         (*env)->DeleteLocalRef(env, description);
827     }
828
829     return ret;
830 }
831
832 static int mediaformat_jni_getInt32(FFAMediaFormat* ctx, const char *name, int32_t *out)
833 {
834     int ret = 1;
835     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
836     JNIEnv *env = NULL;
837     jstring key = NULL;
838     jboolean contains_key;
839
840     av_assert0(format != NULL);
841
842     JNI_GET_ENV_OR_RETURN(env, format, 0);
843
844     key = ff_jni_utf_chars_to_jstring(env, name, format);
845     if (!key) {
846         ret = 0;
847         goto fail;
848     }
849
850     contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
851     if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
852         ret = 0;
853         goto fail;
854     }
855
856     *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
857     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
858         ret = 0;
859         goto fail;
860     }
861
862     ret = 1;
863 fail:
864     if (key) {
865         (*env)->DeleteLocalRef(env, key);
866     }
867
868     return ret;
869 }
870
871 static int mediaformat_jni_getInt64(FFAMediaFormat* ctx, const char *name, int64_t *out)
872 {
873     int ret = 1;
874     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
875     JNIEnv *env = NULL;
876     jstring key = NULL;
877     jboolean contains_key;
878
879     av_assert0(format != NULL);
880
881     JNI_GET_ENV_OR_RETURN(env, format, 0);
882
883     key = ff_jni_utf_chars_to_jstring(env, name, format);
884     if (!key) {
885         ret = 0;
886         goto fail;
887     }
888
889     contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
890     if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
891         ret = 0;
892         goto fail;
893     }
894
895     *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
896     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
897         ret = 0;
898         goto fail;
899     }
900
901     ret = 1;
902 fail:
903     if (key) {
904         (*env)->DeleteLocalRef(env, key);
905     }
906
907     return ret;
908 }
909
910 static int mediaformat_jni_getFloat(FFAMediaFormat* ctx, const char *name, float *out)
911 {
912     int ret = 1;
913     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
914     JNIEnv *env = NULL;
915     jstring key = NULL;
916     jboolean contains_key;
917
918     av_assert0(format != NULL);
919
920     JNI_GET_ENV_OR_RETURN(env, format, 0);
921
922     key = ff_jni_utf_chars_to_jstring(env, name, format);
923     if (!key) {
924         ret = 0;
925         goto fail;
926     }
927
928     contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
929     if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
930         ret = 0;
931         goto fail;
932     }
933
934     *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
935     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
936         ret = 0;
937         goto fail;
938     }
939
940     ret = 1;
941 fail:
942     if (key) {
943         (*env)->DeleteLocalRef(env, key);
944     }
945
946     return ret;
947 }
948
949 static int mediaformat_jni_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size)
950 {
951     int ret = 1;
952     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
953     JNIEnv *env = NULL;
954     jstring key = NULL;
955     jboolean contains_key;
956     jobject result = NULL;
957
958     av_assert0(format != NULL);
959
960     JNI_GET_ENV_OR_RETURN(env, format, 0);
961
962     key = ff_jni_utf_chars_to_jstring(env, name, format);
963     if (!key) {
964         ret = 0;
965         goto fail;
966     }
967
968     contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
969     if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
970         ret = 0;
971         goto fail;
972     }
973
974     result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
975     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
976         ret = 0;
977         goto fail;
978     }
979
980     *data = (*env)->GetDirectBufferAddress(env, result);
981     *size = (*env)->GetDirectBufferCapacity(env, result);
982
983     if (*data && *size) {
984         void *src = *data;
985         *data = av_malloc(*size);
986         if (!*data) {
987             ret = 0;
988             goto fail;
989         }
990
991         memcpy(*data, src, *size);
992     }
993
994     ret = 1;
995 fail:
996     if (key) {
997         (*env)->DeleteLocalRef(env, key);
998     }
999
1000     if (result) {
1001         (*env)->DeleteLocalRef(env, result);
1002     }
1003
1004     return ret;
1005 }
1006
1007 static int mediaformat_jni_getString(FFAMediaFormat* ctx, const char *name, const char **out)
1008 {
1009     int ret = 1;
1010     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
1011     JNIEnv *env = NULL;
1012     jstring key = NULL;
1013     jboolean contains_key;
1014     jstring result = NULL;
1015
1016     av_assert0(format != NULL);
1017
1018     JNI_GET_ENV_OR_RETURN(env, format, 0);
1019
1020     key = ff_jni_utf_chars_to_jstring(env, name, format);
1021     if (!key) {
1022         ret = 0;
1023         goto fail;
1024     }
1025
1026     contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key);
1027     if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) {
1028         ret = 0;
1029         goto fail;
1030     }
1031
1032     result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
1033     if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
1034         ret = 0;
1035         goto fail;
1036     }
1037
1038     *out = ff_jni_jstring_to_utf_chars(env, result, format);
1039     if (!*out) {
1040         ret = 0;
1041         goto fail;
1042     }
1043
1044     ret = 1;
1045 fail:
1046     if (key) {
1047         (*env)->DeleteLocalRef(env, key);
1048     }
1049
1050     if (result) {
1051         (*env)->DeleteLocalRef(env, result);
1052     }
1053
1054     return ret;
1055 }
1056
1057 static void mediaformat_jni_setInt32(FFAMediaFormat* ctx, const char* name, int32_t value)
1058 {
1059     JNIEnv *env = NULL;
1060     jstring key = NULL;
1061     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
1062
1063     av_assert0(format != NULL);
1064
1065     JNI_GET_ENV_OR_RETURN_VOID(env, format);
1066
1067     key = ff_jni_utf_chars_to_jstring(env, name, format);
1068     if (!key) {
1069         goto fail;
1070     }
1071
1072     (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
1073     if (ff_jni_exception_check(env, 1, format) < 0) {
1074         goto fail;
1075     }
1076
1077 fail:
1078     if (key) {
1079         (*env)->DeleteLocalRef(env, key);
1080     }
1081 }
1082
1083 static void mediaformat_jni_setInt64(FFAMediaFormat* ctx, const char* name, int64_t value)
1084 {
1085     JNIEnv *env = NULL;
1086     jstring key = NULL;
1087     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
1088
1089     av_assert0(format != NULL);
1090
1091     JNI_GET_ENV_OR_RETURN_VOID(env, format);
1092
1093     key = ff_jni_utf_chars_to_jstring(env, name, format);
1094     if (!key) {
1095         goto fail;
1096     }
1097
1098     (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
1099     if (ff_jni_exception_check(env, 1, format) < 0) {
1100         goto fail;
1101     }
1102
1103 fail:
1104     if (key) {
1105         (*env)->DeleteLocalRef(env, key);
1106     }
1107 }
1108
1109 static void mediaformat_jni_setFloat(FFAMediaFormat* ctx, const char* name, float value)
1110 {
1111     JNIEnv *env = NULL;
1112     jstring key = NULL;
1113     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
1114
1115     av_assert0(format != NULL);
1116
1117     JNI_GET_ENV_OR_RETURN_VOID(env, format);
1118
1119     key = ff_jni_utf_chars_to_jstring(env, name, format);
1120     if (!key) {
1121         goto fail;
1122     }
1123
1124     (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
1125     if (ff_jni_exception_check(env, 1, format) < 0) {
1126         goto fail;
1127     }
1128
1129 fail:
1130     if (key) {
1131         (*env)->DeleteLocalRef(env, key);
1132     }
1133 }
1134
1135 static void mediaformat_jni_setString(FFAMediaFormat* ctx, const char* name, const char* value)
1136 {
1137     JNIEnv *env = NULL;
1138     jstring key = NULL;
1139     jstring string = NULL;
1140     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
1141
1142     av_assert0(format != NULL);
1143
1144     JNI_GET_ENV_OR_RETURN_VOID(env, format);
1145
1146     key = ff_jni_utf_chars_to_jstring(env, name, format);
1147     if (!key) {
1148         goto fail;
1149     }
1150
1151     string = ff_jni_utf_chars_to_jstring(env, value, format);
1152     if (!string) {
1153         goto fail;
1154     }
1155
1156     (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
1157     if (ff_jni_exception_check(env, 1, format) < 0) {
1158         goto fail;
1159     }
1160
1161 fail:
1162     if (key) {
1163         (*env)->DeleteLocalRef(env, key);
1164     }
1165
1166     if (string) {
1167         (*env)->DeleteLocalRef(env, string);
1168     }
1169 }
1170
1171 static void mediaformat_jni_setBuffer(FFAMediaFormat* ctx, const char* name, void* data, size_t size)
1172 {
1173     JNIEnv *env = NULL;
1174     jstring key = NULL;
1175     jobject buffer = NULL;
1176     void *buffer_data = NULL;
1177     FFAMediaFormatJni *format = (FFAMediaFormatJni *)ctx;
1178
1179     av_assert0(format != NULL);
1180
1181     JNI_GET_ENV_OR_RETURN_VOID(env, format);
1182
1183     key = ff_jni_utf_chars_to_jstring(env, name, format);
1184     if (!key) {
1185         goto fail;
1186     }
1187
1188     if (!data || !size) {
1189         goto fail;
1190     }
1191
1192     buffer_data = av_malloc(size);
1193     if (!buffer_data) {
1194         goto fail;
1195     }
1196
1197     memcpy(buffer_data, data, size);
1198
1199     buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
1200     if (!buffer) {
1201         goto fail;
1202     }
1203
1204     (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
1205     if (ff_jni_exception_check(env, 1, format) < 0) {
1206         goto fail;
1207     }
1208
1209 fail:
1210     if (key) {
1211         (*env)->DeleteLocalRef(env, key);
1212     }
1213
1214     if (buffer) {
1215         (*env)->DeleteLocalRef(env, buffer);
1216     }
1217 }
1218
1219 static int codec_init_static_fields(FFAMediaCodecJni *codec)
1220 {
1221     int ret = 0;
1222     JNIEnv *env = NULL;
1223
1224     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1225
1226     codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1227     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1228         goto fail;
1229     }
1230
1231     codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
1232     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1233         goto fail;
1234     }
1235
1236     codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
1237     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1238         goto fail;
1239     }
1240
1241     if (codec->jfields.buffer_flag_key_frame_id) {
1242         codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
1243         if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1244             goto fail;
1245         }
1246     }
1247
1248     codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
1249     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1250         goto fail;
1251     }
1252
1253     codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
1254     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1255         goto fail;
1256     }
1257
1258     codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
1259     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1260         goto fail;
1261     }
1262
1263     codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
1264     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1265         goto fail;
1266     }
1267
1268 fail:
1269
1270     return ret;
1271 }
1272
1273 #define CREATE_CODEC_BY_NAME   0
1274 #define CREATE_DECODER_BY_TYPE 1
1275 #define CREATE_ENCODER_BY_TYPE 2
1276
1277 static inline FFAMediaCodec *codec_create(int method, const char *arg)
1278 {
1279     int ret = -1;
1280     JNIEnv *env = NULL;
1281     FFAMediaCodecJni *codec = NULL;
1282     jstring jarg = NULL;
1283     jobject object = NULL;
1284     jobject buffer_info = NULL;
1285     jmethodID create_id = NULL;
1286
1287     codec = av_mallocz(sizeof(*codec));
1288     if (!codec) {
1289         return NULL;
1290     }
1291     codec->api = media_codec_jni;
1292
1293     env = ff_jni_get_env(codec);
1294     if (!env) {
1295         av_freep(&codec);
1296         return NULL;
1297     }
1298
1299     if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
1300         goto fail;
1301     }
1302
1303     jarg = ff_jni_utf_chars_to_jstring(env, arg, codec);
1304     if (!jarg) {
1305         goto fail;
1306     }
1307
1308     switch (method) {
1309     case CREATE_CODEC_BY_NAME:   create_id = codec->jfields.create_by_codec_name_id;   break;
1310     case CREATE_DECODER_BY_TYPE: create_id = codec->jfields.create_decoder_by_type_id; break;
1311     case CREATE_ENCODER_BY_TYPE: create_id = codec->jfields.create_encoder_by_type_id; break;
1312     default:
1313         av_assert0(0);
1314     }
1315
1316     object = (*env)->CallStaticObjectMethod(env,
1317                                             codec->jfields.mediacodec_class,
1318                                             create_id,
1319                                             jarg);
1320     if (ff_jni_exception_check(env, 1, codec) < 0) {
1321         goto fail;
1322     }
1323
1324     codec->object = (*env)->NewGlobalRef(env, object);
1325     if (!codec->object) {
1326         goto fail;
1327     }
1328
1329     if (codec_init_static_fields(codec) < 0) {
1330         goto fail;
1331     }
1332
1333     if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
1334         codec->has_get_i_o_buffer = 1;
1335     }
1336
1337     buffer_info = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
1338     if (ff_jni_exception_check(env, 1, codec) < 0) {
1339         goto fail;
1340     }
1341
1342     codec->buffer_info = (*env)->NewGlobalRef(env, buffer_info);
1343     if (!codec->buffer_info) {
1344         goto fail;
1345     }
1346
1347     ret = 0;
1348 fail:
1349     if (jarg) {
1350         (*env)->DeleteLocalRef(env, jarg);
1351     }
1352
1353     if (object) {
1354         (*env)->DeleteLocalRef(env, object);
1355     }
1356
1357     if (buffer_info) {
1358         (*env)->DeleteLocalRef(env, buffer_info);
1359     }
1360
1361     if (ret < 0) {
1362         if (codec->object) {
1363             (*env)->DeleteGlobalRef(env, codec->object);
1364         }
1365
1366         if (codec->buffer_info) {
1367             (*env)->DeleteGlobalRef(env, codec->buffer_info);
1368         }
1369
1370         ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1371         av_freep(&codec);
1372     }
1373
1374     return (FFAMediaCodec *)codec;
1375 }
1376
1377 #define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \
1378 static FFAMediaCodec *mediacodec_jni_##name(const char *arg)    \
1379 {                                                        \
1380     return codec_create(method, arg);                    \
1381 }                                                        \
1382
1383 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createCodecByName,   CREATE_CODEC_BY_NAME)
1384 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE)
1385 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE)
1386
1387 static int mediacodec_jni_delete(FFAMediaCodec* ctx)
1388 {
1389     int ret = 0;
1390     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1391     JNIEnv *env = NULL;
1392
1393     if (!codec) {
1394         return 0;
1395     }
1396
1397     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1398
1399     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
1400     if (ff_jni_exception_check(env, 1, codec) < 0) {
1401         ret = AVERROR_EXTERNAL;
1402     }
1403
1404     (*env)->DeleteGlobalRef(env, codec->input_buffers);
1405     codec->input_buffers = NULL;
1406
1407     (*env)->DeleteGlobalRef(env, codec->output_buffers);
1408     codec->output_buffers = NULL;
1409
1410     (*env)->DeleteGlobalRef(env, codec->object);
1411     codec->object = NULL;
1412
1413     (*env)->DeleteGlobalRef(env, codec->buffer_info);
1414     codec->buffer_info = NULL;
1415
1416     ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
1417
1418     av_freep(&codec);
1419
1420     return ret;
1421 }
1422
1423 static char *mediacodec_jni_getName(FFAMediaCodec *ctx)
1424 {
1425     char *ret = NULL;
1426     JNIEnv *env = NULL;
1427     jobject *name = NULL;
1428     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1429
1430     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1431
1432     name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
1433     if (ff_jni_exception_check(env, 1, codec) < 0) {
1434         goto fail;
1435     }
1436
1437     ret = ff_jni_jstring_to_utf_chars(env, name, codec);
1438
1439 fail:
1440     if (name) {
1441         (*env)->DeleteLocalRef(env, name);
1442     }
1443
1444     return ret;
1445 }
1446
1447 static int mediacodec_jni_configure(FFAMediaCodec *ctx,
1448                                     const FFAMediaFormat* format_ctx,
1449                                     FFANativeWindow* window,
1450                                     void *crypto,
1451                                     uint32_t flags)
1452 {
1453     int ret = 0;
1454     JNIEnv *env = NULL;
1455     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1456     const FFAMediaFormatJni *format = (FFAMediaFormatJni *)format_ctx;
1457     jobject *surface = window ? window->surface : NULL;
1458
1459     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1460
1461     if (flags & codec->CONFIGURE_FLAG_ENCODE) {
1462         if (surface && !codec->jfields.set_input_surface_id) {
1463             av_log(ctx, AV_LOG_ERROR, "System doesn't support setInputSurface\n");
1464             return AVERROR_EXTERNAL;
1465         }
1466
1467         (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, NULL, NULL, flags);
1468         if (ff_jni_exception_check(env, 1, codec) < 0)
1469             return AVERROR_EXTERNAL;
1470
1471         if (!surface)
1472             return 0;
1473
1474         (*env)->CallVoidMethod(env, codec->object, codec->jfields.set_input_surface_id, surface);
1475         if (ff_jni_exception_check(env, 1, codec) < 0)
1476             return AVERROR_EXTERNAL;
1477         return 0;
1478     } else {
1479         (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, surface, NULL, flags);
1480     }
1481     if (ff_jni_exception_check(env, 1, codec) < 0) {
1482         ret = AVERROR_EXTERNAL;
1483         goto fail;
1484     }
1485
1486 fail:
1487     return ret;
1488 }
1489
1490 static int mediacodec_jni_start(FFAMediaCodec* ctx)
1491 {
1492     int ret = 0;
1493     JNIEnv *env = NULL;
1494     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1495
1496     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1497
1498     (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
1499     if (ff_jni_exception_check(env, 1, codec) < 0) {
1500         ret = AVERROR_EXTERNAL;
1501         goto fail;
1502     }
1503
1504 fail:
1505     return ret;
1506 }
1507
1508 static int mediacodec_jni_stop(FFAMediaCodec* ctx)
1509 {
1510     int ret = 0;
1511     JNIEnv *env = NULL;
1512     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1513
1514     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1515
1516     (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
1517     if (ff_jni_exception_check(env, 1, codec) < 0) {
1518         ret = AVERROR_EXTERNAL;
1519         goto fail;
1520     }
1521
1522 fail:
1523     return ret;
1524 }
1525
1526 static int mediacodec_jni_flush(FFAMediaCodec* ctx)
1527 {
1528     int ret = 0;
1529     JNIEnv *env = NULL;
1530     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1531
1532     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1533
1534     (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
1535     if (ff_jni_exception_check(env, 1, codec) < 0) {
1536         ret = AVERROR_EXTERNAL;
1537         goto fail;
1538     }
1539
1540 fail:
1541     return ret;
1542 }
1543
1544 static int mediacodec_jni_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render)
1545 {
1546     int ret = 0;
1547     JNIEnv *env = NULL;
1548     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1549
1550     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1551
1552     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, (jint)idx, (jboolean)render);
1553     if (ff_jni_exception_check(env, 1, codec) < 0) {
1554         ret = AVERROR_EXTERNAL;
1555         goto fail;
1556     }
1557
1558 fail:
1559     return ret;
1560 }
1561
1562 static int mediacodec_jni_releaseOutputBufferAtTime(FFAMediaCodec *ctx, size_t idx, int64_t timestampNs)
1563 {
1564     int ret = 0;
1565     JNIEnv *env = NULL;
1566     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1567
1568     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1569
1570     (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, (jint)idx, (jlong)timestampNs);
1571     if (ff_jni_exception_check(env, 1, codec) < 0) {
1572         ret = AVERROR_EXTERNAL;
1573         goto fail;
1574     }
1575
1576 fail:
1577     return ret;
1578 }
1579
1580 static ssize_t mediacodec_jni_dequeueInputBuffer(FFAMediaCodec* ctx, int64_t timeoutUs)
1581 {
1582     int ret = 0;
1583     JNIEnv *env = NULL;
1584     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1585
1586     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1587
1588     ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
1589     if (ff_jni_exception_check(env, 1, codec) < 0) {
1590         ret = AVERROR_EXTERNAL;
1591         goto fail;
1592     }
1593
1594 fail:
1595     return ret;
1596 }
1597
1598 static int mediacodec_jni_queueInputBuffer(FFAMediaCodec* ctx, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
1599 {
1600     int ret = 0;
1601     JNIEnv *env = NULL;
1602     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1603
1604     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1605
1606     (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, (jint)idx, (jint)offset, (jint)size, time, flags);
1607     if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
1608         ret = AVERROR_EXTERNAL;
1609         goto fail;
1610     }
1611
1612 fail:
1613     return ret;
1614 }
1615
1616 static ssize_t mediacodec_jni_dequeueOutputBuffer(FFAMediaCodec* ctx, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
1617 {
1618     int ret = 0;
1619     JNIEnv *env = NULL;
1620     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1621
1622     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1623
1624     ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs);
1625     if (ff_jni_exception_check(env, 1, codec) < 0) {
1626         return AVERROR_EXTERNAL;
1627     }
1628
1629     info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id);
1630     if (ff_jni_exception_check(env, 1, codec) < 0) {
1631         return AVERROR_EXTERNAL;
1632     }
1633
1634     info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id);
1635     if (ff_jni_exception_check(env, 1, codec) < 0) {
1636         return AVERROR_EXTERNAL;
1637     }
1638
1639     info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id);
1640     if (ff_jni_exception_check(env, 1, codec) < 0) {
1641         return AVERROR_EXTERNAL;
1642     }
1643
1644     info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id);
1645     if (ff_jni_exception_check(env, 1, codec) < 0) {
1646         return AVERROR_EXTERNAL;
1647     }
1648
1649     return ret;
1650 }
1651
1652 static uint8_t* mediacodec_jni_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
1653 {
1654     uint8_t *ret = NULL;
1655     JNIEnv *env = NULL;
1656     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1657     jobject buffer = NULL;
1658     jobject input_buffers = NULL;
1659
1660     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1661
1662     if (codec->has_get_i_o_buffer) {
1663         buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, (jint)idx);
1664         if (ff_jni_exception_check(env, 1, codec) < 0) {
1665             goto fail;
1666         }
1667     } else {
1668         if (!codec->input_buffers) {
1669             input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
1670             if (ff_jni_exception_check(env, 1, codec) < 0) {
1671                 goto fail;
1672             }
1673
1674             codec->input_buffers = (*env)->NewGlobalRef(env, input_buffers);
1675             if (ff_jni_exception_check(env, 1, codec) < 0) {
1676                 goto fail;
1677             }
1678         }
1679
1680         buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
1681         if (ff_jni_exception_check(env, 1, codec) < 0) {
1682             goto fail;
1683         }
1684     }
1685
1686     ret = (*env)->GetDirectBufferAddress(env, buffer);
1687     *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1688 fail:
1689     if (buffer) {
1690         (*env)->DeleteLocalRef(env, buffer);
1691     }
1692
1693     if (input_buffers) {
1694         (*env)->DeleteLocalRef(env, input_buffers);
1695     }
1696
1697     return ret;
1698 }
1699
1700 static uint8_t* mediacodec_jni_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
1701 {
1702     uint8_t *ret = NULL;
1703     JNIEnv *env = NULL;
1704     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1705     jobject buffer = NULL;
1706     jobject output_buffers = NULL;
1707
1708     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1709
1710     if (codec->has_get_i_o_buffer) {
1711         buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, (jint)idx);
1712         if (ff_jni_exception_check(env, 1, codec) < 0) {
1713             goto fail;
1714         }
1715     } else {
1716         if (!codec->output_buffers) {
1717             output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
1718             if (ff_jni_exception_check(env, 1, codec) < 0) {
1719                 goto fail;
1720             }
1721
1722             codec->output_buffers = (*env)->NewGlobalRef(env, output_buffers);
1723             if (ff_jni_exception_check(env, 1, codec) < 0) {
1724                 goto fail;
1725             }
1726         }
1727
1728         buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
1729         if (ff_jni_exception_check(env, 1, codec) < 0) {
1730             goto fail;
1731         }
1732     }
1733
1734     ret = (*env)->GetDirectBufferAddress(env, buffer);
1735     *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
1736 fail:
1737     if (buffer) {
1738         (*env)->DeleteLocalRef(env, buffer);
1739     }
1740
1741     if (output_buffers) {
1742         (*env)->DeleteLocalRef(env, output_buffers);
1743     }
1744
1745     return ret;
1746 }
1747
1748 static FFAMediaFormat* mediacodec_jni_getOutputFormat(FFAMediaCodec* ctx)
1749 {
1750     FFAMediaFormat *ret = NULL;
1751     JNIEnv *env = NULL;
1752     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1753
1754     jobject mediaformat = NULL;
1755
1756     JNI_GET_ENV_OR_RETURN(env, codec, NULL);
1757
1758     mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
1759     if (ff_jni_exception_check(env, 1, codec) < 0) {
1760         goto fail;
1761     }
1762
1763     ret = mediaformat_jni_newFromObject(mediaformat);
1764 fail:
1765     if (mediaformat) {
1766         (*env)->DeleteLocalRef(env, mediaformat);
1767     }
1768
1769     return ret;
1770 }
1771
1772 static int mediacodec_jni_infoTryAgainLater(FFAMediaCodec *ctx, ssize_t idx)
1773 {
1774     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1775     return idx == codec->INFO_TRY_AGAIN_LATER;
1776 }
1777
1778 static int mediacodec_jni_infoOutputBuffersChanged(FFAMediaCodec *ctx, ssize_t idx)
1779 {
1780     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1781     return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
1782 }
1783
1784 static int mediacodec_jni_infoOutputFormatChanged(FFAMediaCodec *ctx, ssize_t idx)
1785 {
1786     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1787     return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
1788 }
1789
1790 static int mediacodec_jni_getBufferFlagCodecConfig(FFAMediaCodec *ctx)
1791 {
1792     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1793     return codec->BUFFER_FLAG_CODEC_CONFIG;
1794 }
1795
1796 static int mediacodec_jni_getBufferFlagEndOfStream(FFAMediaCodec *ctx)
1797 {
1798     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1799     return codec->BUFFER_FLAG_END_OF_STREAM;
1800 }
1801
1802 static int mediacodec_jni_getBufferFlagKeyFrame(FFAMediaCodec *ctx)
1803 {
1804     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1805     return codec->BUFFER_FLAG_KEY_FRAME;
1806 }
1807
1808 static int mediacodec_jni_getConfigureFlagEncode(FFAMediaCodec *ctx)
1809 {
1810     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1811     return codec->CONFIGURE_FLAG_ENCODE;
1812 }
1813
1814 static int mediacodec_jni_cleanOutputBuffers(FFAMediaCodec *ctx)
1815 {
1816     int ret = 0;
1817     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1818
1819     if (!codec->has_get_i_o_buffer) {
1820         if (codec->output_buffers) {
1821             JNIEnv *env = NULL;
1822
1823             env = ff_jni_get_env(codec);
1824             if (!env) {
1825                 ret = AVERROR_EXTERNAL;
1826                 goto fail;
1827             }
1828
1829             (*env)->DeleteGlobalRef(env, codec->output_buffers);
1830             codec->output_buffers = NULL;
1831         }
1832     }
1833
1834 fail:
1835     return ret;
1836 }
1837
1838 static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx)
1839 {
1840     JNIEnv *env = NULL;
1841     FFAMediaCodecJni *codec = (FFAMediaCodecJni *)ctx;
1842
1843     JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
1844
1845     (*env)->CallVoidMethod(env, codec->object, codec->jfields.signal_end_of_input_stream_id);
1846     if (ff_jni_exception_check(env, 1, codec) < 0) {
1847         return AVERROR_EXTERNAL;
1848     }
1849
1850     return 0;
1851 }
1852
1853 static const FFAMediaFormat media_format_jni = {
1854     .class = &amediaformat_class,
1855
1856     .create = mediaformat_jni_new,
1857     .delete = mediaformat_jni_delete,
1858
1859     .toString = mediaformat_jni_toString,
1860
1861     .getInt32 = mediaformat_jni_getInt32,
1862     .getInt64 = mediaformat_jni_getInt64,
1863     .getFloat = mediaformat_jni_getFloat,
1864     .getBuffer = mediaformat_jni_getBuffer,
1865     .getString = mediaformat_jni_getString,
1866
1867     .setInt32 = mediaformat_jni_setInt32,
1868     .setInt64 = mediaformat_jni_setInt64,
1869     .setFloat = mediaformat_jni_setFloat,
1870     .setString = mediaformat_jni_setString,
1871     .setBuffer = mediaformat_jni_setBuffer,
1872 };
1873
1874 static const FFAMediaCodec media_codec_jni = {
1875     .class = &amediacodec_class,
1876
1877     .getName = mediacodec_jni_getName,
1878
1879     .createCodecByName = mediacodec_jni_createCodecByName,
1880     .createDecoderByType = mediacodec_jni_createDecoderByType,
1881     .createEncoderByType = mediacodec_jni_createEncoderByType,
1882     .delete = mediacodec_jni_delete,
1883
1884     .configure = mediacodec_jni_configure,
1885     .start = mediacodec_jni_start,
1886     .stop = mediacodec_jni_stop,
1887     .flush = mediacodec_jni_flush,
1888
1889     .getInputBuffer = mediacodec_jni_getInputBuffer,
1890     .getOutputBuffer = mediacodec_jni_getOutputBuffer,
1891
1892     .dequeueInputBuffer = mediacodec_jni_dequeueInputBuffer,
1893     .queueInputBuffer = mediacodec_jni_queueInputBuffer,
1894
1895     .dequeueOutputBuffer = mediacodec_jni_dequeueOutputBuffer,
1896     .getOutputFormat = mediacodec_jni_getOutputFormat,
1897
1898     .releaseOutputBuffer = mediacodec_jni_releaseOutputBuffer,
1899     .releaseOutputBufferAtTime = mediacodec_jni_releaseOutputBufferAtTime,
1900
1901     .infoTryAgainLater = mediacodec_jni_infoTryAgainLater,
1902     .infoOutputBuffersChanged = mediacodec_jni_infoOutputBuffersChanged,
1903     .infoOutputFormatChanged = mediacodec_jni_infoOutputFormatChanged,
1904
1905     .getBufferFlagCodecConfig = mediacodec_jni_getBufferFlagCodecConfig,
1906     .getBufferFlagEndOfStream = mediacodec_jni_getBufferFlagEndOfStream,
1907     .getBufferFlagKeyFrame = mediacodec_jni_getBufferFlagKeyFrame,
1908
1909     .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,
1910     .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,
1911     .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,
1912 };
1913
1914 typedef struct FFAMediaFormatNdk {
1915     FFAMediaFormat api;
1916
1917     void *libmedia;
1918     AMediaFormat *impl;
1919
1920     AMediaFormat *(*new)(void);
1921     media_status_t (*delete)(AMediaFormat*);
1922
1923     const char* (*toString)(AMediaFormat*);
1924
1925     bool (*getInt32)(AMediaFormat*, const char *name, int32_t *out);
1926     bool (*getInt64)(AMediaFormat*, const char *name, int64_t *out);
1927     bool (*getFloat)(AMediaFormat*, const char *name, float *out);
1928     bool (*getSize)(AMediaFormat*, const char *name, size_t *out);
1929     bool (*getBuffer)(AMediaFormat*, const char *name, void** data, size_t *size);
1930     bool (*getString)(AMediaFormat*, const char *name, const char **out);
1931     bool (*getRect)(AMediaFormat *, const char *name,
1932                     int32_t *left, int32_t *top, int32_t *right, int32_t *bottom);
1933
1934     void (*setInt32)(AMediaFormat*, const char* name, int32_t value);
1935     void (*setInt64)(AMediaFormat*, const char* name, int64_t value);
1936     void (*setFloat)(AMediaFormat*, const char* name, float value);
1937     void (*setString)(AMediaFormat*, const char* name, const char* value);
1938     void (*setBuffer)(AMediaFormat*, const char* name, const void* data, size_t size);
1939     void (*setRect)(AMediaFormat *, const char *name,
1940                     int32_t left, int32_t top, int32_t right, int32_t bottom);
1941 } FFAMediaFormatNdk;
1942
1943 typedef struct FFAMediaCodecNdk {
1944     FFAMediaCodec api;
1945
1946     void *libmedia;
1947     AMediaCodec *impl;
1948     ANativeWindow *window;
1949
1950     AMediaCodec* (*createCodecByName)(const char *name);
1951     AMediaCodec* (*createDecoderByType)(const char *mime_type);
1952     AMediaCodec* (*createEncoderByType)(const char *mime_type);
1953     media_status_t (*delete)(AMediaCodec*);
1954
1955     media_status_t (*configure)(AMediaCodec *,
1956                                 const AMediaFormat *format,
1957                                 ANativeWindow *surface,
1958                                 AMediaCrypto *crypto,
1959                                 uint32_t flags);
1960     media_status_t (*start)(AMediaCodec*);
1961     media_status_t (*stop)(AMediaCodec*);
1962     media_status_t (*flush)(AMediaCodec*);
1963
1964     uint8_t* (*getInputBuffer)(AMediaCodec*, size_t idx, size_t *out_size);
1965     uint8_t* (*getOutputBuffer)(AMediaCodec*, size_t idx, size_t *out_size);
1966
1967     ssize_t (*dequeueInputBuffer)(AMediaCodec*, int64_t timeoutUs);
1968     media_status_t (*queueInputBuffer)(AMediaCodec*, size_t idx,
1969                                        long offset, size_t size,
1970                                        uint64_t time, uint32_t flags);
1971
1972     ssize_t (*dequeueOutputBuffer)(AMediaCodec*, AMediaCodecBufferInfo *info, int64_t timeoutUs);
1973     AMediaFormat* (*getOutputFormat)(AMediaCodec*);
1974
1975     media_status_t (*releaseOutputBuffer)(AMediaCodec*, size_t idx, bool render);
1976     media_status_t (*releaseOutputBufferAtTime)(AMediaCodec *mData, size_t idx, int64_t timestampNs);
1977
1978     // Available since API level 28.
1979     media_status_t (*getName)(AMediaCodec*, char** out_name);
1980     void (*releaseName)(AMediaCodec*, char* name);
1981
1982     // Available since API level 26.
1983     media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *);
1984     media_status_t (*signalEndOfInputStream)(AMediaCodec *);
1985 } FFAMediaCodecNdk;
1986
1987 static const FFAMediaFormat media_format_ndk;
1988 static const FFAMediaCodec media_codec_ndk;
1989
1990 static const AVClass amediaformat_ndk_class = {
1991     .class_name = "amediaformat_ndk",
1992     .item_name  = av_default_item_name,
1993     .version    = LIBAVUTIL_VERSION_INT,
1994 };
1995
1996 static const AVClass amediacodec_ndk_class = {
1997     .class_name = "amediacodec_ndk",
1998     .item_name  = av_default_item_name,
1999     .version    = LIBAVUTIL_VERSION_INT,
2000 };
2001
2002 static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl)
2003 {
2004     FFAMediaFormatNdk *format = av_mallocz(sizeof(*format));
2005     if (!format)
2006         return NULL;
2007
2008     format->api = media_format_ndk;
2009
2010     format->libmedia = dlopen("libmediandk.so", RTLD_NOW);
2011     if (!format->libmedia)
2012         goto error;
2013
2014 #define GET_OPTIONAL_SYMBOL(sym) \
2015     format->sym = dlsym(format->libmedia, "AMediaFormat_" #sym);
2016
2017 #define GET_SYMBOL(sym)         \
2018     GET_OPTIONAL_SYMBOL(sym)    \
2019     if (!format->sym)           \
2020         goto error;
2021
2022     GET_SYMBOL(new)
2023     GET_SYMBOL(delete)
2024
2025     GET_SYMBOL(toString)
2026
2027     GET_SYMBOL(getInt32)
2028     GET_SYMBOL(getInt64)
2029     GET_SYMBOL(getFloat)
2030     GET_SYMBOL(getSize)
2031     GET_SYMBOL(getBuffer)
2032     GET_SYMBOL(getString)
2033     GET_OPTIONAL_SYMBOL(getRect)
2034
2035     GET_SYMBOL(setInt32)
2036     GET_SYMBOL(setInt64)
2037     GET_SYMBOL(setFloat)
2038     GET_SYMBOL(setString)
2039     GET_SYMBOL(setBuffer)
2040     GET_OPTIONAL_SYMBOL(setRect)
2041
2042 #undef GET_SYMBOL
2043 #undef GET_OPTIONAL_SYMBOL
2044
2045     if (impl) {
2046         format->impl = impl;
2047     } else {
2048         format->impl = format->new();
2049         if (!format->impl)
2050             goto error;
2051     }
2052
2053     return (FFAMediaFormat *)format;
2054
2055 error:
2056     if (format->libmedia)
2057         dlclose(format->libmedia);
2058     av_freep(&format);
2059     return NULL;
2060 }
2061
2062 static FFAMediaFormat *mediaformat_ndk_new(void)
2063 {
2064     return mediaformat_ndk_create(NULL);
2065 }
2066
2067 static int mediaformat_ndk_delete(FFAMediaFormat* ctx)
2068 {
2069     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2070     int ret = 0;
2071     if (!format)
2072         return 0;
2073
2074     av_assert0(format->api.class == &amediaformat_ndk_class);
2075
2076     if (format->impl && (format->delete(format->impl) != AMEDIA_OK))
2077             ret = AVERROR_EXTERNAL;
2078     if (format->libmedia)
2079         dlclose(format->libmedia);
2080     av_free(format);
2081
2082     return ret;
2083 }
2084
2085 static char* mediaformat_ndk_toString(FFAMediaFormat* ctx)
2086 {
2087     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2088     const char *str = format->toString(format->impl);
2089     return av_strdup(str);
2090 }
2091
2092 static int mediaformat_ndk_getInt32(FFAMediaFormat* ctx, const char *name, int32_t *out)
2093 {
2094     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2095     return format->getInt32(format->impl, name, out);
2096 }
2097
2098 static int mediaformat_ndk_getInt64(FFAMediaFormat* ctx, const char *name, int64_t *out)
2099 {
2100     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2101     return format->getInt64(format->impl, name, out);
2102 }
2103
2104 static int mediaformat_ndk_getFloat(FFAMediaFormat* ctx, const char *name, float *out)
2105 {
2106     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2107     return format->getFloat(format->impl, name, out);
2108 }
2109
2110 static int mediaformat_ndk_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size)
2111 {
2112     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2113     return format->getBuffer(format->impl, name, data, size);
2114 }
2115
2116 static int mediaformat_ndk_getString(FFAMediaFormat* ctx, const char *name, const char **out)
2117 {
2118     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2119     const char *tmp = NULL;
2120     int ret = format->getString(format->impl, name, &tmp);
2121
2122     if (tmp)
2123         *out = av_strdup(tmp);
2124     return ret;
2125 }
2126
2127 static int mediaformat_ndk_getRect(FFAMediaFormat *ctx, const char *name,
2128                                    int32_t *left, int32_t *top, int32_t *right, int32_t *bottom)
2129 {
2130     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2131     if (!format->getRect)
2132         return AVERROR_EXTERNAL;
2133     return format->getRect(format->impl, name, left, top, right, bottom);
2134 }
2135
2136 static void mediaformat_ndk_setInt32(FFAMediaFormat* ctx, const char* name, int32_t value)
2137 {
2138     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2139     format->setInt32(format->impl, name, value);
2140 }
2141
2142 static void mediaformat_ndk_setInt64(FFAMediaFormat* ctx, const char* name, int64_t value)
2143 {
2144     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2145     format->setInt64(format->impl, name, value);
2146 }
2147
2148 static void mediaformat_ndk_setFloat(FFAMediaFormat* ctx, const char* name, float value)
2149 {
2150     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2151     format->setFloat(format->impl, name, value);
2152 }
2153
2154 static void mediaformat_ndk_setString(FFAMediaFormat* ctx, const char* name, const char* value)
2155 {
2156     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2157     format->setString(format->impl, name, value);
2158 }
2159
2160 static void mediaformat_ndk_setBuffer(FFAMediaFormat* ctx, const char* name, void* data, size_t size)
2161 {
2162     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2163     format->setBuffer(format->impl, name, data, size);
2164 }
2165
2166 static void mediaformat_ndk_setRect(FFAMediaFormat *ctx, const char *name,
2167                                      int32_t left, int32_t top, int32_t right, int32_t bottom)
2168 {
2169     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx;
2170     if (!format->setRect) {
2171         av_log(ctx, AV_LOG_WARNING, "Doesn't support setRect\n");
2172         return;
2173     }
2174     format->setRect(format->impl, name, left, top, right, bottom);
2175 }
2176
2177 static char *mediacodec_ndk_getName(FFAMediaCodec *ctx)
2178 {
2179     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2180     char *ret = NULL;
2181     char *name = NULL;
2182
2183     if (!codec->getName || !codec->releaseName) {
2184         av_log(ctx, AV_LOG_DEBUG, "getName() unavailable\n");
2185         return ret;
2186     }
2187
2188     codec->getName(codec->impl, &name);
2189     if (name) {
2190         ret = av_strdup(name);
2191         codec->releaseName(codec->impl, name);
2192     }
2193
2194     return ret;
2195 }
2196
2197 static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) {
2198     FFAMediaCodecNdk *codec = av_mallocz(sizeof(*codec));
2199     const char *lib_name = "libmediandk.so";
2200
2201     if (!codec)
2202         return NULL;
2203
2204     codec->api = media_codec_ndk;
2205     codec->libmedia = dlopen(lib_name, RTLD_NOW);
2206     if (!codec->libmedia)
2207         goto error;
2208
2209 #define GET_SYMBOL(sym, required)                                   \
2210     codec->sym = dlsym(codec->libmedia, "AMediaCodec_" #sym);       \
2211     if (!codec->sym) {                                              \
2212         av_log(codec, required ? AV_LOG_ERROR : AV_LOG_INFO,        \
2213                #sym "() unavailable from %s\n", lib_name);          \
2214         if (required)                                               \
2215             goto error;                                             \
2216     }
2217
2218     GET_SYMBOL(createCodecByName, 1)
2219     GET_SYMBOL(createDecoderByType, 1)
2220     GET_SYMBOL(createEncoderByType, 1)
2221     GET_SYMBOL(delete, 1)
2222
2223     GET_SYMBOL(configure, 1)
2224     GET_SYMBOL(start, 1)
2225     GET_SYMBOL(stop, 1)
2226     GET_SYMBOL(flush, 1)
2227
2228     GET_SYMBOL(getInputBuffer, 1)
2229     GET_SYMBOL(getOutputBuffer, 1)
2230
2231     GET_SYMBOL(dequeueInputBuffer, 1)
2232     GET_SYMBOL(queueInputBuffer, 1)
2233
2234     GET_SYMBOL(dequeueOutputBuffer, 1)
2235     GET_SYMBOL(getOutputFormat, 1)
2236
2237     GET_SYMBOL(releaseOutputBuffer, 1)
2238     GET_SYMBOL(releaseOutputBufferAtTime, 1)
2239
2240     GET_SYMBOL(getName, 0)
2241     GET_SYMBOL(releaseName, 0)
2242
2243     GET_SYMBOL(setInputSurface, 0)
2244     GET_SYMBOL(signalEndOfInputStream, 0)
2245
2246 #undef GET_SYMBOL
2247
2248     switch (method) {
2249     case CREATE_CODEC_BY_NAME:
2250         codec->impl = codec->createCodecByName(arg);
2251         break;
2252     case CREATE_DECODER_BY_TYPE:
2253         codec->impl = codec->createDecoderByType(arg);
2254         break;
2255     case CREATE_ENCODER_BY_TYPE:
2256         codec->impl = codec->createEncoderByType(arg);
2257         break;
2258     default:
2259         av_assert0(0);
2260     }
2261     if (!codec->impl)
2262         goto error;
2263
2264     return (FFAMediaCodec *)codec;
2265
2266 error:
2267     if (codec->libmedia)
2268         dlclose(codec->libmedia);
2269     av_freep(&codec);
2270     return NULL;
2271 }
2272
2273 #define DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(name, method)       \
2274 static FFAMediaCodec *mediacodec_ndk_##name(const char *arg)    \
2275 {                                                               \
2276     return ndk_codec_create(method, arg);                       \
2277 }                                                               \
2278
2279 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createCodecByName,   CREATE_CODEC_BY_NAME)
2280 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE)
2281 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE)
2282
2283 static int mediacodec_ndk_delete(FFAMediaCodec* ctx)
2284 {
2285     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2286     int ret = 0;
2287
2288     if (!codec)
2289         return 0;
2290
2291     av_assert0(codec->api.class == &amediacodec_ndk_class);
2292
2293     if (codec->impl && (codec->delete(codec->impl) != AMEDIA_OK))
2294         ret = AVERROR_EXTERNAL;
2295     if (codec->window)
2296         ANativeWindow_release(codec->window);
2297     if (codec->libmedia)
2298         dlclose(codec->libmedia);
2299     av_free(codec);
2300
2301     return ret;
2302 }
2303
2304 static int mediacodec_ndk_configure(FFAMediaCodec* ctx,
2305                                     const FFAMediaFormat* format_ctx,
2306                                     FFANativeWindow* window,
2307                                     void *crypto,
2308                                     uint32_t flags)
2309 {
2310     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2311     FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)format_ctx;
2312     media_status_t status;
2313     ANativeWindow *native_window = NULL;
2314
2315     if (window) {
2316         if (window->surface) {
2317             JNIEnv *env = NULL;
2318             JNI_GET_ENV_OR_RETURN(env, ctx, -1);
2319             native_window = ANativeWindow_fromSurface(env, window->surface);
2320             // Save for release
2321             codec->window = native_window;
2322         } else if (window->native_window) {
2323             native_window = window->native_window;
2324         }
2325     }
2326
2327     if (format_ctx->class != &amediaformat_ndk_class) {
2328         av_log(ctx, AV_LOG_ERROR, "invalid media format\n");
2329         return AVERROR(EINVAL);
2330     }
2331
2332     if (flags & AMEDIACODEC_CONFIGURE_FLAG_ENCODE) {
2333         if (native_window && !codec->setInputSurface) {
2334             av_log(ctx, AV_LOG_ERROR, "System doesn't support setInputSurface\n");
2335             return AVERROR_EXTERNAL;
2336         }
2337
2338         status = codec->configure(codec->impl, format->impl, NULL, NULL, flags);
2339         if (status != AMEDIA_OK) {
2340             av_log(codec, AV_LOG_ERROR, "Encoder configure failed, %d\n", status);
2341             return AVERROR_EXTERNAL;
2342         }
2343
2344         if (!native_window)
2345             return 0;
2346
2347         status = codec->setInputSurface(codec->impl, native_window);
2348         if (status != AMEDIA_OK) {
2349             av_log(codec, AV_LOG_ERROR, "Encoder set input surface failed, %d\n", status);
2350             return AVERROR_EXTERNAL;
2351         }
2352     } else {
2353         status = codec->configure(codec->impl, format->impl, native_window, NULL, flags);
2354         if (status != AMEDIA_OK) {
2355             av_log(codec, AV_LOG_ERROR, "Decoder configure failed, %d\n", status);
2356             return AVERROR_EXTERNAL;
2357         }
2358     }
2359
2360     return 0;
2361 }
2362
2363 #define MEDIACODEC_NDK_WRAPPER(method)                                   \
2364 static int mediacodec_ndk_ ## method(FFAMediaCodec* ctx)                 \
2365 {                                                                        \
2366     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;                   \
2367     media_status_t status = codec->method(codec->impl);                  \
2368                                                                          \
2369     if (status != AMEDIA_OK) {                                           \
2370         av_log(codec, AV_LOG_ERROR, #method " failed, %d\n", status);    \
2371         return AVERROR_EXTERNAL;                                         \
2372     }                                                                    \
2373                                                                          \
2374     return 0;                                                            \
2375 }                                                                        \
2376
2377 MEDIACODEC_NDK_WRAPPER(start)
2378 MEDIACODEC_NDK_WRAPPER(stop)
2379 MEDIACODEC_NDK_WRAPPER(flush)
2380
2381 static uint8_t* mediacodec_ndk_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
2382 {
2383     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2384     return codec->getInputBuffer(codec->impl, idx, out_size);
2385 }
2386
2387 static uint8_t* mediacodec_ndk_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size)
2388 {
2389     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2390     return codec->getOutputBuffer(codec->impl, idx, out_size);
2391 }
2392
2393 static ssize_t mediacodec_ndk_dequeueInputBuffer(FFAMediaCodec* ctx, int64_t timeoutUs)
2394 {
2395     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2396     return codec->dequeueInputBuffer(codec->impl, timeoutUs);
2397 }
2398
2399 static int mediacodec_ndk_queueInputBuffer(FFAMediaCodec *ctx, size_t idx,
2400                                            off_t offset, size_t size,
2401                                            uint64_t time, uint32_t flags)
2402 {
2403     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2404     return codec->queueInputBuffer(codec->impl, idx, offset, size, time, flags);
2405 }
2406
2407 static ssize_t mediacodec_ndk_dequeueOutputBuffer(FFAMediaCodec* ctx, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
2408 {
2409     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2410     AMediaCodecBufferInfo buf_info = {0};
2411     ssize_t ret;
2412
2413     ret = codec->dequeueOutputBuffer(codec->impl, &buf_info, timeoutUs);
2414     info->offset = buf_info.offset;
2415     info->size = buf_info.size;
2416     info->presentationTimeUs = buf_info.presentationTimeUs;
2417     info->flags = buf_info.flags;
2418
2419     return ret;
2420 }
2421
2422 static FFAMediaFormat* mediacodec_ndk_getOutputFormat(FFAMediaCodec* ctx)
2423 {
2424     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2425     AMediaFormat *format = codec->getOutputFormat(codec->impl);
2426
2427     if (!format)
2428         return NULL;
2429     return mediaformat_ndk_create(format);
2430 }
2431
2432 static int mediacodec_ndk_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render)
2433 {
2434     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2435     media_status_t status;
2436
2437     status = codec->releaseOutputBuffer(codec->impl, idx, render);
2438     if (status != AMEDIA_OK) {
2439         av_log(codec, AV_LOG_ERROR, "release output buffer failed, %d\n", status);
2440         return AVERROR_EXTERNAL;
2441     }
2442
2443     return 0;
2444 }
2445
2446 static int mediacodec_ndk_releaseOutputBufferAtTime(FFAMediaCodec *ctx, size_t idx, int64_t timestampNs)
2447 {
2448     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2449     media_status_t status;
2450
2451     status = codec->releaseOutputBufferAtTime(codec->impl, idx, timestampNs);
2452     if (status != AMEDIA_OK) {
2453         av_log(codec, AV_LOG_ERROR, "releaseOutputBufferAtTime failed, %d\n", status);
2454         return AVERROR_EXTERNAL;
2455     }
2456
2457     return 0;
2458 }
2459
2460 static int mediacodec_ndk_infoTryAgainLater(FFAMediaCodec *ctx, ssize_t idx)
2461 {
2462     return idx == AMEDIACODEC_INFO_TRY_AGAIN_LATER;
2463 }
2464
2465 static int mediacodec_ndk_infoOutputBuffersChanged(FFAMediaCodec *ctx, ssize_t idx)
2466 {
2467     return idx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
2468 }
2469
2470 static int mediacodec_ndk_infoOutputFormatChanged(FFAMediaCodec *ctx, ssize_t idx)
2471 {
2472     return idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
2473 }
2474
2475 static int mediacodec_ndk_getBufferFlagCodecConfig(FFAMediaCodec *ctx)
2476 {
2477     return AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
2478 }
2479
2480 static int mediacodec_ndk_getBufferFlagEndOfStream(FFAMediaCodec *ctx)
2481 {
2482     return AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
2483 }
2484
2485 static int mediacodec_ndk_getBufferFlagKeyFrame(FFAMediaCodec *ctx)
2486 {
2487     return 1;
2488 }
2489
2490 static int mediacodec_ndk_getConfigureFlagEncode(FFAMediaCodec *ctx)
2491 {
2492     return AMEDIACODEC_CONFIGURE_FLAG_ENCODE;
2493 }
2494
2495 static int mediacodec_ndk_cleanOutputBuffers(FFAMediaCodec *ctx)
2496 {
2497     return 0;
2498 }
2499
2500 static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx)
2501 {
2502     FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2503     media_status_t status;
2504
2505     if (!codec->signalEndOfInputStream) {
2506         av_log(codec, AV_LOG_ERROR, "signalEndOfInputStream unavailable\n");
2507         return AVERROR_EXTERNAL;
2508     }
2509
2510     status = codec->signalEndOfInputStream(codec->impl);
2511     if (status != AMEDIA_OK) {
2512         av_log(codec, AV_LOG_ERROR, "signalEndOfInputStream failed, %d\n", status);
2513         return AVERROR_EXTERNAL;
2514     }
2515     av_log(codec, AV_LOG_DEBUG, "signalEndOfInputStream success\n");
2516
2517     return 0;
2518 }
2519
2520 static const FFAMediaFormat media_format_ndk = {
2521     .class = &amediaformat_ndk_class,
2522
2523     .create = mediaformat_ndk_new,
2524     .delete = mediaformat_ndk_delete,
2525
2526     .toString = mediaformat_ndk_toString,
2527
2528     .getInt32 = mediaformat_ndk_getInt32,
2529     .getInt64 = mediaformat_ndk_getInt64,
2530     .getFloat = mediaformat_ndk_getFloat,
2531     .getBuffer = mediaformat_ndk_getBuffer,
2532     .getString = mediaformat_ndk_getString,
2533     .getRect = mediaformat_ndk_getRect,
2534
2535     .setInt32 = mediaformat_ndk_setInt32,
2536     .setInt64 = mediaformat_ndk_setInt64,
2537     .setFloat = mediaformat_ndk_setFloat,
2538     .setString = mediaformat_ndk_setString,
2539     .setBuffer = mediaformat_ndk_setBuffer,
2540     .setRect = mediaformat_ndk_setRect,
2541 };
2542
2543 static const FFAMediaCodec media_codec_ndk = {
2544     .class = &amediacodec_ndk_class,
2545
2546     .getName = mediacodec_ndk_getName,
2547
2548     .createCodecByName = mediacodec_ndk_createCodecByName,
2549     .createDecoderByType = mediacodec_ndk_createDecoderByType,
2550     .createEncoderByType = mediacodec_ndk_createEncoderByType,
2551     .delete = mediacodec_ndk_delete,
2552
2553     .configure = mediacodec_ndk_configure,
2554     .start = mediacodec_ndk_start,
2555     .stop = mediacodec_ndk_stop,
2556     .flush = mediacodec_ndk_flush,
2557
2558     .getInputBuffer = mediacodec_ndk_getInputBuffer,
2559     .getOutputBuffer = mediacodec_ndk_getOutputBuffer,
2560
2561     .dequeueInputBuffer = mediacodec_ndk_dequeueInputBuffer,
2562     .queueInputBuffer = mediacodec_ndk_queueInputBuffer,
2563
2564     .dequeueOutputBuffer = mediacodec_ndk_dequeueOutputBuffer,
2565     .getOutputFormat = mediacodec_ndk_getOutputFormat,
2566
2567     .releaseOutputBuffer = mediacodec_ndk_releaseOutputBuffer,
2568     .releaseOutputBufferAtTime = mediacodec_ndk_releaseOutputBufferAtTime,
2569
2570     .infoTryAgainLater = mediacodec_ndk_infoTryAgainLater,
2571     .infoOutputBuffersChanged = mediacodec_ndk_infoOutputBuffersChanged,
2572     .infoOutputFormatChanged = mediacodec_ndk_infoOutputFormatChanged,
2573
2574     .getBufferFlagCodecConfig = mediacodec_ndk_getBufferFlagCodecConfig,
2575     .getBufferFlagEndOfStream = mediacodec_ndk_getBufferFlagEndOfStream,
2576     .getBufferFlagKeyFrame = mediacodec_ndk_getBufferFlagKeyFrame,
2577
2578     .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,
2579     .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,
2580     .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,
2581 };
2582
2583 FFAMediaFormat *ff_AMediaFormat_new(int ndk)
2584 {
2585     if (ndk)
2586         return media_format_ndk.create();
2587     return media_format_jni.create();
2588 }
2589
2590 FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name, int ndk)
2591 {
2592     if (ndk)
2593         return media_codec_ndk.createCodecByName(name);
2594     return media_codec_jni.createCodecByName(name);
2595 }
2596
2597 FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime_type, int ndk)
2598 {
2599    if (ndk)
2600         return media_codec_ndk.createDecoderByType(mime_type);
2601     return media_codec_jni.createDecoderByType(mime_type);
2602 }
2603
2604 FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime_type, int ndk)
2605 {
2606     if (ndk)
2607         return media_codec_ndk.createEncoderByType(mime_type);
2608     return media_codec_jni.createEncoderByType(mime_type);
2609 }
2610
2611 int ff_Build_SDK_INT(AVCodecContext *avctx)
2612 {
2613     int ret = -1;
2614
2615 #if __ANDROID_API__ >= 24
2616     // android_get_device_api_level() is a static inline before API level 29.
2617     // dlsym() might doesn't work.
2618     //
2619     // We can implement android_get_device_api_level() by
2620     // __system_property_get(), but __system_property_get() has created a lot of
2621     // troubles and is deprecated. So avoid using __system_property_get() for
2622     // now.
2623     //
2624     // Hopy we can remove the conditional compilation finally by bumping the
2625     // required API level.
2626     //
2627     ret = android_get_device_api_level();
2628 #else
2629     JNIEnv *env = NULL;
2630     jclass versionClass;
2631     jfieldID sdkIntFieldID;
2632     JNI_GET_ENV_OR_RETURN(env, avctx, -1);
2633
2634     versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
2635     sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I");
2636     ret = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
2637     (*env)->DeleteLocalRef(env, versionClass);
2638 #endif
2639     av_log(avctx, AV_LOG_DEBUG, "device api level %d\n", ret);
2640
2641     return ret;
2642 }
2643
2644 static struct {
2645     enum FFAMediaFormatColorRange mf_range;
2646     enum AVColorRange range;
2647 } color_range_map[] = {
2648     { COLOR_RANGE_FULL,     AVCOL_RANGE_JPEG },
2649     { COLOR_RANGE_LIMITED,  AVCOL_RANGE_MPEG },
2650 };
2651
2652 static struct {
2653     enum FFAMediaFormatColorStandard mf_standard;
2654     enum AVColorSpace space;
2655 } color_space_map[] = {
2656     { COLOR_STANDARD_BT709,         AVCOL_SPC_BT709         },
2657     { COLOR_STANDARD_BT601_PAL,     AVCOL_SPC_BT470BG       },
2658     { COLOR_STANDARD_BT601_NTSC,    AVCOL_SPC_SMPTE170M     },
2659     { COLOR_STANDARD_BT2020,        AVCOL_SPC_BT2020_NCL    },
2660 };
2661
2662 static struct {
2663     enum FFAMediaFormatColorStandard mf_standard;
2664     enum AVColorPrimaries primaries;
2665 } color_primaries_map[] = {
2666     { COLOR_STANDARD_BT709,         AVCOL_PRI_BT709     },
2667     { COLOR_STANDARD_BT601_PAL,     AVCOL_PRI_BT470BG   },
2668     { COLOR_STANDARD_BT601_NTSC,    AVCOL_PRI_SMPTE170M },
2669     { COLOR_STANDARD_BT2020,        AVCOL_PRI_BT2020    },
2670 };
2671
2672 static struct {
2673     enum FFAMediaFormatColorTransfer mf_transfer;
2674     enum AVColorTransferCharacteristic transfer;
2675 } color_transfer_map[] = {
2676     { COLOR_TRANSFER_LINEAR,        AVCOL_TRC_LINEAR        },
2677     { COLOR_TRANSFER_SDR_VIDEO,     AVCOL_TRC_SMPTE170M     },
2678     { COLOR_TRANSFER_ST2084,        AVCOL_TRC_SMPTEST2084   },
2679     { COLOR_TRANSFER_HLG,           AVCOL_TRC_ARIB_STD_B67  },
2680 };
2681
2682 enum AVColorRange ff_AMediaFormatColorRange_to_AVColorRange(int color_range)
2683 {
2684     for (int i = 0; i < FF_ARRAY_ELEMS(color_range_map); i++)
2685         if (color_range_map[i].mf_range == color_range)
2686             return color_range_map[i].range;
2687
2688     return AVCOL_RANGE_UNSPECIFIED;
2689 }
2690
2691 int ff_AMediaFormatColorRange_from_AVColorRange(enum AVColorRange color_range)
2692 {
2693     for (int i = 0; i < FF_ARRAY_ELEMS(color_range_map); i++)
2694         if (color_range_map[i].range == color_range)
2695             return color_range_map[i].mf_range;
2696     return COLOR_RANGE_UNSPECIFIED;
2697 }
2698
2699 enum AVColorSpace ff_AMediaFormatColorStandard_to_AVColorSpace(int color_standard)
2700 {
2701     for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++)
2702         if (color_space_map[i].mf_standard == color_standard)
2703             return color_space_map[i].space;
2704
2705     return AVCOL_SPC_UNSPECIFIED;
2706 }
2707
2708 int ff_AMediaFormatColorStandard_from_AVColorSpace(enum AVColorSpace color_space)
2709 {
2710     for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++)
2711         if (color_space_map[i].space == color_space)
2712             return color_space_map[i].mf_standard;
2713
2714     return COLOR_STANDARD_UNSPECIFIED;
2715 }
2716
2717 enum AVColorPrimaries ff_AMediaFormatColorStandard_to_AVColorPrimaries(int color_standard)
2718 {
2719     for (int i = 0; i < FF_ARRAY_ELEMS(color_primaries_map); i++)
2720         if (color_primaries_map[i].mf_standard == color_standard)
2721             return color_primaries_map[i].primaries;
2722
2723     return AVCOL_PRI_UNSPECIFIED;
2724 }
2725
2726 enum AVColorTransferCharacteristic
2727 ff_AMediaFormatColorTransfer_to_AVColorTransfer(int color_transfer)
2728 {
2729     for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++)
2730         if (color_transfer_map[i].mf_transfer == color_transfer)
2731             return color_transfer_map[i].transfer;
2732
2733     return AVCOL_TRC_UNSPECIFIED;
2734 }
2735
2736 int ff_AMediaFormatColorTransfer_from_AVColorTransfer(
2737     enum AVColorTransferCharacteristic color_transfer)
2738 {
2739     for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++)
2740         if (color_transfer_map[i].transfer == color_transfer)
2741             return color_transfer_map[i].mf_transfer;
2742
2743     return COLOR_TRANSFER_UNSPECIFIED;
2744 }