tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mediacodec_wrapper.c (89030B)


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