2 * Android MediaCodec Wrapper
4 * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
6 * This file is part of FFmpeg.
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.
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.
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
25 #include "libavutil/avassert.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/avstring.h"
31 #include "mediacodec_wrapper.h"
33 struct JNIAMediaCodecListFields
{
35 jclass mediacodec_list_class
;
37 jmethodID find_decoder_for_format_id
;
39 jmethodID get_codec_count_id
;
40 jmethodID get_codec_info_at_id
;
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
;
49 jclass codec_capabilities_class
;
50 jfieldID color_formats_id
;
51 jfieldID profile_levels_id
;
53 jclass codec_profile_level_class
;
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
;
65 jfieldID hevc_profile_main_id
;
66 jfieldID hevc_profile_main10_id
;
67 jfieldID hevc_profile_main10_hdr10_id
;
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 },
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 },
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 },
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 },
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 },
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 },
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 },
109 struct JNIAMediaFormatFields
{
111 jclass mediaformat_class
;
115 jmethodID contains_key_id
;
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
;
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
;
129 jmethodID to_string_id
;
133 static const struct FFJniField jni_amediaformat_mapping
[] = {
134 { "android/media/MediaFormat", NULL
, NULL
, FF_JNI_CLASS
, offsetof(struct JNIAMediaFormatFields
, mediaformat_class
), 1 },
136 { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD
, offsetof(struct JNIAMediaFormatFields
, init_id
), 1 },
138 { "android/media/MediaFormat", "containsKey", "(Ljava/lang/String;)Z", FF_JNI_METHOD
,offsetof(struct JNIAMediaFormatFields
, contains_key_id
), 1 },
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 },
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 },
152 { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD
, offsetof(struct JNIAMediaFormatFields
, to_string_id
), 1 },
157 static const AVClass amediaformat_class
= {
158 .class_name
= "amediaformat",
159 .item_name
= av_default_item_name
,
160 .version
= LIBAVUTIL_VERSION_INT
,
163 struct FFAMediaFormat
{
165 const AVClass
*class;
166 struct JNIAMediaFormatFields jfields
;
170 struct JNIAMediaCodecFields
{
172 jclass mediacodec_class
;
174 jfieldID info_try_again_later_id
;
175 jfieldID info_output_buffers_changed_id
;
176 jfieldID info_output_format_changed_id
;
178 jfieldID buffer_flag_codec_config_id
;
179 jfieldID buffer_flag_end_of_stream_id
;
180 jfieldID buffer_flag_key_frame_id
;
182 jfieldID configure_flag_encode_id
;
184 jmethodID create_by_codec_name_id
;
185 jmethodID create_decoder_by_type_id
;
186 jmethodID create_encoder_by_type_id
;
188 jmethodID get_name_id
;
190 jmethodID configure_id
;
194 jmethodID release_id
;
196 jmethodID get_output_format_id
;
198 jmethodID dequeue_input_buffer_id
;
199 jmethodID queue_input_buffer_id
;
200 jmethodID get_input_buffer_id
;
201 jmethodID get_input_buffers_id
;
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
;
209 jclass mediainfo_class
;
215 jfieldID presentation_time_us_id
;
220 static const struct FFJniField jni_amediacodec_mapping
[] = {
221 { "android/media/MediaCodec", NULL
, NULL
, FF_JNI_CLASS
, offsetof(struct JNIAMediaCodecFields
, mediacodec_class
), 1 },
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 },
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 },
231 { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD
, offsetof(struct JNIAMediaCodecFields
, configure_flag_encode_id
), 1 },
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 },
237 { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD
, offsetof(struct JNIAMediaCodecFields
, get_name_id
), 1 },
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 },
245 { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD
, offsetof(struct JNIAMediaCodecFields
, get_output_format_id
), 1 },
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 },
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 },
258 { "android/media/MediaCodec$BufferInfo", NULL
, NULL
, FF_JNI_CLASS
, offsetof(struct JNIAMediaCodecFields
, mediainfo_class
), 1 },
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 },
269 static const AVClass amediacodec_class
= {
270 .class_name
= "amediacodec",
271 .item_name
= av_default_item_name
,
272 .version
= LIBAVUTIL_VERSION_INT
,
275 struct FFAMediaCodec
{
277 const AVClass
*class;
279 struct JNIAMediaCodecFields jfields
;
284 jobject input_buffers
;
285 jobject output_buffers
;
287 int INFO_TRY_AGAIN_LATER
;
288 int INFO_OUTPUT_BUFFERS_CHANGED
;
289 int INFO_OUTPUT_FORMAT_CHANGED
;
291 int BUFFER_FLAG_CODEC_CONFIG
;
292 int BUFFER_FLAG_END_OF_STREAM
;
293 int BUFFER_FLAG_KEY_FRAME
;
295 int CONFIGURE_FLAG_ENCODE
;
297 int has_get_i_o_buffer
;
300 #define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do { \
301 (env) = ff_jni_get_env(log_ctx); \
307 #define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do { \
308 (env) = ff_jni_get_env(log_ctx); \
314 int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext
*avctx
)
319 struct JNIAMediaCodecListFields jfields
= { 0 };
320 jfieldID field_id
= 0;
322 JNI_GET_ENV_OR_RETURN(env
, avctx
, -1);
324 if (ff_jni_init_jfields(env
, &jfields
, jni_amediacodeclist_mapping
, 0, avctx
) < 0) {
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
;
334 case FF_PROFILE_H264_MAIN
:
335 field_id
= jfields
.avc_profile_main_id
;
337 case FF_PROFILE_H264_EXTENDED
:
338 field_id
= jfields
.avc_profile_extended_id
;
340 case FF_PROFILE_H264_HIGH
:
341 field_id
= jfields
.avc_profile_high_id
;
343 case FF_PROFILE_H264_HIGH_10
:
344 case FF_PROFILE_H264_HIGH_10_INTRA
:
345 field_id
= jfields
.avc_profile_high10_id
;
347 case FF_PROFILE_H264_HIGH_422
:
348 case FF_PROFILE_H264_HIGH_422_INTRA
:
349 field_id
= jfields
.avc_profile_high422_id
;
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
;
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
;
363 case FF_PROFILE_HEVC_MAIN_10
:
364 field_id
= jfields
.hevc_profile_main10_id
;
370 ret
= (*env
)->GetStaticIntField(env
, jfields
.codec_profile_level_class
, field_id
);
371 if (ff_jni_exception_check(env
, 1, avctx
) < 0) {
378 ff_jni_reset_jfields(env
, &jfields
, jni_amediacodeclist_mapping
, 0, avctx
);
383 char *ff_AMediaCodecList_getCodecNameByType(const char *mime
, int profile
, int encoder
, void *log_ctx
)
390 char *supported_type
= NULL
;
393 struct JNIAMediaCodecListFields jfields
= { 0 };
394 struct JNIAMediaFormatFields mediaformat_jfields
= { 0 };
396 jobject codec_name
= NULL
;
400 jobjectArray types
= NULL
;
402 jobject capabilities
= NULL
;
403 jobject profile_level
= NULL
;
404 jobjectArray profile_levels
= NULL
;
406 JNI_GET_ENV_OR_RETURN(env
, log_ctx
, NULL
);
408 if ((ret
= ff_jni_init_jfields(env
, &jfields
, jni_amediacodeclist_mapping
, 0, log_ctx
)) < 0) {
412 if ((ret
= ff_jni_init_jfields(env
, &mediaformat_jfields
, jni_amediaformat_mapping
, 0, log_ctx
)) < 0) {
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) {
421 for(i
= 0; i
< codec_count
; i
++) {
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) {
431 types
= (*env
)->CallObjectMethod(env
, info
, jfields
.get_supported_types_id
);
432 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
436 is_encoder
= (*env
)->CallBooleanMethod(env
, info
, jfields
.is_encoder_id
);
437 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
441 if (is_encoder
!= encoder
) {
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) {
451 if (is_software_only
) {
456 codec_name
= (*env
)->CallObjectMethod(env
, info
, jfields
.get_name_id
);
457 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
461 name
= ff_jni_jstring_to_utf_chars(env
, codec_name
, log_ctx
);
467 (*env
)->DeleteLocalRef(env
, codec_name
);
471 /* Skip software decoders */
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")) {
480 type_count
= (*env
)->GetArrayLength(env
, types
);
481 for (j
= 0; j
< type_count
; j
++) {
485 type
= (*env
)->GetObjectArrayElement(env
, types
, j
);
486 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
490 supported_type
= ff_jni_jstring_to_utf_chars(env
, type
, log_ctx
);
491 if (!supported_type
) {
495 if (av_strcasecmp(supported_type
, mime
)) {
499 capabilities
= (*env
)->CallObjectMethod(env
, info
, jfields
.get_codec_capabilities_id
, type
);
500 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
504 profile_levels
= (*env
)->GetObjectField(env
, capabilities
, jfields
.profile_levels_id
);
505 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
509 profile_count
= (*env
)->GetArrayLength(env
, profile_levels
);
510 if (!profile_count
) {
513 for (k
= 0; k
< profile_count
; k
++) {
514 int supported_profile
= 0;
521 profile_level
= (*env
)->GetObjectArrayElement(env
, profile_levels
, k
);
522 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
526 supported_profile
= (*env
)->GetIntField(env
, profile_level
, jfields
.profile_id
);
527 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
531 found_codec
= profile
== supported_profile
;
534 (*env
)->DeleteLocalRef(env
, profile_level
);
535 profile_level
= NULL
;
544 if (profile_levels
) {
545 (*env
)->DeleteLocalRef(env
, profile_levels
);
546 profile_levels
= NULL
;
550 (*env
)->DeleteLocalRef(env
, capabilities
);
555 (*env
)->DeleteLocalRef(env
, type
);
559 av_freep(&supported_type
);
568 (*env
)->DeleteLocalRef(env
, info
);
573 (*env
)->DeleteLocalRef(env
, types
);
586 (*env
)->DeleteLocalRef(env
, codec_name
);
590 (*env
)->DeleteLocalRef(env
, info
);
594 (*env
)->DeleteLocalRef(env
, type
);
598 (*env
)->DeleteLocalRef(env
, types
);
602 (*env
)->DeleteLocalRef(env
, capabilities
);
606 (*env
)->DeleteLocalRef(env
, profile_level
);
609 if (profile_levels
) {
610 (*env
)->DeleteLocalRef(env
, profile_levels
);
613 av_freep(&supported_type
);
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
);
625 FFAMediaFormat
*ff_AMediaFormat_new(void)
628 FFAMediaFormat
*format
= NULL
;
629 jobject object
= NULL
;
631 format
= av_mallocz(sizeof(FFAMediaFormat
));
635 format
->class = &amediaformat_class
;
637 env
= ff_jni_get_env(format
);
643 if (ff_jni_init_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
) < 0) {
647 object
= (*env
)->NewObject(env
, format
->jfields
.mediaformat_class
, format
->jfields
.init_id
);
652 format
->object
= (*env
)->NewGlobalRef(env
, object
);
653 if (!format
->object
) {
659 (*env
)->DeleteLocalRef(env
, object
);
662 if (!format
->object
) {
663 ff_jni_reset_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
);
670 static FFAMediaFormat
*ff_AMediaFormat_newFromObject(void *object
)
673 FFAMediaFormat
*format
= NULL
;
675 format
= av_mallocz(sizeof(FFAMediaFormat
));
679 format
->class = &amediaformat_class
;
681 env
= ff_jni_get_env(format
);
687 if (ff_jni_init_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
) < 0) {
691 format
->object
= (*env
)->NewGlobalRef(env
, object
);
692 if (!format
->object
) {
698 ff_jni_reset_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
);
705 int ff_AMediaFormat_delete(FFAMediaFormat
* format
)
715 JNI_GET_ENV_OR_RETURN(env
, format
, AVERROR_EXTERNAL
);
717 (*env
)->DeleteGlobalRef(env
, format
->object
);
718 format
->object
= NULL
;
720 ff_jni_reset_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
);
727 char* ff_AMediaFormat_toString(FFAMediaFormat
* format
)
732 jstring description
= NULL
;
734 av_assert0(format
!= NULL
);
736 JNI_GET_ENV_OR_RETURN(env
, format
, NULL
);
738 description
= (*env
)->CallObjectMethod(env
, format
->object
, format
->jfields
.to_string_id
);
739 if (ff_jni_exception_check(env
, 1, NULL
) < 0) {
743 ret
= ff_jni_jstring_to_utf_chars(env
, description
, format
);
746 (*env
)->DeleteLocalRef(env
, description
);
752 int ff_AMediaFormat_getInt32(FFAMediaFormat
* format
, const char *name
, int32_t *out
)
758 jboolean contains_key
;
760 av_assert0(format
!= NULL
);
762 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
764 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
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) {
776 *out
= (*env
)->CallIntMethod(env
, format
->object
, format
->jfields
.get_integer_id
, key
);
777 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
785 (*env
)->DeleteLocalRef(env
, key
);
791 int ff_AMediaFormat_getInt64(FFAMediaFormat
* format
, const char *name
, int64_t *out
)
797 jboolean contains_key
;
799 av_assert0(format
!= NULL
);
801 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
803 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
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) {
815 *out
= (*env
)->CallLongMethod(env
, format
->object
, format
->jfields
.get_long_id
, key
);
816 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
824 (*env
)->DeleteLocalRef(env
, key
);
830 int ff_AMediaFormat_getFloat(FFAMediaFormat
* format
, const char *name
, float *out
)
836 jboolean contains_key
;
838 av_assert0(format
!= NULL
);
840 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
842 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
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) {
854 *out
= (*env
)->CallFloatMethod(env
, format
->object
, format
->jfields
.get_float_id
, key
);
855 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
863 (*env
)->DeleteLocalRef(env
, key
);
869 int ff_AMediaFormat_getBuffer(FFAMediaFormat
* format
, const char *name
, void** data
, size_t *size
)
875 jboolean contains_key
;
876 jobject result
= NULL
;
878 av_assert0(format
!= NULL
);
880 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
882 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
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) {
894 result
= (*env
)->CallObjectMethod(env
, format
->object
, format
->jfields
.get_bytebuffer_id
, key
);
895 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
900 *data
= (*env
)->GetDirectBufferAddress(env
, result
);
901 *size
= (*env
)->GetDirectBufferCapacity(env
, result
);
903 if (*data
&& *size
) {
905 *data
= av_malloc(*size
);
911 memcpy(*data
, src
, *size
);
917 (*env
)->DeleteLocalRef(env
, key
);
921 (*env
)->DeleteLocalRef(env
, result
);
927 int ff_AMediaFormat_getString(FFAMediaFormat
* format
, const char *name
, const char **out
)
933 jboolean contains_key
;
934 jstring result
= NULL
;
936 av_assert0(format
!= NULL
);
938 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
940 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
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) {
952 result
= (*env
)->CallObjectMethod(env
, format
->object
, format
->jfields
.get_string_id
, key
);
953 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
958 *out
= ff_jni_jstring_to_utf_chars(env
, result
, format
);
967 (*env
)->DeleteLocalRef(env
, key
);
971 (*env
)->DeleteLocalRef(env
, result
);
977 void ff_AMediaFormat_setInt32(FFAMediaFormat
* format
, const char* name
, int32_t value
)
982 av_assert0(format
!= NULL
);
984 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
986 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
991 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_integer_id
, key
, value
);
992 if (ff_jni_exception_check(env
, 1, format
) < 0) {
998 (*env
)->DeleteLocalRef(env
, key
);
1002 void ff_AMediaFormat_setInt64(FFAMediaFormat
* format
, const char* name
, int64_t value
)
1007 av_assert0(format
!= NULL
);
1009 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1011 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1016 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_long_id
, key
, value
);
1017 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1023 (*env
)->DeleteLocalRef(env
, key
);
1027 void ff_AMediaFormat_setFloat(FFAMediaFormat
* format
, const char* name
, float value
)
1032 av_assert0(format
!= NULL
);
1034 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1036 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1041 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_float_id
, key
, value
);
1042 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1048 (*env
)->DeleteLocalRef(env
, key
);
1052 void ff_AMediaFormat_setString(FFAMediaFormat
* format
, const char* name
, const char* value
)
1056 jstring string
= NULL
;
1058 av_assert0(format
!= NULL
);
1060 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1062 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1067 string
= ff_jni_utf_chars_to_jstring(env
, value
, format
);
1072 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_string_id
, key
, string
);
1073 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1079 (*env
)->DeleteLocalRef(env
, key
);
1083 (*env
)->DeleteLocalRef(env
, string
);
1087 void ff_AMediaFormat_setBuffer(FFAMediaFormat
* format
, const char* name
, void* data
, size_t size
)
1091 jobject buffer
= NULL
;
1092 void *buffer_data
= NULL
;
1094 av_assert0(format
!= NULL
);
1096 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1098 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1103 if (!data
|| !size
) {
1107 buffer_data
= av_malloc(size
);
1112 memcpy(buffer_data
, data
, size
);
1114 buffer
= (*env
)->NewDirectByteBuffer(env
, buffer_data
, size
);
1119 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_bytebuffer_id
, key
, buffer
);
1120 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1126 (*env
)->DeleteLocalRef(env
, key
);
1130 (*env
)->DeleteLocalRef(env
, buffer
);
1134 static int codec_init_static_fields(FFAMediaCodec
*codec
)
1139 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
1188 #define CREATE_CODEC_BY_NAME 0
1189 #define CREATE_DECODER_BY_TYPE 1
1190 #define CREATE_ENCODER_BY_TYPE 2
1192 static inline FFAMediaCodec
*codec_create(int method
, const char *arg
)
1196 FFAMediaCodec
*codec
= NULL
;
1197 jstring jarg
= NULL
;
1198 jobject object
= NULL
;
1199 jobject buffer_info
= NULL
;
1200 jmethodID create_id
= NULL
;
1202 codec
= av_mallocz(sizeof(FFAMediaCodec
));
1206 codec
->class = &amediacodec_class
;
1208 env
= ff_jni_get_env(codec
);
1214 if (ff_jni_init_jfields(env
, &codec
->jfields
, jni_amediacodec_mapping
, 1, codec
) < 0) {
1218 jarg
= ff_jni_utf_chars_to_jstring(env
, arg
, codec
);
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;
1231 object
= (*env
)->CallStaticObjectMethod(env
,
1232 codec
->jfields
.mediacodec_class
,
1235 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1239 codec
->object
= (*env
)->NewGlobalRef(env
, object
);
1240 if (!codec
->object
) {
1244 if (codec_init_static_fields(codec
) < 0) {
1248 if (codec
->jfields
.get_input_buffer_id
&& codec
->jfields
.get_output_buffer_id
) {
1249 codec
->has_get_i_o_buffer
= 1;
1252 buffer_info
= (*env
)->NewObject(env
, codec
->jfields
.mediainfo_class
, codec
->jfields
.init_id
);
1253 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1257 codec
->buffer_info
= (*env
)->NewGlobalRef(env
, buffer_info
);
1258 if (!codec
->buffer_info
) {
1265 (*env
)->DeleteLocalRef(env
, jarg
);
1269 (*env
)->DeleteLocalRef(env
, object
);
1273 (*env
)->DeleteLocalRef(env
, buffer_info
);
1277 if (codec
->object
) {
1278 (*env
)->DeleteGlobalRef(env
, codec
->object
);
1281 if (codec
->buffer_info
) {
1282 (*env
)->DeleteGlobalRef(env
, codec
->buffer_info
);
1285 ff_jni_reset_jfields(env
, &codec
->jfields
, jni_amediacodec_mapping
, 1, codec
);
1292 #define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \
1293 FFAMediaCodec *ff_AMediaCodec_##name(const char *arg) \
1295 return codec_create(method, arg); \
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
)
1302 int ff_AMediaCodec_delete(FFAMediaCodec
* codec
)
1312 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1314 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.release_id
);
1315 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1316 ret
= AVERROR_EXTERNAL
;
1319 (*env
)->DeleteGlobalRef(env
, codec
->input_buffers
);
1320 codec
->input_buffers
= NULL
;
1322 (*env
)->DeleteGlobalRef(env
, codec
->output_buffers
);
1323 codec
->output_buffers
= NULL
;
1325 (*env
)->DeleteGlobalRef(env
, codec
->object
);
1326 codec
->object
= NULL
;
1328 (*env
)->DeleteGlobalRef(env
, codec
->buffer_info
);
1329 codec
->buffer_info
= NULL
;
1331 ff_jni_reset_jfields(env
, &codec
->jfields
, jni_amediacodec_mapping
, 1, codec
);
1338 char *ff_AMediaCodec_getName(FFAMediaCodec
*codec
)
1342 jobject
*name
= NULL
;
1344 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
1346 name
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_name_id
);
1347 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1351 ret
= ff_jni_jstring_to_utf_chars(env
, name
, codec
);
1355 (*env
)->DeleteLocalRef(env
, name
);
1361 int ff_AMediaCodec_configure(FFAMediaCodec
* codec
, const FFAMediaFormat
* format
, void* surface
, void *crypto
, uint32_t flags
)
1366 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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
;
1378 int ff_AMediaCodec_start(FFAMediaCodec
* codec
)
1383 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1385 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.start_id
);
1386 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1387 ret
= AVERROR_EXTERNAL
;
1395 int ff_AMediaCodec_stop(FFAMediaCodec
* codec
)
1400 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1402 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.stop_id
);
1403 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1404 ret
= AVERROR_EXTERNAL
;
1412 int ff_AMediaCodec_flush(FFAMediaCodec
* codec
)
1417 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1419 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.flush_id
);
1420 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1421 ret
= AVERROR_EXTERNAL
;
1429 int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec
* codec
, size_t idx
, int render
)
1434 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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
;
1446 int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec
*codec
, size_t idx
, int64_t timestampNs
)
1451 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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
;
1463 ssize_t
ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec
* codec
, int64_t timeoutUs
)
1468 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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
;
1480 int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec
* codec
, size_t idx
, off_t offset
, size_t size
, uint64_t time
, uint32_t flags
)
1485 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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
;
1497 ssize_t
ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec
* codec
, FFAMediaCodecBufferInfo
*info
, int64_t timeoutUs
)
1502 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
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
;
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
;
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
;
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
;
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
;
1532 uint8_t* ff_AMediaCodec_getInputBuffer(FFAMediaCodec
* codec
, size_t idx
, size_t *out_size
)
1534 uint8_t *ret
= NULL
;
1537 jobject buffer
= NULL
;
1538 jobject input_buffers
= NULL
;
1540 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
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) {
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) {
1554 codec
->input_buffers
= (*env
)->NewGlobalRef(env
, input_buffers
);
1555 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1560 buffer
= (*env
)->GetObjectArrayElement(env
, codec
->input_buffers
, idx
);
1561 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1566 ret
= (*env
)->GetDirectBufferAddress(env
, buffer
);
1567 *out_size
= (*env
)->GetDirectBufferCapacity(env
, buffer
);
1570 (*env
)->DeleteLocalRef(env
, buffer
);
1573 if (input_buffers
) {
1574 (*env
)->DeleteLocalRef(env
, input_buffers
);
1580 uint8_t* ff_AMediaCodec_getOutputBuffer(FFAMediaCodec
* codec
, size_t idx
, size_t *out_size
)
1582 uint8_t *ret
= NULL
;
1585 jobject buffer
= NULL
;
1586 jobject output_buffers
= NULL
;
1588 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
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) {
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) {
1602 codec
->output_buffers
= (*env
)->NewGlobalRef(env
, output_buffers
);
1603 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1608 buffer
= (*env
)->GetObjectArrayElement(env
, codec
->output_buffers
, idx
);
1609 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1614 ret
= (*env
)->GetDirectBufferAddress(env
, buffer
);
1615 *out_size
= (*env
)->GetDirectBufferCapacity(env
, buffer
);
1618 (*env
)->DeleteLocalRef(env
, buffer
);
1621 if (output_buffers
) {
1622 (*env
)->DeleteLocalRef(env
, output_buffers
);
1628 FFAMediaFormat
* ff_AMediaCodec_getOutputFormat(FFAMediaCodec
* codec
)
1630 FFAMediaFormat
*ret
= NULL
;
1633 jobject mediaformat
= NULL
;
1635 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
1637 mediaformat
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_output_format_id
);
1638 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1642 ret
= ff_AMediaFormat_newFromObject(mediaformat
);
1645 (*env
)->DeleteLocalRef(env
, mediaformat
);
1651 int ff_AMediaCodec_infoTryAgainLater(FFAMediaCodec
*codec
, ssize_t idx
)
1653 return idx
== codec
->INFO_TRY_AGAIN_LATER
;
1656 int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec
*codec
, ssize_t idx
)
1658 return idx
== codec
->INFO_OUTPUT_BUFFERS_CHANGED
;
1661 int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec
*codec
, ssize_t idx
)
1663 return idx
== codec
->INFO_OUTPUT_FORMAT_CHANGED
;
1666 int ff_AMediaCodec_getBufferFlagCodecConfig(FFAMediaCodec
*codec
)
1668 return codec
->BUFFER_FLAG_CODEC_CONFIG
;
1671 int ff_AMediaCodec_getBufferFlagEndOfStream(FFAMediaCodec
*codec
)
1673 return codec
->BUFFER_FLAG_END_OF_STREAM
;
1676 int ff_AMediaCodec_getBufferFlagKeyFrame(FFAMediaCodec
*codec
)
1678 return codec
->BUFFER_FLAG_KEY_FRAME
;
1681 int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec
*codec
)
1683 return codec
->CONFIGURE_FLAG_ENCODE
;
1686 int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec
*codec
)
1690 if (!codec
->has_get_i_o_buffer
) {
1691 if (codec
->output_buffers
) {
1694 env
= ff_jni_get_env(codec
);
1696 ret
= AVERROR_EXTERNAL
;
1700 (*env
)->DeleteGlobalRef(env
, codec
->output_buffers
);
1701 codec
->output_buffers
= NULL
;
1709 int ff_Build_SDK_INT(AVCodecContext
*avctx
)
1713 jclass versionClass
;
1714 jfieldID sdkIntFieldID
;
1715 JNI_GET_ENV_OR_RETURN(env
, avctx
, -1);
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
);