tor-browser

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

mediacodecenc.c (52727B)


      1 /*
      2 * Android MediaCodec encoders
      3 *
      4 * Copyright (c) 2022 Zhao Zhili <zhilizhao@tencent.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 "config_components.h"
     24 
     25 #include "libavutil/avassert.h"
     26 #include "libavutil/fifo.h"
     27 #include "libavutil/avstring.h"
     28 #include "libavutil/hwcontext_mediacodec.h"
     29 #include "libavutil/imgutils.h"
     30 #include "libavutil/mem.h"
     31 #include "libavutil/opt.h"
     32 #include "libavutil/thread.h"
     33 
     34 #include "avcodec.h"
     35 #include "bsf.h"
     36 #include "codec_internal.h"
     37 #include "encode.h"
     38 #include "hwconfig.h"
     39 #include "fffjni.h"
     40 #include "mediacodec.h"
     41 #include "mediacodec_wrapper.h"
     42 #include "mediacodecdec_common.h"
     43 #include "profiles.h"
     44 
     45 #define INPUT_DEQUEUE_TIMEOUT_US 8000
     46 #define OUTPUT_DEQUEUE_TIMEOUT_US 8000
     47 
     48 enum BitrateMode {
     49    /* Constant quality mode */
     50    BITRATE_MODE_CQ = 0,
     51    /* Variable bitrate mode */
     52    BITRATE_MODE_VBR = 1,
     53    /* Constant bitrate mode */
     54    BITRATE_MODE_CBR = 2,
     55    /* Constant bitrate mode with frame drops */
     56    BITRATE_MODE_CBR_FD = 3,
     57 };
     58 
     59 typedef struct MediaCodecAsyncOutput {
     60    int32_t index;
     61    FFAMediaCodecBufferInfo buf_info;
     62 } MediaCodecAsyncOutput;
     63 
     64 typedef struct MediaCodecEncContext {
     65    AVClass *avclass;
     66    FFAMediaCodec *codec;
     67    int use_ndk_codec;
     68    const char *name;
     69    FFANativeWindow *window;
     70 
     71    int fps;
     72    int width;
     73    int height;
     74 
     75    uint8_t *extradata;
     76    int extradata_size;
     77    int eof_sent;
     78 
     79    AVFrame *frame;
     80    AVBSFContext *bsf;
     81 
     82    int bitrate_mode;
     83    int level;
     84    int pts_as_dts;
     85    int extract_extradata;
     86    // Ref. MediaFormat KEY_OPERATING_RATE
     87    int operating_rate;
     88    int async_mode;
     89 
     90    AVMutex input_mutex;
     91    AVCond input_cond;
     92    AVFifo *input_index;
     93 
     94    AVMutex output_mutex;
     95    AVCond output_cond;
     96    int encode_status;
     97    AVFifo *async_output;
     98 } MediaCodecEncContext;
     99 
    100 enum {
    101    COLOR_FormatYUV420Planar                              = 0x13,
    102    COLOR_FormatYUV420SemiPlanar                          = 0x15,
    103    COLOR_FormatSurface                                   = 0x7F000789,
    104 };
    105 
    106 static const struct {
    107    int color_format;
    108    enum AVPixelFormat pix_fmt;
    109 } color_formats[] = {
    110    { COLOR_FormatYUV420Planar,         AV_PIX_FMT_YUV420P },
    111    { COLOR_FormatYUV420SemiPlanar,     AV_PIX_FMT_NV12    },
    112    { COLOR_FormatSurface,              AV_PIX_FMT_MEDIACODEC },
    113 };
    114 
    115 static const enum AVPixelFormat avc_pix_fmts[] = {
    116    AV_PIX_FMT_MEDIACODEC,
    117    AV_PIX_FMT_YUV420P,
    118    AV_PIX_FMT_NV12,
    119    AV_PIX_FMT_NONE
    120 };
    121 
    122 static void mediacodec_dump_format(AVCodecContext *avctx,
    123        FFAMediaFormat *out_format)
    124 {
    125    MediaCodecEncContext *s = avctx->priv_data;
    126    const char *name = s->name;
    127    char *str = ff_AMediaFormat_toString(out_format);
    128 
    129    av_log(avctx, AV_LOG_DEBUG, "MediaCodec encoder %s output format %s\n",
    130           name ? name : "unknown", str);
    131    av_free(str);
    132 }
    133 
    134 static void mediacodec_output_format(AVCodecContext *avctx)
    135 {
    136    MediaCodecEncContext *s = avctx->priv_data;
    137    FFAMediaFormat *out_format = ff_AMediaCodec_getOutputFormat(s->codec);
    138 
    139    if (!s->name)
    140        s->name = ff_AMediaCodec_getName(s->codec);
    141    mediacodec_dump_format(avctx, out_format);
    142    ff_AMediaFormat_delete(out_format);
    143 }
    144 
    145 static int extract_extradata_support(AVCodecContext *avctx)
    146 {
    147    const AVBitStreamFilter *bsf = av_bsf_get_by_name("extract_extradata");
    148 
    149    if (!bsf) {
    150        av_log(avctx, AV_LOG_WARNING, "extract_extradata bsf not found\n");
    151        return 0;
    152    }
    153 
    154    for (int i = 0; bsf->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
    155        if (bsf->codec_ids[i] == avctx->codec_id)
    156            return 1;
    157    }
    158 
    159    return 0;
    160 }
    161 
    162 static int mediacodec_init_bsf(AVCodecContext *avctx)
    163 {
    164    MediaCodecEncContext *s = avctx->priv_data;
    165    char str[128] = {0};
    166    int ret;
    167    int crop_right = s->width - avctx->width;
    168    int crop_bottom = s->height - avctx->height;
    169 
    170    /* Nothing can be done for this format now */
    171    if (avctx->pix_fmt == AV_PIX_FMT_MEDIACODEC)
    172        return 0;
    173 
    174    s->extract_extradata = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) &&
    175                           extract_extradata_support(avctx);
    176    if (!crop_right && !crop_bottom && !s->extract_extradata)
    177        return 0;
    178 
    179    ret = 0;
    180    if (crop_right || crop_bottom) {
    181        if (avctx->codec_id == AV_CODEC_ID_H264)
    182            ret = snprintf(str, sizeof(str), "h264_metadata=crop_right=%d:crop_bottom=%d",
    183                           crop_right, crop_bottom);
    184        else if (avctx->codec_id == AV_CODEC_ID_HEVC)
    185            /* Encoder can use CTU size larger than 16x16, so the real crop
    186             * margin can be larger than crop_right/crop_bottom. Let bsf figure
    187             * out the real crop margin.
    188             */
    189            ret = snprintf(str, sizeof(str), "hevc_metadata=width=%d:height=%d",
    190                           avctx->width, avctx->height);
    191        if (ret >= sizeof(str))
    192            return AVERROR_BUFFER_TOO_SMALL;
    193    }
    194 
    195    if (s->extract_extradata) {
    196        ret = av_strlcatf(str, sizeof(str), "%sextract_extradata", ret ? "," : "");
    197        if (ret >= sizeof(str))
    198            return AVERROR_BUFFER_TOO_SMALL;
    199    }
    200 
    201    ret = av_bsf_list_parse_str(str, &s->bsf);
    202    if (ret < 0)
    203        return ret;
    204 
    205    ret = avcodec_parameters_from_context(s->bsf->par_in, avctx);
    206    if (ret < 0)
    207        return ret;
    208    s->bsf->time_base_in = avctx->time_base;
    209    ret = av_bsf_init(s->bsf);
    210 
    211    return ret;
    212 }
    213 
    214 static void copy_frame_to_buffer(AVCodecContext *avctx, const AVFrame *frame,
    215                                 uint8_t *dst, size_t size)
    216 {
    217    MediaCodecEncContext *s = avctx->priv_data;
    218    uint8_t *dst_data[4] = {};
    219    int dst_linesize[4] = {};
    220 
    221    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
    222        dst_data[0] = dst;
    223        dst_data[1] = dst + s->width * s->height;
    224        dst_data[2] = dst_data[1] + s->width * s->height / 4;
    225 
    226        dst_linesize[0] = s->width;
    227        dst_linesize[1] = dst_linesize[2] = s->width / 2;
    228    } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
    229        dst_data[0] = dst;
    230        dst_data[1] = dst + s->width * s->height;
    231 
    232        dst_linesize[0] = s->width;
    233        dst_linesize[1] = s->width;
    234    } else {
    235        av_assert0(0);
    236    }
    237 
    238    av_image_copy2(dst_data, dst_linesize, frame->data, frame->linesize,
    239                   avctx->pix_fmt, avctx->width, avctx->height);
    240 }
    241 
    242 
    243 static void on_error(FFAMediaCodec *codec, void *userdata, int error,
    244                     const char *detail)
    245 {
    246    AVCodecContext *avctx = userdata;
    247    MediaCodecEncContext *s = avctx->priv_data;
    248 
    249    if (error == AVERROR(EAGAIN))
    250        return;
    251 
    252    av_log(avctx, AV_LOG_ERROR, "On error, %s, %s\n", av_err2str(error), detail);
    253 
    254    ff_mutex_lock(&s->input_mutex);
    255    ff_mutex_lock(&s->output_mutex);
    256    s->encode_status = error;
    257    ff_mutex_unlock(&s->output_mutex);
    258    ff_mutex_unlock(&s->input_mutex);
    259 
    260    ff_cond_signal(&s->output_cond);
    261    ff_cond_signal(&s->input_cond);
    262 }
    263 
    264 static void on_input_available(FFAMediaCodec *codec, void *userdata,
    265                               int32_t index)
    266 {
    267    AVCodecContext *avctx = userdata;
    268    MediaCodecEncContext *s = avctx->priv_data;
    269    int ret;
    270 
    271    ff_mutex_lock(&s->input_mutex);
    272    ret = av_fifo_write(s->input_index, &index, 1);
    273    if (ret >= 0)
    274        ff_cond_signal(&s->input_cond);
    275    ff_mutex_unlock(&s->input_mutex);
    276 
    277    if (ret < 0)
    278        on_error(codec, userdata, ret, "av_fifo_write failed");
    279 }
    280 
    281 static void on_output_available(FFAMediaCodec *codec, void *userdata,
    282                               int32_t index,
    283                               FFAMediaCodecBufferInfo *out_info)
    284 {
    285    AVCodecContext *avctx = userdata;
    286    MediaCodecEncContext *s = avctx->priv_data;
    287    MediaCodecAsyncOutput output = {
    288        .index = index,
    289        .buf_info = *out_info,
    290    };
    291    int ret;
    292 
    293    ff_mutex_lock(&s->output_mutex);
    294    ret = av_fifo_write(s->async_output, &output, 1);
    295    if (ret >= 0)
    296        ff_cond_signal(&s->output_cond);
    297    ff_mutex_unlock(&s->output_mutex);
    298 
    299    if (ret < 0)
    300        on_error(codec, userdata, ret, "av_fifo_write failed");
    301 }
    302 
    303 static void on_format_changed(FFAMediaCodec *codec, void *userdata,
    304                              FFAMediaFormat *format)
    305 {
    306    mediacodec_dump_format(userdata, format);
    307 }
    308 
    309 static int mediacodec_init_async_state(AVCodecContext *avctx)
    310 {
    311    MediaCodecEncContext *s = avctx->priv_data;
    312    size_t fifo_size = 16;
    313 
    314    if (!s->async_mode)
    315        return 0;
    316 
    317    ff_mutex_init(&s->input_mutex, NULL);
    318    ff_cond_init(&s->input_cond, NULL);
    319 
    320    ff_mutex_init(&s->output_mutex, NULL);
    321    ff_cond_init(&s->output_cond, NULL);
    322 
    323    s->input_index = av_fifo_alloc2(fifo_size, sizeof(int32_t), AV_FIFO_FLAG_AUTO_GROW);
    324    s->async_output = av_fifo_alloc2(fifo_size, sizeof(MediaCodecAsyncOutput),
    325                                     AV_FIFO_FLAG_AUTO_GROW);
    326 
    327    if (!s->input_index || !s->async_output)
    328        return AVERROR(ENOMEM);
    329 
    330    return 0;
    331 }
    332 
    333 static void mediacodec_uninit_async_state(AVCodecContext *avctx)
    334 {
    335    MediaCodecEncContext *s = avctx->priv_data;
    336 
    337    if (!s->async_mode)
    338        return;
    339 
    340    ff_mutex_destroy(&s->input_mutex);
    341    ff_cond_destroy(&s->input_cond);
    342 
    343    ff_mutex_destroy(&s->output_mutex);
    344    ff_cond_destroy(&s->output_cond);
    345 
    346    av_fifo_freep2(&s->input_index);
    347    av_fifo_freep2(&s->async_output);
    348 
    349    s->async_mode = 0;
    350 }
    351 
    352 static int mediacodec_generate_extradata(AVCodecContext *avctx);
    353 
    354 static av_cold int mediacodec_init(AVCodecContext *avctx)
    355 {
    356    const char *codec_mime = NULL;
    357    MediaCodecEncContext *s = avctx->priv_data;
    358    FFAMediaFormat *format = NULL;
    359    int ret;
    360    int gop;
    361 
    362    // Init async state first, so we can do cleanup safely on error path.
    363    ret = mediacodec_init_async_state(avctx);
    364    if (ret < 0)
    365        return ret;
    366 
    367    if (s->use_ndk_codec < 0)
    368        s->use_ndk_codec = !av_jni_get_java_vm(avctx);
    369 
    370    switch (avctx->codec_id) {
    371    case AV_CODEC_ID_H264:
    372        codec_mime = "video/avc";
    373        break;
    374    case AV_CODEC_ID_HEVC:
    375        codec_mime = "video/hevc";
    376        break;
    377    case AV_CODEC_ID_VP8:
    378        codec_mime = "video/x-vnd.on2.vp8";
    379        break;
    380    case AV_CODEC_ID_VP9:
    381        codec_mime = "video/x-vnd.on2.vp9";
    382        break;
    383    case AV_CODEC_ID_MPEG4:
    384        codec_mime = "video/mp4v-es";
    385        break;
    386    case AV_CODEC_ID_AV1:
    387        codec_mime = "video/av01";
    388        break;
    389    default:
    390        av_assert0(0);
    391    }
    392 
    393    if (s->name)
    394        s->codec = ff_AMediaCodec_createCodecByName(s->name, s->use_ndk_codec);
    395    else
    396        s->codec = ff_AMediaCodec_createEncoderByType(codec_mime, s->use_ndk_codec);
    397    if (!s->codec) {
    398        av_log(avctx, AV_LOG_ERROR, "Failed to create encoder for type %s\n",
    399               codec_mime);
    400        return AVERROR_EXTERNAL;
    401    }
    402 
    403    format = ff_AMediaFormat_new(s->use_ndk_codec);
    404    if (!format) {
    405        av_log(avctx, AV_LOG_ERROR, "Failed to create media format\n");
    406        return AVERROR_EXTERNAL;
    407    }
    408 
    409    ff_AMediaFormat_setString(format, "mime", codec_mime);
    410    // Workaround the alignment requirement of mediacodec. We can't do it
    411    // silently for AV_PIX_FMT_MEDIACODEC.
    412    if (avctx->pix_fmt != AV_PIX_FMT_MEDIACODEC &&
    413        (avctx->codec_id == AV_CODEC_ID_H264 ||
    414         avctx->codec_id == AV_CODEC_ID_HEVC)) {
    415        s->width = FFALIGN(avctx->width, 16);
    416        s->height = FFALIGN(avctx->height, 16);
    417    } else {
    418        s->width = avctx->width;
    419        s->height = avctx->height;
    420        if (s->width % 16 || s->height % 16)
    421            av_log(avctx, AV_LOG_WARNING,
    422                    "Video size %dx%d isn't align to 16, it may have device compatibility issue\n",
    423                    s->width, s->height);
    424    }
    425    ff_AMediaFormat_setInt32(format, "width", s->width);
    426    ff_AMediaFormat_setInt32(format, "height", s->height);
    427 
    428    if (avctx->pix_fmt == AV_PIX_FMT_MEDIACODEC) {
    429        AVMediaCodecContext *user_ctx = avctx->hwaccel_context;
    430        if (avctx->hw_device_ctx) {
    431            AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
    432            AVMediaCodecDeviceContext *dev_ctx;
    433 
    434            if (device_ctx->type != AV_HWDEVICE_TYPE_MEDIACODEC || !device_ctx->hwctx) {
    435                ret = AVERROR(EINVAL);
    436                goto bailout;
    437            }
    438            dev_ctx = device_ctx->hwctx;
    439            s->window = ff_mediacodec_surface_ref(dev_ctx->surface, dev_ctx->native_window, avctx);
    440        }
    441 
    442        if (!s->window && user_ctx && user_ctx->surface)
    443            s->window = ff_mediacodec_surface_ref(user_ctx->surface, NULL, avctx);
    444 
    445        if (!s->window) {
    446            ret = AVERROR(EINVAL);
    447            av_log(avctx, AV_LOG_ERROR, "Missing hw_device_ctx or hwaccel_context for AV_PIX_FMT_MEDIACODEC\n");
    448            goto bailout;
    449        }
    450        /* Although there is a method ANativeWindow_toSurface() introduced in
    451         * API level 26, it's easier and safe to always require a Surface for
    452         * Java MediaCodec.
    453         */
    454        if (!s->use_ndk_codec && !s->window->surface) {
    455            ret = AVERROR(EINVAL);
    456            av_log(avctx, AV_LOG_ERROR, "Missing jobject Surface for AV_PIX_FMT_MEDIACODEC. "
    457                    "Please note that Java MediaCodec doesn't work with ANativeWindow.\n");
    458            goto bailout;
    459        }
    460    }
    461 
    462    for (int i = 0; i < FF_ARRAY_ELEMS(color_formats); i++) {
    463        if (avctx->pix_fmt == color_formats[i].pix_fmt) {
    464            ff_AMediaFormat_setInt32(format, "color-format",
    465                                     color_formats[i].color_format);
    466            break;
    467        }
    468    }
    469 
    470    ret = ff_AMediaFormatColorRange_from_AVColorRange(avctx->color_range);
    471    if (ret != COLOR_RANGE_UNSPECIFIED)
    472        ff_AMediaFormat_setInt32(format, "color-range", ret);
    473    ret = ff_AMediaFormatColorStandard_from_AVColorSpace(avctx->colorspace);
    474    if (ret != COLOR_STANDARD_UNSPECIFIED)
    475        ff_AMediaFormat_setInt32(format, "color-standard", ret);
    476    ret = ff_AMediaFormatColorTransfer_from_AVColorTransfer(avctx->color_trc);
    477    if (ret != COLOR_TRANSFER_UNSPECIFIED)
    478        ff_AMediaFormat_setInt32(format, "color-transfer", ret);
    479 
    480    if (avctx->bit_rate)
    481        ff_AMediaFormat_setInt32(format, "bitrate", avctx->bit_rate);
    482    if (s->bitrate_mode >= 0) {
    483        ff_AMediaFormat_setInt32(format, "bitrate-mode", s->bitrate_mode);
    484        if (s->bitrate_mode == BITRATE_MODE_CQ && avctx->global_quality > 0)
    485            ff_AMediaFormat_setInt32(format, "quality", avctx->global_quality);
    486    }
    487    // frame-rate and i-frame-interval are required to configure codec
    488    if (avctx->framerate.num >= avctx->framerate.den && avctx->framerate.den > 0) {
    489        s->fps = avctx->framerate.num / avctx->framerate.den;
    490    } else {
    491        s->fps = 30;
    492        av_log(avctx, AV_LOG_INFO, "Use %d as the default MediaFormat frame-rate\n", s->fps);
    493    }
    494    gop = round(avctx->gop_size / s->fps);
    495    if (gop == 0) {
    496        gop = 1;
    497        av_log(avctx, AV_LOG_INFO,
    498                "Use %d as the default MediaFormat i-frame-interval, "
    499                "please set gop_size properly (>= fps)\n", gop);
    500    } else {
    501        av_log(avctx, AV_LOG_DEBUG, "Set i-frame-interval to %d\n", gop);
    502    }
    503 
    504    ff_AMediaFormat_setInt32(format, "frame-rate", s->fps);
    505    ff_AMediaFormat_setInt32(format, "i-frame-interval", gop);
    506 
    507    ret = ff_AMediaCodecProfile_getProfileFromAVCodecContext(avctx);
    508    if (ret > 0) {
    509        av_log(avctx, AV_LOG_DEBUG, "set profile to 0x%x\n", ret);
    510        ff_AMediaFormat_setInt32(format, "profile", ret);
    511    }
    512    if (s->level > 0) {
    513        av_log(avctx, AV_LOG_DEBUG, "set level to 0x%x\n", s->level);
    514        ff_AMediaFormat_setInt32(format, "level", s->level);
    515    }
    516    if (avctx->max_b_frames > 0) {
    517        if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
    518            av_log(avctx, AV_LOG_ERROR,
    519                    "Enabling B frames will produce packets with no DTS. "
    520                    "Use -strict experimental to use it anyway.\n");
    521            ret = AVERROR(EINVAL);
    522            goto bailout;
    523        }
    524        ff_AMediaFormat_setInt32(format, "max-bframes", avctx->max_b_frames);
    525    }
    526    if (s->pts_as_dts == -1)
    527        s->pts_as_dts = avctx->max_b_frames <= 0;
    528    if (s->operating_rate > 0)
    529        ff_AMediaFormat_setInt32(format, "operating-rate", s->operating_rate);
    530 
    531    ret = ff_AMediaCodec_getConfigureFlagEncode(s->codec);
    532    ret = ff_AMediaCodec_configure(s->codec, format, s->window, NULL, ret);
    533    if (ret) {
    534        av_log(avctx, AV_LOG_ERROR, "MediaCodec configure failed, %s\n", av_err2str(ret));
    535        if (avctx->pix_fmt == AV_PIX_FMT_YUV420P)
    536            av_log(avctx, AV_LOG_ERROR, "Please try -pix_fmt nv12, some devices don't "
    537                                        "support yuv420p as encoder input format.\n");
    538        goto bailout;
    539    }
    540 
    541    if (s->async_mode) {
    542        FFAMediaCodecOnAsyncNotifyCallback cb = {
    543                .onAsyncInputAvailable = on_input_available,
    544                .onAsyncOutputAvailable = on_output_available,
    545                .onAsyncFormatChanged = on_format_changed,
    546                .onAsyncError = on_error,
    547        };
    548 
    549        ret = ff_AMediaCodec_setAsyncNotifyCallback(s->codec, &cb, avctx);
    550        if (ret < 0) {
    551            av_log(avctx, AV_LOG_WARNING,
    552                   "Try MediaCodec async mode failed, %s, switch to sync mode\n",
    553                   av_err2str(ret));
    554            mediacodec_uninit_async_state(avctx);
    555        }
    556    }
    557 
    558    ret = mediacodec_init_bsf(avctx);
    559    if (ret)
    560        goto bailout;
    561 
    562    mediacodec_output_format(avctx);
    563 
    564    s->frame = av_frame_alloc();
    565    if (!s->frame) {
    566        ret = AVERROR(ENOMEM);
    567        goto bailout;
    568    }
    569 
    570    ret = ff_AMediaCodec_start(s->codec);
    571    if (ret) {
    572        av_log(avctx, AV_LOG_ERROR, "MediaCodec failed to start, %s\n",
    573               av_err2str(ret));
    574        goto bailout;
    575    }
    576 
    577    ret = mediacodec_generate_extradata(avctx);
    578 
    579 bailout:
    580    if (format)
    581        ff_AMediaFormat_delete(format);
    582    return ret;
    583 }
    584 
    585 static int mediacodec_get_output_index(AVCodecContext *avctx, ssize_t *index,
    586                                       FFAMediaCodecBufferInfo *out_info)
    587 {
    588    MediaCodecEncContext *s = avctx->priv_data;
    589    FFAMediaCodec *codec = s->codec;
    590    int64_t timeout_us = s->eof_sent ? OUTPUT_DEQUEUE_TIMEOUT_US : 0;
    591    MediaCodecAsyncOutput output = { .index = -1 };
    592    int ret;
    593 
    594    if (!s->async_mode) {
    595        *index = ff_AMediaCodec_dequeueOutputBuffer(codec, out_info, timeout_us);
    596        return 0;
    597    }
    598 
    599    ff_mutex_lock(&s->output_mutex);
    600 
    601    while (!s->encode_status) {
    602        if (av_fifo_read(s->async_output, &output, 1) >= 0)
    603            break;
    604 
    605        // Only wait after signalEndOfInputStream
    606        if (s->eof_sent && !s->encode_status)
    607            ff_cond_wait(&s->output_cond, &s->output_mutex);
    608        else
    609            break;
    610    }
    611 
    612    ret = s->encode_status;
    613    ff_mutex_unlock(&s->output_mutex);
    614 
    615    // Get output index success
    616    if (output.index >= 0) {
    617        *index = output.index;
    618        *out_info = output.buf_info;
    619        return 0;
    620    }
    621 
    622    return ret ? ret : AVERROR(EAGAIN);
    623 }
    624 
    625 static int mediacodec_receive(AVCodecContext *avctx, AVPacket *pkt)
    626 {
    627    MediaCodecEncContext *s = avctx->priv_data;
    628    FFAMediaCodec *codec = s->codec;
    629    ssize_t index;
    630    FFAMediaCodecBufferInfo out_info = {0};
    631    uint8_t *out_buf;
    632    size_t out_size = 0;
    633    int ret;
    634    int extradata_size = 0;
    635 
    636    ret = mediacodec_get_output_index(avctx, &index, &out_info);
    637    if (ret < 0)
    638        return ret;
    639 
    640    if (ff_AMediaCodec_infoTryAgainLater(codec, index))
    641        return AVERROR(EAGAIN);
    642 
    643    if (ff_AMediaCodec_infoOutputFormatChanged(codec, index)) {
    644        mediacodec_output_format(avctx);
    645        return AVERROR(EAGAIN);
    646    }
    647 
    648    if (ff_AMediaCodec_infoOutputBuffersChanged(codec, index)) {
    649        ff_AMediaCodec_cleanOutputBuffers(codec);
    650        return AVERROR(EAGAIN);
    651    }
    652 
    653    if (index < 0)
    654        return AVERROR_EXTERNAL;
    655 
    656    if (out_info.flags & ff_AMediaCodec_getBufferFlagEndOfStream(codec))
    657        return AVERROR_EOF;
    658 
    659    out_buf = ff_AMediaCodec_getOutputBuffer(codec, index, &out_size);
    660    if (!out_buf) {
    661        ret = AVERROR_EXTERNAL;
    662        goto bailout;
    663    }
    664 
    665    if (out_info.flags & ff_AMediaCodec_getBufferFlagCodecConfig(codec)) {
    666        if (avctx->codec_id == AV_CODEC_ID_AV1) {
    667            // Skip AV1CodecConfigurationRecord without configOBUs
    668            if (out_info.size <= 4) {
    669                ff_AMediaCodec_releaseOutputBuffer(codec, index, false);
    670                return mediacodec_receive(avctx, pkt);
    671            }
    672            out_info.size -= 4;
    673            out_info.offset += 4;
    674        }
    675 
    676        ret = av_reallocp(&s->extradata, out_info.size);
    677        if (ret)
    678            goto bailout;
    679 
    680        s->extradata_size = out_info.size;
    681        memcpy(s->extradata, out_buf + out_info.offset, out_info.size);
    682        ff_AMediaCodec_releaseOutputBuffer(codec, index, false);
    683        // try immediately
    684        return mediacodec_receive(avctx, pkt);
    685    }
    686 
    687    ret = ff_get_encode_buffer(avctx, pkt, out_info.size + s->extradata_size, 0);
    688    if (ret < 0)
    689      goto bailout;
    690 
    691    if (s->extradata_size) {
    692        extradata_size = s->extradata_size;
    693        s->extradata_size = 0;
    694        memcpy(pkt->data, s->extradata, extradata_size);
    695    }
    696    memcpy(pkt->data + extradata_size, out_buf + out_info.offset, out_info.size);
    697    pkt->pts = av_rescale_q(out_info.presentationTimeUs, AV_TIME_BASE_Q, avctx->time_base);
    698    if (s->pts_as_dts)
    699        pkt->dts = pkt->pts;
    700    if (out_info.flags & ff_AMediaCodec_getBufferFlagKeyFrame(codec))
    701        pkt->flags |= AV_PKT_FLAG_KEY;
    702    ret = 0;
    703 
    704    av_log(avctx, AV_LOG_TRACE, "receive packet pts %" PRId64 " dts %" PRId64
    705           " flags %d extradata %d\n",
    706           pkt->pts, pkt->dts, pkt->flags, extradata_size);
    707 
    708 bailout:
    709    ff_AMediaCodec_releaseOutputBuffer(codec, index, false);
    710    return ret;
    711 }
    712 
    713 static int mediacodec_get_input_index(AVCodecContext *avctx, ssize_t *index)
    714 {
    715    MediaCodecEncContext *s = avctx->priv_data;
    716    FFAMediaCodec *codec = s->codec;
    717    int ret = 0;
    718    int32_t n;
    719 
    720    if (!s->async_mode) {
    721        *index = ff_AMediaCodec_dequeueInputBuffer(codec, INPUT_DEQUEUE_TIMEOUT_US);
    722        return 0;
    723    }
    724 
    725    ff_mutex_lock(&s->input_mutex);
    726 
    727    n = -1;
    728    while (n < 0 && !s->encode_status) {
    729        if (av_fifo_can_read(s->input_index) > 0) {
    730            av_fifo_read(s->input_index, &n, 1);
    731            break;
    732        }
    733 
    734        if (n < 0 && !s->encode_status)
    735            ff_cond_wait(&s->input_cond, &s->input_mutex);
    736    }
    737 
    738    ret = s->encode_status;
    739    *index = n;
    740    ff_mutex_unlock(&s->input_mutex);
    741 
    742    return ret;
    743 }
    744 
    745 
    746 static int mediacodec_send(AVCodecContext *avctx,
    747                           const AVFrame *frame) {
    748    MediaCodecEncContext *s = avctx->priv_data;
    749    FFAMediaCodec *codec = s->codec;
    750    ssize_t index;
    751    uint8_t *input_buf = NULL;
    752    size_t input_size = 0;
    753    int64_t pts = 0;
    754    uint32_t flags = 0;
    755    int ret;
    756 
    757    if (s->eof_sent)
    758        return 0;
    759 
    760    if (s->window) {
    761        if (!frame) {
    762            s->eof_sent = 1;
    763            return ff_AMediaCodec_signalEndOfInputStream(codec);
    764        }
    765 
    766        if (frame->data[3])
    767            av_mediacodec_release_buffer((AVMediaCodecBuffer *)frame->data[3], 1);
    768        return 0;
    769    }
    770 
    771    ret = mediacodec_get_input_index(avctx, &index);
    772    if (ret < 0)
    773        return ret;
    774 
    775    if (ff_AMediaCodec_infoTryAgainLater(codec, index))
    776        return AVERROR(EAGAIN);
    777 
    778    if (index < 0) {
    779        av_log(avctx, AV_LOG_ERROR, "dequeue input buffer failed, %zd", index);
    780        return AVERROR_EXTERNAL;
    781    }
    782 
    783    if (frame) {
    784        input_buf = ff_AMediaCodec_getInputBuffer(codec, index, &input_size);
    785        copy_frame_to_buffer(avctx, frame, input_buf, input_size);
    786 
    787        pts = av_rescale_q(frame->pts, avctx->time_base, AV_TIME_BASE_Q);
    788 
    789        if (frame->pict_type == AV_PICTURE_TYPE_I) {
    790            FFAMediaFormat *format = ff_AMediaFormat_new(s->use_ndk_codec);
    791            ff_AMediaFormat_setInt32(format, "request-sync", 0);
    792            ff_AMediaCodec_setParameters(codec, format);
    793            ff_AMediaFormat_delete(format);
    794        }
    795    } else {
    796        flags |= ff_AMediaCodec_getBufferFlagEndOfStream(codec);
    797        s->eof_sent = 1;
    798    }
    799 
    800    ff_AMediaCodec_queueInputBuffer(codec, index, 0, input_size, pts, flags);
    801    return 0;
    802 }
    803 
    804 static int mediacodec_encode(AVCodecContext *avctx, AVPacket *pkt)
    805 {
    806    MediaCodecEncContext *s = avctx->priv_data;
    807    int ret;
    808 
    809    // Return on three case:
    810    // 1. Serious error
    811    // 2. Got a packet success
    812    // 3. No AVFrame is available yet (don't return if get_frame return EOF)
    813    while (1) {
    814        if (s->bsf) {
    815            ret = av_bsf_receive_packet(s->bsf, pkt);
    816            if (!ret)
    817                return 0;
    818            if (ret != AVERROR(EAGAIN))
    819                return ret;
    820        }
    821 
    822        ret = mediacodec_receive(avctx, pkt);
    823        if (s->bsf) {
    824            if (!ret || ret == AVERROR_EOF)
    825                ret = av_bsf_send_packet(s->bsf, pkt);
    826        } else {
    827            if (!ret)
    828                return 0;
    829        }
    830 
    831        if (ret < 0 && ret != AVERROR(EAGAIN))
    832            return ret;
    833 
    834        if (!s->frame->buf[0]) {
    835            ret = ff_encode_get_frame(avctx, s->frame);
    836            if (ret && ret != AVERROR_EOF)
    837                return ret;
    838        }
    839 
    840        ret = mediacodec_send(avctx, s->frame->buf[0] ? s->frame : NULL);
    841        if (!ret)
    842            av_frame_unref(s->frame);
    843        else if (ret != AVERROR(EAGAIN))
    844            return ret;
    845    }
    846 
    847    return 0;
    848 }
    849 
    850 static int mediacodec_send_dummy_frame(AVCodecContext *avctx)
    851 {
    852    MediaCodecEncContext *s = avctx->priv_data;
    853    int ret;
    854 
    855    s->frame->width = avctx->width;
    856    s->frame->height = avctx->height;
    857    s->frame->format = avctx->pix_fmt;
    858    s->frame->pts = 0;
    859 
    860    ret = av_frame_get_buffer(s->frame, 0);
    861    if (ret < 0)
    862        return ret;
    863 
    864    do {
    865        ret = mediacodec_send(avctx, s->frame);
    866    } while (ret == AVERROR(EAGAIN));
    867    av_frame_unref(s->frame);
    868 
    869    if (ret < 0)
    870        return ret;
    871 
    872    ret = mediacodec_send(avctx, NULL);
    873    if (ret < 0) {
    874        av_log(avctx, AV_LOG_ERROR, "Flush failed: %s\n", av_err2str(ret));
    875        return ret;
    876    }
    877 
    878    return 0;
    879 }
    880 
    881 static int mediacodec_receive_dummy_pkt(AVCodecContext *avctx, AVPacket *pkt)
    882 {
    883    MediaCodecEncContext *s = avctx->priv_data;
    884    int ret;
    885 
    886    do {
    887        ret = mediacodec_receive(avctx, pkt);
    888    } while (ret == AVERROR(EAGAIN));
    889 
    890    if (ret < 0)
    891        return ret;
    892 
    893    do {
    894        ret = av_bsf_send_packet(s->bsf, pkt);
    895        if (ret < 0)
    896            return ret;
    897        ret = av_bsf_receive_packet(s->bsf, pkt);
    898    } while (ret == AVERROR(EAGAIN));
    899 
    900    return ret;
    901 }
    902 
    903 static int mediacodec_generate_extradata(AVCodecContext *avctx)
    904 {
    905    MediaCodecEncContext *s = avctx->priv_data;
    906    AVPacket *pkt = NULL;
    907    int ret;
    908    size_t side_size;
    909    uint8_t *side;
    910 
    911    if (!(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER))
    912        return 0;
    913 
    914    // Send dummy frame and receive a packet doesn't work in async mode
    915    if (s->async_mode || !s->extract_extradata) {
    916        av_log(avctx, AV_LOG_WARNING,
    917               "Mediacodec encoder doesn't support AV_CODEC_FLAG_GLOBAL_HEADER. "
    918               "Use extract_extradata bsf when necessary.\n");
    919        return 0;
    920    }
    921 
    922    pkt = av_packet_alloc();
    923    if (!pkt)
    924        return AVERROR(ENOMEM);
    925 
    926    ret = mediacodec_send_dummy_frame(avctx);
    927    if (ret < 0)
    928        goto bailout;
    929    ret = mediacodec_receive_dummy_pkt(avctx, pkt);
    930    if (ret < 0)
    931        goto bailout;
    932 
    933    side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
    934    if (side && side_size > 0) {
    935        avctx->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
    936        if (!avctx->extradata) {
    937            ret = AVERROR(ENOMEM);
    938            goto bailout;
    939        }
    940 
    941        memcpy(avctx->extradata, side, side_size);
    942        avctx->extradata_size = side_size;
    943    }
    944 
    945 bailout:
    946    if (s->eof_sent) {
    947        s->eof_sent = 0;
    948        ff_AMediaCodec_flush(s->codec);
    949    }
    950    av_bsf_flush(s->bsf);
    951    av_packet_free(&pkt);
    952    return ret;
    953 }
    954 
    955 static av_cold int mediacodec_close(AVCodecContext *avctx)
    956 {
    957    MediaCodecEncContext *s = avctx->priv_data;
    958    if (s->codec) {
    959        ff_AMediaCodec_stop(s->codec);
    960        ff_AMediaCodec_delete(s->codec);
    961        s->codec = NULL;
    962    }
    963 
    964    if (s->window) {
    965        ff_mediacodec_surface_unref(s->window, avctx);
    966        s->window = NULL;
    967    }
    968 
    969    av_bsf_free(&s->bsf);
    970    av_frame_free(&s->frame);
    971 
    972    mediacodec_uninit_async_state(avctx);
    973 
    974    return 0;
    975 }
    976 
    977 static av_cold void mediacodec_flush(AVCodecContext *avctx)
    978 {
    979    MediaCodecEncContext *s = avctx->priv_data;
    980    if (s->bsf)
    981        av_bsf_flush(s->bsf);
    982    av_frame_unref(s->frame);
    983    ff_AMediaCodec_flush(s->codec);
    984 }
    985 
    986 static const AVCodecHWConfigInternal *const mediacodec_hw_configs[] = {
    987    &(const AVCodecHWConfigInternal) {
    988        .public          = {
    989            .pix_fmt     = AV_PIX_FMT_MEDIACODEC,
    990            .methods     = AV_CODEC_HW_CONFIG_METHOD_AD_HOC |
    991                           AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
    992            .device_type = AV_HWDEVICE_TYPE_MEDIACODEC,
    993        },
    994        .hwaccel         = NULL,
    995    },
    996    NULL
    997 };
    998 
    999 #define OFFSET(x) offsetof(MediaCodecEncContext, x)
   1000 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
   1001 #define COMMON_OPTION                                                                                       \
   1002    { "ndk_codec", "Use MediaCodec from NDK",                                                               \
   1003                    OFFSET(use_ndk_codec), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE },                      \
   1004    { "ndk_async", "Try NDK MediaCodec in async mode",                                                      \
   1005                    OFFSET(async_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE },                           \
   1006    { "codec_name", "Select codec by name",                                                                 \
   1007                    OFFSET(name), AV_OPT_TYPE_STRING, {0}, 0, 0, VE },                                      \
   1008    { "bitrate_mode", "Bitrate control method",                                                             \
   1009                    OFFSET(bitrate_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, .unit = "bitrate_mode" },  \
   1010    { "cq", "Constant quality mode",                                                                                \
   1011                    0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_CQ}, 0, 0, VE, .unit = "bitrate_mode" },             \
   1012    { "vbr", "Variable bitrate mode",                                                                               \
   1013                    0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_VBR}, 0, 0, VE, .unit = "bitrate_mode" },            \
   1014    { "cbr", "Constant bitrate mode",                                                                               \
   1015                    0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_CBR}, 0, 0, VE, .unit = "bitrate_mode" },            \
   1016    { "cbr_fd", "Constant bitrate mode with frame drops",                                                           \
   1017                    0, AV_OPT_TYPE_CONST, {.i64 = BITRATE_MODE_CBR_FD}, 0, 0, VE, .unit = "bitrate_mode" },         \
   1018    { "pts_as_dts", "Use PTS as DTS. It is enabled automatically if avctx max_b_frames <= 0, "              \
   1019                    "since most of Android devices don't output B frames by default.",                      \
   1020                    OFFSET(pts_as_dts), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE },                         \
   1021    { "operating_rate", "The desired operating rate that the codec will need to operate at, zero for unspecified",    \
   1022            OFFSET(operating_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE },                                          \
   1023 
   1024 #define MEDIACODEC_ENCODER_CLASS(name)              \
   1025 static const AVClass name ## _mediacodec_class = {  \
   1026    .class_name = #name "_mediacodec",              \
   1027    .item_name  = av_default_item_name,             \
   1028    .option     = name ## _options,                 \
   1029    .version    = LIBAVUTIL_VERSION_INT,            \
   1030 };                                                  \
   1031 
   1032 #define DECLARE_MEDIACODEC_ENCODER(short_name, long_name, codec_id)     \
   1033 MEDIACODEC_ENCODER_CLASS(short_name)                                    \
   1034 const FFCodec ff_ ## short_name ## _mediacodec_encoder = {              \
   1035    .p.name           = #short_name "_mediacodec",                      \
   1036    CODEC_LONG_NAME(long_name " Android MediaCodec encoder"),           \
   1037    .p.type           = AVMEDIA_TYPE_VIDEO,                             \
   1038    .p.id             = codec_id,                                       \
   1039    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |         \
   1040                        AV_CODEC_CAP_HARDWARE |                         \
   1041                        AV_CODEC_CAP_ENCODER_FLUSH,                     \
   1042    .priv_data_size   = sizeof(MediaCodecEncContext),                   \
   1043    .p.pix_fmts       = avc_pix_fmts,                                   \
   1044    .color_ranges   = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,              \
   1045    .init             = mediacodec_init,                                \
   1046    FF_CODEC_RECEIVE_PACKET_CB(mediacodec_encode),                      \
   1047    .close            = mediacodec_close,                               \
   1048    .flush            = mediacodec_flush,                               \
   1049    .p.priv_class     = &short_name ## _mediacodec_class,               \
   1050    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,                      \
   1051    .p.wrapper_name = "mediacodec",                                     \
   1052    .hw_configs     = mediacodec_hw_configs,                            \
   1053 };                                                                      \
   1054 
   1055 #if CONFIG_H264_MEDIACODEC_ENCODER
   1056 
   1057 enum MediaCodecAvcLevel {
   1058    AVCLevel1       = 0x01,
   1059    AVCLevel1b      = 0x02,
   1060    AVCLevel11      = 0x04,
   1061    AVCLevel12      = 0x08,
   1062    AVCLevel13      = 0x10,
   1063    AVCLevel2       = 0x20,
   1064    AVCLevel21      = 0x40,
   1065    AVCLevel22      = 0x80,
   1066    AVCLevel3       = 0x100,
   1067    AVCLevel31      = 0x200,
   1068    AVCLevel32      = 0x400,
   1069    AVCLevel4       = 0x800,
   1070    AVCLevel41      = 0x1000,
   1071    AVCLevel42      = 0x2000,
   1072    AVCLevel5       = 0x4000,
   1073    AVCLevel51      = 0x8000,
   1074    AVCLevel52      = 0x10000,
   1075    AVCLevel6       = 0x20000,
   1076    AVCLevel61      = 0x40000,
   1077    AVCLevel62      = 0x80000,
   1078 };
   1079 
   1080 static const AVOption h264_options[] = {
   1081    COMMON_OPTION
   1082 
   1083    FF_AVCTX_PROFILE_OPTION("baseline",             NULL, VIDEO, AV_PROFILE_H264_BASELINE)
   1084    FF_AVCTX_PROFILE_OPTION("constrained_baseline", NULL, VIDEO, AV_PROFILE_H264_CONSTRAINED_BASELINE)
   1085    FF_AVCTX_PROFILE_OPTION("main",                 NULL, VIDEO, AV_PROFILE_H264_MAIN)
   1086    FF_AVCTX_PROFILE_OPTION("extended",             NULL, VIDEO, AV_PROFILE_H264_EXTENDED)
   1087    FF_AVCTX_PROFILE_OPTION("high",                 NULL, VIDEO, AV_PROFILE_H264_HIGH)
   1088    FF_AVCTX_PROFILE_OPTION("high10",               NULL, VIDEO, AV_PROFILE_H264_HIGH_10)
   1089    FF_AVCTX_PROFILE_OPTION("high422",              NULL, VIDEO, AV_PROFILE_H264_HIGH_422)
   1090    FF_AVCTX_PROFILE_OPTION("high444",              NULL, VIDEO, AV_PROFILE_H264_HIGH_444)
   1091 
   1092    { "level", "Specify level",
   1093                OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" },
   1094    { "1",      "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel1  }, 0, 0, VE, .unit = "level" },
   1095    { "1b",     "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel1b }, 0, 0, VE, .unit = "level" },
   1096    { "1.1",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel11 }, 0, 0, VE, .unit = "level" },
   1097    { "1.2",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel12 }, 0, 0, VE, .unit = "level" },
   1098    { "1.3",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel13 }, 0, 0, VE, .unit = "level" },
   1099    { "2",      "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel2  }, 0, 0, VE, .unit = "level" },
   1100    { "2.1",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel21 }, 0, 0, VE, .unit = "level" },
   1101    { "2.2",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel22 }, 0, 0, VE, .unit = "level" },
   1102    { "3",      "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel3  }, 0, 0, VE, .unit = "level" },
   1103    { "3.1",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel31 }, 0, 0, VE, .unit = "level" },
   1104    { "3.2",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel32 }, 0, 0, VE, .unit = "level" },
   1105    { "4",      "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel4  }, 0, 0, VE, .unit = "level" },
   1106    { "4.1",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel41 }, 0, 0, VE, .unit = "level" },
   1107    { "4.2",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel42 }, 0, 0, VE, .unit = "level" },
   1108    { "5",      "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel5  }, 0, 0, VE, .unit = "level" },
   1109    { "5.1",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel51 }, 0, 0, VE, .unit = "level" },
   1110    { "5.2",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel52 }, 0, 0, VE, .unit = "level" },
   1111    { "6.0",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel6  }, 0, 0, VE, .unit = "level" },
   1112    { "6.1",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel61 }, 0, 0, VE, .unit = "level" },
   1113    { "6.2",    "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel62 }, 0, 0, VE, .unit = "level" },
   1114    { NULL, }
   1115 };
   1116 
   1117 DECLARE_MEDIACODEC_ENCODER(h264, "H.264", AV_CODEC_ID_H264)
   1118 
   1119 #endif  // CONFIG_H264_MEDIACODEC_ENCODER
   1120 
   1121 #if CONFIG_HEVC_MEDIACODEC_ENCODER
   1122 
   1123 enum MediaCodecHevcLevel {
   1124    HEVCMainTierLevel1  = 0x1,
   1125    HEVCHighTierLevel1  = 0x2,
   1126    HEVCMainTierLevel2  = 0x4,
   1127    HEVCHighTierLevel2  = 0x8,
   1128    HEVCMainTierLevel21 = 0x10,
   1129    HEVCHighTierLevel21 = 0x20,
   1130    HEVCMainTierLevel3  = 0x40,
   1131    HEVCHighTierLevel3  = 0x80,
   1132    HEVCMainTierLevel31 = 0x100,
   1133    HEVCHighTierLevel31 = 0x200,
   1134    HEVCMainTierLevel4  = 0x400,
   1135    HEVCHighTierLevel4  = 0x800,
   1136    HEVCMainTierLevel41 = 0x1000,
   1137    HEVCHighTierLevel41 = 0x2000,
   1138    HEVCMainTierLevel5  = 0x4000,
   1139    HEVCHighTierLevel5  = 0x8000,
   1140    HEVCMainTierLevel51 = 0x10000,
   1141    HEVCHighTierLevel51 = 0x20000,
   1142    HEVCMainTierLevel52 = 0x40000,
   1143    HEVCHighTierLevel52 = 0x80000,
   1144    HEVCMainTierLevel6  = 0x100000,
   1145    HEVCHighTierLevel6  = 0x200000,
   1146    HEVCMainTierLevel61 = 0x400000,
   1147    HEVCHighTierLevel61 = 0x800000,
   1148    HEVCMainTierLevel62 = 0x1000000,
   1149    HEVCHighTierLevel62 = 0x2000000,
   1150 };
   1151 
   1152 static const AVOption hevc_options[] = {
   1153    COMMON_OPTION
   1154 
   1155    FF_AVCTX_PROFILE_OPTION("main",   NULL, VIDEO, AV_PROFILE_HEVC_MAIN)
   1156    FF_AVCTX_PROFILE_OPTION("main10", NULL, VIDEO, AV_PROFILE_HEVC_MAIN_10)
   1157 
   1158    { "level", "Specify tier and level",
   1159                OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" },
   1160    { "m1",    "Main tier level 1",
   1161                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel1  },  0, 0, VE,  .unit = "level" },
   1162    { "h1",    "High tier level 1",
   1163                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel1  },  0, 0, VE,  .unit = "level" },
   1164    { "m2",    "Main tier level 2",
   1165                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel2  },  0, 0, VE,  .unit = "level" },
   1166    { "h2",    "High tier level 2",
   1167                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel2  },  0, 0, VE,  .unit = "level" },
   1168    { "m2.1",  "Main tier level 2.1",
   1169                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel21 },  0, 0, VE,  .unit = "level" },
   1170    { "h2.1",  "High tier level 2.1",
   1171                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel21 },  0, 0, VE,  .unit = "level" },
   1172    { "m3",    "Main tier level 3",
   1173                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel3  },  0, 0, VE,  .unit = "level" },
   1174    { "h3",    "High tier level 3",
   1175                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel3  },  0, 0, VE,  .unit = "level" },
   1176    { "m3.1",  "Main tier level 3.1",
   1177                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel31 },  0, 0, VE,  .unit = "level" },
   1178    { "h3.1",  "High tier level 3.1",
   1179                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel31 },  0, 0, VE,  .unit = "level" },
   1180    { "m4",    "Main tier level 4",
   1181                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel4  },  0, 0, VE,  .unit = "level" },
   1182    { "h4",    "High tier level 4",
   1183                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel4  },  0, 0, VE,  .unit = "level" },
   1184    { "m4.1",  "Main tier level 4.1",
   1185                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel41 },  0, 0, VE,  .unit = "level" },
   1186    { "h4.1",  "High tier level 4.1",
   1187                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel41 },  0, 0, VE,  .unit = "level" },
   1188    { "m5",    "Main tier level 5",
   1189                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel5  },  0, 0, VE,  .unit = "level" },
   1190    { "h5",    "High tier level 5",
   1191                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel5  },  0, 0, VE,  .unit = "level" },
   1192    { "m5.1",  "Main tier level 5.1",
   1193                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel51 },  0, 0, VE,  .unit = "level" },
   1194    { "h5.1",  "High tier level 5.1",
   1195                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel51 },  0, 0, VE,  .unit = "level" },
   1196    { "m5.2",  "Main tier level 5.2",
   1197                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel52 },  0, 0, VE,  .unit = "level" },
   1198    { "h5.2",  "High tier level 5.2",
   1199                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel52 },  0, 0, VE,  .unit = "level" },
   1200    { "m6",    "Main tier level 6",
   1201                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel6  },  0, 0, VE,  .unit = "level" },
   1202    { "h6",    "High tier level 6",
   1203                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel6  },  0, 0, VE,  .unit = "level" },
   1204    { "m6.1",  "Main tier level 6.1",
   1205                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel61 },  0, 0, VE,  .unit = "level" },
   1206    { "h6.1",  "High tier level 6.1",
   1207                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel61 },  0, 0, VE,  .unit = "level" },
   1208    { "m6.2",  "Main tier level 6.2",
   1209                0, AV_OPT_TYPE_CONST, { .i64 = HEVCMainTierLevel62 },  0, 0, VE,  .unit = "level" },
   1210    { "h6.2",  "High tier level 6.2",
   1211                0, AV_OPT_TYPE_CONST, { .i64 = HEVCHighTierLevel62 },  0, 0, VE,  .unit = "level" },
   1212    { NULL, }
   1213 };
   1214 
   1215 DECLARE_MEDIACODEC_ENCODER(hevc, "H.265", AV_CODEC_ID_HEVC)
   1216 
   1217 #endif  // CONFIG_HEVC_MEDIACODEC_ENCODER
   1218 
   1219 #if CONFIG_VP8_MEDIACODEC_ENCODER
   1220 
   1221 enum MediaCodecVP8Level {
   1222    VP8Level_Version0 = 0x01,
   1223    VP8Level_Version1 = 0x02,
   1224    VP8Level_Version2 = 0x04,
   1225    VP8Level_Version3 = 0x08,
   1226 };
   1227 
   1228 static const AVOption vp8_options[] = {
   1229    COMMON_OPTION
   1230    { "level", "Specify tier and level",
   1231                OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" },
   1232    { "V0",    "Level Version 0",
   1233                0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version0 },  0, 0, VE,  .unit = "level" },
   1234    { "V1",    "Level Version 1",
   1235                0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version1 },  0, 0, VE,  .unit = "level" },
   1236    { "V2",    "Level Version 2",
   1237                0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version2 },  0, 0, VE,  .unit = "level" },
   1238    { "V3",    "Level Version 3",
   1239                0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version3 },  0, 0, VE,  .unit = "level" },
   1240    { NULL, }
   1241 };
   1242 
   1243 DECLARE_MEDIACODEC_ENCODER(vp8, "VP8", AV_CODEC_ID_VP8)
   1244 
   1245 #endif  // CONFIG_VP8_MEDIACODEC_ENCODER
   1246 
   1247 #if CONFIG_VP9_MEDIACODEC_ENCODER
   1248 
   1249 enum MediaCodecVP9Level {
   1250    VP9Level1  = 0x1,
   1251    VP9Level11  = 0x2,
   1252    VP9Level2  = 0x4,
   1253    VP9Level21  = 0x8,
   1254    VP9Level3 = 0x10,
   1255    VP9Level31 = 0x20,
   1256    VP9Level4  = 0x40,
   1257    VP9Level41  = 0x80,
   1258    VP9Level5 = 0x100,
   1259    VP9Level51 = 0x200,
   1260    VP9Level52  = 0x400,
   1261    VP9Level6  = 0x800,
   1262    VP9Level61 = 0x1000,
   1263    VP9Level62 = 0x2000,
   1264 };
   1265 
   1266 static const AVOption vp9_options[] = {
   1267    COMMON_OPTION
   1268 
   1269    FF_AVCTX_PROFILE_OPTION("profile0",   NULL, VIDEO, AV_PROFILE_VP9_0)
   1270    FF_AVCTX_PROFILE_OPTION("profile1",   NULL, VIDEO, AV_PROFILE_VP9_1)
   1271    FF_AVCTX_PROFILE_OPTION("profile2",   NULL, VIDEO, AV_PROFILE_VP9_2)
   1272    FF_AVCTX_PROFILE_OPTION("profile3",   NULL, VIDEO, AV_PROFILE_VP9_3)
   1273 
   1274    { "level", "Specify tier and level",
   1275                OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" },
   1276    { "1",     "Level 1",
   1277                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level1  },  0, 0, VE,  .unit = "level" },
   1278    { "1.1",   "Level 1.1",
   1279                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level11 },  0, 0, VE,  .unit = "level" },
   1280    { "2",     "Level 2",
   1281                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level2  },  0, 0, VE,  .unit = "level" },
   1282    { "2.1",   "Level 2.1",
   1283                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level21 },  0, 0, VE,  .unit = "level" },
   1284    { "3",     "Level 3",
   1285                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level3  },  0, 0, VE,  .unit = "level" },
   1286    { "3.1",   "Level 3.1",
   1287                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level31 },  0, 0, VE,  .unit = "level" },
   1288    { "4",     "Level 4",
   1289                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level4  },  0, 0, VE,  .unit = "level" },
   1290    { "4.1",   "Level 4.1",
   1291                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level41 },  0, 0, VE,  .unit = "level" },
   1292    { "5",     "Level 5",
   1293                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level5  },  0, 0, VE,  .unit = "level" },
   1294    { "5.1",   "Level 5.1",
   1295                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level51 },  0, 0, VE,  .unit = "level" },
   1296    { "5.2",   "Level 5.2",
   1297                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level52 },  0, 0, VE,  .unit = "level" },
   1298    { "6",     "Level 6",
   1299                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level6  },  0, 0, VE,  .unit = "level" },
   1300    { "6.1",   "Level 4.1",
   1301                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level61 },  0, 0, VE,  .unit = "level" },
   1302    { "6.2",   "Level 6.2",
   1303                0, AV_OPT_TYPE_CONST, { .i64 = VP9Level62 },  0, 0, VE,  .unit = "level" },
   1304    { NULL, }
   1305 };
   1306 
   1307 DECLARE_MEDIACODEC_ENCODER(vp9, "VP9", AV_CODEC_ID_VP9)
   1308 
   1309 #endif  // CONFIG_VP9_MEDIACODEC_ENCODER
   1310 
   1311 #if CONFIG_MPEG4_MEDIACODEC_ENCODER
   1312 
   1313 enum MediaCodecMpeg4Level {
   1314    MPEG4Level0  = 0x01,
   1315    MPEG4Level0b  = 0x02,
   1316    MPEG4Level1 = 0x04,
   1317    MPEG4Level2  = 0x08,
   1318    MPEG4Level3 = 0x10,
   1319    MPEG4Level3b = 0x18,
   1320    MPEG4Level4 = 0x20,
   1321    MPEG4Level4a  = 0x40,
   1322    MPEG4Level5  = 0x80,
   1323    MPEG4Level6 = 0x100,
   1324 };
   1325 
   1326 static const AVOption mpeg4_options[] = {
   1327    COMMON_OPTION
   1328 
   1329    FF_MPEG4_PROFILE_OPTS
   1330 
   1331    { "level", "Specify tier and level",
   1332                OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" },
   1333    { "0",     "Level 0",
   1334                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level0  },  0, 0, VE,  .unit = "level" },
   1335    { "0b",    "Level 0b",
   1336                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level0b },  0, 0, VE,  .unit = "level" },
   1337    { "1",     "Level 1",
   1338                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level1  },  0, 0, VE,  .unit = "level" },
   1339    { "2",     "Level 2",
   1340                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level2 },  0, 0, VE,  .unit = "level" },
   1341    { "3",     "Level 3",
   1342                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level3  },  0, 0, VE,  .unit = "level" },
   1343    { "3b",    "Level 3b",
   1344                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level3b },  0, 0, VE,  .unit = "level" },
   1345    { "4",     "Level 4",
   1346                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level4  },  0, 0, VE,  .unit = "level" },
   1347    { "4a",    "Level 4a",
   1348                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level4a },  0, 0, VE,  .unit = "level" },
   1349    { "5",     "Level 5",
   1350                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level5  },  0, 0, VE,  .unit = "level" },
   1351    { "6",     "Level 6",
   1352                0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level6  },  0, 0, VE,  .unit = "level" },
   1353    { NULL, }
   1354 };
   1355 
   1356 DECLARE_MEDIACODEC_ENCODER(mpeg4, "MPEG-4", AV_CODEC_ID_MPEG4)
   1357 
   1358 #endif  // CONFIG_MPEG4_MEDIACODEC_ENCODER
   1359 
   1360 #if CONFIG_AV1_MEDIACODEC_ENCODER
   1361 
   1362 enum MediaCodecAV1Level {
   1363    AV1Level2  = 0x1,
   1364    AV1Level21 = 0x2,
   1365    AV1Level22 = 0x4,
   1366    AV1Level23 = 0x8,
   1367    AV1Level3  = 0x10,
   1368    AV1Level31 = 0x20,
   1369    AV1Level32 = 0x40,
   1370    AV1Level33 = 0x80,
   1371    AV1Level4  = 0x100,
   1372    AV1Level41 = 0x200,
   1373    AV1Level42 = 0x400,
   1374    AV1Level43 = 0x800,
   1375    AV1Level5  = 0x1000,
   1376    AV1Level51 = 0x2000,
   1377    AV1Level52 = 0x4000,
   1378    AV1Level53 = 0x8000,
   1379    AV1Level6  = 0x10000,
   1380    AV1Level61 = 0x20000,
   1381    AV1Level62 = 0x40000,
   1382    AV1Level63 = 0x80000,
   1383    AV1Level7  = 0x100000,
   1384    AV1Level71 = 0x200000,
   1385    AV1Level72 = 0x400000,
   1386    AV1Level73 = 0x800000,
   1387 };
   1388 
   1389 static const AVOption av1_options[] = {
   1390    COMMON_OPTION
   1391 
   1392    FF_AV1_PROFILE_OPTS
   1393 
   1394    { "level", "Specify tier and level",
   1395                OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, .unit = "level" },
   1396    { "2",     "Level 2",
   1397                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level2  },  0, 0, VE,  .unit = "level" },
   1398    { "2.1",    "Level 2.1",
   1399                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level21 },  0, 0, VE,  .unit = "level" },
   1400    { "2.2",    "Level 2.2",
   1401                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level22 },  0, 0, VE,  .unit = "level" },
   1402    { "2.3",    "Level 2.3",
   1403                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level23 },  0, 0, VE,  .unit = "level" },
   1404    { "3",      "Level 3",
   1405                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level3  },  0, 0, VE,  .unit = "level" },
   1406    { "3.1",    "Level 3.1",
   1407                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level31 },  0, 0, VE,  .unit = "level" },
   1408    { "3.2",    "Level 3.2",
   1409                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level32 },  0, 0, VE,  .unit = "level" },
   1410    { "3.3",    "Level 3.3",
   1411                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level33 },  0, 0, VE,  .unit = "level" },
   1412    { "4",      "Level 4",
   1413                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level4  },  0, 0, VE,  .unit = "level" },
   1414    { "4.1",    "Level 4.1",
   1415                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level41 },  0, 0, VE,  .unit = "level" },
   1416    { "4.2",    "Level 4.2",
   1417                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level42 },  0, 0, VE,  .unit = "level" },
   1418    { "4.3",    "Level 4.3",
   1419                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level43 },  0, 0, VE,  .unit = "level" },
   1420    { "5",      "Level 5",
   1421                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level5  },  0, 0, VE,  .unit = "level" },
   1422    { "5.1",    "Level 5.1",
   1423                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level51 },  0, 0, VE,  .unit = "level" },
   1424    { "5.2",    "Level 5.2",
   1425                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level52 },  0, 0, VE,  .unit = "level" },
   1426    { "5.3",    "Level 5.3",
   1427                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level53 },  0, 0, VE,  .unit = "level" },
   1428    { "6",      "Level 6",
   1429                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level6  },  0, 0, VE,  .unit = "level" },
   1430    { "6.1",    "Level 6.1",
   1431                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level61 },  0, 0, VE,  .unit = "level" },
   1432    { "6.2",    "Level 6.2",
   1433                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level62 },  0, 0, VE,  .unit = "level" },
   1434    { "6.3",    "Level 6.3",
   1435                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level63 },  0, 0, VE,  .unit = "level" },
   1436    { "7",      "Level 7",
   1437                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level7  },  0, 0, VE,  .unit = "level" },
   1438    { "7.1",    "Level 7.1",
   1439                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level71 },  0, 0, VE,  .unit = "level" },
   1440    { "7.2",    "Level 7.2",
   1441                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level72 },  0, 0, VE,  .unit = "level" },
   1442    { "7.3",    "Level 7.3",
   1443                0, AV_OPT_TYPE_CONST, { .i64 = AV1Level73 },  0, 0, VE,  .unit = "level" },
   1444    { NULL, }
   1445 };
   1446 
   1447 DECLARE_MEDIACODEC_ENCODER(av1, "AV1", AV_CODEC_ID_AV1)
   1448 
   1449 #endif  // CONFIG_AV1_MEDIACODEC_ENCODER