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
26 #include <media/NdkMediaFormat.h>
27 #include <media/NdkMediaCodec.h>
28 #include <android/native_window_jni.h>
30 #include "libavutil/avassert.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/avstring.h"
36 #include "mediacodec_wrapper.h"
38 struct JNIAMediaCodecListFields
{
40 jclass mediacodec_list_class
;
42 jmethodID find_decoder_for_format_id
;
44 jmethodID get_codec_count_id
;
45 jmethodID get_codec_info_at_id
;
47 jclass mediacodec_info_class
;
48 jmethodID get_name_id
;
49 jmethodID get_codec_capabilities_id
;
50 jmethodID get_supported_types_id
;
51 jmethodID is_encoder_id
;
52 jmethodID is_software_only_id
;
54 jclass codec_capabilities_class
;
55 jfieldID color_formats_id
;
56 jfieldID profile_levels_id
;
58 jclass codec_profile_level_class
;
63 #define OFFSET(x) offsetof(struct JNIAMediaCodecListFields, x)
64 static const struct FFJniField jni_amediacodeclist_mapping
[] = {
65 { "android/media/MediaCodecList", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(mediacodec_list_class
), 1 },
66 { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD
, OFFSET(init_id
), 0 },
67 { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD
, OFFSET(find_decoder_for_format_id
), 0 },
69 { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD
, OFFSET(get_codec_count_id
), 1 },
70 { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD
, OFFSET(get_codec_info_at_id
), 1 },
72 { "android/media/MediaCodecInfo", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(mediacodec_info_class
), 1 },
73 { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD
, OFFSET(get_name_id
), 1 },
74 { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD
, OFFSET(get_codec_capabilities_id
), 1 },
75 { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD
, OFFSET(get_supported_types_id
), 1 },
76 { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD
, OFFSET(is_encoder_id
), 1 },
77 { "android/media/MediaCodecInfo", "isSoftwareOnly", "()Z", FF_JNI_METHOD
, OFFSET(is_software_only_id
), 0 },
79 { "android/media/MediaCodecInfo$CodecCapabilities", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(codec_capabilities_class
), 1 },
80 { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD
, OFFSET(color_formats_id
), 1 },
81 { "android/media/MediaCodecInfo$CodecCapabilities", "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", FF_JNI_FIELD
, OFFSET(profile_levels_id
), 1 },
83 { "android/media/MediaCodecInfo$CodecProfileLevel", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(codec_profile_level_class
), 1 },
84 { "android/media/MediaCodecInfo$CodecProfileLevel", "profile", "I", FF_JNI_FIELD
, OFFSET(profile_id
), 1 },
85 { "android/media/MediaCodecInfo$CodecProfileLevel", "level", "I", FF_JNI_FIELD
, OFFSET(level_id
), 1 },
91 struct JNIAMediaFormatFields
{
93 jclass mediaformat_class
;
97 jmethodID contains_key_id
;
99 jmethodID get_integer_id
;
100 jmethodID get_long_id
;
101 jmethodID get_float_id
;
102 jmethodID get_bytebuffer_id
;
103 jmethodID get_string_id
;
105 jmethodID set_integer_id
;
106 jmethodID set_long_id
;
107 jmethodID set_float_id
;
108 jmethodID set_bytebuffer_id
;
109 jmethodID set_string_id
;
111 jmethodID to_string_id
;
115 #define OFFSET(x) offsetof(struct JNIAMediaFormatFields, x)
116 static const struct FFJniField jni_amediaformat_mapping
[] = {
117 { "android/media/MediaFormat", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(mediaformat_class
), 1 },
119 { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD
, OFFSET(init_id
), 1 },
121 { "android/media/MediaFormat", "containsKey", "(Ljava/lang/String;)Z", FF_JNI_METHOD
, OFFSET(contains_key_id
), 1 },
123 { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD
, OFFSET(get_integer_id
), 1 },
124 { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD
, OFFSET(get_long_id
), 1 },
125 { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD
, OFFSET(get_float_id
), 1 },
126 { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD
, OFFSET(get_bytebuffer_id
), 1 },
127 { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD
, OFFSET(get_string_id
), 1 },
129 { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD
, OFFSET(set_integer_id
), 1 },
130 { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD
, OFFSET(set_long_id
), 1 },
131 { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD
, OFFSET(set_float_id
), 1 },
132 { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD
, OFFSET(set_bytebuffer_id
), 1 },
133 { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD
, OFFSET(set_string_id
), 1 },
135 { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD
, OFFSET(to_string_id
), 1 },
141 static const AVClass amediaformat_class
= {
142 .class_name
= "amediaformat",
143 .item_name
= av_default_item_name
,
144 .version
= LIBAVUTIL_VERSION_INT
,
147 typedef struct FFAMediaFormatJni
{
150 struct JNIAMediaFormatFields jfields
;
154 static const FFAMediaFormat media_format_jni
;
156 struct JNIAMediaCodecFields
{
158 jclass mediacodec_class
;
160 jfieldID info_try_again_later_id
;
161 jfieldID info_output_buffers_changed_id
;
162 jfieldID info_output_format_changed_id
;
164 jfieldID buffer_flag_codec_config_id
;
165 jfieldID buffer_flag_end_of_stream_id
;
166 jfieldID buffer_flag_key_frame_id
;
168 jfieldID configure_flag_encode_id
;
170 jmethodID create_by_codec_name_id
;
171 jmethodID create_decoder_by_type_id
;
172 jmethodID create_encoder_by_type_id
;
174 jmethodID get_name_id
;
176 jmethodID configure_id
;
180 jmethodID release_id
;
182 jmethodID get_output_format_id
;
184 jmethodID dequeue_input_buffer_id
;
185 jmethodID queue_input_buffer_id
;
186 jmethodID get_input_buffer_id
;
187 jmethodID get_input_buffers_id
;
189 jmethodID dequeue_output_buffer_id
;
190 jmethodID get_output_buffer_id
;
191 jmethodID get_output_buffers_id
;
192 jmethodID release_output_buffer_id
;
193 jmethodID release_output_buffer_at_time_id
;
195 jmethodID set_input_surface_id
;
196 jmethodID signal_end_of_input_stream_id
;
198 jclass mediainfo_class
;
204 jfieldID presentation_time_us_id
;
209 #define OFFSET(x) offsetof(struct JNIAMediaCodecFields, x)
210 static const struct FFJniField jni_amediacodec_mapping
[] = {
211 { "android/media/MediaCodec", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(mediacodec_class
), 1 },
213 { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD
, OFFSET(info_try_again_later_id
), 1 },
214 { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD
, OFFSET(info_output_buffers_changed_id
), 1 },
215 { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD
, OFFSET(info_output_format_changed_id
), 1 },
217 { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD
, OFFSET(buffer_flag_codec_config_id
), 1 },
218 { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD
, OFFSET(buffer_flag_end_of_stream_id
), 1 },
219 { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD
, OFFSET(buffer_flag_key_frame_id
), 0 },
221 { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD
, OFFSET(configure_flag_encode_id
), 1 },
223 { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD
, OFFSET(create_by_codec_name_id
), 1 },
224 { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD
, OFFSET(create_decoder_by_type_id
), 1 },
225 { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD
, OFFSET(create_encoder_by_type_id
), 1 },
227 { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD
, OFFSET(get_name_id
), 1 },
229 { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD
, OFFSET(configure_id
), 1 },
230 { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD
, OFFSET(start_id
), 1 },
231 { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD
, OFFSET(flush_id
), 1 },
232 { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD
, OFFSET(stop_id
), 1 },
233 { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD
, OFFSET(release_id
), 1 },
235 { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD
, OFFSET(get_output_format_id
), 1 },
237 { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD
, OFFSET(dequeue_input_buffer_id
), 1 },
238 { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD
, OFFSET(queue_input_buffer_id
), 1 },
239 { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD
, OFFSET(get_input_buffer_id
), 0 },
240 { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD
, OFFSET(get_input_buffers_id
), 1 },
242 { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD
, OFFSET(dequeue_output_buffer_id
), 1 },
243 { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD
, OFFSET(get_output_buffer_id
), 0 },
244 { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD
, OFFSET(get_output_buffers_id
), 1 },
245 { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD
, OFFSET(release_output_buffer_id
), 1 },
246 { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD
, OFFSET(release_output_buffer_at_time_id
), 0 },
248 { "android/media/MediaCodec", "setInputSurface", "(Landroid/view/Surface;)V", FF_JNI_METHOD
, OFFSET(set_input_surface_id
), 0 },
249 { "android/media/MediaCodec", "signalEndOfInputStream", "()V", FF_JNI_METHOD
, OFFSET(signal_end_of_input_stream_id
), 0 },
251 { "android/media/MediaCodec$BufferInfo", NULL
, NULL
, FF_JNI_CLASS
, OFFSET(mediainfo_class
), 1 },
253 { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD
, OFFSET(init_id
), 1 },
254 { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD
, OFFSET(flags_id
), 1 },
255 { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD
, OFFSET(offset_id
), 1 },
256 { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD
, OFFSET(presentation_time_us_id
), 1 },
257 { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD
, OFFSET(size_id
), 1 },
263 static const AVClass amediacodec_class
= {
264 .class_name
= "amediacodec",
265 .item_name
= av_default_item_name
,
266 .version
= LIBAVUTIL_VERSION_INT
,
269 typedef struct FFAMediaCodecJni
{
272 struct JNIAMediaCodecFields jfields
;
277 jobject input_buffers
;
278 jobject output_buffers
;
280 int INFO_TRY_AGAIN_LATER
;
281 int INFO_OUTPUT_BUFFERS_CHANGED
;
282 int INFO_OUTPUT_FORMAT_CHANGED
;
284 int BUFFER_FLAG_CODEC_CONFIG
;
285 int BUFFER_FLAG_END_OF_STREAM
;
286 int BUFFER_FLAG_KEY_FRAME
;
288 int CONFIGURE_FLAG_ENCODE
;
290 int has_get_i_o_buffer
;
293 static const FFAMediaCodec media_codec_jni
;
295 #define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do { \
296 (env) = ff_jni_get_env(log_ctx); \
302 #define JNI_GET_ENV_OR_RETURN_VOID(env, log_ctx) do { \
303 (env) = ff_jni_get_env(log_ctx); \
309 int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext
*avctx
)
311 // Copy and modified from MediaCodecInfo.java
312 static const int AVCProfileBaseline
= 0x01;
313 static const int AVCProfileMain
= 0x02;
314 static const int AVCProfileExtended
= 0x04;
315 static const int AVCProfileHigh
= 0x08;
316 static const int AVCProfileHigh10
= 0x10;
317 static const int AVCProfileHigh422
= 0x20;
318 static const int AVCProfileHigh444
= 0x40;
319 static const int AVCProfileConstrainedBaseline
= 0x10000;
320 static const int AVCProfileConstrainedHigh
= 0x80000;
322 static const int HEVCProfileMain
= 0x01;
323 static const int HEVCProfileMain10
= 0x02;
324 static const int HEVCProfileMainStill
= 0x04;
325 static const int HEVCProfileMain10HDR10
= 0x1000;
326 static const int HEVCProfileMain10HDR10Plus
= 0x2000;
328 static const int VP9Profile0
= 0x01;
329 static const int VP9Profile1
= 0x02;
330 static const int VP9Profile2
= 0x04;
331 static const int VP9Profile3
= 0x08;
332 static const int VP9Profile2HDR
= 0x1000;
333 static const int VP9Profile3HDR
= 0x2000;
334 static const int VP9Profile2HDR10Plus
= 0x4000;
335 static const int VP9Profile3HDR10Plus
= 0x8000;
337 static const int MPEG4ProfileSimple
= 0x01;
338 static const int MPEG4ProfileSimpleScalable
= 0x02;
339 static const int MPEG4ProfileCore
= 0x04;
340 static const int MPEG4ProfileMain
= 0x08;
341 static const int MPEG4ProfileNbit
= 0x10;
342 static const int MPEG4ProfileScalableTexture
= 0x20;
343 static const int MPEG4ProfileSimpleFBA
= 0x80;
344 static const int MPEG4ProfileSimpleFace
= 0x40;
345 static const int MPEG4ProfileBasicAnimated
= 0x100;
346 static const int MPEG4ProfileHybrid
= 0x200;
347 static const int MPEG4ProfileAdvancedRealTime
= 0x400;
348 static const int MPEG4ProfileCoreScalable
= 0x800;
349 static const int MPEG4ProfileAdvancedCoding
= 0x1000;
350 static const int MPEG4ProfileAdvancedCore
= 0x2000;
351 static const int MPEG4ProfileAdvancedScalable
= 0x4000;
352 static const int MPEG4ProfileAdvancedSimple
= 0x8000;
355 static const int AV1ProfileMain8
= 0x1;
356 static const int AV1ProfileMain10
= 0x2;
357 static const int AV1ProfileMain10HDR10
= 0x1000;
358 static const int AV1ProfileMain10HDR10Plus
= 0x2000;
361 (void)AVCProfileConstrainedHigh
;
362 (void)HEVCProfileMain10HDR10
;
363 (void)HEVCProfileMain10HDR10Plus
;
364 (void)VP9Profile2HDR
;
365 (void)VP9Profile3HDR
;
366 (void)VP9Profile2HDR10Plus
;
367 (void)VP9Profile3HDR10Plus
;
368 (void)MPEG4ProfileSimpleFace
;
369 (void)AV1ProfileMain10
;
370 (void)AV1ProfileMain10HDR10
;
371 (void)AV1ProfileMain10HDR10Plus
;
373 if (avctx
->codec_id
== AV_CODEC_ID_H264
) {
374 switch(avctx
->profile
) {
375 case AV_PROFILE_H264_BASELINE
:
376 return AVCProfileBaseline
;
377 case AV_PROFILE_H264_CONSTRAINED_BASELINE
:
378 return AVCProfileConstrainedBaseline
;
379 case AV_PROFILE_H264_MAIN
:
380 return AVCProfileMain
;
382 case AV_PROFILE_H264_EXTENDED
:
383 return AVCProfileExtended
;
384 case AV_PROFILE_H264_HIGH
:
385 return AVCProfileHigh
;
386 case AV_PROFILE_H264_HIGH_10
:
387 case AV_PROFILE_H264_HIGH_10_INTRA
:
388 return AVCProfileHigh10
;
389 case AV_PROFILE_H264_HIGH_422
:
390 case AV_PROFILE_H264_HIGH_422_INTRA
:
391 return AVCProfileHigh422
;
392 case AV_PROFILE_H264_HIGH_444
:
393 case AV_PROFILE_H264_HIGH_444_INTRA
:
394 case AV_PROFILE_H264_HIGH_444_PREDICTIVE
:
395 return AVCProfileHigh444
;
397 } else if (avctx
->codec_id
== AV_CODEC_ID_HEVC
) {
398 switch (avctx
->profile
) {
399 case AV_PROFILE_HEVC_MAIN
:
400 return HEVCProfileMain
;
401 case AV_PROFILE_HEVC_MAIN_STILL_PICTURE
:
402 return HEVCProfileMainStill
;
403 case AV_PROFILE_HEVC_MAIN_10
:
404 return HEVCProfileMain10
;
406 } else if (avctx
->codec_id
== AV_CODEC_ID_VP9
) {
407 switch (avctx
->profile
) {
408 case AV_PROFILE_VP9_0
:
410 case AV_PROFILE_VP9_1
:
412 case AV_PROFILE_VP9_2
:
414 case AV_PROFILE_VP9_3
:
417 } else if(avctx
->codec_id
== AV_CODEC_ID_MPEG4
) {
418 switch (avctx
->profile
)
420 case AV_PROFILE_MPEG4_SIMPLE
:
421 return MPEG4ProfileSimple
;
422 case AV_PROFILE_MPEG4_SIMPLE_SCALABLE
:
423 return MPEG4ProfileSimpleScalable
;
424 case AV_PROFILE_MPEG4_CORE
:
425 return MPEG4ProfileCore
;
426 case AV_PROFILE_MPEG4_MAIN
:
427 return MPEG4ProfileMain
;
428 case AV_PROFILE_MPEG4_N_BIT
:
429 return MPEG4ProfileNbit
;
430 case AV_PROFILE_MPEG4_SCALABLE_TEXTURE
:
431 return MPEG4ProfileScalableTexture
;
432 case AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION
:
433 return MPEG4ProfileSimpleFBA
;
434 case AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE
:
435 return MPEG4ProfileBasicAnimated
;
436 case AV_PROFILE_MPEG4_HYBRID
:
437 return MPEG4ProfileHybrid
;
438 case AV_PROFILE_MPEG4_ADVANCED_REAL_TIME
:
439 return MPEG4ProfileAdvancedRealTime
;
440 case AV_PROFILE_MPEG4_CORE_SCALABLE
:
441 return MPEG4ProfileCoreScalable
;
442 case AV_PROFILE_MPEG4_ADVANCED_CODING
:
443 return MPEG4ProfileAdvancedCoding
;
444 case AV_PROFILE_MPEG4_ADVANCED_CORE
:
445 return MPEG4ProfileAdvancedCore
;
446 case AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE
:
447 return MPEG4ProfileAdvancedScalable
;
448 case AV_PROFILE_MPEG4_ADVANCED_SIMPLE
:
449 return MPEG4ProfileAdvancedSimple
;
450 case AV_PROFILE_MPEG4_SIMPLE_STUDIO
:
451 // Studio profiles are not supported by mediacodec.
455 } else if(avctx
->codec_id
== AV_CODEC_ID_AV1
) {
456 switch (avctx
->profile
)
458 case AV_PROFILE_AV1_MAIN
:
459 return AV1ProfileMain8
;
460 case AV_PROFILE_AV1_HIGH
:
461 case AV_PROFILE_AV1_PROFESSIONAL
:
470 char *ff_AMediaCodecList_getCodecNameByType(const char *mime
, int profile
, int encoder
, void *log_ctx
)
477 char *supported_type
= NULL
;
480 struct JNIAMediaCodecListFields jfields
= { 0 };
481 struct JNIAMediaFormatFields mediaformat_jfields
= { 0 };
483 jobject codec_name
= NULL
;
487 jobjectArray types
= NULL
;
489 jobject capabilities
= NULL
;
490 jobject profile_level
= NULL
;
491 jobjectArray profile_levels
= NULL
;
493 JNI_GET_ENV_OR_RETURN(env
, log_ctx
, NULL
);
495 if ((ret
= ff_jni_init_jfields(env
, &jfields
, jni_amediacodeclist_mapping
, 0, log_ctx
)) < 0) {
499 if ((ret
= ff_jni_init_jfields(env
, &mediaformat_jfields
, jni_amediaformat_mapping
, 0, log_ctx
)) < 0) {
503 codec_count
= (*env
)->CallStaticIntMethod(env
, jfields
.mediacodec_list_class
, jfields
.get_codec_count_id
);
504 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
508 for(i
= 0; i
< codec_count
; i
++) {
513 info
= (*env
)->CallStaticObjectMethod(env
, jfields
.mediacodec_list_class
, jfields
.get_codec_info_at_id
, i
);
514 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
518 types
= (*env
)->CallObjectMethod(env
, info
, jfields
.get_supported_types_id
);
519 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
523 is_encoder
= (*env
)->CallBooleanMethod(env
, info
, jfields
.is_encoder_id
);
524 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
528 if (is_encoder
!= encoder
) {
532 if (jfields
.is_software_only_id
) {
533 int is_software_only
= (*env
)->CallBooleanMethod(env
, info
, jfields
.is_software_only_id
);
534 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
538 if (is_software_only
) {
543 codec_name
= (*env
)->CallObjectMethod(env
, info
, jfields
.get_name_id
);
544 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
548 name
= ff_jni_jstring_to_utf_chars(env
, codec_name
, log_ctx
);
553 (*env
)->DeleteLocalRef(env
, codec_name
);
556 /* Skip software decoders */
558 strstr(name
, "OMX.google") ||
559 strstr(name
, "OMX.ffmpeg") ||
560 (strstr(name
, "OMX.SEC") && strstr(name
, ".sw.")) ||
561 !strcmp(name
, "OMX.qcom.video.decoder.hevcswvdec")) {
565 type_count
= (*env
)->GetArrayLength(env
, types
);
566 for (j
= 0; j
< type_count
; j
++) {
570 type
= (*env
)->GetObjectArrayElement(env
, types
, j
);
571 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
575 supported_type
= ff_jni_jstring_to_utf_chars(env
, type
, log_ctx
);
576 if (!supported_type
) {
580 if (av_strcasecmp(supported_type
, mime
)) {
584 capabilities
= (*env
)->CallObjectMethod(env
, info
, jfields
.get_codec_capabilities_id
, type
);
585 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
589 profile_levels
= (*env
)->GetObjectField(env
, capabilities
, jfields
.profile_levels_id
);
590 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
594 profile_count
= (*env
)->GetArrayLength(env
, profile_levels
);
595 if (!profile_count
) {
598 for (k
= 0; k
< profile_count
; k
++) {
599 int supported_profile
= 0;
606 profile_level
= (*env
)->GetObjectArrayElement(env
, profile_levels
, k
);
607 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
611 supported_profile
= (*env
)->GetIntField(env
, profile_level
, jfields
.profile_id
);
612 if (ff_jni_exception_check(env
, 1, log_ctx
) < 0) {
616 found_codec
= profile
== supported_profile
;
618 (*env
)->DeleteLocalRef(env
, profile_level
);
619 profile_level
= NULL
;
627 (*env
)->DeleteLocalRef(env
, profile_levels
);
628 profile_levels
= NULL
;
630 (*env
)->DeleteLocalRef(env
, capabilities
);
633 (*env
)->DeleteLocalRef(env
, type
);
636 av_freep(&supported_type
);
644 (*env
)->DeleteLocalRef(env
, info
);
647 (*env
)->DeleteLocalRef(env
, types
);
658 (*env
)->DeleteLocalRef(env
, codec_name
);
659 (*env
)->DeleteLocalRef(env
, info
);
660 (*env
)->DeleteLocalRef(env
, type
);
661 (*env
)->DeleteLocalRef(env
, types
);
662 (*env
)->DeleteLocalRef(env
, capabilities
);
663 (*env
)->DeleteLocalRef(env
, profile_level
);
664 (*env
)->DeleteLocalRef(env
, profile_levels
);
666 av_freep(&supported_type
);
668 ff_jni_reset_jfields(env
, &jfields
, jni_amediacodeclist_mapping
, 0, log_ctx
);
669 ff_jni_reset_jfields(env
, &mediaformat_jfields
, jni_amediaformat_mapping
, 0, log_ctx
);
678 static FFAMediaFormat
*mediaformat_jni_new(void)
681 FFAMediaFormatJni
*format
= NULL
;
682 jobject object
= NULL
;
684 format
= av_mallocz(sizeof(*format
));
688 format
->api
= media_format_jni
;
690 env
= ff_jni_get_env(format
);
696 if (ff_jni_init_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
) < 0) {
700 object
= (*env
)->NewObject(env
, format
->jfields
.mediaformat_class
, format
->jfields
.init_id
);
705 format
->object
= (*env
)->NewGlobalRef(env
, object
);
706 if (!format
->object
) {
711 (*env
)->DeleteLocalRef(env
, object
);
713 if (!format
->object
) {
714 ff_jni_reset_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
);
718 return (FFAMediaFormat
*)format
;
721 static FFAMediaFormat
*mediaformat_jni_newFromObject(void *object
)
724 FFAMediaFormatJni
*format
= NULL
;
726 format
= av_mallocz(sizeof(*format
));
730 format
->api
= media_format_jni
;
732 env
= ff_jni_get_env(format
);
738 if (ff_jni_init_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
) < 0) {
742 format
->object
= (*env
)->NewGlobalRef(env
, object
);
743 if (!format
->object
) {
747 return (FFAMediaFormat
*)format
;
749 ff_jni_reset_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
);
756 static int mediaformat_jni_delete(FFAMediaFormat
* ctx
)
759 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
766 JNI_GET_ENV_OR_RETURN(env
, format
, AVERROR_EXTERNAL
);
768 (*env
)->DeleteGlobalRef(env
, format
->object
);
769 format
->object
= NULL
;
771 ff_jni_reset_jfields(env
, &format
->jfields
, jni_amediaformat_mapping
, 1, format
);
778 static char* mediaformat_jni_toString(FFAMediaFormat
* ctx
)
781 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
783 jstring description
= NULL
;
785 av_assert0(format
!= NULL
);
787 JNI_GET_ENV_OR_RETURN(env
, format
, NULL
);
789 description
= (*env
)->CallObjectMethod(env
, format
->object
, format
->jfields
.to_string_id
);
790 if (ff_jni_exception_check(env
, 1, NULL
) < 0) {
794 ret
= ff_jni_jstring_to_utf_chars(env
, description
, format
);
796 (*env
)->DeleteLocalRef(env
, description
);
801 static int mediaformat_jni_getInt32(FFAMediaFormat
* ctx
, const char *name
, int32_t *out
)
804 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
807 jboolean contains_key
;
809 av_assert0(format
!= NULL
);
811 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
813 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
819 contains_key
= (*env
)->CallBooleanMethod(env
, format
->object
, format
->jfields
.contains_key_id
, key
);
820 if (!contains_key
|| (ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
825 *out
= (*env
)->CallIntMethod(env
, format
->object
, format
->jfields
.get_integer_id
, key
);
826 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
833 (*env
)->DeleteLocalRef(env
, key
);
838 static int mediaformat_jni_getInt64(FFAMediaFormat
* ctx
, const char *name
, int64_t *out
)
841 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
844 jboolean contains_key
;
846 av_assert0(format
!= NULL
);
848 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
850 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
856 contains_key
= (*env
)->CallBooleanMethod(env
, format
->object
, format
->jfields
.contains_key_id
, key
);
857 if (!contains_key
|| (ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
862 *out
= (*env
)->CallLongMethod(env
, format
->object
, format
->jfields
.get_long_id
, key
);
863 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
870 (*env
)->DeleteLocalRef(env
, key
);
875 static int mediaformat_jni_getFloat(FFAMediaFormat
* ctx
, const char *name
, float *out
)
878 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
881 jboolean contains_key
;
883 av_assert0(format
!= NULL
);
885 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
887 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
893 contains_key
= (*env
)->CallBooleanMethod(env
, format
->object
, format
->jfields
.contains_key_id
, key
);
894 if (!contains_key
|| (ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
899 *out
= (*env
)->CallFloatMethod(env
, format
->object
, format
->jfields
.get_float_id
, key
);
900 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
907 (*env
)->DeleteLocalRef(env
, key
);
912 static int mediaformat_jni_getBuffer(FFAMediaFormat
* ctx
, const char *name
, void** data
, size_t *size
)
915 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
918 jboolean contains_key
;
919 jobject result
= NULL
;
921 av_assert0(format
!= NULL
);
923 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
925 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
931 contains_key
= (*env
)->CallBooleanMethod(env
, format
->object
, format
->jfields
.contains_key_id
, key
);
932 if (!contains_key
|| (ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
937 result
= (*env
)->CallObjectMethod(env
, format
->object
, format
->jfields
.get_bytebuffer_id
, key
);
938 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
943 *data
= (*env
)->GetDirectBufferAddress(env
, result
);
944 *size
= (*env
)->GetDirectBufferCapacity(env
, result
);
946 if (*data
&& *size
) {
948 *data
= av_malloc(*size
);
954 memcpy(*data
, src
, *size
);
959 (*env
)->DeleteLocalRef(env
, key
);
960 (*env
)->DeleteLocalRef(env
, result
);
965 static int mediaformat_jni_getString(FFAMediaFormat
* ctx
, const char *name
, const char **out
)
968 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
971 jboolean contains_key
;
972 jstring result
= NULL
;
974 av_assert0(format
!= NULL
);
976 JNI_GET_ENV_OR_RETURN(env
, format
, 0);
978 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
984 contains_key
= (*env
)->CallBooleanMethod(env
, format
->object
, format
->jfields
.contains_key_id
, key
);
985 if (!contains_key
|| (ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
990 result
= (*env
)->CallObjectMethod(env
, format
->object
, format
->jfields
.get_string_id
, key
);
991 if ((ret
= ff_jni_exception_check(env
, 1, format
)) < 0) {
996 *out
= ff_jni_jstring_to_utf_chars(env
, result
, format
);
1004 (*env
)->DeleteLocalRef(env
, key
);
1005 (*env
)->DeleteLocalRef(env
, result
);
1010 static void mediaformat_jni_setInt32(FFAMediaFormat
* ctx
, const char* name
, int32_t value
)
1014 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
1016 av_assert0(format
!= NULL
);
1018 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1020 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1025 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_integer_id
, key
, value
);
1026 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1031 (*env
)->DeleteLocalRef(env
, key
);
1034 static void mediaformat_jni_setInt64(FFAMediaFormat
* ctx
, const char* name
, int64_t value
)
1038 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
1040 av_assert0(format
!= NULL
);
1042 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1044 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1049 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_long_id
, key
, value
);
1050 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1055 (*env
)->DeleteLocalRef(env
, key
);
1058 static void mediaformat_jni_setFloat(FFAMediaFormat
* ctx
, const char* name
, float value
)
1062 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
1064 av_assert0(format
!= NULL
);
1066 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1068 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1073 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_float_id
, key
, value
);
1074 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1079 (*env
)->DeleteLocalRef(env
, key
);
1082 static void mediaformat_jni_setString(FFAMediaFormat
* ctx
, const char* name
, const char* value
)
1086 jstring string
= NULL
;
1087 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
1089 av_assert0(format
!= NULL
);
1091 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1093 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1098 string
= ff_jni_utf_chars_to_jstring(env
, value
, format
);
1103 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_string_id
, key
, string
);
1104 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1109 (*env
)->DeleteLocalRef(env
, key
);
1110 (*env
)->DeleteLocalRef(env
, string
);
1113 static void mediaformat_jni_setBuffer(FFAMediaFormat
* ctx
, const char* name
, void* data
, size_t size
)
1117 jobject buffer
= NULL
;
1118 void *buffer_data
= NULL
;
1119 FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)ctx
;
1121 av_assert0(format
!= NULL
);
1123 JNI_GET_ENV_OR_RETURN_VOID(env
, format
);
1125 key
= ff_jni_utf_chars_to_jstring(env
, name
, format
);
1130 if (!data
|| !size
) {
1134 buffer_data
= av_malloc(size
);
1139 memcpy(buffer_data
, data
, size
);
1141 buffer
= (*env
)->NewDirectByteBuffer(env
, buffer_data
, size
);
1146 (*env
)->CallVoidMethod(env
, format
->object
, format
->jfields
.set_bytebuffer_id
, key
, buffer
);
1147 if (ff_jni_exception_check(env
, 1, format
) < 0) {
1152 (*env
)->DeleteLocalRef(env
, key
);
1153 (*env
)->DeleteLocalRef(env
, buffer
);
1156 static int codec_init_static_fields(FFAMediaCodecJni
*codec
)
1161 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1163 codec
->INFO_TRY_AGAIN_LATER
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.info_try_again_later_id
);
1164 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1168 codec
->BUFFER_FLAG_CODEC_CONFIG
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.buffer_flag_codec_config_id
);
1169 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1173 codec
->BUFFER_FLAG_END_OF_STREAM
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.buffer_flag_end_of_stream_id
);
1174 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1178 if (codec
->jfields
.buffer_flag_key_frame_id
) {
1179 codec
->BUFFER_FLAG_KEY_FRAME
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.buffer_flag_key_frame_id
);
1180 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1185 codec
->CONFIGURE_FLAG_ENCODE
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.configure_flag_encode_id
);
1186 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1190 codec
->INFO_TRY_AGAIN_LATER
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.info_try_again_later_id
);
1191 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1195 codec
->INFO_OUTPUT_BUFFERS_CHANGED
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.info_output_buffers_changed_id
);
1196 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1200 codec
->INFO_OUTPUT_FORMAT_CHANGED
= (*env
)->GetStaticIntField(env
, codec
->jfields
.mediacodec_class
, codec
->jfields
.info_output_format_changed_id
);
1201 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1210 #define CREATE_CODEC_BY_NAME 0
1211 #define CREATE_DECODER_BY_TYPE 1
1212 #define CREATE_ENCODER_BY_TYPE 2
1214 static inline FFAMediaCodec
*codec_create(int method
, const char *arg
)
1218 FFAMediaCodecJni
*codec
= NULL
;
1219 jstring jarg
= NULL
;
1220 jobject object
= NULL
;
1221 jobject buffer_info
= NULL
;
1222 jmethodID create_id
= NULL
;
1224 codec
= av_mallocz(sizeof(*codec
));
1228 codec
->api
= media_codec_jni
;
1230 env
= ff_jni_get_env(codec
);
1236 if (ff_jni_init_jfields(env
, &codec
->jfields
, jni_amediacodec_mapping
, 1, codec
) < 0) {
1240 jarg
= ff_jni_utf_chars_to_jstring(env
, arg
, codec
);
1246 case CREATE_CODEC_BY_NAME
: create_id
= codec
->jfields
.create_by_codec_name_id
; break;
1247 case CREATE_DECODER_BY_TYPE
: create_id
= codec
->jfields
.create_decoder_by_type_id
; break;
1248 case CREATE_ENCODER_BY_TYPE
: create_id
= codec
->jfields
.create_encoder_by_type_id
; break;
1253 object
= (*env
)->CallStaticObjectMethod(env
,
1254 codec
->jfields
.mediacodec_class
,
1257 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1261 codec
->object
= (*env
)->NewGlobalRef(env
, object
);
1262 if (!codec
->object
) {
1266 if (codec_init_static_fields(codec
) < 0) {
1270 if (codec
->jfields
.get_input_buffer_id
&& codec
->jfields
.get_output_buffer_id
) {
1271 codec
->has_get_i_o_buffer
= 1;
1274 buffer_info
= (*env
)->NewObject(env
, codec
->jfields
.mediainfo_class
, codec
->jfields
.init_id
);
1275 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1279 codec
->buffer_info
= (*env
)->NewGlobalRef(env
, buffer_info
);
1280 if (!codec
->buffer_info
) {
1286 (*env
)->DeleteLocalRef(env
, jarg
);
1287 (*env
)->DeleteLocalRef(env
, object
);
1288 (*env
)->DeleteLocalRef(env
, buffer_info
);
1291 (*env
)->DeleteGlobalRef(env
, codec
->object
);
1292 (*env
)->DeleteGlobalRef(env
, codec
->buffer_info
);
1294 ff_jni_reset_jfields(env
, &codec
->jfields
, jni_amediacodec_mapping
, 1, codec
);
1298 return (FFAMediaCodec
*)codec
;
1301 #define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \
1302 static FFAMediaCodec *mediacodec_jni_##name(const char *arg) \
1304 return codec_create(method, arg); \
1307 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME)
1308 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createDecoderByType
, CREATE_DECODER_BY_TYPE
)
1309 DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createEncoderByType
, CREATE_ENCODER_BY_TYPE
)
1311 static int mediacodec_jni_delete(FFAMediaCodec
* ctx
)
1314 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1321 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1323 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.release_id
);
1324 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1325 ret
= AVERROR_EXTERNAL
;
1328 (*env
)->DeleteGlobalRef(env
, codec
->input_buffers
);
1329 codec
->input_buffers
= NULL
;
1331 (*env
)->DeleteGlobalRef(env
, codec
->output_buffers
);
1332 codec
->output_buffers
= NULL
;
1334 (*env
)->DeleteGlobalRef(env
, codec
->object
);
1335 codec
->object
= NULL
;
1337 (*env
)->DeleteGlobalRef(env
, codec
->buffer_info
);
1338 codec
->buffer_info
= NULL
;
1340 ff_jni_reset_jfields(env
, &codec
->jfields
, jni_amediacodec_mapping
, 1, codec
);
1347 static char *mediacodec_jni_getName(FFAMediaCodec
*ctx
)
1351 jobject
*name
= NULL
;
1352 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1354 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
1356 name
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_name_id
);
1357 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1361 ret
= ff_jni_jstring_to_utf_chars(env
, name
, codec
);
1365 (*env
)->DeleteLocalRef(env
, name
);
1371 static int mediacodec_jni_configure(FFAMediaCodec
*ctx
,
1372 const FFAMediaFormat
* format_ctx
,
1373 FFANativeWindow
* window
,
1379 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1380 const FFAMediaFormatJni
*format
= (FFAMediaFormatJni
*)format_ctx
;
1381 jobject
*surface
= window
? window
->surface
: NULL
;
1383 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1385 if (flags
& codec
->CONFIGURE_FLAG_ENCODE
) {
1386 if (surface
&& !codec
->jfields
.set_input_surface_id
) {
1387 av_log(ctx
, AV_LOG_ERROR
, "System doesn't support setInputSurface\n");
1388 return AVERROR_EXTERNAL
;
1391 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.configure_id
, format
->object
, NULL
, NULL
, flags
);
1392 if (ff_jni_exception_check(env
, 1, codec
) < 0)
1393 return AVERROR_EXTERNAL
;
1398 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.set_input_surface_id
, surface
);
1399 if (ff_jni_exception_check(env
, 1, codec
) < 0)
1400 return AVERROR_EXTERNAL
;
1403 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.configure_id
, format
->object
, surface
, NULL
, flags
);
1405 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1406 ret
= AVERROR_EXTERNAL
;
1414 static int mediacodec_jni_start(FFAMediaCodec
* ctx
)
1418 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1420 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1422 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.start_id
);
1423 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1424 ret
= AVERROR_EXTERNAL
;
1432 static int mediacodec_jni_stop(FFAMediaCodec
* ctx
)
1436 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1438 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1440 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.stop_id
);
1441 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1442 ret
= AVERROR_EXTERNAL
;
1450 static int mediacodec_jni_flush(FFAMediaCodec
* ctx
)
1454 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1456 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1458 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.flush_id
);
1459 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1460 ret
= AVERROR_EXTERNAL
;
1468 static int mediacodec_jni_releaseOutputBuffer(FFAMediaCodec
* ctx
, size_t idx
, int render
)
1472 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1474 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1476 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.release_output_buffer_id
, (jint
)idx
, (jboolean
)render
);
1477 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1478 ret
= AVERROR_EXTERNAL
;
1486 static int mediacodec_jni_releaseOutputBufferAtTime(FFAMediaCodec
*ctx
, size_t idx
, int64_t timestampNs
)
1490 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1492 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1494 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.release_output_buffer_at_time_id
, (jint
)idx
, (jlong
)timestampNs
);
1495 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1496 ret
= AVERROR_EXTERNAL
;
1504 static ssize_t
mediacodec_jni_dequeueInputBuffer(FFAMediaCodec
* ctx
, int64_t timeoutUs
)
1508 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1510 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1512 ret
= (*env
)->CallIntMethod(env
, codec
->object
, codec
->jfields
.dequeue_input_buffer_id
, timeoutUs
);
1513 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1514 ret
= AVERROR_EXTERNAL
;
1522 static int mediacodec_jni_queueInputBuffer(FFAMediaCodec
* ctx
, size_t idx
, off_t offset
, size_t size
, uint64_t time
, uint32_t flags
)
1526 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1528 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1530 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.queue_input_buffer_id
, (jint
)idx
, (jint
)offset
, (jint
)size
, time
, flags
);
1531 if ((ret
= ff_jni_exception_check(env
, 1, codec
)) < 0) {
1532 ret
= AVERROR_EXTERNAL
;
1540 static ssize_t
mediacodec_jni_dequeueOutputBuffer(FFAMediaCodec
* ctx
, FFAMediaCodecBufferInfo
*info
, int64_t timeoutUs
)
1544 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1546 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1548 ret
= (*env
)->CallIntMethod(env
, codec
->object
, codec
->jfields
.dequeue_output_buffer_id
, codec
->buffer_info
, timeoutUs
);
1549 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1550 return AVERROR_EXTERNAL
;
1553 info
->flags
= (*env
)->GetIntField(env
, codec
->buffer_info
, codec
->jfields
.flags_id
);
1554 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1555 return AVERROR_EXTERNAL
;
1558 info
->offset
= (*env
)->GetIntField(env
, codec
->buffer_info
, codec
->jfields
.offset_id
);
1559 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1560 return AVERROR_EXTERNAL
;
1563 info
->presentationTimeUs
= (*env
)->GetLongField(env
, codec
->buffer_info
, codec
->jfields
.presentation_time_us_id
);
1564 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1565 return AVERROR_EXTERNAL
;
1568 info
->size
= (*env
)->GetIntField(env
, codec
->buffer_info
, codec
->jfields
.size_id
);
1569 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1570 return AVERROR_EXTERNAL
;
1576 static uint8_t* mediacodec_jni_getInputBuffer(FFAMediaCodec
* ctx
, size_t idx
, size_t *out_size
)
1578 uint8_t *ret
= NULL
;
1580 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1581 jobject buffer
= NULL
;
1582 jobject input_buffers
= NULL
;
1584 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
1586 if (codec
->has_get_i_o_buffer
) {
1587 buffer
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_input_buffer_id
, (jint
)idx
);
1588 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1592 if (!codec
->input_buffers
) {
1593 input_buffers
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_input_buffers_id
);
1594 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1598 codec
->input_buffers
= (*env
)->NewGlobalRef(env
, input_buffers
);
1599 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1604 buffer
= (*env
)->GetObjectArrayElement(env
, codec
->input_buffers
, idx
);
1605 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1610 ret
= (*env
)->GetDirectBufferAddress(env
, buffer
);
1611 *out_size
= (*env
)->GetDirectBufferCapacity(env
, buffer
);
1613 (*env
)->DeleteLocalRef(env
, buffer
);
1614 (*env
)->DeleteLocalRef(env
, input_buffers
);
1619 static uint8_t* mediacodec_jni_getOutputBuffer(FFAMediaCodec
* ctx
, size_t idx
, size_t *out_size
)
1621 uint8_t *ret
= NULL
;
1623 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1624 jobject buffer
= NULL
;
1625 jobject output_buffers
= NULL
;
1627 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
1629 if (codec
->has_get_i_o_buffer
) {
1630 buffer
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_output_buffer_id
, (jint
)idx
);
1631 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1635 if (!codec
->output_buffers
) {
1636 output_buffers
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_output_buffers_id
);
1637 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1641 codec
->output_buffers
= (*env
)->NewGlobalRef(env
, output_buffers
);
1642 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1647 buffer
= (*env
)->GetObjectArrayElement(env
, codec
->output_buffers
, idx
);
1648 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1653 ret
= (*env
)->GetDirectBufferAddress(env
, buffer
);
1654 *out_size
= (*env
)->GetDirectBufferCapacity(env
, buffer
);
1656 (*env
)->DeleteLocalRef(env
, buffer
);
1657 (*env
)->DeleteLocalRef(env
, output_buffers
);
1662 static FFAMediaFormat
* mediacodec_jni_getOutputFormat(FFAMediaCodec
* ctx
)
1664 FFAMediaFormat
*ret
= NULL
;
1666 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1668 jobject mediaformat
= NULL
;
1670 JNI_GET_ENV_OR_RETURN(env
, codec
, NULL
);
1672 mediaformat
= (*env
)->CallObjectMethod(env
, codec
->object
, codec
->jfields
.get_output_format_id
);
1673 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1677 ret
= mediaformat_jni_newFromObject(mediaformat
);
1679 (*env
)->DeleteLocalRef(env
, mediaformat
);
1684 static int mediacodec_jni_infoTryAgainLater(FFAMediaCodec
*ctx
, ssize_t idx
)
1686 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1687 return idx
== codec
->INFO_TRY_AGAIN_LATER
;
1690 static int mediacodec_jni_infoOutputBuffersChanged(FFAMediaCodec
*ctx
, ssize_t idx
)
1692 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1693 return idx
== codec
->INFO_OUTPUT_BUFFERS_CHANGED
;
1696 static int mediacodec_jni_infoOutputFormatChanged(FFAMediaCodec
*ctx
, ssize_t idx
)
1698 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1699 return idx
== codec
->INFO_OUTPUT_FORMAT_CHANGED
;
1702 static int mediacodec_jni_getBufferFlagCodecConfig(FFAMediaCodec
*ctx
)
1704 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1705 return codec
->BUFFER_FLAG_CODEC_CONFIG
;
1708 static int mediacodec_jni_getBufferFlagEndOfStream(FFAMediaCodec
*ctx
)
1710 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1711 return codec
->BUFFER_FLAG_END_OF_STREAM
;
1714 static int mediacodec_jni_getBufferFlagKeyFrame(FFAMediaCodec
*ctx
)
1716 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1717 return codec
->BUFFER_FLAG_KEY_FRAME
;
1720 static int mediacodec_jni_getConfigureFlagEncode(FFAMediaCodec
*ctx
)
1722 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1723 return codec
->CONFIGURE_FLAG_ENCODE
;
1726 static int mediacodec_jni_cleanOutputBuffers(FFAMediaCodec
*ctx
)
1729 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1731 if (!codec
->has_get_i_o_buffer
) {
1732 if (codec
->output_buffers
) {
1735 env
= ff_jni_get_env(codec
);
1737 ret
= AVERROR_EXTERNAL
;
1741 (*env
)->DeleteGlobalRef(env
, codec
->output_buffers
);
1742 codec
->output_buffers
= NULL
;
1750 static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec
*ctx
)
1753 FFAMediaCodecJni
*codec
= (FFAMediaCodecJni
*)ctx
;
1755 JNI_GET_ENV_OR_RETURN(env
, codec
, AVERROR_EXTERNAL
);
1757 (*env
)->CallVoidMethod(env
, codec
->object
, codec
->jfields
.signal_end_of_input_stream_id
);
1758 if (ff_jni_exception_check(env
, 1, codec
) < 0) {
1759 return AVERROR_EXTERNAL
;
1765 static int mediacodec_jni_setAsyncNotifyCallback(FFAMediaCodec
*codec
,
1766 const FFAMediaCodecOnAsyncNotifyCallback
*callback
,
1769 av_log(codec
, AV_LOG_ERROR
, "Doesn't support aync mode with JNI, please try ndk_codec=1\n");
1770 return AVERROR(ENOSYS
);
1773 static const FFAMediaFormat media_format_jni
= {
1774 .class = &amediaformat_class
,
1776 .create
= mediaformat_jni_new
,
1777 .delete = mediaformat_jni_delete
,
1779 .toString
= mediaformat_jni_toString
,
1781 .getInt32
= mediaformat_jni_getInt32
,
1782 .getInt64
= mediaformat_jni_getInt64
,
1783 .getFloat
= mediaformat_jni_getFloat
,
1784 .getBuffer
= mediaformat_jni_getBuffer
,
1785 .getString
= mediaformat_jni_getString
,
1787 .setInt32
= mediaformat_jni_setInt32
,
1788 .setInt64
= mediaformat_jni_setInt64
,
1789 .setFloat
= mediaformat_jni_setFloat
,
1790 .setString
= mediaformat_jni_setString
,
1791 .setBuffer
= mediaformat_jni_setBuffer
,
1794 static const FFAMediaCodec media_codec_jni
= {
1795 .class = &amediacodec_class
,
1797 .getName
= mediacodec_jni_getName
,
1799 .createCodecByName
= mediacodec_jni_createCodecByName
,
1800 .createDecoderByType
= mediacodec_jni_createDecoderByType
,
1801 .createEncoderByType
= mediacodec_jni_createEncoderByType
,
1802 .delete = mediacodec_jni_delete
,
1804 .configure
= mediacodec_jni_configure
,
1805 .start
= mediacodec_jni_start
,
1806 .stop
= mediacodec_jni_stop
,
1807 .flush
= mediacodec_jni_flush
,
1809 .getInputBuffer
= mediacodec_jni_getInputBuffer
,
1810 .getOutputBuffer
= mediacodec_jni_getOutputBuffer
,
1812 .dequeueInputBuffer
= mediacodec_jni_dequeueInputBuffer
,
1813 .queueInputBuffer
= mediacodec_jni_queueInputBuffer
,
1815 .dequeueOutputBuffer
= mediacodec_jni_dequeueOutputBuffer
,
1816 .getOutputFormat
= mediacodec_jni_getOutputFormat
,
1818 .releaseOutputBuffer
= mediacodec_jni_releaseOutputBuffer
,
1819 .releaseOutputBufferAtTime
= mediacodec_jni_releaseOutputBufferAtTime
,
1821 .infoTryAgainLater
= mediacodec_jni_infoTryAgainLater
,
1822 .infoOutputBuffersChanged
= mediacodec_jni_infoOutputBuffersChanged
,
1823 .infoOutputFormatChanged
= mediacodec_jni_infoOutputFormatChanged
,
1825 .getBufferFlagCodecConfig
= mediacodec_jni_getBufferFlagCodecConfig
,
1826 .getBufferFlagEndOfStream
= mediacodec_jni_getBufferFlagEndOfStream
,
1827 .getBufferFlagKeyFrame
= mediacodec_jni_getBufferFlagKeyFrame
,
1829 .getConfigureFlagEncode
= mediacodec_jni_getConfigureFlagEncode
,
1830 .cleanOutputBuffers
= mediacodec_jni_cleanOutputBuffers
,
1831 .signalEndOfInputStream
= mediacodec_jni_signalEndOfInputStream
,
1832 .setAsyncNotifyCallback
= mediacodec_jni_setAsyncNotifyCallback
,
1835 typedef struct FFAMediaFormatNdk
{
1841 bool (*getRect
)(AMediaFormat
*, const char *name
,
1842 int32_t *left
, int32_t *top
, int32_t *right
, int32_t *bottom
);
1843 void (*setRect
)(AMediaFormat
*, const char *name
,
1844 int32_t left
, int32_t top
, int32_t right
, int32_t bottom
);
1845 } FFAMediaFormatNdk
;
1847 typedef struct FFAMediaCodecNdk
{
1852 ANativeWindow
*window
;
1854 FFAMediaCodecOnAsyncNotifyCallback async_cb
;
1855 void *async_userdata
;
1857 // Available since API level 28.
1858 media_status_t (*getName
)(AMediaCodec
*, char** out_name
);
1859 void (*releaseName
)(AMediaCodec
*, char* name
);
1861 // Available since API level 26.
1862 media_status_t (*setInputSurface
)(AMediaCodec
*, ANativeWindow
*);
1863 media_status_t (*signalEndOfInputStream
)(AMediaCodec
*);
1864 media_status_t (*setAsyncNotifyCallback
)(AMediaCodec
*,
1865 struct AMediaCodecOnAsyncNotifyCallback callback
, void *userdata
);
1868 static const FFAMediaFormat media_format_ndk
;
1869 static const FFAMediaCodec media_codec_ndk
;
1871 static const AVClass amediaformat_ndk_class
= {
1872 .class_name
= "amediaformat_ndk",
1873 .item_name
= av_default_item_name
,
1874 .version
= LIBAVUTIL_VERSION_INT
,
1877 static const AVClass amediacodec_ndk_class
= {
1878 .class_name
= "amediacodec_ndk",
1879 .item_name
= av_default_item_name
,
1880 .version
= LIBAVUTIL_VERSION_INT
,
1883 static int media_status_to_error(media_status_t status
)
1888 case AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE
:
1889 return AVERROR(ENOMEM
);
1890 case AMEDIA_ERROR_MALFORMED
:
1891 return AVERROR_INVALIDDATA
;
1892 case AMEDIA_ERROR_UNSUPPORTED
:
1893 return AVERROR(ENOTSUP
);
1894 case AMEDIA_ERROR_INVALID_PARAMETER
:
1895 return AVERROR(EINVAL
);
1896 case AMEDIA_ERROR_INVALID_OPERATION
:
1897 return AVERROR(EOPNOTSUPP
);
1898 case AMEDIA_ERROR_END_OF_STREAM
:
1900 case AMEDIA_ERROR_IO
:
1901 return AVERROR(EIO
);
1902 case AMEDIA_ERROR_WOULD_BLOCK
:
1903 return AVERROR(EWOULDBLOCK
);
1905 return AVERROR_EXTERNAL
;
1909 static FFAMediaFormat
*mediaformat_ndk_create(AMediaFormat
*impl
)
1911 FFAMediaFormatNdk
*format
= av_mallocz(sizeof(*format
));
1915 format
->api
= media_format_ndk
;
1917 format
->libmedia
= dlopen("libmediandk.so", RTLD_NOW
);
1918 if (!format
->libmedia
)
1921 #define GET_OPTIONAL_SYMBOL(sym) \
1922 format->sym = dlsym(format->libmedia, "AMediaFormat_" #sym);
1924 GET_OPTIONAL_SYMBOL(getRect
)
1925 GET_OPTIONAL_SYMBOL(setRect
)
1927 #undef GET_OPTIONAL_SYMBOL
1930 format
->impl
= impl
;
1932 format
->impl
= AMediaFormat_new();
1937 return (FFAMediaFormat
*)format
;
1940 if (format
->libmedia
)
1941 dlclose(format
->libmedia
);
1946 static FFAMediaFormat
*mediaformat_ndk_new(void)
1948 return mediaformat_ndk_create(NULL
);
1951 static int mediaformat_ndk_delete(FFAMediaFormat
* ctx
)
1953 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
1958 av_assert0(format
->api
.class == &amediaformat_ndk_class
);
1960 if (format
->impl
&& (AMediaFormat_delete(format
->impl
) != AMEDIA_OK
))
1961 ret
= AVERROR_EXTERNAL
;
1962 if (format
->libmedia
)
1963 dlclose(format
->libmedia
);
1969 static char* mediaformat_ndk_toString(FFAMediaFormat
* ctx
)
1971 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
1972 const char *str
= AMediaFormat_toString(format
->impl
);
1973 return av_strdup(str
);
1976 static int mediaformat_ndk_getInt32(FFAMediaFormat
* ctx
, const char *name
, int32_t *out
)
1978 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
1979 return AMediaFormat_getInt32(format
->impl
, name
, out
);
1982 static int mediaformat_ndk_getInt64(FFAMediaFormat
* ctx
, const char *name
, int64_t *out
)
1984 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
1985 return AMediaFormat_getInt64(format
->impl
, name
, out
);
1988 static int mediaformat_ndk_getFloat(FFAMediaFormat
* ctx
, const char *name
, float *out
)
1990 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
1991 return AMediaFormat_getFloat(format
->impl
, name
, out
);
1994 static int mediaformat_ndk_getBuffer(FFAMediaFormat
* ctx
, const char *name
, void** data
, size_t *size
)
1996 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
1997 return AMediaFormat_getBuffer(format
->impl
, name
, data
, size
);
2000 static int mediaformat_ndk_getString(FFAMediaFormat
* ctx
, const char *name
, const char **out
)
2002 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2003 const char *tmp
= NULL
;
2004 int ret
= AMediaFormat_getString(format
->impl
, name
, &tmp
);
2007 *out
= av_strdup(tmp
);
2011 static int mediaformat_ndk_getRect(FFAMediaFormat
*ctx
, const char *name
,
2012 int32_t *left
, int32_t *top
, int32_t *right
, int32_t *bottom
)
2014 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2015 if (!format
->getRect
)
2016 return AVERROR_EXTERNAL
;
2017 return format
->getRect(format
->impl
, name
, left
, top
, right
, bottom
);
2020 static void mediaformat_ndk_setInt32(FFAMediaFormat
* ctx
, const char* name
, int32_t value
)
2022 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2023 AMediaFormat_setInt32(format
->impl
, name
, value
);
2026 static void mediaformat_ndk_setInt64(FFAMediaFormat
* ctx
, const char* name
, int64_t value
)
2028 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2029 AMediaFormat_setInt64(format
->impl
, name
, value
);
2032 static void mediaformat_ndk_setFloat(FFAMediaFormat
* ctx
, const char* name
, float value
)
2034 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2035 AMediaFormat_setFloat(format
->impl
, name
, value
);
2038 static void mediaformat_ndk_setString(FFAMediaFormat
* ctx
, const char* name
, const char* value
)
2040 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2041 AMediaFormat_setString(format
->impl
, name
, value
);
2044 static void mediaformat_ndk_setBuffer(FFAMediaFormat
* ctx
, const char* name
, void* data
, size_t size
)
2046 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2047 AMediaFormat_setBuffer(format
->impl
, name
, data
, size
);
2050 static void mediaformat_ndk_setRect(FFAMediaFormat
*ctx
, const char *name
,
2051 int32_t left
, int32_t top
, int32_t right
, int32_t bottom
)
2053 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)ctx
;
2054 if (!format
->setRect
) {
2055 av_log(ctx
, AV_LOG_WARNING
, "Doesn't support setRect\n");
2058 format
->setRect(format
->impl
, name
, left
, top
, right
, bottom
);
2061 static char *mediacodec_ndk_getName(FFAMediaCodec
*ctx
)
2063 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2067 if (!codec
->getName
|| !codec
->releaseName
) {
2068 av_log(ctx
, AV_LOG_DEBUG
, "getName() unavailable\n");
2072 codec
->getName(codec
->impl
, &name
);
2074 ret
= av_strdup(name
);
2075 codec
->releaseName(codec
->impl
, name
);
2081 static inline FFAMediaCodec
*ndk_codec_create(int method
, const char *arg
) {
2082 FFAMediaCodecNdk
*codec
= av_mallocz(sizeof(*codec
));
2083 const char *lib_name
= "libmediandk.so";
2088 codec
->api
= media_codec_ndk
;
2089 codec
->libmedia
= dlopen(lib_name
, RTLD_NOW
);
2090 if (!codec
->libmedia
)
2093 #define GET_SYMBOL(sym) \
2094 codec->sym = dlsym(codec->libmedia, "AMediaCodec_" #sym); \
2096 av_log(codec, AV_LOG_INFO, #sym "() unavailable from %s\n", lib_name);
2099 GET_SYMBOL(releaseName
)
2101 GET_SYMBOL(setInputSurface
)
2102 GET_SYMBOL(signalEndOfInputStream
)
2103 GET_SYMBOL(setAsyncNotifyCallback
)
2108 case CREATE_CODEC_BY_NAME
:
2109 codec
->impl
= AMediaCodec_createCodecByName(arg
);
2111 case CREATE_DECODER_BY_TYPE
:
2112 codec
->impl
= AMediaCodec_createDecoderByType(arg
);
2114 case CREATE_ENCODER_BY_TYPE
:
2115 codec
->impl
= AMediaCodec_createEncoderByType(arg
);
2123 return (FFAMediaCodec
*)codec
;
2126 if (codec
->libmedia
)
2127 dlclose(codec
->libmedia
);
2132 #define DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(name, method) \
2133 static FFAMediaCodec *mediacodec_ndk_##name(const char *arg) \
2135 return ndk_codec_create(method, arg); \
2138 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME)
2139 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createDecoderByType
, CREATE_DECODER_BY_TYPE
)
2140 DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createEncoderByType
, CREATE_ENCODER_BY_TYPE
)
2142 static int mediacodec_ndk_delete(FFAMediaCodec
* ctx
)
2144 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2150 av_assert0(codec
->api
.class == &amediacodec_ndk_class
);
2152 if (codec
->impl
&& (AMediaCodec_delete(codec
->impl
) != AMEDIA_OK
))
2153 ret
= AVERROR_EXTERNAL
;
2155 ANativeWindow_release(codec
->window
);
2156 if (codec
->libmedia
)
2157 dlclose(codec
->libmedia
);
2163 static int mediacodec_ndk_configure(FFAMediaCodec
* ctx
,
2164 const FFAMediaFormat
* format_ctx
,
2165 FFANativeWindow
* window
,
2169 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2170 FFAMediaFormatNdk
*format
= (FFAMediaFormatNdk
*)format_ctx
;
2171 media_status_t status
;
2172 ANativeWindow
*native_window
= NULL
;
2175 if (window
->surface
) {
2177 JNI_GET_ENV_OR_RETURN(env
, ctx
, -1);
2178 native_window
= ANativeWindow_fromSurface(env
, window
->surface
);
2180 codec
->window
= native_window
;
2181 } else if (window
->native_window
) {
2182 native_window
= window
->native_window
;
2186 if (format_ctx
->class != &amediaformat_ndk_class
) {
2187 av_log(ctx
, AV_LOG_ERROR
, "invalid media format\n");
2188 return AVERROR(EINVAL
);
2191 if (flags
& AMEDIACODEC_CONFIGURE_FLAG_ENCODE
) {
2192 if (native_window
&& !codec
->setInputSurface
) {
2193 av_log(ctx
, AV_LOG_ERROR
, "System doesn't support setInputSurface\n");
2194 return AVERROR_EXTERNAL
;
2197 status
= AMediaCodec_configure(codec
->impl
, format
->impl
, NULL
, NULL
, flags
);
2198 if (status
!= AMEDIA_OK
) {
2199 av_log(codec
, AV_LOG_ERROR
, "Encoder configure failed, %d\n", status
);
2200 return AVERROR_EXTERNAL
;
2206 status
= codec
->setInputSurface(codec
->impl
, native_window
);
2207 if (status
!= AMEDIA_OK
) {
2208 av_log(codec
, AV_LOG_ERROR
, "Encoder set input surface failed, %d\n", status
);
2209 return AVERROR_EXTERNAL
;
2212 status
= AMediaCodec_configure(codec
->impl
, format
->impl
, native_window
, NULL
, flags
);
2213 if (status
!= AMEDIA_OK
) {
2214 av_log(codec
, AV_LOG_ERROR
, "Decoder configure failed, %d\n", status
);
2215 return AVERROR_EXTERNAL
;
2222 #define MEDIACODEC_NDK_WRAPPER(method) \
2223 static int mediacodec_ndk_ ## method(FFAMediaCodec* ctx) \
2225 FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; \
2226 media_status_t status = AMediaCodec_ ## method (codec->impl); \
2228 if (status != AMEDIA_OK) { \
2229 av_log(codec, AV_LOG_ERROR, #method " failed, %d\n", status); \
2230 return AVERROR_EXTERNAL; \
2236 MEDIACODEC_NDK_WRAPPER(start)
2237 MEDIACODEC_NDK_WRAPPER(stop
)
2238 MEDIACODEC_NDK_WRAPPER(flush
)
2240 static uint8_t* mediacodec_ndk_getInputBuffer(FFAMediaCodec
* ctx
, size_t idx
, size_t *out_size
)
2242 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2243 return AMediaCodec_getInputBuffer(codec
->impl
, idx
, out_size
);
2246 static uint8_t* mediacodec_ndk_getOutputBuffer(FFAMediaCodec
* ctx
, size_t idx
, size_t *out_size
)
2248 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2249 return AMediaCodec_getOutputBuffer(codec
->impl
, idx
, out_size
);
2252 static ssize_t
mediacodec_ndk_dequeueInputBuffer(FFAMediaCodec
* ctx
, int64_t timeoutUs
)
2254 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2255 return AMediaCodec_dequeueInputBuffer(codec
->impl
, timeoutUs
);
2258 static int mediacodec_ndk_queueInputBuffer(FFAMediaCodec
*ctx
, size_t idx
,
2259 off_t offset
, size_t size
,
2260 uint64_t time
, uint32_t flags
)
2262 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2263 return AMediaCodec_queueInputBuffer(codec
->impl
, idx
, offset
, size
, time
, flags
);
2266 static ssize_t
mediacodec_ndk_dequeueOutputBuffer(FFAMediaCodec
* ctx
, FFAMediaCodecBufferInfo
*info
, int64_t timeoutUs
)
2268 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2269 AMediaCodecBufferInfo buf_info
= {0};
2272 ret
= AMediaCodec_dequeueOutputBuffer(codec
->impl
, &buf_info
, timeoutUs
);
2273 info
->offset
= buf_info
.offset
;
2274 info
->size
= buf_info
.size
;
2275 info
->presentationTimeUs
= buf_info
.presentationTimeUs
;
2276 info
->flags
= buf_info
.flags
;
2281 static FFAMediaFormat
* mediacodec_ndk_getOutputFormat(FFAMediaCodec
* ctx
)
2283 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2284 AMediaFormat
*format
= AMediaCodec_getOutputFormat(codec
->impl
);
2288 return mediaformat_ndk_create(format
);
2291 static int mediacodec_ndk_releaseOutputBuffer(FFAMediaCodec
* ctx
, size_t idx
, int render
)
2293 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2294 media_status_t status
;
2296 status
= AMediaCodec_releaseOutputBuffer(codec
->impl
, idx
, render
);
2297 if (status
!= AMEDIA_OK
) {
2298 av_log(codec
, AV_LOG_ERROR
, "release output buffer failed, %d\n", status
);
2299 return AVERROR_EXTERNAL
;
2305 static int mediacodec_ndk_releaseOutputBufferAtTime(FFAMediaCodec
*ctx
, size_t idx
, int64_t timestampNs
)
2307 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2308 media_status_t status
;
2310 status
= AMediaCodec_releaseOutputBufferAtTime(codec
->impl
, idx
, timestampNs
);
2311 if (status
!= AMEDIA_OK
) {
2312 av_log(codec
, AV_LOG_ERROR
, "releaseOutputBufferAtTime failed, %d\n", status
);
2313 return AVERROR_EXTERNAL
;
2319 static int mediacodec_ndk_infoTryAgainLater(FFAMediaCodec
*ctx
, ssize_t idx
)
2321 return idx
== AMEDIACODEC_INFO_TRY_AGAIN_LATER
;
2324 static int mediacodec_ndk_infoOutputBuffersChanged(FFAMediaCodec
*ctx
, ssize_t idx
)
2326 return idx
== AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED
;
2329 static int mediacodec_ndk_infoOutputFormatChanged(FFAMediaCodec
*ctx
, ssize_t idx
)
2331 return idx
== AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED
;
2334 static int mediacodec_ndk_getBufferFlagCodecConfig(FFAMediaCodec
*ctx
)
2336 return AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG
;
2339 static int mediacodec_ndk_getBufferFlagEndOfStream(FFAMediaCodec
*ctx
)
2341 return AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM
;
2344 static int mediacodec_ndk_getBufferFlagKeyFrame(FFAMediaCodec
*ctx
)
2349 static int mediacodec_ndk_getConfigureFlagEncode(FFAMediaCodec
*ctx
)
2351 return AMEDIACODEC_CONFIGURE_FLAG_ENCODE
;
2354 static int mediacodec_ndk_cleanOutputBuffers(FFAMediaCodec
*ctx
)
2359 static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec
*ctx
)
2361 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2362 media_status_t status
;
2364 if (!codec
->signalEndOfInputStream
) {
2365 av_log(codec
, AV_LOG_ERROR
, "signalEndOfInputStream unavailable\n");
2366 return AVERROR_EXTERNAL
;
2369 status
= codec
->signalEndOfInputStream(codec
->impl
);
2370 if (status
!= AMEDIA_OK
) {
2371 av_log(codec
, AV_LOG_ERROR
, "signalEndOfInputStream failed, %d\n", status
);
2372 return AVERROR_EXTERNAL
;
2374 av_log(codec
, AV_LOG_DEBUG
, "signalEndOfInputStream success\n");
2379 static void mediacodec_ndk_onInputAvailable(AMediaCodec
*impl
, void *userdata
,
2382 FFAMediaCodecNdk
*codec
= userdata
;
2383 codec
->async_cb
.onAsyncInputAvailable((FFAMediaCodec
*) codec
,
2384 codec
->async_userdata
, index
);
2387 static void mediacodec_ndk_onOutputAvailable(AMediaCodec
*impl
,
2390 AMediaCodecBufferInfo
*buffer_info
)
2392 FFAMediaCodecNdk
*codec
= userdata
;
2393 FFAMediaCodecBufferInfo info
= {
2394 .offset
= buffer_info
->offset
,
2395 .size
= buffer_info
->size
,
2396 .presentationTimeUs
= buffer_info
->presentationTimeUs
,
2397 .flags
= buffer_info
->flags
,
2400 codec
->async_cb
.onAsyncOutputAvailable(&codec
->api
, codec
->async_userdata
,
2404 static void mediacodec_ndk_onFormatChanged(AMediaCodec
*impl
, void *userdata
,
2405 AMediaFormat
*format
)
2407 FFAMediaCodecNdk
*codec
= userdata
;
2408 FFAMediaFormat
*media_format
= mediaformat_ndk_create(format
);
2412 codec
->async_cb
.onAsyncFormatChanged(&codec
->api
, codec
->async_userdata
,
2414 ff_AMediaFormat_delete(media_format
);
2417 static void mediacodec_ndk_onError(AMediaCodec
*impl
, void *userdata
,
2418 media_status_t status
,
2422 FFAMediaCodecNdk
*codec
= userdata
;
2423 int error
= media_status_to_error(status
);
2425 codec
->async_cb
.onAsyncError(&codec
->api
, codec
->async_userdata
, error
,
2429 static int mediacodec_ndk_setAsyncNotifyCallback(FFAMediaCodec
*ctx
,
2430 const FFAMediaCodecOnAsyncNotifyCallback
*callback
,
2433 FFAMediaCodecNdk
*codec
= (FFAMediaCodecNdk
*)ctx
;
2434 struct AMediaCodecOnAsyncNotifyCallback cb
= {
2435 .onAsyncInputAvailable
= mediacodec_ndk_onInputAvailable
,
2436 .onAsyncOutputAvailable
= mediacodec_ndk_onOutputAvailable
,
2437 .onAsyncFormatChanged
= mediacodec_ndk_onFormatChanged
,
2438 .onAsyncError
= mediacodec_ndk_onError
,
2440 media_status_t status
;
2442 if (!codec
->setAsyncNotifyCallback
) {
2443 av_log(codec
, AV_LOG_ERROR
, "setAsyncNotifyCallback unavailable\n");
2444 return AVERROR(ENOSYS
);
2448 !callback
->onAsyncInputAvailable
||
2449 !callback
->onAsyncOutputAvailable
||
2450 !callback
->onAsyncFormatChanged
||
2451 !callback
->onAsyncError
)
2452 return AVERROR(EINVAL
);
2454 codec
->async_cb
= *callback
;
2455 codec
->async_userdata
= userdata
;
2457 status
= codec
->setAsyncNotifyCallback(codec
->impl
, cb
, codec
);
2458 if (status
!= AMEDIA_OK
) {
2459 av_log(codec
, AV_LOG_ERROR
, "setAsyncNotifyCallback failed, %d\n",
2461 return AVERROR_EXTERNAL
;
2467 static const FFAMediaFormat media_format_ndk
= {
2468 .class = &amediaformat_ndk_class
,
2470 .create
= mediaformat_ndk_new
,
2471 .delete = mediaformat_ndk_delete
,
2473 .toString
= mediaformat_ndk_toString
,
2475 .getInt32
= mediaformat_ndk_getInt32
,
2476 .getInt64
= mediaformat_ndk_getInt64
,
2477 .getFloat
= mediaformat_ndk_getFloat
,
2478 .getBuffer
= mediaformat_ndk_getBuffer
,
2479 .getString
= mediaformat_ndk_getString
,
2480 .getRect
= mediaformat_ndk_getRect
,
2482 .setInt32
= mediaformat_ndk_setInt32
,
2483 .setInt64
= mediaformat_ndk_setInt64
,
2484 .setFloat
= mediaformat_ndk_setFloat
,
2485 .setString
= mediaformat_ndk_setString
,
2486 .setBuffer
= mediaformat_ndk_setBuffer
,
2487 .setRect
= mediaformat_ndk_setRect
,
2490 static const FFAMediaCodec media_codec_ndk
= {
2491 .class = &amediacodec_ndk_class
,
2493 .getName
= mediacodec_ndk_getName
,
2495 .createCodecByName
= mediacodec_ndk_createCodecByName
,
2496 .createDecoderByType
= mediacodec_ndk_createDecoderByType
,
2497 .createEncoderByType
= mediacodec_ndk_createEncoderByType
,
2498 .delete = mediacodec_ndk_delete
,
2500 .configure
= mediacodec_ndk_configure
,
2501 .start
= mediacodec_ndk_start
,
2502 .stop
= mediacodec_ndk_stop
,
2503 .flush
= mediacodec_ndk_flush
,
2505 .getInputBuffer
= mediacodec_ndk_getInputBuffer
,
2506 .getOutputBuffer
= mediacodec_ndk_getOutputBuffer
,
2508 .dequeueInputBuffer
= mediacodec_ndk_dequeueInputBuffer
,
2509 .queueInputBuffer
= mediacodec_ndk_queueInputBuffer
,
2511 .dequeueOutputBuffer
= mediacodec_ndk_dequeueOutputBuffer
,
2512 .getOutputFormat
= mediacodec_ndk_getOutputFormat
,
2514 .releaseOutputBuffer
= mediacodec_ndk_releaseOutputBuffer
,
2515 .releaseOutputBufferAtTime
= mediacodec_ndk_releaseOutputBufferAtTime
,
2517 .infoTryAgainLater
= mediacodec_ndk_infoTryAgainLater
,
2518 .infoOutputBuffersChanged
= mediacodec_ndk_infoOutputBuffersChanged
,
2519 .infoOutputFormatChanged
= mediacodec_ndk_infoOutputFormatChanged
,
2521 .getBufferFlagCodecConfig
= mediacodec_ndk_getBufferFlagCodecConfig
,
2522 .getBufferFlagEndOfStream
= mediacodec_ndk_getBufferFlagEndOfStream
,
2523 .getBufferFlagKeyFrame
= mediacodec_ndk_getBufferFlagKeyFrame
,
2525 .getConfigureFlagEncode
= mediacodec_ndk_getConfigureFlagEncode
,
2526 .cleanOutputBuffers
= mediacodec_ndk_cleanOutputBuffers
,
2527 .signalEndOfInputStream
= mediacodec_ndk_signalEndOfInputStream
,
2528 .setAsyncNotifyCallback
= mediacodec_ndk_setAsyncNotifyCallback
,
2531 FFAMediaFormat
*ff_AMediaFormat_new(int ndk
)
2534 return media_format_ndk
.create();
2535 return media_format_jni
.create();
2538 FFAMediaCodec
* ff_AMediaCodec_createCodecByName(const char *name
, int ndk
)
2541 return media_codec_ndk
.createCodecByName(name
);
2542 return media_codec_jni
.createCodecByName(name
);
2545 FFAMediaCodec
* ff_AMediaCodec_createDecoderByType(const char *mime_type
, int ndk
)
2548 return media_codec_ndk
.createDecoderByType(mime_type
);
2549 return media_codec_jni
.createDecoderByType(mime_type
);
2552 FFAMediaCodec
* ff_AMediaCodec_createEncoderByType(const char *mime_type
, int ndk
)
2555 return media_codec_ndk
.createEncoderByType(mime_type
);
2556 return media_codec_jni
.createEncoderByType(mime_type
);
2559 int ff_Build_SDK_INT(AVCodecContext
*avctx
)
2563 #if __ANDROID_API__ >= 24
2564 // android_get_device_api_level() is a static inline before API level 29.
2565 // dlsym() might doesn't work.
2567 // We can implement android_get_device_api_level() by
2568 // __system_property_get(), but __system_property_get() has created a lot of
2569 // troubles and is deprecated. So avoid using __system_property_get() for
2572 // Hopy we can remove the conditional compilation finally by bumping the
2573 // required API level.
2575 ret
= android_get_device_api_level();
2578 jclass versionClass
;
2579 jfieldID sdkIntFieldID
;
2580 JNI_GET_ENV_OR_RETURN(env
, avctx
, -1);
2582 versionClass
= (*env
)->FindClass(env
, "android/os/Build$VERSION");
2583 sdkIntFieldID
= (*env
)->GetStaticFieldID(env
, versionClass
, "SDK_INT", "I");
2584 ret
= (*env
)->GetStaticIntField(env
, versionClass
, sdkIntFieldID
);
2585 (*env
)->DeleteLocalRef(env
, versionClass
);
2587 av_log(avctx
, AV_LOG_DEBUG
, "device api level %d\n", ret
);
2593 enum FFAMediaFormatColorRange mf_range
;
2594 enum AVColorRange range
;
2595 } color_range_map
[] = {
2596 { COLOR_RANGE_FULL
, AVCOL_RANGE_JPEG
},
2597 { COLOR_RANGE_LIMITED
, AVCOL_RANGE_MPEG
},
2601 enum FFAMediaFormatColorStandard mf_standard
;
2602 enum AVColorSpace space
;
2603 } color_space_map
[] = {
2604 { COLOR_STANDARD_BT709
, AVCOL_SPC_BT709
},
2605 { COLOR_STANDARD_BT601_PAL
, AVCOL_SPC_BT470BG
},
2606 { COLOR_STANDARD_BT601_NTSC
, AVCOL_SPC_SMPTE170M
},
2607 { COLOR_STANDARD_BT2020
, AVCOL_SPC_BT2020_NCL
},
2611 enum FFAMediaFormatColorStandard mf_standard
;
2612 enum AVColorPrimaries primaries
;
2613 } color_primaries_map
[] = {
2614 { COLOR_STANDARD_BT709
, AVCOL_PRI_BT709
},
2615 { COLOR_STANDARD_BT601_PAL
, AVCOL_PRI_BT470BG
},
2616 { COLOR_STANDARD_BT601_NTSC
, AVCOL_PRI_SMPTE170M
},
2617 { COLOR_STANDARD_BT2020
, AVCOL_PRI_BT2020
},
2621 enum FFAMediaFormatColorTransfer mf_transfer
;
2622 enum AVColorTransferCharacteristic transfer
;
2623 } color_transfer_map
[] = {
2624 { COLOR_TRANSFER_LINEAR
, AVCOL_TRC_LINEAR
},
2625 { COLOR_TRANSFER_SDR_VIDEO
, AVCOL_TRC_SMPTE170M
},
2626 { COLOR_TRANSFER_ST2084
, AVCOL_TRC_SMPTEST2084
},
2627 { COLOR_TRANSFER_HLG
, AVCOL_TRC_ARIB_STD_B67
},
2630 enum AVColorRange
ff_AMediaFormatColorRange_to_AVColorRange(int color_range
)
2632 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_range_map
); i
++)
2633 if (color_range_map
[i
].mf_range
== color_range
)
2634 return color_range_map
[i
].range
;
2636 return AVCOL_RANGE_UNSPECIFIED
;
2639 int ff_AMediaFormatColorRange_from_AVColorRange(enum AVColorRange color_range
)
2641 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_range_map
); i
++)
2642 if (color_range_map
[i
].range
== color_range
)
2643 return color_range_map
[i
].mf_range
;
2644 return COLOR_RANGE_UNSPECIFIED
;
2647 enum AVColorSpace
ff_AMediaFormatColorStandard_to_AVColorSpace(int color_standard
)
2649 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_space_map
); i
++)
2650 if (color_space_map
[i
].mf_standard
== color_standard
)
2651 return color_space_map
[i
].space
;
2653 return AVCOL_SPC_UNSPECIFIED
;
2656 int ff_AMediaFormatColorStandard_from_AVColorSpace(enum AVColorSpace color_space
)
2658 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_space_map
); i
++)
2659 if (color_space_map
[i
].space
== color_space
)
2660 return color_space_map
[i
].mf_standard
;
2662 return COLOR_STANDARD_UNSPECIFIED
;
2665 enum AVColorPrimaries
ff_AMediaFormatColorStandard_to_AVColorPrimaries(int color_standard
)
2667 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_primaries_map
); i
++)
2668 if (color_primaries_map
[i
].mf_standard
== color_standard
)
2669 return color_primaries_map
[i
].primaries
;
2671 return AVCOL_PRI_UNSPECIFIED
;
2674 enum AVColorTransferCharacteristic
2675 ff_AMediaFormatColorTransfer_to_AVColorTransfer(int color_transfer
)
2677 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_transfer_map
); i
++)
2678 if (color_transfer_map
[i
].mf_transfer
== color_transfer
)
2679 return color_transfer_map
[i
].transfer
;
2681 return AVCOL_TRC_UNSPECIFIED
;
2684 int ff_AMediaFormatColorTransfer_from_AVColorTransfer(
2685 enum AVColorTransferCharacteristic color_transfer
)
2687 for (int i
= 0; i
< FF_ARRAY_ELEMS(color_transfer_map
); i
++)
2688 if (color_transfer_map
[i
].transfer
== color_transfer
)
2689 return color_transfer_map
[i
].mf_transfer
;
2691 return COLOR_TRANSFER_UNSPECIFIED
;