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