tor-browser

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

av1_cx_iface.c (222216B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 #include <limits.h>
     12 #include <math.h>
     13 #include <stdbool.h>
     14 #include <stdint.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 
     18 #include "config/aom_config.h"
     19 #include "config/aom_version.h"
     20 
     21 #include "aom/aomcx.h"
     22 #include "aom/aom_encoder.h"
     23 #include "aom/aom_external_partition.h"
     24 #include "aom/aom_image.h"
     25 #include "aom/internal/aom_codec_internal.h"
     26 #include "aom_dsp/flow_estimation/flow_estimation.h"
     27 #include "aom_mem/aom_mem.h"
     28 #include "aom_scale/yv12config.h"
     29 #include "aom_util/aom_pthread.h"
     30 
     31 #include "av1/av1_cx_iface.h"
     32 #include "av1/av1_iface_common.h"
     33 #include "av1/common/av1_common_int.h"
     34 #include "av1/common/enums.h"
     35 #include "av1/common/quant_common.h"
     36 #include "av1/common/scale.h"
     37 #include "av1/encoder/bitstream.h"
     38 #include "av1/encoder/enc_enums.h"
     39 #include "av1/encoder/encoder.h"
     40 #include "av1/encoder/encoder_alloc.h"
     41 #include "av1/encoder/encoder_utils.h"
     42 #include "av1/encoder/ethread.h"
     43 #include "av1/encoder/external_partition.h"
     44 #include "av1/encoder/firstpass.h"
     45 #include "av1/encoder/lookahead.h"
     46 #include "av1/encoder/rc_utils.h"
     47 #include "av1/arg_defs.h"
     48 
     49 #include "common/args_helper.h"
     50 
     51 struct av1_extracfg {
     52  int cpu_used;
     53  unsigned int enable_auto_alt_ref;
     54  unsigned int enable_auto_bwd_ref;
     55  unsigned int noise_sensitivity;
     56  unsigned int sharpness;
     57  unsigned int enable_adaptive_sharpness;
     58  unsigned int static_thresh;
     59  unsigned int row_mt;
     60  unsigned int fp_mt;
     61  unsigned int tile_columns;  // log2 number of tile columns
     62  unsigned int tile_rows;     // log2 number of tile rows
     63  unsigned int auto_tiles;
     64  unsigned int enable_tpl_model;
     65  unsigned int enable_keyframe_filtering;
     66  unsigned int arnr_max_frames;
     67  unsigned int arnr_strength;
     68  unsigned int min_gf_interval;
     69  unsigned int max_gf_interval;
     70  unsigned int gf_min_pyr_height;
     71  unsigned int gf_max_pyr_height;
     72  aom_tune_metric tuning;
     73  const char *vmaf_model_path;
     74  const char *partition_info_path;
     75  unsigned int enable_rate_guide_deltaq;
     76  const char *rate_distribution_info;
     77  aom_dist_metric dist_metric;
     78  unsigned int cq_level;  // constrained quality level
     79  unsigned int rc_max_intra_bitrate_pct;
     80  unsigned int rc_max_inter_bitrate_pct;
     81  unsigned int gf_cbr_boost_pct;
     82  unsigned int lossless;
     83  unsigned int enable_cdef;
     84  unsigned int enable_restoration;
     85  unsigned int force_video_mode;
     86  unsigned int enable_obmc;
     87  unsigned int disable_trellis_quant;
     88  unsigned int enable_qm;
     89  unsigned int qm_y;
     90  unsigned int qm_u;
     91  unsigned int qm_v;
     92  unsigned int qm_min;
     93  unsigned int qm_max;
     94  unsigned int num_tg;
     95  unsigned int mtu_size;
     96 
     97  aom_timing_info_type_t timing_info_type;
     98  unsigned int frame_parallel_decoding_mode;
     99  int enable_dual_filter;
    100  unsigned int enable_chroma_deltaq;
    101  AQ_MODE aq_mode;
    102  DELTAQ_MODE deltaq_mode;
    103  unsigned int deltaq_strength;
    104  int deltalf_mode;
    105  unsigned int frame_periodic_boost;
    106  aom_tune_content content;
    107  aom_color_primaries_t color_primaries;
    108  aom_transfer_characteristics_t transfer_characteristics;
    109  aom_matrix_coefficients_t matrix_coefficients;
    110  aom_chroma_sample_position_t chroma_sample_position;
    111  int color_range;
    112  int render_width;
    113  int render_height;
    114  aom_superblock_size_t superblock_size;
    115  unsigned int single_tile_decoding;
    116  int error_resilient_mode;
    117  int s_frame_mode;
    118 
    119  int film_grain_test_vector;
    120  const char *film_grain_table_filename;
    121  unsigned int motion_vector_unit_test;
    122 #if CONFIG_FPMT_TEST
    123  unsigned int fpmt_unit_test;
    124 #endif
    125  unsigned int cdf_update_mode;
    126  int enable_rect_partitions;    // enable rectangular partitions for sequence
    127  int enable_ab_partitions;      // enable AB partitions for sequence
    128  int enable_1to4_partitions;    // enable 1:4 and 4:1 partitions for sequence
    129  int min_partition_size;        // min partition size [4,8,16,32,64,128]
    130  int max_partition_size;        // max partition size [4,8,16,32,64,128]
    131  int enable_intra_edge_filter;  // enable intra-edge filter for sequence
    132  int enable_order_hint;         // enable order hint for sequence
    133  int enable_tx64;               // enable 64-pt transform usage for sequence
    134  int enable_flip_idtx;          // enable flip and identity transform types
    135  int enable_rect_tx;        // enable rectangular transform usage for sequence
    136  int enable_dist_wtd_comp;  // enable dist wtd compound for sequence
    137  int max_reference_frames;  // maximum number of references per frame
    138  int enable_reduced_reference_set;  // enable reduced set of references
    139  int enable_ref_frame_mvs;          // sequence level
    140  int allow_ref_frame_mvs;           // frame level
    141  int enable_masked_comp;            // enable masked compound for sequence
    142  int enable_onesided_comp;          // enable one sided compound for sequence
    143  int enable_interintra_comp;        // enable interintra compound for sequence
    144  int enable_smooth_interintra;      // enable smooth interintra mode usage
    145  int enable_diff_wtd_comp;          // enable diff-wtd compound usage
    146  int enable_interinter_wedge;       // enable interinter-wedge compound usage
    147  int enable_interintra_wedge;       // enable interintra-wedge compound usage
    148  int enable_global_motion;          // enable global motion usage for sequence
    149  int enable_warped_motion;          // sequence level
    150  int allow_warped_motion;           // frame level
    151  int enable_filter_intra;           // enable filter intra for sequence
    152  int enable_smooth_intra;           // enable smooth intra modes for sequence
    153  int enable_paeth_intra;            // enable Paeth intra mode for sequence
    154  int enable_cfl_intra;              // enable CFL uv intra mode for sequence
    155  int enable_directional_intra;      // enable directional modes for sequence
    156  int enable_diagonal_intra;  // enable D45 to D203 intra modes for sequence
    157  int enable_superres;
    158  int enable_overlay;  // enable overlay for filtered arf frames
    159  int enable_palette;
    160  int enable_intrabc;
    161  int enable_angle_delta;
    162 #if CONFIG_DENOISE
    163  float noise_level;
    164  int noise_block_size;
    165  int enable_dnl_denoising;
    166 #endif
    167 
    168  unsigned int enable_low_complexity_decode;
    169  unsigned int chroma_subsampling_x;
    170  unsigned int chroma_subsampling_y;
    171  int reduced_tx_type_set;
    172  int use_intra_dct_only;
    173  int use_inter_dct_only;
    174  int use_intra_default_tx_only;
    175  int enable_tx_size_search;
    176  int quant_b_adapt;
    177  unsigned int vbr_corpus_complexity_lap;
    178  AV1_LEVEL target_seq_level_idx[MAX_NUM_OPERATING_POINTS];
    179  // Bit mask to specify which tier each of the 32 possible operating points
    180  // conforms to.
    181  unsigned int tier_mask;
    182  // min_cr / 100 is the target minimum compression ratio for each frame.
    183  unsigned int min_cr;
    184  COST_UPDATE_TYPE coeff_cost_upd_freq;
    185  COST_UPDATE_TYPE mode_cost_upd_freq;
    186  COST_UPDATE_TYPE mv_cost_upd_freq;
    187  COST_UPDATE_TYPE dv_cost_upd_freq;
    188  unsigned int ext_tile_debug;
    189  unsigned int sb_multipass_unit_test;
    190  // Total number of passes. If this number is -1, then we assume passes = 1 or
    191  // 2 (passes = 1 if pass == AOM_RC_ONE_PASS and passes = 2 otherwise).
    192  int passes;
    193  int fwd_kf_dist;
    194 
    195  LOOPFILTER_CONTROL loopfilter_control;
    196  // Indicates if the application of post-processing filters should be skipped
    197  // on reconstructed frame.
    198  unsigned int skip_postproc_filtering;
    199  // the name of the second pass output file when passes > 2
    200  const char *two_pass_output;
    201  const char *second_pass_log;
    202  // Automatically determine whether to disable several intra tools
    203  // when "--deltaq-mode=3" is true.
    204  // Default as 0.
    205  // When set to 1, the encoder will analyze the reconstruction quality
    206  // as compared to the source image in the preprocessing pass.
    207  // If the recontruction quality is considered high enough, we disable
    208  // the following intra coding tools, for better encoding speed:
    209  // "--enable_smooth_intra",
    210  // "--enable_paeth_intra",
    211  // "--enable_cfl_intra",
    212  // "--enable_diagonal_intra".
    213  int auto_intra_tools_off;
    214  int strict_level_conformance;
    215  int kf_max_pyr_height;
    216  int sb_qp_sweep;
    217  aom_screen_detection_mode screen_detection_mode;
    218 };
    219 
    220 #if !CONFIG_REALTIME_ONLY
    221 static const struct av1_extracfg default_extra_cfg = {
    222  0,              // cpu_used
    223  1,              // enable_auto_alt_ref
    224  0,              // enable_auto_bwd_ref
    225  0,              // noise_sensitivity
    226  0,              // sharpness
    227  0,              // enable_adaptive_sharpness
    228  0,              // static_thresh
    229  1,              // row_mt
    230  0,              // fp_mt
    231  0,              // tile_columns
    232  0,              // tile_rows
    233  0,              // auto_tiles
    234  1,              // enable_tpl_model
    235  1,              // enable_keyframe_filtering
    236  7,              // arnr_max_frames
    237  5,              // arnr_strength
    238  0,              // min_gf_interval; 0 -> default decision
    239  0,              // max_gf_interval; 0 -> default decision
    240  0,              // gf_min_pyr_height
    241  5,              // gf_max_pyr_height
    242  AOM_TUNE_PSNR,  // tuning
    243  "/usr/local/share/model/vmaf_v0.6.1.json",  // VMAF model path
    244  ".",                                        // partition info path
    245  0,                                          // enable rate guide deltaq
    246  "./rate_map.txt",                           // rate distribution input
    247  AOM_DIST_METRIC_PSNR,                       // dist_metric
    248  10,                                         // cq_level
    249  0,                                          // rc_max_intra_bitrate_pct
    250  0,                                          // rc_max_inter_bitrate_pct
    251  0,                                          // gf_cbr_boost_pct
    252  0,                                          // lossless
    253  1,                                          // enable_cdef
    254  1,                                          // enable_restoration
    255  0,                                          // force_video_mode
    256  1,                                          // enable_obmc
    257  3,                                          // disable_trellis_quant
    258  0,                                          // enable_qm
    259  DEFAULT_QM_Y,                               // qm_y
    260  DEFAULT_QM_U,                               // qm_u
    261  DEFAULT_QM_V,                               // qm_v
    262  DEFAULT_QM_FIRST,                           // qm_min
    263  DEFAULT_QM_LAST,                            // qm_max
    264  1,                                          // max number of tile groups
    265  0,                                          // mtu_size
    266  AOM_TIMING_UNSPECIFIED,       // No picture timing signaling in bitstream
    267  0,                            // frame_parallel_decoding_mode
    268  1,                            // enable dual filter
    269  0,                            // enable delta quant in chroma planes
    270  NO_AQ,                        // aq_mode
    271  DELTA_Q_OBJECTIVE,            // deltaq_mode
    272  100,                          // deltaq_strength
    273  0,                            // delta lf mode
    274  0,                            // frame_periodic_boost
    275  AOM_CONTENT_DEFAULT,          // content
    276  AOM_CICP_CP_UNSPECIFIED,      // CICP color primaries
    277  AOM_CICP_TC_UNSPECIFIED,      // CICP transfer characteristics
    278  AOM_CICP_MC_UNSPECIFIED,      // CICP matrix coefficients
    279  AOM_CSP_UNKNOWN,              // chroma sample position
    280  0,                            // color range
    281  0,                            // render width
    282  0,                            // render height
    283  AOM_SUPERBLOCK_SIZE_DYNAMIC,  // superblock_size
    284  1,                            // this depends on large_scale_tile.
    285  0,                            // error_resilient_mode off by default.
    286  0,                            // s_frame_mode off by default.
    287  0,                            // film_grain_test_vector
    288  NULL,                         // film_grain_table_filename
    289  0,                            // motion_vector_unit_test
    290 #if CONFIG_FPMT_TEST
    291  0,  // fpmt_unit_test
    292 #endif
    293  1,    // CDF update mode
    294  1,    // enable rectangular partitions
    295  1,    // enable ab shape partitions
    296  1,    // enable 1:4 and 4:1 partitions
    297  4,    // min_partition_size
    298  128,  // max_partition_size
    299  1,    // enable intra edge filter
    300  1,    // frame order hint
    301  1,    // enable 64-pt transform usage
    302  1,    // enable flip and identity transform
    303  1,    // enable rectangular transform usage
    304  1,    // dist-wtd compound
    305  7,    // max_reference_frames
    306  0,    // enable_reduced_reference_set
    307  1,    // enable_ref_frame_mvs sequence level
    308  1,    // allow ref_frame_mvs frame level
    309  1,    // enable masked compound at sequence level
    310  1,    // enable one sided compound at sequence level
    311  1,    // enable interintra compound at sequence level
    312  1,    // enable smooth interintra mode
    313  1,    // enable difference-weighted compound
    314  1,    // enable interinter wedge compound
    315  1,    // enable interintra wedge compound
    316  1,    // enable_global_motion usage
    317  1,    // enable_warped_motion at sequence level
    318  1,    // allow_warped_motion at frame level
    319  1,    // enable filter intra at sequence level
    320  1,    // enable smooth intra modes usage for sequence
    321  1,    // enable Paeth intra mode usage for sequence
    322  1,    // enable CFL uv intra mode usage for sequence
    323  1,    // enable directional intra mode usage for sequence
    324  1,    // enable D45 to D203 intra mode usage for sequence
    325  1,    // superres
    326  1,    // enable overlay
    327  1,    // enable palette
    328  1,    // enable intrabc
    329  1,    // enable angle delta
    330 #if CONFIG_DENOISE
    331  0,   // noise_level
    332  32,  // noise_block_size
    333  1,   // enable_dnl_denoising
    334 #endif
    335 
    336  0,  // enable_low_complexity_decode
    337  0,  // chroma_subsampling_x
    338  0,  // chroma_subsampling_y
    339  0,  // reduced_tx_type_set
    340  0,  // use_intra_dct_only
    341  0,  // use_inter_dct_only
    342  0,  // use_intra_default_tx_only
    343  1,  // enable_tx_size_search
    344  0,  // quant_b_adapt
    345  0,  // vbr_corpus_complexity_lap
    346  {
    347      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    348      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    349      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    350      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    351      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    352      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    353      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    354  },               // target_seq_level_idx
    355  0,               // tier_mask
    356  0,               // min_cr
    357  COST_UPD_SB,     // coeff_cost_upd_freq
    358  COST_UPD_SB,     // mode_cost_upd_freq
    359  COST_UPD_SB,     // mv_cost_upd_freq
    360  COST_UPD_SB,     // dv_cost_upd_freq
    361  0,               // ext_tile_debug
    362  0,               // sb_multipass_unit_test
    363  -1,              // passes
    364  -1,              // fwd_kf_dist
    365  LOOPFILTER_ALL,  // loopfilter_control
    366  0,               // skip_postproc_filtering
    367  NULL,            // two_pass_output
    368  NULL,            // second_pass_log
    369  0,               // auto_intra_tools_off
    370  0,               // strict_level_conformance
    371  -1,              // kf_max_pyr_height
    372  0,               // sb_qp_sweep
    373  AOM_SCREEN_DETECTION_STANDARD,
    374 };
    375 #else
    376 // Some settings are changed for realtime only build.
    377 static const struct av1_extracfg default_extra_cfg = {
    378  10,             // cpu_used
    379  1,              // enable_auto_alt_ref
    380  0,              // enable_auto_bwd_ref
    381  0,              // noise_sensitivity
    382  0,              // sharpness
    383  0,              // enable_adaptive_sharpness
    384  0,              // static_thresh
    385  1,              // row_mt
    386  0,              // fp_mt
    387  0,              // tile_columns
    388  0,              // tile_rows
    389  0,              // auto_tiles
    390  0,              // enable_tpl_model
    391  0,              // enable_keyframe_filtering
    392  7,              // arnr_max_frames
    393  5,              // arnr_strength
    394  0,              // min_gf_interval; 0 -> default decision
    395  0,              // max_gf_interval; 0 -> default decision
    396  0,              // gf_min_pyr_height
    397  5,              // gf_max_pyr_height
    398  AOM_TUNE_PSNR,  // tuning
    399  "/usr/local/share/model/vmaf_v0.6.1.json",  // VMAF model path
    400  ".",                                        // partition info path
    401  0,                                          // enable rate guide deltaq
    402  "./rate_map.txt",                           // rate distribution input
    403  AOM_DIST_METRIC_PSNR,                       // dist_metric
    404  10,                                         // cq_level
    405  300,                                        // rc_max_intra_bitrate_pct
    406  0,                                          // rc_max_inter_bitrate_pct
    407  0,                                          // gf_cbr_boost_pct
    408  0,                                          // lossless
    409  1,                                          // enable_cdef
    410  0,                                          // enable_restoration
    411  0,                                          // force_video_mode
    412  0,                                          // enable_obmc
    413  3,                                          // disable_trellis_quant
    414  0,                                          // enable_qm
    415  DEFAULT_QM_Y,                               // qm_y
    416  DEFAULT_QM_U,                               // qm_u
    417  DEFAULT_QM_V,                               // qm_v
    418  DEFAULT_QM_FIRST,                           // qm_min
    419  DEFAULT_QM_LAST,                            // qm_max
    420  1,                                          // max number of tile groups
    421  0,                                          // mtu_size
    422  AOM_TIMING_UNSPECIFIED,       // No picture timing signaling in bitstream
    423  0,                            // frame_parallel_decoding_mode
    424  0,                            // enable dual filter
    425  0,                            // enable delta quant in chroma planes
    426  CYCLIC_REFRESH_AQ,            // aq_mode
    427  NO_DELTA_Q,                   // deltaq_mode
    428  100,                          // deltaq_strength
    429  0,                            // delta lf mode
    430  0,                            // frame_periodic_boost
    431  AOM_CONTENT_DEFAULT,          // content
    432  AOM_CICP_CP_UNSPECIFIED,      // CICP color primaries
    433  AOM_CICP_TC_UNSPECIFIED,      // CICP transfer characteristics
    434  AOM_CICP_MC_UNSPECIFIED,      // CICP matrix coefficients
    435  AOM_CSP_UNKNOWN,              // chroma sample position
    436  0,                            // color range
    437  0,                            // render width
    438  0,                            // render height
    439  AOM_SUPERBLOCK_SIZE_DYNAMIC,  // superblock_size
    440  1,                            // this depends on large_scale_tile.
    441  0,                            // error_resilient_mode off by default.
    442  0,                            // s_frame_mode off by default.
    443  0,                            // film_grain_test_vector
    444  NULL,                         // film_grain_table_filename
    445  0,                            // motion_vector_unit_test
    446 #if CONFIG_FPMT_TEST
    447  0,  // fpmt_unit_test
    448 #endif
    449  1,    // CDF update mode
    450  0,    // enable rectangular partitions
    451  0,    // enable ab shape partitions
    452  0,    // enable 1:4 and 4:1 partitions
    453  4,    // min_partition_size
    454  128,  // max_partition_size
    455  0,    // enable intra edge filter
    456  0,    // frame order hint
    457  0,    // enable 64-pt transform usage
    458  1,    // enable flip and identity transform
    459  1,    // enable rectangular transform usage
    460  0,    // dist-wtd compound
    461  3,    // max_reference_frames
    462  0,    // enable_reduced_reference_set
    463  0,    // enable_ref_frame_mvs sequence level
    464  0,    // allow ref_frame_mvs frame level
    465  0,    // enable masked compound at sequence level
    466  0,    // enable one sided compound at sequence level
    467  0,    // enable interintra compound at sequence level
    468  0,    // enable smooth interintra mode
    469  0,    // enable difference-weighted compound
    470  0,    // enable interinter wedge compound
    471  0,    // enable interintra wedge compound
    472  0,    // enable_global_motion usage
    473  0,    // enable_warped_motion at sequence level
    474  0,    // allow_warped_motion at frame level
    475  0,    // enable filter intra at sequence level
    476  0,    // enable smooth intra modes usage for sequence
    477  0,    // enable Paeth intra mode usage for sequence
    478  0,    // enable CFL uv intra mode usage for sequence
    479  1,    // enable directional intra mode usage for sequence
    480  1,    // enable D45 to D203 intra mode usage for sequence
    481  0,    // superres
    482  0,    // enable overlay
    483  1,    // enable palette
    484  0,    // enable intrabc
    485  0,    // enable angle delta
    486 #if CONFIG_DENOISE
    487  0,   // noise_level
    488  32,  // noise_block_size
    489  1,   // enable_dnl_denoising
    490 #endif
    491 
    492  0,  // enable_low_complexity_decode
    493  0,  // chroma_subsampling_x
    494  0,  // chroma_subsampling_y
    495  0,  // reduced_tx_type_set
    496  0,  // use_intra_dct_only
    497  0,  // use_inter_dct_only
    498  1,  // use_intra_default_tx_only
    499  1,  // enable_tx_size_search
    500  0,  // quant_b_adapt
    501  0,  // vbr_corpus_complexity_lap
    502  {
    503      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    504      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    505      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    506      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    507      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    508      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    509      SEQ_LEVEL_MAX, SEQ_LEVEL_MAX,
    510  },               // target_seq_level_idx
    511  0,               // tier_mask
    512  0,               // min_cr
    513  COST_UPD_OFF,    // coeff_cost_upd_freq
    514  COST_UPD_OFF,    // mode_cost_upd_freq
    515  COST_UPD_OFF,    // mv_cost_upd_freq
    516  COST_UPD_OFF,    // dv_cost_upd_freq
    517  0,               // ext_tile_debug
    518  0,               // sb_multipass_unit_test
    519  -1,              // passes
    520  -1,              // fwd_kf_dist
    521  LOOPFILTER_ALL,  // loopfilter_control
    522  0,               // skip_postproc_filtering
    523  NULL,            // two_pass_output
    524  NULL,            // second_pass_log
    525  0,               // auto_intra_tools_off
    526  0,               // strict_level_conformance
    527  -1,              // kf_max_pyr_height
    528  0,               // sb_qp_sweep
    529  AOM_SCREEN_DETECTION_STANDARD,
    530 };
    531 #endif
    532 
    533 struct aom_codec_alg_priv {
    534  aom_codec_priv_t base;
    535  aom_codec_enc_cfg_t cfg;
    536  struct av1_extracfg extra_cfg;
    537  aom_rational64_t timestamp_ratio;
    538  aom_codec_pts_t pts_offset;
    539  unsigned char pts_offset_initialized;
    540  AV1EncoderConfig oxcf;
    541  AV1_PRIMARY *ppi;
    542  unsigned char *cx_data;
    543  size_t cx_data_sz;
    544  size_t pending_cx_data_sz;
    545  aom_image_t preview_img;
    546  aom_enc_frame_flags_t next_frame_flags;
    547  aom_codec_pkt_list_decl(256) pkt_list;
    548  unsigned int fixed_kf_cntr;
    549  // BufferPool that holds all reference frames.
    550  BufferPool *buffer_pool;
    551 
    552  // lookahead instance variables
    553  BufferPool *buffer_pool_lap;
    554  FIRSTPASS_STATS *frame_stats_buffer;
    555  // Number of stats buffers required for look ahead
    556  int num_lap_buffers;
    557  STATS_BUFFER_CTX stats_buf_context;
    558  bool monochrome_on_init;
    559 };
    560 
    561 static inline int gcd(int64_t a, int b) {
    562  int remainder;
    563  while (b > 0) {
    564    remainder = (int)(a % b);
    565    a = b;
    566    b = remainder;
    567  }
    568 
    569  return (int)a;
    570 }
    571 
    572 static void reduce_ratio(aom_rational64_t *ratio) {
    573  const int denom = gcd(ratio->num, ratio->den);
    574  ratio->num /= denom;
    575  ratio->den /= denom;
    576 }
    577 
    578 // Called by encoder_encode() only. Must not be called by encoder_init()
    579 // because the `error` paramerer will be destroyed by aom_codec_enc_init_ver()
    580 // after encoder_init() returns an error. See the "IMPORTANT" comment in
    581 // aom_codec_enc_init_ver().
    582 static aom_codec_err_t update_error_state(
    583    aom_codec_alg_priv_t *ctx, const struct aom_internal_error_info *error) {
    584  const aom_codec_err_t res = error->error_code;
    585 
    586  if (res != AOM_CODEC_OK)
    587    ctx->base.err_detail = error->has_detail ? error->detail : NULL;
    588 
    589  return res;
    590 }
    591 
    592 // This function deep copies a string src to *dst. For default string we will
    593 // use a string literal, and otherwise we will allocate memory for the string.
    594 static aom_codec_err_t allocate_and_set_string(const char *src,
    595                                               const char *default_src,
    596                                               const char **dst,
    597                                               char *err_detail) {
    598  if (!src) {
    599    snprintf(err_detail, ARG_ERR_MSG_MAX_LEN,
    600             "Null pointer given to a string parameter.");
    601    return AOM_CODEC_INVALID_PARAM;
    602  }
    603  if (*dst && strcmp(src, *dst) == 0) return AOM_CODEC_OK;
    604  // If the input is exactly the same as default, we will use the string
    605  // literal, so do not free here.
    606  if (*dst != default_src) {
    607    aom_free((void *)*dst);
    608  }
    609 
    610  if (default_src && strcmp(src, default_src) == 0) {
    611    // default_src should be a string literal
    612    *dst = default_src;
    613  } else {
    614    size_t len = strlen(src) + 1;
    615    char *tmp = aom_malloc(len * sizeof(*tmp));
    616    if (!tmp) {
    617      snprintf(err_detail, ARG_ERR_MSG_MAX_LEN,
    618               "Failed to allocate memory for copying parameters.");
    619      return AOM_CODEC_MEM_ERROR;
    620    }
    621    memcpy(tmp, src, len);
    622    *dst = tmp;
    623  }
    624  return 0;
    625 }
    626 
    627 #undef ERROR
    628 #define ERROR(str)                  \
    629  do {                              \
    630    ctx->base.err_detail = str;     \
    631    return AOM_CODEC_INVALID_PARAM; \
    632  } while (0)
    633 
    634 #define RANGE_CHECK(p, memb, lo, hi)                   \
    635  do {                                                 \
    636    if (!((p)->memb >= (lo) && (p)->memb <= (hi)))     \
    637      ERROR(#memb " out of range [" #lo ".." #hi "]"); \
    638  } while (0)
    639 
    640 #define RANGE_CHECK_HI(p, memb, hi)                                     \
    641  do {                                                                  \
    642    if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \
    643  } while (0)
    644 
    645 #define RANGE_CHECK_BOOL(p, memb)                                     \
    646  do {                                                                \
    647    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
    648  } while (0)
    649 
    650 static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
    651                                       const aom_codec_enc_cfg_t *cfg,
    652                                       const struct av1_extracfg *extra_cfg) {
    653  RANGE_CHECK(cfg, g_w, 1, 65536);                        // 16 bits available
    654  RANGE_CHECK(cfg, g_h, 1, 65536);                        // 16 bits available
    655  RANGE_CHECK_HI(cfg, g_forced_max_frame_width, 65536);   // 16 bits available
    656  RANGE_CHECK_HI(cfg, g_forced_max_frame_height, 65536);  // 16 bits available
    657  if (cfg->g_forced_max_frame_width) {
    658    RANGE_CHECK_HI(cfg, g_w, cfg->g_forced_max_frame_width);
    659  }
    660  if (cfg->g_forced_max_frame_height) {
    661    RANGE_CHECK_HI(cfg, g_h, cfg->g_forced_max_frame_height);
    662  }
    663  // To avoid integer overflows when multiplying width by height (or values
    664  // derived from width and height) using the int type, impose a maximum frame
    665  // area (width * height) of 2^30.
    666  const unsigned int max_frame_width =
    667      cfg->g_forced_max_frame_width ? cfg->g_forced_max_frame_width : cfg->g_w;
    668  const unsigned int max_frame_height = cfg->g_forced_max_frame_height
    669                                            ? cfg->g_forced_max_frame_height
    670                                            : cfg->g_h;
    671  const int64_t max_frame_area = (int64_t)max_frame_width * max_frame_height;
    672  if (max_frame_area > (1 << 30)) {
    673    ERROR("max_frame_area out of range [..2^30]");
    674  }
    675  RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
    676  RANGE_CHECK(cfg, g_timebase.num, 1, 1000000000);
    677  RANGE_CHECK_HI(cfg, g_profile, MAX_PROFILES - 1);
    678 
    679  RANGE_CHECK_HI(cfg, rc_target_bitrate, 2000000);
    680  RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
    681  RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
    682  RANGE_CHECK_BOOL(extra_cfg, lossless);
    683  RANGE_CHECK_HI(extra_cfg, aq_mode, AQ_MODE_COUNT - 1);
    684  RANGE_CHECK_HI(extra_cfg, deltaq_mode, DELTA_Q_MODE_COUNT - 1);
    685 
    686  if (cfg->g_usage != ALLINTRA &&
    687      extra_cfg->deltaq_mode == DELTA_Q_VARIANCE_BOOST) {
    688    ERROR("Variance Boost (deltaq_mode = 6) can only be set in all intra mode");
    689  }
    690 
    691  RANGE_CHECK_HI(extra_cfg, deltalf_mode, 1);
    692  RANGE_CHECK_HI(extra_cfg, frame_periodic_boost, 1);
    693 #if CONFIG_REALTIME_ONLY
    694  RANGE_CHECK(cfg, g_usage, AOM_USAGE_REALTIME, AOM_USAGE_REALTIME);
    695 #else
    696  RANGE_CHECK_HI(cfg, g_usage, AOM_USAGE_ALL_INTRA);
    697 #endif
    698  RANGE_CHECK_HI(cfg, g_threads, MAX_NUM_THREADS);
    699  RANGE_CHECK(cfg, rc_end_usage, AOM_VBR, AOM_Q);
    700  RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
    701  RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
    702  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
    703  RANGE_CHECK(cfg, kf_mode, AOM_KF_DISABLED, AOM_KF_AUTO);
    704  RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
    705  RANGE_CHECK(cfg, g_pass, AOM_RC_ONE_PASS, AOM_RC_THIRD_PASS);
    706  RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
    707  if (cfg->g_usage == AOM_USAGE_ALL_INTRA) {
    708    RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
    709    RANGE_CHECK_HI(cfg, kf_max_dist, 0);
    710  }
    711  RANGE_CHECK_HI(extra_cfg, min_gf_interval, MAX_LAG_BUFFERS - 1);
    712  RANGE_CHECK_HI(extra_cfg, max_gf_interval, MAX_LAG_BUFFERS - 1);
    713  if (extra_cfg->max_gf_interval > 0) {
    714    RANGE_CHECK(extra_cfg, max_gf_interval,
    715                AOMMAX(2, extra_cfg->min_gf_interval), (MAX_LAG_BUFFERS - 1));
    716  }
    717  RANGE_CHECK_HI(extra_cfg, gf_min_pyr_height, 5);
    718  RANGE_CHECK_HI(extra_cfg, gf_max_pyr_height, 5);
    719  if (extra_cfg->gf_min_pyr_height > extra_cfg->gf_max_pyr_height) {
    720    ERROR(
    721        "gf_min_pyr_height must be less than or equal to "
    722        "gf_max_pyramid_height");
    723  }
    724 
    725  RANGE_CHECK_HI(cfg, rc_resize_mode, RESIZE_MODES - 1);
    726  RANGE_CHECK(cfg, rc_resize_denominator, SCALE_NUMERATOR,
    727              SCALE_NUMERATOR << 1);
    728  RANGE_CHECK(cfg, rc_resize_kf_denominator, SCALE_NUMERATOR,
    729              SCALE_NUMERATOR << 1);
    730  RANGE_CHECK_HI(cfg, rc_superres_mode, AOM_SUPERRES_AUTO);
    731  RANGE_CHECK(cfg, rc_superres_denominator, SCALE_NUMERATOR,
    732              SCALE_NUMERATOR << 1);
    733  RANGE_CHECK(cfg, rc_superres_kf_denominator, SCALE_NUMERATOR,
    734              SCALE_NUMERATOR << 1);
    735  RANGE_CHECK(cfg, rc_superres_qthresh, 1, 63);
    736  RANGE_CHECK(cfg, rc_superres_kf_qthresh, 1, 63);
    737  RANGE_CHECK_HI(extra_cfg, cdf_update_mode, 2);
    738 
    739  RANGE_CHECK_HI(extra_cfg, motion_vector_unit_test, 2);
    740 #if CONFIG_FPMT_TEST
    741  RANGE_CHECK_HI(extra_cfg, fpmt_unit_test, 1);
    742 #endif
    743  RANGE_CHECK_HI(extra_cfg, sb_multipass_unit_test, 1);
    744  RANGE_CHECK_HI(extra_cfg, ext_tile_debug, 1);
    745  RANGE_CHECK_HI(extra_cfg, enable_auto_alt_ref, 1);
    746  RANGE_CHECK_HI(extra_cfg, enable_auto_bwd_ref, 2);
    747  RANGE_CHECK(extra_cfg, cpu_used, 0,
    748              (cfg->g_usage == AOM_USAGE_REALTIME) ? 12 : 9);
    749  RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
    750  RANGE_CHECK(extra_cfg, superblock_size, AOM_SUPERBLOCK_SIZE_64X64,
    751              AOM_SUPERBLOCK_SIZE_DYNAMIC);
    752  RANGE_CHECK_HI(cfg, large_scale_tile, 1);
    753  RANGE_CHECK_HI(extra_cfg, single_tile_decoding, 1);
    754  RANGE_CHECK_HI(extra_cfg, enable_rate_guide_deltaq, 1);
    755 
    756  RANGE_CHECK_HI(extra_cfg, row_mt, 1);
    757  RANGE_CHECK_HI(extra_cfg, fp_mt, 1);
    758 
    759  RANGE_CHECK_HI(extra_cfg, tile_columns, 6);
    760  RANGE_CHECK_HI(extra_cfg, tile_rows, 6);
    761  RANGE_CHECK_HI(extra_cfg, auto_tiles, 1);
    762 
    763  RANGE_CHECK_HI(cfg, monochrome, 1);
    764 
    765  if (cfg->large_scale_tile && extra_cfg->aq_mode)
    766    ERROR(
    767        "Adaptive quantization are not supported in large scale tile "
    768        "coding.");
    769 
    770  RANGE_CHECK_HI(extra_cfg, sharpness, 7);
    771  RANGE_CHECK_HI(extra_cfg, enable_adaptive_sharpness, 1);
    772  RANGE_CHECK_HI(extra_cfg, arnr_max_frames, 15);
    773  RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
    774  RANGE_CHECK_HI(extra_cfg, cq_level, 63);
    775  RANGE_CHECK(cfg, g_bit_depth, AOM_BITS_8, AOM_BITS_12);
    776  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
    777  RANGE_CHECK(extra_cfg, content, AOM_CONTENT_DEFAULT, AOM_CONTENT_INVALID - 1);
    778 
    779  if (cfg->g_pass >= AOM_RC_SECOND_PASS) {
    780    const size_t packet_sz = sizeof(FIRSTPASS_STATS);
    781    const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
    782    const FIRSTPASS_STATS *stats;
    783 
    784    if (cfg->rc_twopass_stats_in.buf == NULL)
    785      ERROR("rc_twopass_stats_in.buf not set.");
    786 
    787    if (cfg->rc_twopass_stats_in.sz % packet_sz)
    788      ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
    789 
    790    if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
    791      ERROR("rc_twopass_stats_in requires at least two packets.");
    792 
    793    stats =
    794        (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
    795 
    796    if ((int)(stats->count + 0.5) != n_packets - 1)
    797      ERROR("rc_twopass_stats_in missing EOS stats packet");
    798  }
    799 
    800  if (extra_cfg->passes != -1 && cfg->g_pass == AOM_RC_ONE_PASS &&
    801      extra_cfg->passes != 1) {
    802    ERROR("One pass encoding but passes != 1.");
    803  }
    804 
    805  if (extra_cfg->passes != -1 && (int)cfg->g_pass > extra_cfg->passes) {
    806    ERROR("Current pass is larger than total number of passes.");
    807  }
    808 
    809  if (cfg->g_profile == (unsigned int)PROFILE_1 && cfg->monochrome) {
    810    ERROR("Monochrome is not supported in profile 1");
    811  }
    812 
    813  if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
    814      cfg->g_bit_depth > AOM_BITS_10) {
    815    ERROR("Codec bit-depth 12 not supported in profile < 2");
    816  }
    817  if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
    818      cfg->g_input_bit_depth > 10) {
    819    ERROR("Source bit-depth 12 not supported in profile < 2");
    820  }
    821 
    822  if (cfg->rc_end_usage == AOM_Q) {
    823    RANGE_CHECK_HI(cfg, use_fixed_qp_offsets, 1);
    824  } else {
    825    if (cfg->use_fixed_qp_offsets > 0) {
    826      ERROR("--use_fixed_qp_offsets can only be used with --end-usage=q");
    827    }
    828  }
    829 
    830  RANGE_CHECK(extra_cfg, color_primaries, AOM_CICP_CP_BT_709,
    831              AOM_CICP_CP_EBU_3213);  // Need to check range more precisely to
    832                                      // check for reserved values?
    833  RANGE_CHECK(extra_cfg, transfer_characteristics, AOM_CICP_TC_BT_709,
    834              AOM_CICP_TC_HLG);
    835  RANGE_CHECK(extra_cfg, matrix_coefficients, AOM_CICP_MC_IDENTITY,
    836              AOM_CICP_MC_ICTCP);
    837  RANGE_CHECK(extra_cfg, color_range, 0, 1);
    838 
    839  /* Average corpus complexity is supported only in the case of single pass
    840   * VBR*/
    841  if (cfg->g_pass == AOM_RC_ONE_PASS && cfg->rc_end_usage == AOM_VBR)
    842    RANGE_CHECK_HI(extra_cfg, vbr_corpus_complexity_lap,
    843                   MAX_VBR_CORPUS_COMPLEXITY);
    844  else if (extra_cfg->vbr_corpus_complexity_lap != 0)
    845    ERROR(
    846        "VBR corpus complexity is supported only in the case of single pass "
    847        "VBR mode.");
    848 
    849 #if !CONFIG_TUNE_BUTTERAUGLI
    850  if (extra_cfg->tuning == AOM_TUNE_BUTTERAUGLI) {
    851    ERROR(
    852        "This error may be related to the wrong configuration options: try to "
    853        "set -DCONFIG_TUNE_BUTTERAUGLI=1 at the time CMake is run.");
    854  }
    855 #endif
    856 
    857 #if !CONFIG_TUNE_VMAF
    858  if (extra_cfg->tuning >= AOM_TUNE_VMAF_WITH_PREPROCESSING &&
    859      extra_cfg->tuning <= AOM_TUNE_VMAF_NEG_MAX_GAIN) {
    860    ERROR(
    861        "This error may be related to the wrong configuration options: try to "
    862        "set -DCONFIG_TUNE_VMAF=1 at the time CMake is run.");
    863  }
    864 #endif
    865 
    866  RANGE_CHECK(extra_cfg, tuning, AOM_TUNE_PSNR, AOM_TUNE_SSIMULACRA2);
    867 
    868  RANGE_CHECK(extra_cfg, dist_metric, AOM_DIST_METRIC_PSNR,
    869              AOM_DIST_METRIC_QM_PSNR);
    870 
    871  RANGE_CHECK(extra_cfg, timing_info_type, AOM_TIMING_UNSPECIFIED,
    872              AOM_TIMING_DEC_MODEL);
    873 
    874  RANGE_CHECK(extra_cfg, film_grain_test_vector, 0, 16);
    875 
    876  if (extra_cfg->lossless) {
    877    if (extra_cfg->aq_mode != 0)
    878      ERROR("Only --aq_mode=0 can be used with --lossless=1.");
    879    if (extra_cfg->enable_chroma_deltaq)
    880      ERROR("Only --enable_chroma_deltaq=0 can be used with --lossless=1.");
    881  }
    882 
    883  RANGE_CHECK(extra_cfg, max_reference_frames, 3, 7);
    884  RANGE_CHECK(extra_cfg, enable_reduced_reference_set, 0, 1);
    885 
    886  RANGE_CHECK_HI(extra_cfg, enable_low_complexity_decode, 1);
    887  RANGE_CHECK_HI(extra_cfg, chroma_subsampling_x, 1);
    888  RANGE_CHECK_HI(extra_cfg, chroma_subsampling_y, 1);
    889  // 6.4.2 Color config semantics
    890  // If matrix_coefficients is equal to MC_IDENTITY, it is a requirement of
    891  // bitstream conformance that subsampling_x is equal to 0 and subsampling_y
    892  // is equal to 0.
    893  if (extra_cfg->matrix_coefficients == AOM_CICP_MC_IDENTITY &&
    894      (extra_cfg->chroma_subsampling_x != 0 ||
    895       extra_cfg->chroma_subsampling_y != 0)) {
    896    ERROR("Subsampling must be 0 with AOM_CICP_MC_IDENTITY.");
    897  }
    898 
    899  RANGE_CHECK_HI(extra_cfg, disable_trellis_quant, 3);
    900  RANGE_CHECK(extra_cfg, coeff_cost_upd_freq, 0, 3);
    901  RANGE_CHECK(extra_cfg, mode_cost_upd_freq, 0, 3);
    902  RANGE_CHECK(extra_cfg, mv_cost_upd_freq, 0, 3);
    903  RANGE_CHECK(extra_cfg, dv_cost_upd_freq, 0, 3);
    904 
    905  RANGE_CHECK(extra_cfg, min_partition_size, 4, 128);
    906  RANGE_CHECK(extra_cfg, max_partition_size, 4, 128);
    907  RANGE_CHECK_HI(extra_cfg, min_partition_size, extra_cfg->max_partition_size);
    908 
    909  for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
    910    const int level_idx = extra_cfg->target_seq_level_idx[i];
    911    if (!is_valid_seq_level_idx(level_idx) &&
    912        level_idx != SEQ_LEVEL_KEEP_STATS) {
    913      ERROR("Target sequence level index is invalid");
    914    }
    915  }
    916 
    917  RANGE_CHECK_HI(extra_cfg, deltaq_strength, 1000);
    918  RANGE_CHECK_HI(extra_cfg, loopfilter_control, 3);
    919  RANGE_CHECK_BOOL(extra_cfg, skip_postproc_filtering);
    920  RANGE_CHECK_HI(extra_cfg, enable_cdef, 3);
    921  RANGE_CHECK_BOOL(extra_cfg, auto_intra_tools_off);
    922  RANGE_CHECK_BOOL(extra_cfg, strict_level_conformance);
    923  RANGE_CHECK_BOOL(extra_cfg, sb_qp_sweep);
    924 
    925  RANGE_CHECK(extra_cfg, kf_max_pyr_height, -1, 5);
    926  if (extra_cfg->kf_max_pyr_height != -1 &&
    927      extra_cfg->kf_max_pyr_height < (int)extra_cfg->gf_min_pyr_height) {
    928    ERROR(
    929        "The value of kf-max-pyr-height should not be smaller than "
    930        "gf-min-pyr-height");
    931  }
    932 
    933  RANGE_CHECK(extra_cfg, screen_detection_mode, 1, 2);
    934  return AOM_CODEC_OK;
    935 }
    936 
    937 static aom_codec_err_t validate_img(aom_codec_alg_priv_t *ctx,
    938                                    const aom_image_t *img) {
    939  switch (img->fmt) {
    940    case AOM_IMG_FMT_YV12:
    941    case AOM_IMG_FMT_NV12:
    942    case AOM_IMG_FMT_I420:
    943    case AOM_IMG_FMT_YV1216:
    944    case AOM_IMG_FMT_I42016: break;
    945    case AOM_IMG_FMT_I444:
    946    case AOM_IMG_FMT_I44416:
    947      if (ctx->cfg.g_profile == (unsigned int)PROFILE_0 &&
    948          !ctx->cfg.monochrome) {
    949        ERROR("Invalid image format. I444 images not supported in profile.");
    950      }
    951      break;
    952    case AOM_IMG_FMT_I422:
    953    case AOM_IMG_FMT_I42216:
    954      if (ctx->cfg.g_profile != (unsigned int)PROFILE_2) {
    955        ERROR("Invalid image format. I422 images not supported in profile.");
    956      }
    957      break;
    958    default:
    959      ERROR(
    960          "Invalid image format. Only YV12, NV12, I420, I422, I444 images are "
    961          "supported.");
    962      break;
    963  }
    964 
    965  if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
    966    ERROR("Image size must match encoder init configuration size");
    967 
    968  // 6.4.2 Color config semantics
    969  // If matrix_coefficients is equal to MC_IDENTITY, it is a requirement of
    970  // bitstream conformance that subsampling_x is equal to 0 and subsampling_y
    971  // is equal to 0.
    972  if (ctx->oxcf.color_cfg.matrix_coefficients == AOM_CICP_MC_IDENTITY &&
    973      (img->x_chroma_shift != 0 || img->y_chroma_shift != 0)) {
    974    ERROR("Subsampling must be 0 with AOM_CICP_MC_IDENTITY.");
    975  }
    976 
    977 #if CONFIG_TUNE_BUTTERAUGLI
    978  if (ctx->extra_cfg.tuning == AOM_TUNE_BUTTERAUGLI) {
    979    if (img->bit_depth > 8) {
    980      ERROR("Only 8 bit depth images supported in tune=butteraugli mode.");
    981    }
    982    if (img->mc != 0 && img->mc != AOM_CICP_MC_BT_709 &&
    983        img->mc != AOM_CICP_MC_BT_601 && img->mc != AOM_CICP_MC_BT_470_B_G) {
    984      ERROR(
    985          "Only BT.709 and BT.601 matrix coefficients supported in "
    986          "tune=butteraugli mode. Identity matrix is treated as BT.601.");
    987    }
    988  }
    989 #endif
    990 
    991  return AOM_CODEC_OK;
    992 }
    993 
    994 static int get_image_bps(const aom_image_t *img) {
    995  switch (img->fmt) {
    996    case AOM_IMG_FMT_YV12:
    997    case AOM_IMG_FMT_NV12:
    998    case AOM_IMG_FMT_I420: return 12;
    999    case AOM_IMG_FMT_I422: return 16;
   1000    case AOM_IMG_FMT_I444: return 24;
   1001    case AOM_IMG_FMT_YV1216:
   1002    case AOM_IMG_FMT_I42016: return 24;
   1003    case AOM_IMG_FMT_I42216: return 32;
   1004    case AOM_IMG_FMT_I44416: return 48;
   1005    default: assert(0 && "Invalid image format"); break;
   1006  }
   1007  return 0;
   1008 }
   1009 
   1010 // Set appropriate options to disable frame super-resolution.
   1011 static void disable_superres(SuperResCfg *const superres_cfg) {
   1012  superres_cfg->superres_mode = AOM_SUPERRES_NONE;
   1013  superres_cfg->superres_scale_denominator = SCALE_NUMERATOR;
   1014  superres_cfg->superres_kf_scale_denominator = SCALE_NUMERATOR;
   1015  superres_cfg->superres_qthresh = 255;
   1016  superres_cfg->superres_kf_qthresh = 255;
   1017 }
   1018 
   1019 static void set_auto_tiles(TileConfig *const tile_cfg, unsigned int width,
   1020                           unsigned int height, unsigned int threads) {
   1021  int tile_cols_log2 = 0;
   1022  int tile_rows_log2 = 0;
   1023  if (threads < 2) return;
   1024  // Avoid small tiles because they are particularly bad for coding.
   1025  // Use no more tiles than the number of threads. Aim for one tile per
   1026  // thread. Using more than one thread inside one tile could be less
   1027  // efficient. Using more tiles than the number of threads would result
   1028  // in a compression penalty without much benefit.
   1029  const uint32_t kMinTileArea = 128 * 128;
   1030  const uint32_t kMaxTiles = 32;
   1031  uint32_t frame_area = width * height;
   1032  uint32_t tiles = (frame_area + kMinTileArea - 1) / kMinTileArea;
   1033  if (tiles > kMaxTiles) {
   1034    tiles = kMaxTiles;
   1035  }
   1036  if (tiles > threads) {
   1037    tiles = threads;
   1038  }
   1039  int tiles_log2 = (int)log2(tiles);
   1040  // If the frame width is equal or greater than the height, use more tile
   1041  // columns than tile rows.
   1042  if (width >= height) {
   1043    tile_cols_log2 = (tiles_log2 + 1) / 2;
   1044    tile_rows_log2 = tiles_log2 - tile_cols_log2;
   1045  } else {
   1046    tile_rows_log2 = (tiles_log2 + 1) / 2;
   1047    tile_cols_log2 = tiles_log2 - tile_rows_log2;
   1048  }
   1049  tile_cfg->tile_columns = tile_cols_log2;
   1050  tile_cfg->tile_rows = tile_rows_log2;
   1051 }
   1052 
   1053 static void update_default_encoder_config(const cfg_options_t *cfg,
   1054                                          struct av1_extracfg *extra_cfg) {
   1055  extra_cfg->enable_cdef = (cfg->disable_cdef == 0) ? 1 : 0;
   1056  extra_cfg->enable_restoration = (cfg->disable_lr == 0);
   1057  extra_cfg->superblock_size =
   1058      (cfg->super_block_size == 64)    ? AOM_SUPERBLOCK_SIZE_64X64
   1059      : (cfg->super_block_size == 128) ? AOM_SUPERBLOCK_SIZE_128X128
   1060                                       : AOM_SUPERBLOCK_SIZE_DYNAMIC;
   1061  extra_cfg->enable_warped_motion = (cfg->disable_warp_motion == 0);
   1062  extra_cfg->enable_dist_wtd_comp = (cfg->disable_dist_wtd_comp == 0);
   1063  extra_cfg->enable_diff_wtd_comp = (cfg->disable_diff_wtd_comp == 0);
   1064  extra_cfg->enable_dual_filter = (cfg->disable_dual_filter == 0);
   1065  extra_cfg->enable_angle_delta = (cfg->disable_intra_angle_delta == 0);
   1066  extra_cfg->enable_rect_partitions = (cfg->disable_rect_partition_type == 0);
   1067  extra_cfg->enable_ab_partitions = (cfg->disable_ab_partition_type == 0);
   1068  extra_cfg->enable_1to4_partitions = (cfg->disable_1to4_partition_type == 0);
   1069  extra_cfg->max_partition_size = cfg->max_partition_size;
   1070  extra_cfg->min_partition_size = cfg->min_partition_size;
   1071  extra_cfg->enable_intra_edge_filter = (cfg->disable_intra_edge_filter == 0);
   1072  extra_cfg->enable_tx64 = (cfg->disable_tx_64x64 == 0);
   1073  extra_cfg->enable_flip_idtx = (cfg->disable_flip_idtx == 0);
   1074  extra_cfg->enable_masked_comp = (cfg->disable_masked_comp == 0);
   1075  extra_cfg->enable_interintra_comp = (cfg->disable_inter_intra_comp == 0);
   1076  extra_cfg->enable_smooth_interintra = (cfg->disable_smooth_inter_intra == 0);
   1077  extra_cfg->enable_interinter_wedge = (cfg->disable_inter_inter_wedge == 0);
   1078  extra_cfg->enable_interintra_wedge = (cfg->disable_inter_intra_wedge == 0);
   1079  extra_cfg->enable_global_motion = (cfg->disable_global_motion == 0);
   1080  extra_cfg->enable_filter_intra = (cfg->disable_filter_intra == 0);
   1081  extra_cfg->enable_smooth_intra = (cfg->disable_smooth_intra == 0);
   1082  extra_cfg->enable_paeth_intra = (cfg->disable_paeth_intra == 0);
   1083  extra_cfg->enable_cfl_intra = (cfg->disable_cfl == 0);
   1084  extra_cfg->enable_obmc = (cfg->disable_obmc == 0);
   1085  extra_cfg->enable_palette = (cfg->disable_palette == 0);
   1086  extra_cfg->enable_intrabc = (cfg->disable_intrabc == 0);
   1087  extra_cfg->disable_trellis_quant = cfg->disable_trellis_quant;
   1088  extra_cfg->allow_ref_frame_mvs = (cfg->disable_ref_frame_mv == 0);
   1089  extra_cfg->enable_ref_frame_mvs = (cfg->disable_ref_frame_mv == 0);
   1090  extra_cfg->enable_onesided_comp = (cfg->disable_one_sided_comp == 0);
   1091  extra_cfg->enable_reduced_reference_set = cfg->reduced_reference_set;
   1092  extra_cfg->reduced_tx_type_set = cfg->reduced_tx_type_set;
   1093 }
   1094 
   1095 static void set_encoder_config(AV1EncoderConfig *oxcf,
   1096                               const aom_codec_enc_cfg_t *cfg,
   1097                               struct av1_extracfg *extra_cfg) {
   1098  if (cfg->encoder_cfg.init_by_cfg_file) {
   1099    update_default_encoder_config(&cfg->encoder_cfg, extra_cfg);
   1100  }
   1101 
   1102  TuneCfg *const tune_cfg = &oxcf->tune_cfg;
   1103  FrameDimensionCfg *const frm_dim_cfg = &oxcf->frm_dim_cfg;
   1104  TileConfig *const tile_cfg = &oxcf->tile_cfg;
   1105  ResizeCfg *const resize_cfg = &oxcf->resize_cfg;
   1106  GFConfig *const gf_cfg = &oxcf->gf_cfg;
   1107  PartitionCfg *const part_cfg = &oxcf->part_cfg;
   1108  IntraModeCfg *const intra_mode_cfg = &oxcf->intra_mode_cfg;
   1109  TxfmSizeTypeCfg *const txfm_cfg = &oxcf->txfm_cfg;
   1110  CompoundTypeCfg *const comp_type_cfg = &oxcf->comp_type_cfg;
   1111  SuperResCfg *const superres_cfg = &oxcf->superres_cfg;
   1112  KeyFrameCfg *const kf_cfg = &oxcf->kf_cfg;
   1113  DecoderModelCfg *const dec_model_cfg = &oxcf->dec_model_cfg;
   1114  RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
   1115  QuantizationCfg *const q_cfg = &oxcf->q_cfg;
   1116  ColorCfg *const color_cfg = &oxcf->color_cfg;
   1117  InputCfg *const input_cfg = &oxcf->input_cfg;
   1118  AlgoCfg *const algo_cfg = &oxcf->algo_cfg;
   1119  ToolCfg *const tool_cfg = &oxcf->tool_cfg;
   1120 
   1121  oxcf->profile = cfg->g_profile;
   1122  oxcf->max_threads = (int)cfg->g_threads;
   1123 
   1124  switch (cfg->g_usage) {
   1125    case AOM_USAGE_REALTIME: oxcf->mode = REALTIME; break;
   1126    case AOM_USAGE_ALL_INTRA: oxcf->mode = ALLINTRA; break;
   1127    default: oxcf->mode = GOOD; break;
   1128  }
   1129 
   1130  // Set frame-dimension related configuration.
   1131  frm_dim_cfg->width = cfg->g_w;
   1132  frm_dim_cfg->height = cfg->g_h;
   1133  frm_dim_cfg->forced_max_frame_width = cfg->g_forced_max_frame_width;
   1134  frm_dim_cfg->forced_max_frame_height = cfg->g_forced_max_frame_height;
   1135  frm_dim_cfg->render_width = extra_cfg->render_width;
   1136  frm_dim_cfg->render_height = extra_cfg->render_height;
   1137 
   1138  // Set input video related configuration.
   1139  input_cfg->input_bit_depth = cfg->g_input_bit_depth;
   1140  // guess a frame rate if out of whack, use 30
   1141  input_cfg->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
   1142  if (cfg->g_pass >= AOM_RC_SECOND_PASS) {
   1143    const size_t packet_sz = sizeof(FIRSTPASS_STATS);
   1144    const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
   1145    input_cfg->limit = n_packets - 1;
   1146  } else {
   1147    input_cfg->limit = cfg->g_limit;
   1148  }
   1149  input_cfg->chroma_subsampling_x = extra_cfg->chroma_subsampling_x;
   1150  input_cfg->chroma_subsampling_y = extra_cfg->chroma_subsampling_y;
   1151  if (input_cfg->init_framerate > 180) {
   1152    input_cfg->init_framerate = 30;
   1153    dec_model_cfg->timing_info_present = 0;
   1154  }
   1155 
   1156  // Set Decoder model configuration.
   1157  if (extra_cfg->timing_info_type == AOM_TIMING_EQUAL ||
   1158      extra_cfg->timing_info_type == AOM_TIMING_DEC_MODEL) {
   1159    dec_model_cfg->timing_info_present = 1;
   1160    dec_model_cfg->timing_info.num_units_in_display_tick = cfg->g_timebase.num;
   1161    dec_model_cfg->timing_info.time_scale = cfg->g_timebase.den;
   1162    dec_model_cfg->timing_info.num_ticks_per_picture = 1;
   1163  } else {
   1164    dec_model_cfg->timing_info_present = 0;
   1165  }
   1166  if (extra_cfg->timing_info_type == AOM_TIMING_EQUAL) {
   1167    dec_model_cfg->timing_info.equal_picture_interval = 1;
   1168    dec_model_cfg->decoder_model_info_present_flag = 0;
   1169    dec_model_cfg->display_model_info_present_flag = 1;
   1170  } else if (extra_cfg->timing_info_type == AOM_TIMING_DEC_MODEL) {
   1171    dec_model_cfg->num_units_in_decoding_tick = cfg->g_timebase.num;
   1172    dec_model_cfg->timing_info.equal_picture_interval = 0;
   1173    dec_model_cfg->decoder_model_info_present_flag = 1;
   1174    dec_model_cfg->display_model_info_present_flag = 1;
   1175  }
   1176 
   1177  oxcf->pass = cfg->g_pass;
   1178  // For backward compatibility, assume that if extra_cfg->passes==-1, then
   1179  // passes = 1 or 2.
   1180  if (extra_cfg->passes == -1) {
   1181    if (cfg->g_pass == AOM_RC_ONE_PASS) {
   1182      oxcf->passes = 1;
   1183    } else {
   1184      oxcf->passes = 2;
   1185    }
   1186  } else {
   1187    oxcf->passes = extra_cfg->passes;
   1188  }
   1189 
   1190  // Set Rate Control configuration.
   1191  rc_cfg->max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
   1192  rc_cfg->max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct;
   1193  rc_cfg->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct;
   1194  rc_cfg->mode = cfg->rc_end_usage;
   1195  rc_cfg->min_cr = extra_cfg->min_cr;
   1196  rc_cfg->best_allowed_q =
   1197      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_min_quantizer);
   1198  rc_cfg->worst_allowed_q =
   1199      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_max_quantizer);
   1200  rc_cfg->cq_level = av1_quantizer_to_qindex(extra_cfg->cq_level);
   1201  rc_cfg->under_shoot_pct = cfg->rc_undershoot_pct;
   1202  rc_cfg->over_shoot_pct = cfg->rc_overshoot_pct;
   1203  rc_cfg->maximum_buffer_size_ms = cfg->rc_buf_sz;
   1204  rc_cfg->starting_buffer_level_ms = cfg->rc_buf_initial_sz;
   1205  rc_cfg->optimal_buffer_level_ms = cfg->rc_buf_optimal_sz;
   1206  // Convert target bandwidth from Kbit/s to Bit/s
   1207  rc_cfg->target_bandwidth = 1000 * cfg->rc_target_bitrate;
   1208  rc_cfg->drop_frames_water_mark = cfg->rc_dropframe_thresh;
   1209  rc_cfg->vbr_corpus_complexity_lap = extra_cfg->vbr_corpus_complexity_lap;
   1210  rc_cfg->vbrbias = cfg->rc_2pass_vbr_bias_pct;
   1211  rc_cfg->vbrmin_section = cfg->rc_2pass_vbr_minsection_pct;
   1212  rc_cfg->vbrmax_section = cfg->rc_2pass_vbr_maxsection_pct;
   1213 
   1214  // Set Toolset related configuration.
   1215  tool_cfg->bit_depth = cfg->g_bit_depth;
   1216  tool_cfg->cdef_control = (CDEF_CONTROL)extra_cfg->enable_cdef;
   1217  tool_cfg->enable_restoration =
   1218      (cfg->g_usage == AOM_USAGE_REALTIME) ? 0 : extra_cfg->enable_restoration;
   1219  tool_cfg->force_video_mode = extra_cfg->force_video_mode;
   1220  tool_cfg->enable_palette = extra_cfg->enable_palette;
   1221  // FIXME(debargha): Should this be:
   1222  // tool_cfg->enable_ref_frame_mvs  = extra_cfg->allow_ref_frame_mvs &
   1223  //                                         extra_cfg->enable_order_hint ?
   1224  // Disallow using temporal MVs while large_scale_tile = 1.
   1225  tool_cfg->enable_ref_frame_mvs =
   1226      extra_cfg->allow_ref_frame_mvs && !cfg->large_scale_tile;
   1227  tool_cfg->superblock_size = extra_cfg->superblock_size;
   1228  tool_cfg->enable_monochrome = cfg->monochrome;
   1229  tool_cfg->full_still_picture_hdr = cfg->full_still_picture_hdr != 0;
   1230  tool_cfg->enable_dual_filter = extra_cfg->enable_dual_filter;
   1231  tool_cfg->enable_order_hint = extra_cfg->enable_order_hint;
   1232  tool_cfg->enable_interintra_comp = extra_cfg->enable_interintra_comp;
   1233  tool_cfg->ref_frame_mvs_present =
   1234      extra_cfg->enable_ref_frame_mvs & extra_cfg->enable_order_hint;
   1235 
   1236  // Explicitly disable global motion in a few cases:
   1237  // * For realtime mode, we never search global motion, and disabling
   1238  //   it here prevents later code from allocating buffers we don't need
   1239  // * For large scale tile mode, some of the intended use cases expect
   1240  //   all frame headers to be identical. This breaks if global motion is
   1241  //   used, since global motion data is stored in the frame header.
   1242  //   eg, see test/lightfield_test.sh, which checks that all frame headers
   1243  //   are the same.
   1244  tool_cfg->enable_global_motion = extra_cfg->enable_global_motion &&
   1245                                   cfg->g_usage != AOM_USAGE_REALTIME &&
   1246                                   !cfg->large_scale_tile;
   1247 
   1248  tool_cfg->error_resilient_mode =
   1249      cfg->g_error_resilient | extra_cfg->error_resilient_mode;
   1250  tool_cfg->frame_parallel_decoding_mode =
   1251      extra_cfg->frame_parallel_decoding_mode;
   1252 
   1253  // Set Quantization related configuration.
   1254  q_cfg->using_qm = extra_cfg->enable_qm;
   1255  q_cfg->qm_minlevel = extra_cfg->qm_min;
   1256  q_cfg->qm_maxlevel = extra_cfg->qm_max;
   1257  q_cfg->quant_b_adapt = extra_cfg->quant_b_adapt;
   1258  q_cfg->enable_chroma_deltaq = extra_cfg->enable_chroma_deltaq;
   1259  q_cfg->aq_mode = extra_cfg->aq_mode;
   1260  q_cfg->deltaq_mode = extra_cfg->deltaq_mode;
   1261  q_cfg->deltaq_strength = extra_cfg->deltaq_strength;
   1262  q_cfg->use_fixed_qp_offsets =
   1263      cfg->use_fixed_qp_offsets && (rc_cfg->mode == AOM_Q);
   1264  q_cfg->enable_hdr_deltaq =
   1265      (q_cfg->deltaq_mode == DELTA_Q_HDR) &&
   1266      (cfg->g_bit_depth == AOM_BITS_10) &&
   1267      (extra_cfg->color_primaries == AOM_CICP_CP_BT_2020);
   1268 
   1269  tool_cfg->enable_deltalf_mode =
   1270      (q_cfg->deltaq_mode != NO_DELTA_Q) && extra_cfg->deltalf_mode;
   1271 
   1272  // Set cost update frequency configuration.
   1273  oxcf->cost_upd_freq.coeff = (COST_UPDATE_TYPE)extra_cfg->coeff_cost_upd_freq;
   1274  oxcf->cost_upd_freq.mode = (COST_UPDATE_TYPE)extra_cfg->mode_cost_upd_freq;
   1275  // Avoid MV cost update for allintra encoding mode.
   1276  oxcf->cost_upd_freq.mv = (cfg->kf_max_dist != 0)
   1277                               ? (COST_UPDATE_TYPE)extra_cfg->mv_cost_upd_freq
   1278                               : COST_UPD_OFF;
   1279  oxcf->cost_upd_freq.dv = (COST_UPDATE_TYPE)extra_cfg->dv_cost_upd_freq;
   1280 
   1281  // Set frame resize mode configuration.
   1282  resize_cfg->resize_mode = (RESIZE_MODE)cfg->rc_resize_mode;
   1283  resize_cfg->resize_scale_denominator = (uint8_t)cfg->rc_resize_denominator;
   1284  resize_cfg->resize_kf_scale_denominator =
   1285      (uint8_t)cfg->rc_resize_kf_denominator;
   1286  if (resize_cfg->resize_mode == RESIZE_FIXED &&
   1287      resize_cfg->resize_scale_denominator == SCALE_NUMERATOR &&
   1288      resize_cfg->resize_kf_scale_denominator == SCALE_NUMERATOR)
   1289    resize_cfg->resize_mode = RESIZE_NONE;
   1290 
   1291  // Set encoder algorithm related configuration.
   1292  algo_cfg->enable_overlay = extra_cfg->enable_overlay;
   1293  algo_cfg->disable_trellis_quant = extra_cfg->disable_trellis_quant;
   1294  algo_cfg->sharpness = extra_cfg->sharpness;
   1295  algo_cfg->enable_adaptive_sharpness = extra_cfg->enable_adaptive_sharpness;
   1296  algo_cfg->arnr_max_frames = extra_cfg->arnr_max_frames;
   1297  algo_cfg->arnr_strength = extra_cfg->arnr_strength;
   1298  algo_cfg->cdf_update_mode = (uint8_t)extra_cfg->cdf_update_mode;
   1299  // TODO(any): Fix and Enable TPL for resize-mode > 0
   1300  algo_cfg->enable_tpl_model =
   1301      resize_cfg->resize_mode ? 0 : extra_cfg->enable_tpl_model;
   1302  algo_cfg->loopfilter_control = extra_cfg->loopfilter_control;
   1303  algo_cfg->skip_postproc_filtering = extra_cfg->skip_postproc_filtering;
   1304  algo_cfg->screen_detection_mode = extra_cfg->screen_detection_mode;
   1305 
   1306  // Set two-pass stats configuration.
   1307  oxcf->twopass_stats_in = cfg->rc_twopass_stats_in;
   1308 
   1309  if (extra_cfg->two_pass_output)
   1310    oxcf->two_pass_output = extra_cfg->two_pass_output;
   1311 
   1312  oxcf->second_pass_log = extra_cfg->second_pass_log;
   1313 
   1314  // Set Key frame configuration.
   1315  kf_cfg->fwd_kf_enabled = cfg->fwd_kf_enabled;
   1316  kf_cfg->auto_key =
   1317      cfg->kf_mode == AOM_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
   1318  kf_cfg->key_freq_min = cfg->kf_min_dist;
   1319  kf_cfg->key_freq_max = cfg->kf_max_dist;
   1320  kf_cfg->sframe_dist = cfg->sframe_dist;
   1321  kf_cfg->sframe_mode = cfg->sframe_mode;
   1322  kf_cfg->enable_sframe = extra_cfg->s_frame_mode;
   1323  kf_cfg->enable_keyframe_filtering = extra_cfg->enable_keyframe_filtering;
   1324  kf_cfg->fwd_kf_dist = extra_cfg->fwd_kf_dist;
   1325  // Disable key frame filtering in all intra mode.
   1326  if (cfg->kf_max_dist == 0) {
   1327    kf_cfg->enable_keyframe_filtering = 0;
   1328  }
   1329  kf_cfg->enable_intrabc = extra_cfg->enable_intrabc;
   1330 
   1331  oxcf->speed = extra_cfg->cpu_used;
   1332  // TODO(yunqingwang, any) In REALTIME mode, 1080p performance at speed 5 & 6
   1333  // is quite bad. Force to use speed 7 for now. Will investigate it when we
   1334  // work on rd path optimization later.
   1335  if (oxcf->mode == REALTIME && AOMMIN(cfg->g_w, cfg->g_h) >= 1080 &&
   1336      oxcf->speed < 7)
   1337    oxcf->speed = 7;
   1338 
   1339  // Now, low complexity decode mode is only supported for good-quality
   1340  // encoding speed 1 to 3 and for vertical videos with a resolution between
   1341  // 608p and 720p. This can be further modified if needed.
   1342  const int is_low_complexity_decode_mode_supported =
   1343      (cfg->g_usage == AOM_USAGE_GOOD_QUALITY) &&
   1344      (oxcf->speed >= 1 && oxcf->speed <= 3) && (cfg->g_w < cfg->g_h) &&
   1345      (AOMMIN(cfg->g_w, cfg->g_h) >= 608 && AOMMIN(cfg->g_w, cfg->g_h) <= 720);
   1346  oxcf->enable_low_complexity_decode =
   1347      extra_cfg->enable_low_complexity_decode &&
   1348      is_low_complexity_decode_mode_supported;
   1349 
   1350  // Set Color related configuration.
   1351  color_cfg->color_primaries = extra_cfg->color_primaries;
   1352  color_cfg->transfer_characteristics = extra_cfg->transfer_characteristics;
   1353  color_cfg->matrix_coefficients = extra_cfg->matrix_coefficients;
   1354  color_cfg->color_range = extra_cfg->color_range;
   1355  color_cfg->chroma_sample_position = extra_cfg->chroma_sample_position;
   1356 
   1357  // Set Group of frames configuration.
   1358  // Force lag_in_frames to 0 for REALTIME mode
   1359  gf_cfg->lag_in_frames = (oxcf->mode == REALTIME)
   1360                              ? 0
   1361                              : clamp(cfg->g_lag_in_frames, 0, MAX_LAG_BUFFERS);
   1362  gf_cfg->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
   1363  gf_cfg->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
   1364  gf_cfg->min_gf_interval = extra_cfg->min_gf_interval;
   1365  gf_cfg->max_gf_interval = extra_cfg->max_gf_interval;
   1366  gf_cfg->gf_min_pyr_height = extra_cfg->gf_min_pyr_height;
   1367  gf_cfg->gf_max_pyr_height = extra_cfg->gf_max_pyr_height;
   1368 
   1369  // Set tune related configuration.
   1370  tune_cfg->tuning = extra_cfg->tuning;
   1371  tune_cfg->vmaf_model_path = extra_cfg->vmaf_model_path;
   1372  tune_cfg->content = extra_cfg->content;
   1373  if (cfg->large_scale_tile) {
   1374    tune_cfg->film_grain_test_vector = 0;
   1375    tune_cfg->film_grain_table_filename = NULL;
   1376  } else {
   1377    tune_cfg->film_grain_test_vector = extra_cfg->film_grain_test_vector;
   1378    tune_cfg->film_grain_table_filename = extra_cfg->film_grain_table_filename;
   1379  }
   1380  tune_cfg->dist_metric = extra_cfg->dist_metric;
   1381 #if CONFIG_DENOISE
   1382  oxcf->noise_level = extra_cfg->noise_level;
   1383  oxcf->noise_block_size = extra_cfg->noise_block_size;
   1384  oxcf->enable_dnl_denoising = extra_cfg->enable_dnl_denoising;
   1385 #endif
   1386 
   1387 #if CONFIG_AV1_TEMPORAL_DENOISING
   1388  // Temporal denoiser is for nonrd pickmode so disable it for speed < 7.
   1389  // Also disable it for speed 7 for now since it needs to be modified for
   1390  // the check_partition_merge_mode feature.
   1391  if (cfg->g_bit_depth == AOM_BITS_8 && oxcf->speed > 7) {
   1392    oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
   1393  } else {
   1394    oxcf->noise_sensitivity = 0;
   1395  }
   1396 #endif
   1397  // Set Tile related configuration.
   1398  tile_cfg->num_tile_groups = extra_cfg->num_tg;
   1399  // In large-scale tile encoding mode, num_tile_groups is always 1.
   1400  if (cfg->large_scale_tile) tile_cfg->num_tile_groups = 1;
   1401  tile_cfg->mtu = extra_cfg->mtu_size;
   1402  tile_cfg->enable_large_scale_tile = cfg->large_scale_tile;
   1403  tile_cfg->enable_single_tile_decoding =
   1404      (tile_cfg->enable_large_scale_tile) ? extra_cfg->single_tile_decoding : 0;
   1405  if (extra_cfg->auto_tiles) {
   1406    set_auto_tiles(tile_cfg, cfg->g_w, cfg->g_h, cfg->g_threads);
   1407    extra_cfg->tile_columns = tile_cfg->tile_columns;
   1408    extra_cfg->tile_rows = tile_cfg->tile_rows;
   1409  } else {
   1410    tile_cfg->tile_columns = extra_cfg->tile_columns;
   1411    tile_cfg->tile_rows = extra_cfg->tile_rows;
   1412  }
   1413  tile_cfg->tile_width_count = AOMMIN(cfg->tile_width_count, MAX_TILE_COLS);
   1414  tile_cfg->tile_height_count = AOMMIN(cfg->tile_height_count, MAX_TILE_ROWS);
   1415  for (int i = 0; i < tile_cfg->tile_width_count; i++) {
   1416    tile_cfg->tile_widths[i] = cfg->tile_widths[i];
   1417  }
   1418  for (int i = 0; i < tile_cfg->tile_height_count; i++) {
   1419    tile_cfg->tile_heights[i] = cfg->tile_heights[i];
   1420  }
   1421  tile_cfg->enable_ext_tile_debug = extra_cfg->ext_tile_debug;
   1422 
   1423  if (tile_cfg->enable_large_scale_tile) {
   1424    // The superblock_size can only be AOM_SUPERBLOCK_SIZE_64X64 or
   1425    // AOM_SUPERBLOCK_SIZE_128X128 while tile_cfg->enable_large_scale_tile = 1.
   1426    // If superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC, hard set it to
   1427    // AOM_SUPERBLOCK_SIZE_64X64(default value in large_scale_tile).
   1428    if (extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_64X64 &&
   1429        extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_128X128)
   1430      tool_cfg->superblock_size = AOM_SUPERBLOCK_SIZE_64X64;
   1431  }
   1432 
   1433  // Set reference frame related configuration.
   1434  oxcf->ref_frm_cfg.max_reference_frames = extra_cfg->max_reference_frames;
   1435  oxcf->ref_frm_cfg.enable_reduced_reference_set =
   1436      extra_cfg->enable_reduced_reference_set;
   1437  oxcf->ref_frm_cfg.enable_onesided_comp = extra_cfg->enable_onesided_comp;
   1438 
   1439  oxcf->row_mt = extra_cfg->row_mt;
   1440  oxcf->fp_mt = extra_cfg->fp_mt;
   1441 
   1442  // Set motion mode related configuration.
   1443  oxcf->motion_mode_cfg.enable_obmc = extra_cfg->enable_obmc;
   1444  oxcf->motion_mode_cfg.enable_warped_motion = extra_cfg->enable_warped_motion;
   1445 #if !CONFIG_REALTIME_ONLY
   1446  if (cfg->g_usage == AOM_USAGE_REALTIME && oxcf->speed >= 7 &&
   1447      oxcf->tune_cfg.content == AOM_CONTENT_SCREEN) {
   1448    // TODO(marpan): warped motion is causing a crash for RT mode with screen
   1449    // in nonrd (speed >= 7), for non-realtime build.
   1450    // Re-enable/allow when the issue is fixed.
   1451    oxcf->motion_mode_cfg.enable_warped_motion = 0;
   1452    oxcf->motion_mode_cfg.allow_warped_motion = 0;
   1453  } else {
   1454    oxcf->motion_mode_cfg.allow_warped_motion =
   1455        (extra_cfg->allow_warped_motion & extra_cfg->enable_warped_motion);
   1456  }
   1457 #else
   1458  oxcf->motion_mode_cfg.allow_warped_motion =
   1459      (cfg->g_usage == AOM_USAGE_REALTIME && oxcf->speed >= 7)
   1460          ? false
   1461          : (extra_cfg->allow_warped_motion & extra_cfg->enable_warped_motion);
   1462 #endif
   1463 
   1464  // Set partition related configuration.
   1465  part_cfg->enable_rect_partitions = extra_cfg->enable_rect_partitions;
   1466  part_cfg->enable_ab_partitions = extra_cfg->enable_ab_partitions;
   1467  part_cfg->enable_1to4_partitions = extra_cfg->enable_1to4_partitions;
   1468  part_cfg->min_partition_size = extra_cfg->min_partition_size;
   1469  part_cfg->max_partition_size = extra_cfg->max_partition_size;
   1470 
   1471  // Set intra mode configuration.
   1472  intra_mode_cfg->enable_angle_delta = extra_cfg->enable_angle_delta;
   1473  intra_mode_cfg->enable_intra_edge_filter =
   1474      extra_cfg->enable_intra_edge_filter;
   1475  intra_mode_cfg->enable_filter_intra = extra_cfg->enable_filter_intra;
   1476  intra_mode_cfg->enable_smooth_intra = extra_cfg->enable_smooth_intra;
   1477  intra_mode_cfg->enable_paeth_intra = extra_cfg->enable_paeth_intra;
   1478  intra_mode_cfg->enable_cfl_intra = extra_cfg->enable_cfl_intra;
   1479  intra_mode_cfg->enable_directional_intra =
   1480      extra_cfg->enable_directional_intra;
   1481  intra_mode_cfg->enable_diagonal_intra = extra_cfg->enable_diagonal_intra;
   1482  intra_mode_cfg->auto_intra_tools_off = extra_cfg->auto_intra_tools_off;
   1483 
   1484  // Set transform size/type configuration.
   1485  txfm_cfg->enable_tx64 = extra_cfg->enable_tx64;
   1486  txfm_cfg->enable_flip_idtx = extra_cfg->enable_flip_idtx;
   1487  txfm_cfg->enable_rect_tx = extra_cfg->enable_rect_tx;
   1488  txfm_cfg->reduced_tx_type_set = extra_cfg->reduced_tx_type_set;
   1489  txfm_cfg->use_intra_dct_only = extra_cfg->use_intra_dct_only;
   1490  txfm_cfg->use_inter_dct_only = extra_cfg->use_inter_dct_only;
   1491  txfm_cfg->use_intra_default_tx_only = extra_cfg->use_intra_default_tx_only;
   1492  txfm_cfg->enable_tx_size_search = extra_cfg->enable_tx_size_search;
   1493 
   1494  // Set compound type configuration.
   1495  comp_type_cfg->enable_dist_wtd_comp =
   1496      extra_cfg->enable_dist_wtd_comp & extra_cfg->enable_order_hint;
   1497  comp_type_cfg->enable_masked_comp = extra_cfg->enable_masked_comp;
   1498  comp_type_cfg->enable_diff_wtd_comp =
   1499      extra_cfg->enable_masked_comp & extra_cfg->enable_diff_wtd_comp;
   1500  comp_type_cfg->enable_interinter_wedge =
   1501      extra_cfg->enable_masked_comp & extra_cfg->enable_interinter_wedge;
   1502  comp_type_cfg->enable_smooth_interintra =
   1503      extra_cfg->enable_interintra_comp && extra_cfg->enable_smooth_interintra;
   1504  comp_type_cfg->enable_interintra_wedge =
   1505      extra_cfg->enable_interintra_comp & extra_cfg->enable_interintra_wedge;
   1506 
   1507  // Set Super-resolution mode configuration.
   1508  if (extra_cfg->lossless || cfg->large_scale_tile) {
   1509    disable_superres(superres_cfg);
   1510  } else {
   1511    superres_cfg->superres_mode = cfg->rc_superres_mode;
   1512    superres_cfg->superres_scale_denominator =
   1513        (uint8_t)cfg->rc_superres_denominator;
   1514    superres_cfg->superres_kf_scale_denominator =
   1515        (uint8_t)cfg->rc_superres_kf_denominator;
   1516    superres_cfg->superres_qthresh =
   1517        av1_quantizer_to_qindex(cfg->rc_superres_qthresh);
   1518    superres_cfg->superres_kf_qthresh =
   1519        av1_quantizer_to_qindex(cfg->rc_superres_kf_qthresh);
   1520    if (superres_cfg->superres_mode == AOM_SUPERRES_FIXED &&
   1521        superres_cfg->superres_scale_denominator == SCALE_NUMERATOR &&
   1522        superres_cfg->superres_kf_scale_denominator == SCALE_NUMERATOR) {
   1523      disable_superres(superres_cfg);
   1524    }
   1525    if (superres_cfg->superres_mode == AOM_SUPERRES_QTHRESH &&
   1526        superres_cfg->superres_qthresh == 255 &&
   1527        superres_cfg->superres_kf_qthresh == 255) {
   1528      disable_superres(superres_cfg);
   1529    }
   1530  }
   1531 
   1532  superres_cfg->enable_superres =
   1533      (superres_cfg->superres_mode != AOM_SUPERRES_NONE) &&
   1534      extra_cfg->enable_superres;
   1535  if (!superres_cfg->enable_superres) {
   1536    disable_superres(superres_cfg);
   1537  }
   1538 
   1539  if (input_cfg->limit == 1) {
   1540    // still picture mode, display model and timing is meaningless
   1541    dec_model_cfg->display_model_info_present_flag = 0;
   1542    dec_model_cfg->timing_info_present = 0;
   1543  }
   1544 
   1545  oxcf->save_as_annexb = cfg->save_as_annexb;
   1546 
   1547  // Set unit test related configuration.
   1548  oxcf->unit_test_cfg.motion_vector_unit_test =
   1549      extra_cfg->motion_vector_unit_test;
   1550  oxcf->unit_test_cfg.sb_multipass_unit_test =
   1551      extra_cfg->sb_multipass_unit_test;
   1552 
   1553  oxcf->border_in_pixels =
   1554      av1_get_enc_border_size(av1_is_resize_needed(oxcf),
   1555                              (oxcf->kf_cfg.key_freq_max == 0), BLOCK_128X128);
   1556  memcpy(oxcf->target_seq_level_idx, extra_cfg->target_seq_level_idx,
   1557         sizeof(oxcf->target_seq_level_idx));
   1558  oxcf->tier_mask = extra_cfg->tier_mask;
   1559 
   1560  oxcf->partition_info_path = extra_cfg->partition_info_path;
   1561 
   1562  oxcf->enable_rate_guide_deltaq = extra_cfg->enable_rate_guide_deltaq;
   1563  oxcf->rate_distribution_info = extra_cfg->rate_distribution_info;
   1564 
   1565  oxcf->strict_level_conformance = extra_cfg->strict_level_conformance;
   1566 
   1567  oxcf->kf_max_pyr_height = extra_cfg->kf_max_pyr_height;
   1568 
   1569  oxcf->sb_qp_sweep = extra_cfg->sb_qp_sweep;
   1570 }
   1571 
   1572 AV1EncoderConfig av1_get_encoder_config(const aom_codec_enc_cfg_t *cfg) {
   1573  AV1EncoderConfig oxcf;
   1574  struct av1_extracfg extra_cfg = default_extra_cfg;
   1575  set_encoder_config(&oxcf, cfg, &extra_cfg);
   1576  return oxcf;
   1577 }
   1578 
   1579 static aom_codec_err_t encoder_set_config(aom_codec_alg_priv_t *ctx,
   1580                                          const aom_codec_enc_cfg_t *cfg) {
   1581  aom_codec_err_t res;
   1582  int force_key = 0;
   1583 
   1584  if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
   1585    if (cfg->g_lag_in_frames > 1 || cfg->g_pass != AOM_RC_ONE_PASS)
   1586      ERROR("Cannot change width or height after initialization");
   1587    // Note: function encoder_set_config() is allowed to be called multiple
   1588    // times. However, when the original frame width or height is less than two
   1589    // times of the new frame width or height, a forced key frame should be
   1590    // used (for the case of single spatial layer, since otherwise a previous
   1591    // encoded frame at a lower layer may be the desired reference). To make
   1592    // sure the correct detection of a forced key frame, we need
   1593    // to update the frame width and height only when the actual encoding is
   1594    // performed. cpi->last_coded_width and cpi->last_coded_height are used to
   1595    // track the actual coded frame size.
   1596    if (ctx->ppi->cpi->svc.number_spatial_layers == 1 &&
   1597        ctx->ppi->cpi->last_coded_width && ctx->ppi->cpi->last_coded_height &&
   1598        (!valid_ref_frame_size(ctx->ppi->cpi->last_coded_width,
   1599                               ctx->ppi->cpi->last_coded_height, cfg->g_w,
   1600                               cfg->g_h) ||
   1601         ((int)cfg->g_w > ctx->ppi->cpi->last_coded_width) ||
   1602         ((int)cfg->g_h > ctx->ppi->cpi->last_coded_height))) {
   1603      force_key = 1;
   1604    }
   1605  }
   1606 
   1607  if (ctx->monochrome_on_init && cfg->monochrome == 0) {
   1608    // TODO(aomedia:3465): Allow this case to work without requiring re-init
   1609    // of encoder.
   1610    ERROR("Cannot change to monochrome = 0 after init with monochrome");
   1611  }
   1612 
   1613  // Prevent increasing lag_in_frames. This check is stricter than it needs
   1614  // to be -- the limit is not increasing past the first lag_in_frames
   1615  // value, but we don't track the initial config, only the last successful
   1616  // config.
   1617  if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
   1618    ERROR("Cannot increase lag_in_frames");
   1619  // Prevent changing lag_in_frames if Lookahead Processing is enabled
   1620  if (cfg->g_lag_in_frames != ctx->cfg.g_lag_in_frames &&
   1621      ctx->num_lap_buffers > 0)
   1622    ERROR("Cannot change lag_in_frames if LAP is enabled");
   1623 
   1624  res = validate_config(ctx, cfg, &ctx->extra_cfg);
   1625 
   1626  if (res == AOM_CODEC_OK) {
   1627    ctx->cfg = *cfg;
   1628    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
   1629    // On profile change, request a key frame
   1630    force_key |= ctx->ppi->seq_params.profile != ctx->oxcf.profile;
   1631    bool is_sb_size_changed = false;
   1632    av1_change_config_seq(ctx->ppi, &ctx->oxcf, &is_sb_size_changed);
   1633    for (int i = 0; i < ctx->ppi->num_fp_contexts; i++) {
   1634      av1_change_config(ctx->ppi->parallel_cpi[i], &ctx->oxcf,
   1635                        is_sb_size_changed);
   1636    }
   1637    if (ctx->ppi->cpi_lap != NULL) {
   1638      av1_change_config(ctx->ppi->cpi_lap, &ctx->oxcf, is_sb_size_changed);
   1639    }
   1640  }
   1641 
   1642  if (force_key) ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
   1643 
   1644  return res;
   1645 }
   1646 
   1647 static aom_fixed_buf_t *encoder_get_global_headers(aom_codec_alg_priv_t *ctx) {
   1648  return av1_get_global_headers(ctx->ppi);
   1649 }
   1650 
   1651 static aom_codec_err_t ctrl_get_quantizer(aom_codec_alg_priv_t *ctx,
   1652                                          va_list args) {
   1653  int *const arg = va_arg(args, int *);
   1654  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   1655  *arg = av1_get_quantizer(ctx->ppi->cpi);
   1656  return AOM_CODEC_OK;
   1657 }
   1658 
   1659 static aom_codec_err_t ctrl_get_quantizer64(aom_codec_alg_priv_t *ctx,
   1660                                            va_list args) {
   1661  int *const arg = va_arg(args, int *);
   1662  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   1663  *arg = av1_qindex_to_quantizer(av1_get_quantizer(ctx->ppi->cpi));
   1664  return AOM_CODEC_OK;
   1665 }
   1666 
   1667 static aom_codec_err_t ctrl_get_loopfilter_level(aom_codec_alg_priv_t *ctx,
   1668                                                 va_list args) {
   1669  int *const arg = va_arg(args, int *);
   1670  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   1671  *arg = ctx->ppi->cpi->common.lf.filter_level[0];
   1672  return AOM_CODEC_OK;
   1673 }
   1674 
   1675 static aom_codec_err_t ctrl_get_baseline_gf_interval(aom_codec_alg_priv_t *ctx,
   1676                                                     va_list args) {
   1677  int *const arg = va_arg(args, int *);
   1678  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   1679  *arg = ctx->ppi->p_rc.baseline_gf_interval;
   1680  return AOM_CODEC_OK;
   1681 }
   1682 
   1683 static aom_codec_err_t update_encoder_cfg(aom_codec_alg_priv_t *ctx) {
   1684  set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
   1685  av1_check_fpmt_config(ctx->ppi, &ctx->oxcf);
   1686  bool is_sb_size_changed = false;
   1687  av1_change_config_seq(ctx->ppi, &ctx->oxcf, &is_sb_size_changed);
   1688  for (int i = 0; i < ctx->ppi->num_fp_contexts; i++) {
   1689    AV1_COMP *const cpi = ctx->ppi->parallel_cpi[i];
   1690    struct aom_internal_error_info *const error = cpi->common.error;
   1691    if (setjmp(error->jmp)) {
   1692      error->setjmp = 0;
   1693      return error->error_code;
   1694    }
   1695    error->setjmp = 1;
   1696    av1_change_config(cpi, &ctx->oxcf, is_sb_size_changed);
   1697    error->setjmp = 0;
   1698  }
   1699  if (ctx->ppi->cpi_lap != NULL) {
   1700    AV1_COMP *const cpi_lap = ctx->ppi->cpi_lap;
   1701    struct aom_internal_error_info *const error = cpi_lap->common.error;
   1702    if (setjmp(error->jmp)) {
   1703      error->setjmp = 0;
   1704      return error->error_code;
   1705    }
   1706    error->setjmp = 1;
   1707    av1_change_config(cpi_lap, &ctx->oxcf, is_sb_size_changed);
   1708    error->setjmp = 0;
   1709  }
   1710  return AOM_CODEC_OK;
   1711 }
   1712 
   1713 static aom_codec_err_t update_extra_cfg(aom_codec_alg_priv_t *ctx,
   1714                                        const struct av1_extracfg *extra_cfg) {
   1715  const aom_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
   1716  if (res == AOM_CODEC_OK) {
   1717    ctx->extra_cfg = *extra_cfg;
   1718    return update_encoder_cfg(ctx);
   1719  }
   1720  return res;
   1721 }
   1722 
   1723 static aom_codec_err_t ctrl_set_cpuused(aom_codec_alg_priv_t *ctx,
   1724                                        va_list args) {
   1725  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1726  extra_cfg.cpu_used = CAST(AOME_SET_CPUUSED, args);
   1727  return update_extra_cfg(ctx, &extra_cfg);
   1728 }
   1729 
   1730 static aom_codec_err_t ctrl_set_enable_auto_alt_ref(aom_codec_alg_priv_t *ctx,
   1731                                                    va_list args) {
   1732  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1733  extra_cfg.enable_auto_alt_ref = CAST(AOME_SET_ENABLEAUTOALTREF, args);
   1734  return update_extra_cfg(ctx, &extra_cfg);
   1735 }
   1736 
   1737 static aom_codec_err_t ctrl_set_enable_auto_bwd_ref(aom_codec_alg_priv_t *ctx,
   1738                                                    va_list args) {
   1739  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1740  extra_cfg.enable_auto_bwd_ref = CAST(AOME_SET_ENABLEAUTOBWDREF, args);
   1741  return update_extra_cfg(ctx, &extra_cfg);
   1742 }
   1743 
   1744 static aom_codec_err_t ctrl_set_noise_sensitivity(aom_codec_alg_priv_t *ctx,
   1745                                                  va_list args) {
   1746  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1747  extra_cfg.noise_sensitivity = CAST(AV1E_SET_NOISE_SENSITIVITY, args);
   1748  return update_extra_cfg(ctx, &extra_cfg);
   1749 }
   1750 
   1751 static aom_codec_err_t ctrl_set_sharpness(aom_codec_alg_priv_t *ctx,
   1752                                          va_list args) {
   1753  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1754  extra_cfg.sharpness = CAST(AOME_SET_SHARPNESS, args);
   1755  return update_extra_cfg(ctx, &extra_cfg);
   1756 }
   1757 
   1758 static aom_codec_err_t ctrl_set_enable_adaptive_sharpness(
   1759    aom_codec_alg_priv_t *ctx, va_list args) {
   1760  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1761  extra_cfg.enable_adaptive_sharpness =
   1762      CAST(AV1E_SET_ENABLE_ADAPTIVE_SHARPNESS, args);
   1763  return update_extra_cfg(ctx, &extra_cfg);
   1764 }
   1765 
   1766 static aom_codec_err_t ctrl_set_static_thresh(aom_codec_alg_priv_t *ctx,
   1767                                              va_list args) {
   1768  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1769  extra_cfg.static_thresh = CAST(AOME_SET_STATIC_THRESHOLD, args);
   1770  return update_extra_cfg(ctx, &extra_cfg);
   1771 }
   1772 
   1773 static aom_codec_err_t ctrl_set_row_mt(aom_codec_alg_priv_t *ctx,
   1774                                       va_list args) {
   1775  unsigned int row_mt = CAST(AV1E_SET_ROW_MT, args);
   1776  if (row_mt == ctx->extra_cfg.row_mt) return AOM_CODEC_OK;
   1777  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1778  extra_cfg.row_mt = row_mt;
   1779  return update_extra_cfg(ctx, &extra_cfg);
   1780 }
   1781 
   1782 static aom_codec_err_t ctrl_set_tile_columns(aom_codec_alg_priv_t *ctx,
   1783                                             va_list args) {
   1784  // If the control AUTO_TILES is used (set to 1) then don't override
   1785  // the tile_columns set via the AUTO_TILES control.
   1786  if (ctx->extra_cfg.auto_tiles) {
   1787    ERROR("AUTO_TILES is set so AV1E_SET_TILE_COLUMNS should not be called.");
   1788  }
   1789  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1790  unsigned int tile_columns = CAST(AV1E_SET_TILE_COLUMNS, args);
   1791  if (tile_columns == extra_cfg.tile_columns) return AOM_CODEC_OK;
   1792  extra_cfg.tile_columns = tile_columns;
   1793  return update_extra_cfg(ctx, &extra_cfg);
   1794 }
   1795 
   1796 static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx,
   1797                                          va_list args) {
   1798  // If the control AUTO_TILES is used (set to 1) then don't override
   1799  // the tile_rows set via the AUTO_TILES control.
   1800  if (ctx->extra_cfg.auto_tiles) {
   1801    ERROR("AUTO_TILES is set so AV1E_SET_TILE_ROWS should not be called.");
   1802  }
   1803  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1804  unsigned int tile_rows = CAST(AV1E_SET_TILE_ROWS, args);
   1805  if (tile_rows == extra_cfg.tile_rows) return AOM_CODEC_OK;
   1806  extra_cfg.tile_rows = tile_rows;
   1807  return update_extra_cfg(ctx, &extra_cfg);
   1808 }
   1809 
   1810 static aom_codec_err_t ctrl_set_enable_tpl_model(aom_codec_alg_priv_t *ctx,
   1811                                                 va_list args) {
   1812  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1813  const unsigned int tpl_model_arg = CAST(AV1E_SET_ENABLE_TPL_MODEL, args);
   1814 #if CONFIG_REALTIME_ONLY
   1815  if (tpl_model_arg) {
   1816    ERROR("TPL model can't be turned on in realtime only build.");
   1817  }
   1818 #endif
   1819  extra_cfg.enable_tpl_model = tpl_model_arg;
   1820  return update_extra_cfg(ctx, &extra_cfg);
   1821 }
   1822 
   1823 static aom_codec_err_t ctrl_set_enable_keyframe_filtering(
   1824    aom_codec_alg_priv_t *ctx, va_list args) {
   1825  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1826  extra_cfg.enable_keyframe_filtering =
   1827      CAST(AV1E_SET_ENABLE_KEYFRAME_FILTERING, args);
   1828  return update_extra_cfg(ctx, &extra_cfg);
   1829 }
   1830 
   1831 static aom_codec_err_t ctrl_set_arnr_max_frames(aom_codec_alg_priv_t *ctx,
   1832                                                va_list args) {
   1833  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1834  extra_cfg.arnr_max_frames = CAST(AOME_SET_ARNR_MAXFRAMES, args);
   1835  return update_extra_cfg(ctx, &extra_cfg);
   1836 }
   1837 
   1838 static aom_codec_err_t ctrl_set_arnr_strength(aom_codec_alg_priv_t *ctx,
   1839                                              va_list args) {
   1840  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1841  extra_cfg.arnr_strength = CAST(AOME_SET_ARNR_STRENGTH, args);
   1842  return update_extra_cfg(ctx, &extra_cfg);
   1843 }
   1844 
   1845 static aom_codec_err_t handle_tuning(aom_codec_alg_priv_t *ctx,
   1846                                     struct av1_extracfg *extra_cfg) {
   1847  if (extra_cfg->tuning == AOM_TUNE_IQ ||
   1848      extra_cfg->tuning == AOM_TUNE_SSIMULACRA2) {
   1849    if (ctx->cfg.g_usage != AOM_USAGE_ALL_INTRA) return AOM_CODEC_INCAPABLE;
   1850    // Enable QMs as they've been found to be beneficial for images, when used
   1851    // with alternative QM formulas:
   1852    // - aom_get_qmlevel_allintra()
   1853    // - aom_get_qmlevel_luma_ssimulacra2()
   1854    // - aom_get_qmlevel_444_chroma()
   1855    extra_cfg->enable_qm = 1;
   1856    extra_cfg->qm_min = QM_FIRST_IQ_SSIMULACRA2;
   1857    extra_cfg->qm_max = QM_LAST_IQ_SSIMULACRA2;
   1858    // We can turn on sharpness, as frames do not have to serve as references to
   1859    // others.
   1860    extra_cfg->sharpness = 7;
   1861    // Using the QM-PSNR metric was found to be beneficial for images (over the
   1862    // default PSNR metric), as it correlates better with subjective image
   1863    // quality consistency and better SSIMULACRA 2 scores.
   1864    extra_cfg->dist_metric = AOM_DIST_METRIC_QM_PSNR;
   1865    // CDEF_ALL has been found to blur images at medium and high quality
   1866    // qindexes, so let's use a version that adapts CDEF strength on frame
   1867    // qindexes. CDEF_ADAPTIVE strengths look like this for varying qindexes:
   1868    // - CDEF off:          0 -  32
   1869    // - Reduced strength: 33 - 220
   1870    // - Full strength:   221 - 255
   1871    extra_cfg->enable_cdef = CDEF_ADAPTIVE;
   1872    // Enable chroma deltaq so the encoder can factor in chroma subsampling and
   1873    // adjust chroma quality when necessary.
   1874    extra_cfg->enable_chroma_deltaq = 1;
   1875    // Enable "Variance Boost" deltaq mode, optimized for images.
   1876    extra_cfg->deltaq_mode = DELTA_Q_VARIANCE_BOOST;
   1877    // Enable "anti-aliased text and graphics aware" screen detection mode.
   1878    extra_cfg->screen_detection_mode = AOM_SCREEN_DETECTION_ANTIALIASING_AWARE;
   1879  }
   1880  if (extra_cfg->tuning == AOM_TUNE_IQ) {
   1881    // Enable adaptive sharpness to adjust loop filter levels according to QP.
   1882    // Takes a small SSIMULACRA2 hit on the lower quality end, so enable it
   1883    // just for tune IQ.
   1884    extra_cfg->enable_adaptive_sharpness = 1;
   1885  }
   1886  return AOM_CODEC_OK;
   1887 }
   1888 
   1889 static aom_codec_err_t ctrl_set_tuning(aom_codec_alg_priv_t *ctx,
   1890                                       va_list args) {
   1891  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1892  extra_cfg.tuning = CAST(AOME_SET_TUNING, args);
   1893  aom_codec_err_t err = handle_tuning(ctx, &extra_cfg);
   1894  if (err != AOM_CODEC_OK) return err;
   1895  return update_extra_cfg(ctx, &extra_cfg);
   1896 }
   1897 
   1898 static aom_codec_err_t ctrl_set_cq_level(aom_codec_alg_priv_t *ctx,
   1899                                         va_list args) {
   1900  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1901  extra_cfg.cq_level = CAST(AOME_SET_CQ_LEVEL, args);
   1902  return update_extra_cfg(ctx, &extra_cfg);
   1903 }
   1904 
   1905 static aom_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
   1906    aom_codec_alg_priv_t *ctx, va_list args) {
   1907  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1908  extra_cfg.rc_max_intra_bitrate_pct =
   1909      CAST(AOME_SET_MAX_INTRA_BITRATE_PCT, args);
   1910  return update_extra_cfg(ctx, &extra_cfg);
   1911 }
   1912 
   1913 static aom_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
   1914    aom_codec_alg_priv_t *ctx, va_list args) {
   1915  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1916  extra_cfg.rc_max_inter_bitrate_pct =
   1917      CAST(AOME_SET_MAX_INTER_BITRATE_PCT, args);
   1918  return update_extra_cfg(ctx, &extra_cfg);
   1919 }
   1920 
   1921 static aom_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(aom_codec_alg_priv_t *ctx,
   1922                                                    va_list args) {
   1923  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1924  extra_cfg.gf_cbr_boost_pct = CAST(AV1E_SET_GF_CBR_BOOST_PCT, args);
   1925  return update_extra_cfg(ctx, &extra_cfg);
   1926 }
   1927 
   1928 static aom_codec_err_t ctrl_set_lossless(aom_codec_alg_priv_t *ctx,
   1929                                         va_list args) {
   1930  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1931  extra_cfg.lossless = CAST(AV1E_SET_LOSSLESS, args);
   1932  return update_extra_cfg(ctx, &extra_cfg);
   1933 }
   1934 
   1935 static aom_codec_err_t ctrl_set_enable_cdef(aom_codec_alg_priv_t *ctx,
   1936                                            va_list args) {
   1937  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1938  extra_cfg.enable_cdef = CAST(AV1E_SET_ENABLE_CDEF, args);
   1939  return update_extra_cfg(ctx, &extra_cfg);
   1940 }
   1941 
   1942 static aom_codec_err_t ctrl_set_enable_restoration(aom_codec_alg_priv_t *ctx,
   1943                                                   va_list args) {
   1944  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1945  const unsigned int restoration_arg = CAST(AV1E_SET_ENABLE_RESTORATION, args);
   1946 #if CONFIG_REALTIME_ONLY
   1947  if (restoration_arg) {
   1948    ERROR("Restoration can't be turned on in realtime only build.");
   1949  }
   1950 #endif
   1951  extra_cfg.enable_restoration = restoration_arg;
   1952  return update_extra_cfg(ctx, &extra_cfg);
   1953 }
   1954 
   1955 static aom_codec_err_t ctrl_set_force_video_mode(aom_codec_alg_priv_t *ctx,
   1956                                                 va_list args) {
   1957  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1958  extra_cfg.force_video_mode = CAST(AV1E_SET_FORCE_VIDEO_MODE, args);
   1959  return update_extra_cfg(ctx, &extra_cfg);
   1960 }
   1961 
   1962 static aom_codec_err_t ctrl_set_enable_obmc(aom_codec_alg_priv_t *ctx,
   1963                                            va_list args) {
   1964  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1965  const unsigned int obmc_arg = CAST(AV1E_SET_ENABLE_OBMC, args);
   1966 #if CONFIG_REALTIME_ONLY
   1967  if (obmc_arg) {
   1968    ERROR("OBMC can't be enabled in realtime only build.");
   1969  }
   1970 #endif
   1971  extra_cfg.enable_obmc = obmc_arg;
   1972  return update_extra_cfg(ctx, &extra_cfg);
   1973 }
   1974 
   1975 static aom_codec_err_t ctrl_set_disable_trellis_quant(aom_codec_alg_priv_t *ctx,
   1976                                                      va_list args) {
   1977  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1978  extra_cfg.disable_trellis_quant = CAST(AV1E_SET_DISABLE_TRELLIS_QUANT, args);
   1979  return update_extra_cfg(ctx, &extra_cfg);
   1980 }
   1981 
   1982 static aom_codec_err_t ctrl_set_enable_qm(aom_codec_alg_priv_t *ctx,
   1983                                          va_list args) {
   1984  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1985  extra_cfg.enable_qm = CAST(AV1E_SET_ENABLE_QM, args);
   1986 #if !CONFIG_QUANT_MATRIX
   1987  if (extra_cfg.enable_qm) {
   1988    ERROR("QM can't be enabled with CONFIG_QUANT_MATRIX=0.");
   1989  }
   1990 #endif
   1991  return update_extra_cfg(ctx, &extra_cfg);
   1992 }
   1993 static aom_codec_err_t ctrl_set_qm_y(aom_codec_alg_priv_t *ctx, va_list args) {
   1994  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   1995  extra_cfg.qm_y = CAST(AV1E_SET_QM_Y, args);
   1996  return update_extra_cfg(ctx, &extra_cfg);
   1997 }
   1998 static aom_codec_err_t ctrl_set_qm_u(aom_codec_alg_priv_t *ctx, va_list args) {
   1999  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2000  extra_cfg.qm_u = CAST(AV1E_SET_QM_U, args);
   2001  return update_extra_cfg(ctx, &extra_cfg);
   2002 }
   2003 static aom_codec_err_t ctrl_set_qm_v(aom_codec_alg_priv_t *ctx, va_list args) {
   2004  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2005  extra_cfg.qm_v = CAST(AV1E_SET_QM_V, args);
   2006  return update_extra_cfg(ctx, &extra_cfg);
   2007 }
   2008 static aom_codec_err_t ctrl_set_qm_min(aom_codec_alg_priv_t *ctx,
   2009                                       va_list args) {
   2010  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2011  extra_cfg.qm_min = CAST(AV1E_SET_QM_MIN, args);
   2012  return update_extra_cfg(ctx, &extra_cfg);
   2013 }
   2014 
   2015 static aom_codec_err_t ctrl_set_qm_max(aom_codec_alg_priv_t *ctx,
   2016                                       va_list args) {
   2017  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2018  extra_cfg.qm_max = CAST(AV1E_SET_QM_MAX, args);
   2019  return update_extra_cfg(ctx, &extra_cfg);
   2020 }
   2021 
   2022 static aom_codec_err_t ctrl_set_num_tg(aom_codec_alg_priv_t *ctx,
   2023                                       va_list args) {
   2024  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2025  extra_cfg.num_tg = CAST(AV1E_SET_NUM_TG, args);
   2026  return update_extra_cfg(ctx, &extra_cfg);
   2027 }
   2028 
   2029 static aom_codec_err_t ctrl_set_mtu(aom_codec_alg_priv_t *ctx, va_list args) {
   2030  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2031  extra_cfg.mtu_size = CAST(AV1E_SET_MTU, args);
   2032  return update_extra_cfg(ctx, &extra_cfg);
   2033 }
   2034 static aom_codec_err_t ctrl_set_timing_info_type(aom_codec_alg_priv_t *ctx,
   2035                                                 va_list args) {
   2036  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2037  extra_cfg.timing_info_type = CAST(AV1E_SET_TIMING_INFO_TYPE, args);
   2038  return update_extra_cfg(ctx, &extra_cfg);
   2039 }
   2040 
   2041 static aom_codec_err_t ctrl_set_enable_low_complexity_decode(
   2042    aom_codec_alg_priv_t *ctx, va_list args) {
   2043  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2044  extra_cfg.enable_low_complexity_decode =
   2045      CAST(AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE, args);
   2046  return update_extra_cfg(ctx, &extra_cfg);
   2047 }
   2048 
   2049 static aom_codec_err_t ctrl_set_enable_dual_filter(aom_codec_alg_priv_t *ctx,
   2050                                                   va_list args) {
   2051  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2052  extra_cfg.enable_dual_filter = CAST(AV1E_SET_ENABLE_DUAL_FILTER, args);
   2053  return update_extra_cfg(ctx, &extra_cfg);
   2054 }
   2055 
   2056 static aom_codec_err_t ctrl_set_enable_chroma_deltaq(aom_codec_alg_priv_t *ctx,
   2057                                                     va_list args) {
   2058  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2059  extra_cfg.enable_chroma_deltaq = CAST(AV1E_SET_ENABLE_CHROMA_DELTAQ, args);
   2060  return update_extra_cfg(ctx, &extra_cfg);
   2061 }
   2062 
   2063 static aom_codec_err_t ctrl_set_enable_rect_partitions(
   2064    aom_codec_alg_priv_t *ctx, va_list args) {
   2065  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2066  extra_cfg.enable_rect_partitions =
   2067      CAST(AV1E_SET_ENABLE_RECT_PARTITIONS, args);
   2068  return update_extra_cfg(ctx, &extra_cfg);
   2069 }
   2070 
   2071 static aom_codec_err_t ctrl_set_enable_ab_partitions(aom_codec_alg_priv_t *ctx,
   2072                                                     va_list args) {
   2073  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2074  extra_cfg.enable_ab_partitions = CAST(AV1E_SET_ENABLE_AB_PARTITIONS, args);
   2075  return update_extra_cfg(ctx, &extra_cfg);
   2076 }
   2077 
   2078 static aom_codec_err_t ctrl_set_enable_1to4_partitions(
   2079    aom_codec_alg_priv_t *ctx, va_list args) {
   2080  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2081  extra_cfg.enable_1to4_partitions =
   2082      CAST(AV1E_SET_ENABLE_1TO4_PARTITIONS, args);
   2083  return update_extra_cfg(ctx, &extra_cfg);
   2084 }
   2085 
   2086 static aom_codec_err_t ctrl_set_min_partition_size(aom_codec_alg_priv_t *ctx,
   2087                                                   va_list args) {
   2088  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2089  extra_cfg.min_partition_size = CAST(AV1E_SET_MIN_PARTITION_SIZE, args);
   2090  return update_extra_cfg(ctx, &extra_cfg);
   2091 }
   2092 
   2093 static aom_codec_err_t ctrl_set_max_partition_size(aom_codec_alg_priv_t *ctx,
   2094                                                   va_list args) {
   2095  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2096  extra_cfg.max_partition_size = CAST(AV1E_SET_MAX_PARTITION_SIZE, args);
   2097  return update_extra_cfg(ctx, &extra_cfg);
   2098 }
   2099 
   2100 static aom_codec_err_t ctrl_set_enable_intra_edge_filter(
   2101    aom_codec_alg_priv_t *ctx, va_list args) {
   2102  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2103  extra_cfg.enable_intra_edge_filter =
   2104      CAST(AV1E_SET_ENABLE_INTRA_EDGE_FILTER, args);
   2105  return update_extra_cfg(ctx, &extra_cfg);
   2106 }
   2107 
   2108 static aom_codec_err_t ctrl_set_enable_order_hint(aom_codec_alg_priv_t *ctx,
   2109                                                  va_list args) {
   2110  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2111  extra_cfg.enable_order_hint = CAST(AV1E_SET_ENABLE_ORDER_HINT, args);
   2112  return update_extra_cfg(ctx, &extra_cfg);
   2113 }
   2114 
   2115 static aom_codec_err_t ctrl_set_enable_tx64(aom_codec_alg_priv_t *ctx,
   2116                                            va_list args) {
   2117  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2118  extra_cfg.enable_tx64 = CAST(AV1E_SET_ENABLE_TX64, args);
   2119  return update_extra_cfg(ctx, &extra_cfg);
   2120 }
   2121 
   2122 static aom_codec_err_t ctrl_set_enable_flip_idtx(aom_codec_alg_priv_t *ctx,
   2123                                                 va_list args) {
   2124  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2125  extra_cfg.enable_flip_idtx = CAST(AV1E_SET_ENABLE_FLIP_IDTX, args);
   2126  return update_extra_cfg(ctx, &extra_cfg);
   2127 }
   2128 
   2129 static aom_codec_err_t ctrl_set_enable_rect_tx(aom_codec_alg_priv_t *ctx,
   2130                                               va_list args) {
   2131  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2132  extra_cfg.enable_rect_tx = CAST(AV1E_SET_ENABLE_RECT_TX, args);
   2133  return update_extra_cfg(ctx, &extra_cfg);
   2134 }
   2135 
   2136 static aom_codec_err_t ctrl_set_enable_dist_wtd_comp(aom_codec_alg_priv_t *ctx,
   2137                                                     va_list args) {
   2138  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2139  extra_cfg.enable_dist_wtd_comp = CAST(AV1E_SET_ENABLE_DIST_WTD_COMP, args);
   2140  return update_extra_cfg(ctx, &extra_cfg);
   2141 }
   2142 
   2143 static aom_codec_err_t ctrl_set_max_reference_frames(aom_codec_alg_priv_t *ctx,
   2144                                                     va_list args) {
   2145  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2146  extra_cfg.max_reference_frames = CAST(AV1E_SET_MAX_REFERENCE_FRAMES, args);
   2147  return update_extra_cfg(ctx, &extra_cfg);
   2148 }
   2149 
   2150 static aom_codec_err_t ctrl_set_enable_reduced_reference_set(
   2151    aom_codec_alg_priv_t *ctx, va_list args) {
   2152  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2153  extra_cfg.enable_reduced_reference_set =
   2154      CAST(AV1E_SET_REDUCED_REFERENCE_SET, args);
   2155  return update_extra_cfg(ctx, &extra_cfg);
   2156 }
   2157 
   2158 static aom_codec_err_t ctrl_set_enable_ref_frame_mvs(aom_codec_alg_priv_t *ctx,
   2159                                                     va_list args) {
   2160  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2161  extra_cfg.enable_ref_frame_mvs = CAST(AV1E_SET_ENABLE_REF_FRAME_MVS, args);
   2162  return update_extra_cfg(ctx, &extra_cfg);
   2163 }
   2164 
   2165 static aom_codec_err_t ctrl_set_allow_ref_frame_mvs(aom_codec_alg_priv_t *ctx,
   2166                                                    va_list args) {
   2167  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2168  extra_cfg.allow_ref_frame_mvs = CAST(AV1E_SET_ALLOW_REF_FRAME_MVS, args);
   2169  return update_extra_cfg(ctx, &extra_cfg);
   2170 }
   2171 
   2172 static aom_codec_err_t ctrl_set_enable_masked_comp(aom_codec_alg_priv_t *ctx,
   2173                                                   va_list args) {
   2174  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2175  extra_cfg.enable_masked_comp = CAST(AV1E_SET_ENABLE_MASKED_COMP, args);
   2176  return update_extra_cfg(ctx, &extra_cfg);
   2177 }
   2178 
   2179 static aom_codec_err_t ctrl_set_enable_onesided_comp(aom_codec_alg_priv_t *ctx,
   2180                                                     va_list args) {
   2181  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2182  extra_cfg.enable_onesided_comp = CAST(AV1E_SET_ENABLE_ONESIDED_COMP, args);
   2183  return update_extra_cfg(ctx, &extra_cfg);
   2184 }
   2185 
   2186 static aom_codec_err_t ctrl_set_enable_interintra_comp(
   2187    aom_codec_alg_priv_t *ctx, va_list args) {
   2188  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2189  extra_cfg.enable_interintra_comp =
   2190      CAST(AV1E_SET_ENABLE_INTERINTRA_COMP, args);
   2191  return update_extra_cfg(ctx, &extra_cfg);
   2192 }
   2193 
   2194 static aom_codec_err_t ctrl_set_enable_smooth_interintra(
   2195    aom_codec_alg_priv_t *ctx, va_list args) {
   2196  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2197  extra_cfg.enable_smooth_interintra =
   2198      CAST(AV1E_SET_ENABLE_SMOOTH_INTERINTRA, args);
   2199  return update_extra_cfg(ctx, &extra_cfg);
   2200 }
   2201 
   2202 static aom_codec_err_t ctrl_set_enable_diff_wtd_comp(aom_codec_alg_priv_t *ctx,
   2203                                                     va_list args) {
   2204  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2205  extra_cfg.enable_diff_wtd_comp = CAST(AV1E_SET_ENABLE_DIFF_WTD_COMP, args);
   2206  return update_extra_cfg(ctx, &extra_cfg);
   2207 }
   2208 
   2209 static aom_codec_err_t ctrl_set_enable_interinter_wedge(
   2210    aom_codec_alg_priv_t *ctx, va_list args) {
   2211  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2212  extra_cfg.enable_interinter_wedge =
   2213      CAST(AV1E_SET_ENABLE_INTERINTER_WEDGE, args);
   2214  return update_extra_cfg(ctx, &extra_cfg);
   2215 }
   2216 
   2217 static aom_codec_err_t ctrl_set_enable_interintra_wedge(
   2218    aom_codec_alg_priv_t *ctx, va_list args) {
   2219  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2220  extra_cfg.enable_interintra_wedge =
   2221      CAST(AV1E_SET_ENABLE_INTERINTRA_WEDGE, args);
   2222  return update_extra_cfg(ctx, &extra_cfg);
   2223 }
   2224 
   2225 static aom_codec_err_t ctrl_set_enable_global_motion(aom_codec_alg_priv_t *ctx,
   2226                                                     va_list args) {
   2227  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2228  const int global_motion_arg = CAST(AV1E_SET_ENABLE_GLOBAL_MOTION, args);
   2229 #if CONFIG_REALTIME_ONLY
   2230  if (global_motion_arg) {
   2231    ERROR("Global motion can't be enabled in realtime only build.");
   2232  }
   2233 #endif
   2234  extra_cfg.enable_global_motion = global_motion_arg;
   2235  return update_extra_cfg(ctx, &extra_cfg);
   2236 }
   2237 
   2238 static aom_codec_err_t ctrl_set_enable_warped_motion(aom_codec_alg_priv_t *ctx,
   2239                                                     va_list args) {
   2240  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2241  const int warped_motion_arg = CAST(AV1E_SET_ENABLE_WARPED_MOTION, args);
   2242 #if CONFIG_REALTIME_ONLY
   2243  if (warped_motion_arg) {
   2244    ERROR("Warped motion can't be enabled in realtime only build.");
   2245  }
   2246 #endif
   2247  extra_cfg.enable_warped_motion = warped_motion_arg;
   2248  return update_extra_cfg(ctx, &extra_cfg);
   2249 }
   2250 
   2251 static aom_codec_err_t ctrl_set_allow_warped_motion(aom_codec_alg_priv_t *ctx,
   2252                                                    va_list args) {
   2253  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2254  extra_cfg.allow_warped_motion = CAST(AV1E_SET_ALLOW_WARPED_MOTION, args);
   2255  return update_extra_cfg(ctx, &extra_cfg);
   2256 }
   2257 
   2258 static aom_codec_err_t ctrl_set_enable_filter_intra(aom_codec_alg_priv_t *ctx,
   2259                                                    va_list args) {
   2260  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2261  extra_cfg.enable_filter_intra = CAST(AV1E_SET_ENABLE_FILTER_INTRA, args);
   2262  return update_extra_cfg(ctx, &extra_cfg);
   2263 }
   2264 
   2265 static aom_codec_err_t ctrl_set_enable_smooth_intra(aom_codec_alg_priv_t *ctx,
   2266                                                    va_list args) {
   2267  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2268  extra_cfg.enable_smooth_intra = CAST(AV1E_SET_ENABLE_SMOOTH_INTRA, args);
   2269  return update_extra_cfg(ctx, &extra_cfg);
   2270 }
   2271 
   2272 static aom_codec_err_t ctrl_set_enable_directional_intra(
   2273    aom_codec_alg_priv_t *ctx, va_list args) {
   2274  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2275  extra_cfg.enable_directional_intra =
   2276      CAST(AV1E_SET_ENABLE_DIRECTIONAL_INTRA, args);
   2277  return update_extra_cfg(ctx, &extra_cfg);
   2278 }
   2279 
   2280 static aom_codec_err_t ctrl_set_enable_diagonal_intra(aom_codec_alg_priv_t *ctx,
   2281                                                      va_list args) {
   2282  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2283  extra_cfg.enable_diagonal_intra = CAST(AV1E_SET_ENABLE_DIAGONAL_INTRA, args);
   2284  return update_extra_cfg(ctx, &extra_cfg);
   2285 }
   2286 
   2287 static aom_codec_err_t ctrl_set_enable_paeth_intra(aom_codec_alg_priv_t *ctx,
   2288                                                   va_list args) {
   2289  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2290  extra_cfg.enable_paeth_intra = CAST(AV1E_SET_ENABLE_PAETH_INTRA, args);
   2291  return update_extra_cfg(ctx, &extra_cfg);
   2292 }
   2293 
   2294 static aom_codec_err_t ctrl_set_enable_cfl_intra(aom_codec_alg_priv_t *ctx,
   2295                                                 va_list args) {
   2296  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2297  extra_cfg.enable_cfl_intra = CAST(AV1E_SET_ENABLE_CFL_INTRA, args);
   2298 #if CONFIG_REALTIME_ONLY
   2299  if (extra_cfg.enable_cfl_intra) {
   2300    ERROR("cfl can't be turned on in realtime only build.");
   2301  }
   2302 #endif
   2303  return update_extra_cfg(ctx, &extra_cfg);
   2304 }
   2305 
   2306 static aom_codec_err_t ctrl_set_enable_superres(aom_codec_alg_priv_t *ctx,
   2307                                                va_list args) {
   2308  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2309  extra_cfg.enable_superres = CAST(AV1E_SET_ENABLE_SUPERRES, args);
   2310  return update_extra_cfg(ctx, &extra_cfg);
   2311 }
   2312 
   2313 static aom_codec_err_t ctrl_set_enable_overlay(aom_codec_alg_priv_t *ctx,
   2314                                               va_list args) {
   2315  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2316  extra_cfg.enable_overlay = CAST(AV1E_SET_ENABLE_OVERLAY, args);
   2317  return update_extra_cfg(ctx, &extra_cfg);
   2318 }
   2319 
   2320 static aom_codec_err_t ctrl_set_enable_palette(aom_codec_alg_priv_t *ctx,
   2321                                               va_list args) {
   2322  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2323  extra_cfg.enable_palette = CAST(AV1E_SET_ENABLE_PALETTE, args);
   2324  return update_extra_cfg(ctx, &extra_cfg);
   2325 }
   2326 
   2327 static aom_codec_err_t ctrl_set_enable_intrabc(aom_codec_alg_priv_t *ctx,
   2328                                               va_list args) {
   2329  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2330  extra_cfg.enable_intrabc = CAST(AV1E_SET_ENABLE_INTRABC, args);
   2331  return update_extra_cfg(ctx, &extra_cfg);
   2332 }
   2333 
   2334 static aom_codec_err_t ctrl_set_enable_angle_delta(aom_codec_alg_priv_t *ctx,
   2335                                                   va_list args) {
   2336  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2337  extra_cfg.enable_angle_delta = CAST(AV1E_SET_ENABLE_ANGLE_DELTA, args);
   2338  return update_extra_cfg(ctx, &extra_cfg);
   2339 }
   2340 
   2341 static aom_codec_err_t ctrl_set_error_resilient_mode(aom_codec_alg_priv_t *ctx,
   2342                                                     va_list args) {
   2343  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2344  extra_cfg.error_resilient_mode = CAST(AV1E_SET_ERROR_RESILIENT_MODE, args);
   2345  return update_extra_cfg(ctx, &extra_cfg);
   2346 }
   2347 
   2348 static aom_codec_err_t ctrl_set_s_frame_mode(aom_codec_alg_priv_t *ctx,
   2349                                             va_list args) {
   2350  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2351  extra_cfg.s_frame_mode = CAST(AV1E_SET_S_FRAME_MODE, args);
   2352  return update_extra_cfg(ctx, &extra_cfg);
   2353 }
   2354 
   2355 static aom_codec_err_t ctrl_set_frame_parallel_decoding_mode(
   2356    aom_codec_alg_priv_t *ctx, va_list args) {
   2357  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2358  extra_cfg.frame_parallel_decoding_mode =
   2359      CAST(AV1E_SET_FRAME_PARALLEL_DECODING, args);
   2360  return update_extra_cfg(ctx, &extra_cfg);
   2361 }
   2362 
   2363 static aom_codec_err_t ctrl_set_single_tile_decoding(aom_codec_alg_priv_t *ctx,
   2364                                                     va_list args) {
   2365  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2366  extra_cfg.single_tile_decoding = CAST(AV1E_SET_SINGLE_TILE_DECODING, args);
   2367  return update_extra_cfg(ctx, &extra_cfg);
   2368 }
   2369 
   2370 static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
   2371                                        va_list args) {
   2372  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2373  extra_cfg.aq_mode = CAST(AV1E_SET_AQ_MODE, args);
   2374 
   2375  // Skip AQ mode if using fixed QP for current frame.
   2376  if (ctx->ppi->cpi->rc.use_external_qp_one_pass) extra_cfg.aq_mode = 0;
   2377  return update_extra_cfg(ctx, &extra_cfg);
   2378 }
   2379 
   2380 static aom_codec_err_t ctrl_set_reduced_tx_type_set(aom_codec_alg_priv_t *ctx,
   2381                                                    va_list args) {
   2382  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2383  extra_cfg.reduced_tx_type_set = CAST(AV1E_SET_REDUCED_TX_TYPE_SET, args);
   2384  return update_extra_cfg(ctx, &extra_cfg);
   2385 }
   2386 
   2387 static aom_codec_err_t ctrl_set_intra_dct_only(aom_codec_alg_priv_t *ctx,
   2388                                               va_list args) {
   2389  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2390  extra_cfg.use_intra_dct_only = CAST(AV1E_SET_INTRA_DCT_ONLY, args);
   2391  return update_extra_cfg(ctx, &extra_cfg);
   2392 }
   2393 
   2394 static aom_codec_err_t ctrl_set_inter_dct_only(aom_codec_alg_priv_t *ctx,
   2395                                               va_list args) {
   2396  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2397  extra_cfg.use_inter_dct_only = CAST(AV1E_SET_INTER_DCT_ONLY, args);
   2398  return update_extra_cfg(ctx, &extra_cfg);
   2399 }
   2400 
   2401 static aom_codec_err_t ctrl_set_intra_default_tx_only(aom_codec_alg_priv_t *ctx,
   2402                                                      va_list args) {
   2403  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2404  extra_cfg.use_intra_default_tx_only =
   2405      CAST(AV1E_SET_INTRA_DEFAULT_TX_ONLY, args);
   2406  return update_extra_cfg(ctx, &extra_cfg);
   2407 }
   2408 
   2409 static aom_codec_err_t ctrl_set_enable_tx_size_search(aom_codec_alg_priv_t *ctx,
   2410                                                      va_list args) {
   2411  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2412  extra_cfg.enable_tx_size_search = CAST(AV1E_SET_ENABLE_TX_SIZE_SEARCH, args);
   2413  return update_extra_cfg(ctx, &extra_cfg);
   2414 }
   2415 
   2416 static aom_codec_err_t ctrl_set_quant_b_adapt(aom_codec_alg_priv_t *ctx,
   2417                                              va_list args) {
   2418 #if CONFIG_REALTIME_ONLY
   2419  (void)ctx;
   2420  (void)args;
   2421  return AOM_CODEC_INCAPABLE;
   2422 #else
   2423  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2424  extra_cfg.quant_b_adapt = CAST(AV1E_SET_QUANT_B_ADAPT, args);
   2425  return update_extra_cfg(ctx, &extra_cfg);
   2426 #endif
   2427 }
   2428 
   2429 static aom_codec_err_t ctrl_set_vbr_corpus_complexity_lap(
   2430    aom_codec_alg_priv_t *ctx, va_list args) {
   2431  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2432  extra_cfg.vbr_corpus_complexity_lap =
   2433      CAST(AV1E_SET_VBR_CORPUS_COMPLEXITY_LAP, args);
   2434  return update_extra_cfg(ctx, &extra_cfg);
   2435 }
   2436 static aom_codec_err_t ctrl_set_coeff_cost_upd_freq(aom_codec_alg_priv_t *ctx,
   2437                                                    va_list args) {
   2438  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2439  extra_cfg.coeff_cost_upd_freq = CAST(AV1E_SET_COEFF_COST_UPD_FREQ, args);
   2440  return update_extra_cfg(ctx, &extra_cfg);
   2441 }
   2442 
   2443 static aom_codec_err_t ctrl_set_mode_cost_upd_freq(aom_codec_alg_priv_t *ctx,
   2444                                                   va_list args) {
   2445  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2446  extra_cfg.mode_cost_upd_freq = CAST(AV1E_SET_MODE_COST_UPD_FREQ, args);
   2447  return update_extra_cfg(ctx, &extra_cfg);
   2448 }
   2449 
   2450 static aom_codec_err_t ctrl_set_mv_cost_upd_freq(aom_codec_alg_priv_t *ctx,
   2451                                                 va_list args) {
   2452  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2453  extra_cfg.mv_cost_upd_freq = CAST(AV1E_SET_MV_COST_UPD_FREQ, args);
   2454  return update_extra_cfg(ctx, &extra_cfg);
   2455 }
   2456 
   2457 static aom_codec_err_t ctrl_set_dv_cost_upd_freq(aom_codec_alg_priv_t *ctx,
   2458                                                 va_list args) {
   2459  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2460  extra_cfg.dv_cost_upd_freq = CAST(AV1E_SET_DV_COST_UPD_FREQ, args);
   2461  return update_extra_cfg(ctx, &extra_cfg);
   2462 }
   2463 
   2464 static aom_codec_err_t ctrl_set_vmaf_model_path(aom_codec_alg_priv_t *ctx,
   2465                                                va_list args) {
   2466  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2467  const char *str = CAST(AV1E_SET_VMAF_MODEL_PATH, args);
   2468  const aom_codec_err_t ret = allocate_and_set_string(
   2469      str, default_extra_cfg.vmaf_model_path, &extra_cfg.vmaf_model_path,
   2470      ctx->ppi->error.detail);
   2471  if (ret != AOM_CODEC_OK) return ret;
   2472  return update_extra_cfg(ctx, &extra_cfg);
   2473 }
   2474 
   2475 static aom_codec_err_t ctrl_set_partition_info_path(aom_codec_alg_priv_t *ctx,
   2476                                                    va_list args) {
   2477  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2478  const char *str = CAST(AV1E_SET_PARTITION_INFO_PATH, args);
   2479  const aom_codec_err_t ret = allocate_and_set_string(
   2480      str, default_extra_cfg.partition_info_path,
   2481      &extra_cfg.partition_info_path, ctx->ppi->error.detail);
   2482  if (ret != AOM_CODEC_OK) return ret;
   2483  return update_extra_cfg(ctx, &extra_cfg);
   2484 }
   2485 
   2486 static aom_codec_err_t ctrl_enable_rate_guide_deltaq(aom_codec_alg_priv_t *ctx,
   2487                                                     va_list args) {
   2488  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2489  extra_cfg.enable_rate_guide_deltaq =
   2490      CAST(AV1E_ENABLE_RATE_GUIDE_DELTAQ, args);
   2491  return update_extra_cfg(ctx, &extra_cfg);
   2492 }
   2493 
   2494 static aom_codec_err_t ctrl_set_rate_distribution_info(
   2495    aom_codec_alg_priv_t *ctx, va_list args) {
   2496  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2497  const char *str = CAST(AV1E_SET_RATE_DISTRIBUTION_INFO, args);
   2498  const aom_codec_err_t ret = allocate_and_set_string(
   2499      str, default_extra_cfg.rate_distribution_info,
   2500      &extra_cfg.rate_distribution_info, ctx->ppi->error.detail);
   2501  if (ret != AOM_CODEC_OK) return ret;
   2502  return update_extra_cfg(ctx, &extra_cfg);
   2503 }
   2504 
   2505 static aom_codec_err_t ctrl_set_film_grain_test_vector(
   2506    aom_codec_alg_priv_t *ctx, va_list args) {
   2507  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2508  extra_cfg.film_grain_test_vector =
   2509      CAST(AV1E_SET_FILM_GRAIN_TEST_VECTOR, args);
   2510  return update_extra_cfg(ctx, &extra_cfg);
   2511 }
   2512 
   2513 static aom_codec_err_t ctrl_set_film_grain_table(aom_codec_alg_priv_t *ctx,
   2514                                                 va_list args) {
   2515  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2516  const char *str = CAST(AV1E_SET_FILM_GRAIN_TABLE, args);
   2517  if (str == NULL) {
   2518    // this parameter allows NULL as its value
   2519    extra_cfg.film_grain_table_filename = str;
   2520  } else {
   2521 #if CONFIG_REALTIME_ONLY
   2522    ERROR("film_grain removed from realtime only build.");
   2523 #endif
   2524    const aom_codec_err_t ret = allocate_and_set_string(
   2525        str, default_extra_cfg.film_grain_table_filename,
   2526        &extra_cfg.film_grain_table_filename, ctx->ppi->error.detail);
   2527    if (ret != AOM_CODEC_OK) return ret;
   2528  }
   2529  return update_extra_cfg(ctx, &extra_cfg);
   2530 }
   2531 
   2532 static aom_codec_err_t ctrl_set_denoise_noise_level(aom_codec_alg_priv_t *ctx,
   2533                                                    va_list args) {
   2534 #if !CONFIG_DENOISE
   2535  (void)ctx;
   2536  (void)args;
   2537  return AOM_CODEC_INCAPABLE;
   2538 #else
   2539  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2540  extra_cfg.noise_level =
   2541      ((float)CAST(AV1E_SET_DENOISE_NOISE_LEVEL, args)) / 10.0f;
   2542  return update_extra_cfg(ctx, &extra_cfg);
   2543 #endif
   2544 }
   2545 
   2546 static aom_codec_err_t ctrl_set_denoise_block_size(aom_codec_alg_priv_t *ctx,
   2547                                                   va_list args) {
   2548 #if !CONFIG_DENOISE
   2549  (void)ctx;
   2550  (void)args;
   2551  return AOM_CODEC_INCAPABLE;
   2552 #else
   2553  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2554  extra_cfg.noise_block_size = CAST(AV1E_SET_DENOISE_BLOCK_SIZE, args);
   2555  return update_extra_cfg(ctx, &extra_cfg);
   2556 #endif
   2557 }
   2558 
   2559 static aom_codec_err_t ctrl_set_enable_dnl_denoising(aom_codec_alg_priv_t *ctx,
   2560                                                     va_list args) {
   2561 #if !CONFIG_DENOISE
   2562  (void)ctx;
   2563  (void)args;
   2564  return AOM_CODEC_INCAPABLE;
   2565 #else
   2566  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2567  extra_cfg.enable_dnl_denoising = CAST(AV1E_SET_ENABLE_DNL_DENOISING, args);
   2568  return update_extra_cfg(ctx, &extra_cfg);
   2569 #endif
   2570 }
   2571 
   2572 static aom_codec_err_t ctrl_set_deltaq_mode(aom_codec_alg_priv_t *ctx,
   2573                                            va_list args) {
   2574  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2575  const DELTAQ_MODE deltaq_arg = CAST(AV1E_SET_DELTAQ_MODE, args);
   2576 #if CONFIG_REALTIME_ONLY
   2577  if (deltaq_arg > NO_DELTA_Q) {
   2578    ERROR("Delta Q mode can't be enabled in realtime only build.");
   2579  }
   2580 #endif
   2581  extra_cfg.deltaq_mode = deltaq_arg;
   2582  return update_extra_cfg(ctx, &extra_cfg);
   2583 }
   2584 
   2585 static aom_codec_err_t ctrl_set_deltaq_strength(aom_codec_alg_priv_t *ctx,
   2586                                                va_list args) {
   2587  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2588  extra_cfg.deltaq_strength = CAST(AV1E_SET_DELTAQ_STRENGTH, args);
   2589  return update_extra_cfg(ctx, &extra_cfg);
   2590 }
   2591 
   2592 static aom_codec_err_t ctrl_set_deltalf_mode(aom_codec_alg_priv_t *ctx,
   2593                                             va_list args) {
   2594  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2595  extra_cfg.deltalf_mode = CAST(AV1E_SET_DELTALF_MODE, args);
   2596  return update_extra_cfg(ctx, &extra_cfg);
   2597 }
   2598 
   2599 static aom_codec_err_t ctrl_set_min_gf_interval(aom_codec_alg_priv_t *ctx,
   2600                                                va_list args) {
   2601  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2602  extra_cfg.min_gf_interval = CAST(AV1E_SET_MIN_GF_INTERVAL, args);
   2603  return update_extra_cfg(ctx, &extra_cfg);
   2604 }
   2605 
   2606 static aom_codec_err_t ctrl_set_max_gf_interval(aom_codec_alg_priv_t *ctx,
   2607                                                va_list args) {
   2608  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2609  extra_cfg.max_gf_interval = CAST(AV1E_SET_MAX_GF_INTERVAL, args);
   2610  return update_extra_cfg(ctx, &extra_cfg);
   2611 }
   2612 
   2613 static aom_codec_err_t ctrl_set_gf_min_pyr_height(aom_codec_alg_priv_t *ctx,
   2614                                                  va_list args) {
   2615  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2616  extra_cfg.gf_min_pyr_height = CAST(AV1E_SET_GF_MIN_PYRAMID_HEIGHT, args);
   2617  return update_extra_cfg(ctx, &extra_cfg);
   2618 }
   2619 
   2620 static aom_codec_err_t ctrl_set_gf_max_pyr_height(aom_codec_alg_priv_t *ctx,
   2621                                                  va_list args) {
   2622  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2623  extra_cfg.gf_max_pyr_height = CAST(AV1E_SET_GF_MAX_PYRAMID_HEIGHT, args);
   2624  return update_extra_cfg(ctx, &extra_cfg);
   2625 }
   2626 
   2627 static aom_codec_err_t ctrl_set_frame_periodic_boost(aom_codec_alg_priv_t *ctx,
   2628                                                     va_list args) {
   2629  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2630  extra_cfg.frame_periodic_boost = CAST(AV1E_SET_FRAME_PERIODIC_BOOST, args);
   2631  return update_extra_cfg(ctx, &extra_cfg);
   2632 }
   2633 
   2634 static aom_codec_err_t ctrl_enable_motion_vector_unit_test(
   2635    aom_codec_alg_priv_t *ctx, va_list args) {
   2636  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2637  extra_cfg.motion_vector_unit_test =
   2638      CAST(AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, args);
   2639  return update_extra_cfg(ctx, &extra_cfg);
   2640 }
   2641 
   2642 static aom_codec_err_t ctrl_enable_fpmt_unit_test(aom_codec_alg_priv_t *ctx,
   2643                                                  va_list args) {
   2644 #if !CONFIG_FPMT_TEST
   2645  (void)args;
   2646  (void)ctx;
   2647  return AOM_CODEC_INCAPABLE;
   2648 #else
   2649  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2650  extra_cfg.fpmt_unit_test = CAST(AV1E_SET_FP_MT_UNIT_TEST, args);
   2651  ctx->ppi->fpmt_unit_test_cfg = (extra_cfg.fpmt_unit_test == 1)
   2652                                     ? PARALLEL_ENCODE
   2653                                     : PARALLEL_SIMULATION_ENCODE;
   2654  return update_extra_cfg(ctx, &extra_cfg);
   2655 #endif
   2656 }
   2657 
   2658 static aom_codec_err_t ctrl_enable_ext_tile_debug(aom_codec_alg_priv_t *ctx,
   2659                                                  va_list args) {
   2660  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2661  extra_cfg.ext_tile_debug = CAST(AV1E_ENABLE_EXT_TILE_DEBUG, args);
   2662  return update_extra_cfg(ctx, &extra_cfg);
   2663 }
   2664 
   2665 static aom_codec_err_t ctrl_set_target_seq_level_idx(aom_codec_alg_priv_t *ctx,
   2666                                                     va_list args) {
   2667  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2668  const int val = CAST(AV1E_SET_TARGET_SEQ_LEVEL_IDX, args);
   2669  const int level = val % 100;
   2670  const int operating_point_idx = val / 100;
   2671  if (operating_point_idx < 0 ||
   2672      operating_point_idx >= MAX_NUM_OPERATING_POINTS) {
   2673    char *const err_string = ctx->ppi->error.detail;
   2674    snprintf(err_string, ARG_ERR_MSG_MAX_LEN,
   2675             "Invalid operating point index: %d", operating_point_idx);
   2676    ctx->base.err_detail = err_string;
   2677    return AOM_CODEC_INVALID_PARAM;
   2678  }
   2679  extra_cfg.target_seq_level_idx[operating_point_idx] = (AV1_LEVEL)level;
   2680  return update_extra_cfg(ctx, &extra_cfg);
   2681 }
   2682 
   2683 static aom_codec_err_t ctrl_set_tier_mask(aom_codec_alg_priv_t *ctx,
   2684                                          va_list args) {
   2685  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2686  extra_cfg.tier_mask = CAST(AV1E_SET_TIER_MASK, args);
   2687  return update_extra_cfg(ctx, &extra_cfg);
   2688 }
   2689 
   2690 static aom_codec_err_t ctrl_set_min_cr(aom_codec_alg_priv_t *ctx,
   2691                                       va_list args) {
   2692  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2693  extra_cfg.min_cr = CAST(AV1E_SET_MIN_CR, args);
   2694  return update_extra_cfg(ctx, &extra_cfg);
   2695 }
   2696 
   2697 static aom_codec_err_t ctrl_enable_sb_multipass_unit_test(
   2698    aom_codec_alg_priv_t *ctx, va_list args) {
   2699  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2700  extra_cfg.sb_multipass_unit_test =
   2701      CAST(AV1E_ENABLE_SB_MULTIPASS_UNIT_TEST, args);
   2702  return update_extra_cfg(ctx, &extra_cfg);
   2703 }
   2704 
   2705 static aom_codec_err_t ctrl_enable_sb_qp_sweep(aom_codec_alg_priv_t *ctx,
   2706                                               va_list args) {
   2707  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2708  extra_cfg.sb_qp_sweep = CAST(AV1E_ENABLE_SB_QP_SWEEP, args);
   2709  return update_extra_cfg(ctx, &extra_cfg);
   2710 }
   2711 
   2712 static aom_codec_err_t ctrl_set_external_partition(aom_codec_alg_priv_t *ctx,
   2713                                                   va_list args) {
   2714  AV1_COMP *const cpi = ctx->ppi->cpi;
   2715  aom_ext_part_funcs_t funcs = *CAST(AV1E_SET_EXTERNAL_PARTITION, args);
   2716  aom_ext_part_config_t config;
   2717  // TODO(chengchen): verify the sb_size has been set at this point.
   2718  config.superblock_size = cpi->common.seq_params->sb_size;
   2719  const aom_codec_err_t status =
   2720      av1_ext_part_create(funcs, config, &cpi->ext_part_controller);
   2721  return status;
   2722 }
   2723 
   2724 static aom_codec_err_t ctrl_set_loopfilter_control(aom_codec_alg_priv_t *ctx,
   2725                                                   va_list args) {
   2726  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2727  extra_cfg.loopfilter_control = CAST(AV1E_SET_LOOPFILTER_CONTROL, args);
   2728  return update_extra_cfg(ctx, &extra_cfg);
   2729 }
   2730 
   2731 static aom_codec_err_t ctrl_set_skip_postproc_filtering(
   2732    aom_codec_alg_priv_t *ctx, va_list args) {
   2733  // Skipping the application of post-processing filters is allowed only
   2734  // for ALLINTRA mode.
   2735  if (ctx->cfg.g_usage != AOM_USAGE_ALL_INTRA) return AOM_CODEC_INCAPABLE;
   2736  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2737  extra_cfg.skip_postproc_filtering =
   2738      CAST(AV1E_SET_SKIP_POSTPROC_FILTERING, args);
   2739  return update_extra_cfg(ctx, &extra_cfg);
   2740 }
   2741 
   2742 static aom_codec_err_t ctrl_set_rtc_external_rc(aom_codec_alg_priv_t *ctx,
   2743                                                va_list args) {
   2744  ctx->ppi->cpi->rc.rtc_external_ratectrl =
   2745      CAST(AV1E_SET_RTC_EXTERNAL_RC, args);
   2746  return AOM_CODEC_OK;
   2747 }
   2748 
   2749 static aom_codec_err_t ctrl_set_quantizer_one_pass(aom_codec_alg_priv_t *ctx,
   2750                                                   va_list args) {
   2751  const int qp = CAST(AV1E_SET_QUANTIZER_ONE_PASS, args);
   2752 
   2753  if (qp < 0 || qp > 63) return AOM_CODEC_INVALID_PARAM;
   2754 
   2755  aom_codec_enc_cfg_t *cfg = &ctx->cfg;
   2756  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2757  cfg->rc_min_quantizer = cfg->rc_max_quantizer = qp;
   2758  extra_cfg.aq_mode = 0;
   2759  ctx->ppi->cpi->rc.use_external_qp_one_pass = 1;
   2760 
   2761  return update_extra_cfg(ctx, &extra_cfg);
   2762 }
   2763 
   2764 static aom_codec_err_t ctrl_set_bitrate_one_pass_cbr(aom_codec_alg_priv_t *ctx,
   2765                                                     va_list args) {
   2766  AV1_PRIMARY *const ppi = ctx->ppi;
   2767  AV1_COMP *const cpi = ppi->cpi;
   2768  AV1EncoderConfig *oxcf = &cpi->oxcf;
   2769  if (!is_one_pass_rt_params(cpi) || oxcf->rc_cfg.mode != AOM_CBR ||
   2770      cpi->ppi->use_svc || ppi->num_fp_contexts != 1 || ppi->cpi_lap != NULL) {
   2771    return AOM_CODEC_INVALID_PARAM;
   2772  }
   2773  const int new_bitrate = CAST(AV1E_SET_BITRATE_ONE_PASS_CBR, args);
   2774  ctx->cfg.rc_target_bitrate = new_bitrate;
   2775  oxcf->rc_cfg.target_bandwidth = new_bitrate * 1000;
   2776  set_primary_rc_buffer_sizes(oxcf, ppi);
   2777  av1_new_framerate(cpi, cpi->framerate);
   2778  check_reset_rc_flag(cpi);
   2779  return AOM_CODEC_OK;
   2780 }
   2781 
   2782 static aom_codec_err_t ctrl_set_max_consec_frame_drop_cbr(
   2783    aom_codec_alg_priv_t *ctx, va_list args) {
   2784  AV1_PRIMARY *const ppi = ctx->ppi;
   2785  AV1_COMP *const cpi = ppi->cpi;
   2786  const int max_consec_drop = CAST(AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR, args);
   2787  if (max_consec_drop < 0) return AOM_CODEC_INVALID_PARAM;
   2788  cpi->rc.max_consec_drop = max_consec_drop;
   2789  cpi->rc.drop_count_consec = 0;
   2790  return AOM_CODEC_OK;
   2791 }
   2792 
   2793 static aom_codec_err_t ctrl_set_max_consec_frame_drop_ms_cbr(
   2794    aom_codec_alg_priv_t *ctx, va_list args) {
   2795  AV1_PRIMARY *const ppi = ctx->ppi;
   2796  AV1_COMP *const cpi = ppi->cpi;
   2797  const int max_consec_drop_ms =
   2798      CAST(AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR, args);
   2799  if (max_consec_drop_ms < 0) return AOM_CODEC_INVALID_PARAM;
   2800  // max_consec_drop_ms will be converted to frame units inside encoder
   2801  // based on framerate (which can change dynamically).
   2802  ctx->oxcf.rc_cfg.max_consec_drop_ms = max_consec_drop_ms;
   2803  cpi->rc.drop_count_consec = 0;
   2804  return AOM_CODEC_OK;
   2805 }
   2806 
   2807 static aom_codec_err_t ctrl_set_svc_frame_drop_mode(aom_codec_alg_priv_t *ctx,
   2808                                                    va_list args) {
   2809  AV1_PRIMARY *const ppi = ctx->ppi;
   2810  AV1_COMP *const cpi = ppi->cpi;
   2811  cpi->svc.framedrop_mode = CAST(AV1E_SET_SVC_FRAME_DROP_MODE, args);
   2812  if (cpi->svc.framedrop_mode != AOM_LAYER_DROP &&
   2813      cpi->svc.framedrop_mode != AOM_FULL_SUPERFRAME_DROP)
   2814    return AOM_CODEC_INVALID_PARAM;
   2815  else
   2816    return AOM_CODEC_OK;
   2817 }
   2818 
   2819 static aom_codec_err_t ctrl_set_auto_tiles(aom_codec_alg_priv_t *ctx,
   2820                                           va_list args) {
   2821  unsigned int auto_tiles = CAST(AV1E_SET_AUTO_TILES, args);
   2822  if (auto_tiles == ctx->extra_cfg.auto_tiles) return AOM_CODEC_OK;
   2823  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2824  extra_cfg.auto_tiles = auto_tiles;
   2825  return update_extra_cfg(ctx, &extra_cfg);
   2826 }
   2827 
   2828 static aom_codec_err_t ctrl_set_postencode_drop_rtc(aom_codec_alg_priv_t *ctx,
   2829                                                    va_list args) {
   2830  AV1_PRIMARY *const ppi = ctx->ppi;
   2831  AV1_COMP *const cpi = ppi->cpi;
   2832  int enable_postencode_drop = CAST(AV1E_SET_POSTENCODE_DROP_RTC, args);
   2833  if (enable_postencode_drop > 1 || enable_postencode_drop < 0)
   2834    return AOM_CODEC_INVALID_PARAM;
   2835  cpi->rc.postencode_drop = enable_postencode_drop;
   2836  return AOM_CODEC_OK;
   2837 }
   2838 
   2839 static aom_codec_err_t ctrl_set_screen_content_detection_mode(
   2840    aom_codec_alg_priv_t *ctx, va_list args) {
   2841  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2842  const aom_screen_detection_mode screen_detection_mode =
   2843      CAST(AV1E_SET_SCREEN_CONTENT_DETECTION_MODE, args);
   2844 
   2845  extra_cfg.screen_detection_mode = screen_detection_mode;
   2846  return update_extra_cfg(ctx, &extra_cfg);
   2847 }
   2848 
   2849 #if !CONFIG_REALTIME_ONLY
   2850 static aom_codec_err_t create_stats_buffer(FIRSTPASS_STATS **frame_stats_buffer,
   2851                                           STATS_BUFFER_CTX *stats_buf_context,
   2852                                           int num_lap_buffers) {
   2853  aom_codec_err_t res = AOM_CODEC_OK;
   2854 
   2855  int size = get_stats_buf_size(num_lap_buffers, MAX_LAG_BUFFERS);
   2856  *frame_stats_buffer =
   2857      (FIRSTPASS_STATS *)aom_calloc(size, sizeof(FIRSTPASS_STATS));
   2858  if (*frame_stats_buffer == NULL) return AOM_CODEC_MEM_ERROR;
   2859 
   2860  stats_buf_context->stats_in_start = *frame_stats_buffer;
   2861  stats_buf_context->stats_in_end = stats_buf_context->stats_in_start;
   2862  stats_buf_context->stats_in_buf_end =
   2863      stats_buf_context->stats_in_start + size;
   2864 
   2865  stats_buf_context->total_left_stats = aom_calloc(1, sizeof(FIRSTPASS_STATS));
   2866  if (stats_buf_context->total_left_stats == NULL) return AOM_CODEC_MEM_ERROR;
   2867  av1_twopass_zero_stats(stats_buf_context->total_left_stats);
   2868  stats_buf_context->total_stats = aom_calloc(1, sizeof(FIRSTPASS_STATS));
   2869  if (stats_buf_context->total_stats == NULL) return AOM_CODEC_MEM_ERROR;
   2870  av1_twopass_zero_stats(stats_buf_context->total_stats);
   2871  return res;
   2872 }
   2873 #endif
   2874 
   2875 aom_codec_err_t av1_create_context_and_bufferpool(AV1_PRIMARY *ppi,
   2876                                                  AV1_COMP **p_cpi,
   2877                                                  BufferPool **p_buffer_pool,
   2878                                                  const AV1EncoderConfig *oxcf,
   2879                                                  COMPRESSOR_STAGE stage,
   2880                                                  int lap_lag_in_frames) {
   2881  aom_codec_err_t res = AOM_CODEC_OK;
   2882  BufferPool *buffer_pool = *p_buffer_pool;
   2883 
   2884  if (buffer_pool == NULL) {
   2885    buffer_pool = (BufferPool *)aom_calloc(1, sizeof(BufferPool));
   2886    if (buffer_pool == NULL) return AOM_CODEC_MEM_ERROR;
   2887    buffer_pool->num_frame_bufs =
   2888        (oxcf->mode == ALLINTRA) ? FRAME_BUFFERS_ALLINTRA : FRAME_BUFFERS;
   2889    buffer_pool->frame_bufs = (RefCntBuffer *)aom_calloc(
   2890        buffer_pool->num_frame_bufs, sizeof(*buffer_pool->frame_bufs));
   2891    if (buffer_pool->frame_bufs == NULL) {
   2892      buffer_pool->num_frame_bufs = 0;
   2893      aom_free(buffer_pool);
   2894      return AOM_CODEC_MEM_ERROR;
   2895    }
   2896 #if CONFIG_MULTITHREAD
   2897    if (pthread_mutex_init(&buffer_pool->pool_mutex, NULL)) {
   2898      aom_free(buffer_pool->frame_bufs);
   2899      buffer_pool->frame_bufs = NULL;
   2900      buffer_pool->num_frame_bufs = 0;
   2901      aom_free(buffer_pool);
   2902      return AOM_CODEC_MEM_ERROR;
   2903    }
   2904 #endif
   2905    *p_buffer_pool = buffer_pool;
   2906  }
   2907  *p_cpi =
   2908      av1_create_compressor(ppi, oxcf, buffer_pool, stage, lap_lag_in_frames);
   2909  if (*p_cpi == NULL) res = AOM_CODEC_MEM_ERROR;
   2910 
   2911  return res;
   2912 }
   2913 
   2914 static aom_codec_err_t ctrl_set_fp_mt(aom_codec_alg_priv_t *ctx, va_list args) {
   2915  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2916  extra_cfg.fp_mt = CAST(AV1E_SET_FP_MT, args);
   2917  const aom_codec_err_t result = update_extra_cfg(ctx, &extra_cfg);
   2918  int num_fp_contexts = 1;
   2919  if (ctx->ppi->num_fp_contexts == 1) {
   2920    num_fp_contexts =
   2921        av1_compute_num_fp_contexts(ctx->ppi, &ctx->ppi->parallel_cpi[0]->oxcf);
   2922    if (num_fp_contexts > 1) {
   2923      int i;
   2924      for (i = 1; i < num_fp_contexts; i++) {
   2925        int res = av1_create_context_and_bufferpool(
   2926            ctx->ppi, &ctx->ppi->parallel_cpi[i], &ctx->buffer_pool, &ctx->oxcf,
   2927            ENCODE_STAGE, -1);
   2928        if (res != AOM_CODEC_OK) {
   2929          return res;
   2930        }
   2931 #if !CONFIG_REALTIME_ONLY
   2932        ctx->ppi->parallel_cpi[i]->twopass_frame.stats_in =
   2933            ctx->ppi->twopass.stats_buf_ctx->stats_in_start;
   2934 #endif
   2935      }
   2936    }
   2937  }
   2938  ctx->ppi->num_fp_contexts = num_fp_contexts;
   2939  return result;
   2940 }
   2941 
   2942 static aom_codec_err_t ctrl_set_auto_intra_tools_off(aom_codec_alg_priv_t *ctx,
   2943                                                     va_list args) {
   2944  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   2945  extra_cfg.auto_intra_tools_off = CAST(AV1E_SET_AUTO_INTRA_TOOLS_OFF, args);
   2946  return update_extra_cfg(ctx, &extra_cfg);
   2947 }
   2948 
   2949 static aom_codec_err_t encoder_init(aom_codec_ctx_t *ctx) {
   2950  aom_codec_err_t res = AOM_CODEC_OK;
   2951 
   2952  if (ctx->priv == NULL) {
   2953    aom_codec_alg_priv_t *const priv = aom_calloc(1, sizeof(*priv));
   2954    if (priv == NULL) return AOM_CODEC_MEM_ERROR;
   2955 
   2956    ctx->priv = (aom_codec_priv_t *)priv;
   2957    ctx->priv->init_flags = ctx->init_flags;
   2958 
   2959    // Update the reference to the config structure to an internal copy.
   2960    assert(ctx->config.enc);
   2961    priv->cfg = *ctx->config.enc;
   2962    ctx->config.enc = &priv->cfg;
   2963 
   2964    priv->extra_cfg = default_extra_cfg;
   2965    // Special handling:
   2966    // By default, if omitted: --enable-cdef=1, --qm-min=5, and --qm-max=9
   2967    // Here we set its default values to 0, 4, and 10 respectively when
   2968    // --allintra is turned on.
   2969    // However, if users set --enable-cdef, --qm-min, or --qm-max, either from
   2970    // the command line or aom_codec_control(), the encoder still respects it.
   2971    if (priv->cfg.g_usage == AOM_USAGE_ALL_INTRA) {
   2972      // CDEF has been found to blur images, so it's disabled in all-intra mode
   2973      priv->extra_cfg.enable_cdef = 0;
   2974      // These QM min/max values have been found to be beneficial for images,
   2975      // when used with an alternative QM formula (see
   2976      // aom_get_qmlevel_allintra()).
   2977      // These values could also be beneficial for other usage modes, but
   2978      // further testing is required.
   2979      priv->extra_cfg.qm_min = DEFAULT_QM_FIRST_ALLINTRA;
   2980      priv->extra_cfg.qm_max = DEFAULT_QM_LAST_ALLINTRA;
   2981    }
   2982    av1_initialize_enc(priv->cfg.g_usage, priv->cfg.rc_end_usage);
   2983 
   2984    res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
   2985 
   2986    if (res == AOM_CODEC_OK) {
   2987      int *num_lap_buffers = &priv->num_lap_buffers;
   2988      int lap_lag_in_frames = 0;
   2989      *num_lap_buffers = 0;
   2990      priv->timestamp_ratio.den = priv->cfg.g_timebase.den;
   2991      priv->timestamp_ratio.num =
   2992          (int64_t)priv->cfg.g_timebase.num * TICKS_PER_SEC;
   2993      reduce_ratio(&priv->timestamp_ratio);
   2994 
   2995      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
   2996      if (priv->oxcf.rc_cfg.mode != AOM_CBR &&
   2997          priv->oxcf.pass == AOM_RC_ONE_PASS && priv->oxcf.mode == GOOD) {
   2998        // Enable look ahead - enabled for AOM_Q, AOM_CQ, AOM_VBR
   2999        *num_lap_buffers =
   3000            AOMMIN((int)priv->cfg.g_lag_in_frames,
   3001                   AOMMIN(MAX_LAP_BUFFERS, priv->oxcf.kf_cfg.key_freq_max +
   3002                                               SCENE_CUT_KEY_TEST_INTERVAL));
   3003        if ((int)priv->cfg.g_lag_in_frames - (*num_lap_buffers) >=
   3004            LAP_LAG_IN_FRAMES) {
   3005          lap_lag_in_frames = LAP_LAG_IN_FRAMES;
   3006        }
   3007      }
   3008      priv->oxcf.use_highbitdepth =
   3009          (ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
   3010 
   3011      priv->monochrome_on_init = priv->cfg.monochrome;
   3012 
   3013      priv->ppi = av1_create_primary_compressor(&priv->pkt_list.head,
   3014                                                *num_lap_buffers, &priv->oxcf);
   3015      if (!priv->ppi) return AOM_CODEC_MEM_ERROR;
   3016 
   3017 #if !CONFIG_REALTIME_ONLY
   3018      res = create_stats_buffer(&priv->frame_stats_buffer,
   3019                                &priv->stats_buf_context, *num_lap_buffers);
   3020      if (res != AOM_CODEC_OK) return res;
   3021 
   3022      assert(MAX_LAP_BUFFERS >= MAX_LAG_BUFFERS);
   3023      int size = get_stats_buf_size(*num_lap_buffers, MAX_LAG_BUFFERS);
   3024      for (int i = 0; i < size; i++)
   3025        priv->ppi->twopass.frame_stats_arr[i] = &priv->frame_stats_buffer[i];
   3026 
   3027      priv->ppi->twopass.stats_buf_ctx = &priv->stats_buf_context;
   3028 #endif
   3029 
   3030      assert(priv->ppi->num_fp_contexts >= 1);
   3031      res = av1_create_context_and_bufferpool(
   3032          priv->ppi, &priv->ppi->parallel_cpi[0], &priv->buffer_pool,
   3033          &priv->oxcf, ENCODE_STAGE, -1);
   3034      if (res != AOM_CODEC_OK) {
   3035        priv->base.err_detail = "av1_create_context_and_bufferpool() failed";
   3036        return res;
   3037      }
   3038 #if !CONFIG_REALTIME_ONLY
   3039      priv->ppi->parallel_cpi[0]->twopass_frame.stats_in =
   3040          priv->ppi->twopass.stats_buf_ctx->stats_in_start;
   3041 #endif
   3042      priv->ppi->cpi = priv->ppi->parallel_cpi[0];
   3043 
   3044      // Create another compressor if look ahead is enabled
   3045      if (res == AOM_CODEC_OK && *num_lap_buffers) {
   3046        res = av1_create_context_and_bufferpool(
   3047            priv->ppi, &priv->ppi->cpi_lap, &priv->buffer_pool_lap, &priv->oxcf,
   3048            LAP_STAGE, clamp(lap_lag_in_frames, 0, MAX_LAG_BUFFERS));
   3049      }
   3050    }
   3051  }
   3052 
   3053  return res;
   3054 }
   3055 
   3056 void av1_destroy_context_and_bufferpool(AV1_COMP *cpi,
   3057                                        BufferPool **p_buffer_pool) {
   3058  av1_remove_compressor(cpi);
   3059  if (*p_buffer_pool) {
   3060    av1_free_ref_frame_buffers(*p_buffer_pool);
   3061 #if CONFIG_MULTITHREAD
   3062    pthread_mutex_destroy(&(*p_buffer_pool)->pool_mutex);
   3063 #endif
   3064    aom_free(*p_buffer_pool);
   3065    *p_buffer_pool = NULL;
   3066  }
   3067 }
   3068 
   3069 static void destroy_stats_buffer(STATS_BUFFER_CTX *stats_buf_context,
   3070                                 FIRSTPASS_STATS *frame_stats_buffer) {
   3071  aom_free(stats_buf_context->total_left_stats);
   3072  aom_free(stats_buf_context->total_stats);
   3073  aom_free(frame_stats_buffer);
   3074 }
   3075 
   3076 static void check_and_free_string(const char *default_str, const char **ptr) {
   3077  if (*ptr == default_str) {
   3078    // Default should be a literal. Do not free.
   3079    return;
   3080  }
   3081  aom_free((void *)*ptr);
   3082  *ptr = NULL;
   3083 }
   3084 
   3085 static void destroy_extra_config(struct av1_extracfg *extra_cfg) {
   3086 #if CONFIG_TUNE_VMAF
   3087  check_and_free_string(default_extra_cfg.vmaf_model_path,
   3088                        &extra_cfg->vmaf_model_path);
   3089 #endif
   3090  check_and_free_string(default_extra_cfg.two_pass_output,
   3091                        &extra_cfg->two_pass_output);
   3092  check_and_free_string(default_extra_cfg.two_pass_output,
   3093                        &extra_cfg->second_pass_log);
   3094  check_and_free_string(default_extra_cfg.partition_info_path,
   3095                        &extra_cfg->partition_info_path);
   3096  check_and_free_string(default_extra_cfg.rate_distribution_info,
   3097                        &extra_cfg->rate_distribution_info);
   3098  check_and_free_string(default_extra_cfg.film_grain_table_filename,
   3099                        &extra_cfg->film_grain_table_filename);
   3100 }
   3101 
   3102 static aom_codec_err_t encoder_destroy(aom_codec_alg_priv_t *ctx) {
   3103  free(ctx->cx_data);
   3104  destroy_extra_config(&ctx->extra_cfg);
   3105 
   3106  if (ctx->ppi) {
   3107    AV1_PRIMARY *ppi = ctx->ppi;
   3108    for (int i = 0; i < MAX_PARALLEL_FRAMES - 1; i++) {
   3109      if (ppi->parallel_frames_data[i].cx_data) {
   3110        free(ppi->parallel_frames_data[i].cx_data);
   3111      }
   3112    }
   3113 #if CONFIG_ENTROPY_STATS
   3114    print_entropy_stats(ppi);
   3115 #endif
   3116 #if CONFIG_INTERNAL_STATS
   3117    print_internal_stats(ppi);
   3118 #endif
   3119 
   3120    for (int i = 0; i < MAX_PARALLEL_FRAMES; i++) {
   3121      av1_destroy_context_and_bufferpool(ppi->parallel_cpi[i],
   3122                                         &ctx->buffer_pool);
   3123    }
   3124    ppi->cpi = NULL;
   3125 
   3126    if (ppi->cpi_lap) {
   3127      av1_destroy_context_and_bufferpool(ppi->cpi_lap, &ctx->buffer_pool_lap);
   3128    }
   3129    av1_remove_primary_compressor(ppi);
   3130  }
   3131  destroy_stats_buffer(&ctx->stats_buf_context, ctx->frame_stats_buffer);
   3132  aom_free(ctx);
   3133  return AOM_CODEC_OK;
   3134 }
   3135 
   3136 static aom_codec_frame_flags_t get_frame_pkt_flags(const AV1_COMP *cpi,
   3137                                                   unsigned int lib_flags) {
   3138  aom_codec_frame_flags_t flags = lib_flags << 16;
   3139  if (lib_flags & FRAMEFLAGS_KEY) flags |= AOM_FRAME_IS_KEY;
   3140  if (lib_flags & FRAMEFLAGS_INTRAONLY) flags |= AOM_FRAME_IS_INTRAONLY;
   3141  if (lib_flags & FRAMEFLAGS_SWITCH) flags |= AOM_FRAME_IS_SWITCH;
   3142  if (lib_flags & FRAMEFLAGS_ERROR_RESILIENT)
   3143    flags |= AOM_FRAME_IS_ERROR_RESILIENT;
   3144  if (cpi->droppable) flags |= AOM_FRAME_IS_DROPPABLE;
   3145 
   3146  return flags;
   3147 }
   3148 
   3149 static inline int get_src_border_in_pixels(AV1_COMP *cpi, BLOCK_SIZE sb_size) {
   3150  if (cpi->oxcf.mode != REALTIME || av1_is_resize_needed(&cpi->oxcf))
   3151    return cpi->oxcf.border_in_pixels;
   3152 
   3153  const int sb_size_in_pixels_log2 = mi_size_wide_log2[sb_size] + MI_SIZE_LOG2;
   3154  const int sb_aligned_width =
   3155      ALIGN_POWER_OF_TWO(cpi->oxcf.frm_dim_cfg.width, sb_size_in_pixels_log2);
   3156  const int sb_aligned_height =
   3157      ALIGN_POWER_OF_TWO(cpi->oxcf.frm_dim_cfg.height, sb_size_in_pixels_log2);
   3158  // Align the border pixels to a multiple of 32.
   3159  const int border_pixels_width =
   3160      ALIGN_POWER_OF_TWO(sb_aligned_width - cpi->oxcf.frm_dim_cfg.width, 5);
   3161  const int border_pixels_height =
   3162      ALIGN_POWER_OF_TWO(sb_aligned_height - cpi->oxcf.frm_dim_cfg.height, 5);
   3163  const int border_in_pixels =
   3164      AOMMAX(AOMMAX(border_pixels_width, border_pixels_height), 32);
   3165  return border_in_pixels;
   3166 }
   3167 
   3168 // TODO(Mufaddal): Check feasibility of abstracting functions related to LAP
   3169 // into a separate function.
   3170 static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
   3171                                      const aom_image_t *img,
   3172                                      aom_codec_pts_t pts,
   3173                                      unsigned long duration,
   3174                                      aom_enc_frame_flags_t enc_flags) {
   3175  const size_t kMinCompressedSize = 8192;
   3176  volatile aom_codec_err_t res = AOM_CODEC_OK;
   3177  AV1_PRIMARY *const ppi = ctx->ppi;
   3178  volatile aom_codec_pts_t ptsvol = pts;
   3179  AV1_COMP_DATA cpi_data = { 0 };
   3180 
   3181  cpi_data.timestamp_ratio = &ctx->timestamp_ratio;
   3182  cpi_data.flush = !img;
   3183  // LAP context
   3184  AV1_COMP *cpi_lap = ppi->cpi_lap;
   3185  if (ppi->cpi == NULL) return AOM_CODEC_INVALID_PARAM;
   3186 
   3187  ppi->cpi->last_coded_width = ppi->cpi->oxcf.frm_dim_cfg.width;
   3188  ppi->cpi->last_coded_height = ppi->cpi->oxcf.frm_dim_cfg.height;
   3189 
   3190  if (ppi->lap_enabled && cpi_lap == NULL &&
   3191      ppi->cpi->oxcf.pass == AOM_RC_ONE_PASS)
   3192    return AOM_CODEC_INVALID_PARAM;
   3193 
   3194  if (img != NULL) {
   3195    res = validate_img(ctx, img);
   3196    if (res == AOM_CODEC_OK) {
   3197      const uint64_t uncompressed_frame_sz64 =
   3198          (uint64_t)ALIGN_POWER_OF_TWO_UNSIGNED(ctx->cfg.g_w, 5) *
   3199          ALIGN_POWER_OF_TWO_UNSIGNED(ctx->cfg.g_h, 5) * get_image_bps(img) / 8;
   3200 #if UINT64_MAX > SIZE_MAX
   3201      if (uncompressed_frame_sz64 > SIZE_MAX) return AOM_CODEC_MEM_ERROR;
   3202 #endif
   3203      const size_t uncompressed_frame_sz = (size_t)uncompressed_frame_sz64;
   3204 
   3205      // Due to the presence of no-show frames, the ctx->cx_data buffer holds
   3206      // compressed data corresponding to multiple frames. As no-show frames are
   3207      // not possible for all intra frame encoding with no forward key frames,
   3208      // the buffer is allocated with a smaller size in this case.
   3209      //
   3210      // For pseudo random input, the compressed frame size is seen to exceed
   3211      // the uncompressed frame size, but is less than 2 times the uncompressed
   3212      // frame size. Hence the size of the buffer is chosen as 2 times the
   3213      // uncompressed frame size.
   3214      int multiplier = 8;
   3215      if (ppi->cpi->oxcf.kf_cfg.key_freq_max == 0 &&
   3216          !ppi->cpi->oxcf.kf_cfg.fwd_kf_enabled)
   3217        multiplier = 2;
   3218      if (uncompressed_frame_sz > SIZE_MAX / multiplier)
   3219        return AOM_CODEC_MEM_ERROR;
   3220      size_t data_sz = uncompressed_frame_sz * multiplier;
   3221      if (data_sz < kMinCompressedSize) data_sz = kMinCompressedSize;
   3222      if (ctx->cx_data == NULL || ctx->cx_data_sz < data_sz) {
   3223        ctx->cx_data_sz = data_sz;
   3224        free(ctx->cx_data);
   3225        ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
   3226        if (ctx->cx_data == NULL) {
   3227          ctx->cx_data_sz = 0;
   3228          return AOM_CODEC_MEM_ERROR;
   3229        }
   3230      }
   3231      for (int i = 0; i < ppi->num_fp_contexts - 1; i++) {
   3232        if (ppi->parallel_frames_data[i].cx_data == NULL ||
   3233            ppi->parallel_frames_data[i].cx_data_sz < data_sz) {
   3234          ppi->parallel_frames_data[i].cx_data_sz = data_sz;
   3235          free(ppi->parallel_frames_data[i].cx_data);
   3236          ppi->parallel_frames_data[i].frame_size = 0;
   3237          ppi->parallel_frames_data[i].cx_data =
   3238              (unsigned char *)malloc(ppi->parallel_frames_data[i].cx_data_sz);
   3239          if (ppi->parallel_frames_data[i].cx_data == NULL) {
   3240            ppi->parallel_frames_data[i].cx_data_sz = 0;
   3241            return AOM_CODEC_MEM_ERROR;
   3242          }
   3243        }
   3244      }
   3245    }
   3246  }
   3247 
   3248  aom_codec_pkt_list_init(&ctx->pkt_list);
   3249 
   3250  volatile aom_enc_frame_flags_t flags = enc_flags;
   3251 
   3252  // The jmp_buf is valid only for the duration of the function that calls
   3253  // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
   3254  // before it returns.
   3255  if (setjmp(ppi->error.jmp)) {
   3256    ppi->error.setjmp = 0;
   3257    res = update_error_state(ctx, &ppi->error);
   3258    return res;
   3259  }
   3260  ppi->error.setjmp = 1;
   3261 
   3262  if (ppi->use_svc && ppi->cpi->svc.use_flexible_mode == 0 && flags == 0)
   3263    av1_set_svc_fixed_mode(ppi->cpi);
   3264 
   3265  // Note(yunqing): While applying encoding flags, always start from enabling
   3266  // all, and then modifying according to the flags. Previous frame's flags are
   3267  // overwritten.
   3268  av1_apply_encoding_flags(ppi->cpi, flags);
   3269  if (cpi_lap != NULL) {
   3270    av1_apply_encoding_flags(cpi_lap, flags);
   3271  }
   3272 
   3273 #if CONFIG_TUNE_VMAF
   3274  if (ctx->extra_cfg.tuning >= AOM_TUNE_VMAF_WITH_PREPROCESSING &&
   3275      ctx->extra_cfg.tuning <= AOM_TUNE_VMAF_NEG_MAX_GAIN) {
   3276    aom_init_vmaf_model(&ppi->cpi->vmaf_info.vmaf_model,
   3277                        ppi->cpi->oxcf.tune_cfg.vmaf_model_path);
   3278  }
   3279 #endif
   3280 
   3281  // Handle fixed keyframe intervals
   3282  if (is_stat_generation_stage(ppi->cpi) || is_one_pass_rt_params(ppi->cpi)) {
   3283    if (ctx->cfg.kf_mode == AOM_KF_AUTO &&
   3284        ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
   3285      if (ppi->cpi->common.spatial_layer_id == 0 &&
   3286          ++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
   3287        flags |= AOM_EFLAG_FORCE_KF;
   3288        ctx->fixed_kf_cntr = 1;
   3289      }
   3290    }
   3291  }
   3292 
   3293  if (res == AOM_CODEC_OK) {
   3294    AV1_COMP *cpi = ppi->cpi;
   3295 
   3296    // Per-frame PSNR is not supported when g_lag_in_frames is greater than 0.
   3297    if ((flags & AOM_EFLAG_CALCULATE_PSNR) && ctx->cfg.g_lag_in_frames != 0) {
   3298      aom_internal_error(
   3299          &ppi->error, AOM_CODEC_INCAPABLE,
   3300          "Cannot calculate per-frame PSNR when g_lag_in_frames is nonzero");
   3301    }
   3302 
   3303    // Set up internal flags
   3304 #if CONFIG_INTERNAL_STATS
   3305    assert(ppi->b_calculate_psnr == 1);
   3306 #else
   3307    ppi->b_calculate_psnr = (ctx->base.init_flags & AOM_CODEC_USE_PSNR) ||
   3308                            (flags & AOM_EFLAG_CALCULATE_PSNR);
   3309 #endif  // CONFIG_INTERNAL_STATS
   3310 
   3311    if (img != NULL) {
   3312      if (!ctx->pts_offset_initialized) {
   3313        ctx->pts_offset = ptsvol;
   3314        ctx->pts_offset_initialized = 1;
   3315      }
   3316      if (ptsvol < ctx->pts_offset) {
   3317        aom_internal_error(&ppi->error, AOM_CODEC_INVALID_PARAM,
   3318                           "pts is smaller than initial pts");
   3319      }
   3320      ptsvol -= ctx->pts_offset;
   3321      if (ptsvol > INT64_MAX / cpi_data.timestamp_ratio->num) {
   3322        aom_internal_error(
   3323            &ppi->error, AOM_CODEC_INVALID_PARAM,
   3324            "conversion of relative pts to ticks would overflow");
   3325      }
   3326      int64_t src_time_stamp =
   3327          timebase_units_to_ticks(cpi_data.timestamp_ratio, ptsvol);
   3328 #if ULONG_MAX > INT64_MAX
   3329      if (duration > INT64_MAX) {
   3330        aom_internal_error(&ppi->error, AOM_CODEC_INVALID_PARAM,
   3331                           "duration is too big");
   3332      }
   3333 #endif
   3334      if (ptsvol > INT64_MAX - (int64_t)duration) {
   3335        aom_internal_error(&ppi->error, AOM_CODEC_INVALID_PARAM,
   3336                           "relative pts + duration is too big");
   3337      }
   3338      aom_codec_pts_t pts_end = ptsvol + (int64_t)duration;
   3339      if (pts_end > INT64_MAX / cpi_data.timestamp_ratio->num) {
   3340        aom_internal_error(
   3341            &ppi->error, AOM_CODEC_INVALID_PARAM,
   3342            "conversion of relative pts + duration to ticks would overflow");
   3343      }
   3344      int64_t src_end_time_stamp =
   3345          timebase_units_to_ticks(cpi_data.timestamp_ratio, pts_end);
   3346 
   3347      YV12_BUFFER_CONFIG sd;
   3348      res = image2yuvconfig(img, &sd);
   3349      // When generating a monochrome stream, make |sd| a monochrome image.
   3350      if (ctx->cfg.monochrome) {
   3351        sd.u_buffer = sd.v_buffer = NULL;
   3352        sd.uv_stride = 0;
   3353        sd.monochrome = 1;
   3354      }
   3355      int use_highbitdepth = (sd.flags & YV12_FLAG_HIGHBITDEPTH) != 0;
   3356      int subsampling_x = sd.subsampling_x;
   3357      int subsampling_y = sd.subsampling_y;
   3358 
   3359      if (!ppi->lookahead) {
   3360        int lag_in_frames = cpi_lap != NULL ? cpi_lap->oxcf.gf_cfg.lag_in_frames
   3361                                            : cpi->oxcf.gf_cfg.lag_in_frames;
   3362        AV1EncoderConfig *oxcf = &cpi->oxcf;
   3363        const BLOCK_SIZE sb_size = av1_select_sb_size(
   3364            oxcf, oxcf->frm_dim_cfg.width, oxcf->frm_dim_cfg.height,
   3365            ppi->number_spatial_layers);
   3366        oxcf->border_in_pixels =
   3367            av1_get_enc_border_size(av1_is_resize_needed(oxcf),
   3368                                    oxcf->kf_cfg.key_freq_max == 0, sb_size);
   3369        for (int i = 0; i < ppi->num_fp_contexts; i++) {
   3370          ppi->parallel_cpi[i]->oxcf.border_in_pixels = oxcf->border_in_pixels;
   3371        }
   3372 
   3373        const int src_border_in_pixels = get_src_border_in_pixels(cpi, sb_size);
   3374        ppi->lookahead = av1_lookahead_init(
   3375            cpi->oxcf.frm_dim_cfg.width, cpi->oxcf.frm_dim_cfg.height,
   3376            subsampling_x, subsampling_y, use_highbitdepth, lag_in_frames,
   3377            src_border_in_pixels, cpi->common.features.byte_alignment,
   3378            ctx->num_lap_buffers, (cpi->oxcf.kf_cfg.key_freq_max == 0),
   3379            cpi->alloc_pyramid);
   3380      }
   3381      if (!ppi->lookahead)
   3382        aom_internal_error(&ppi->error, AOM_CODEC_MEM_ERROR,
   3383                           "Failed to allocate lag buffers");
   3384      for (int i = 0; i < ppi->num_fp_contexts; i++) {
   3385        aom_codec_err_t err =
   3386            av1_check_initial_width(ppi->parallel_cpi[i], use_highbitdepth,
   3387                                    subsampling_x, subsampling_y);
   3388        if (err != AOM_CODEC_OK) {
   3389          aom_internal_error(&ppi->error, err,
   3390                             "av1_check_initial_width() failed");
   3391        }
   3392      }
   3393      if (cpi_lap != NULL) {
   3394        aom_codec_err_t err = av1_check_initial_width(
   3395            cpi_lap, use_highbitdepth, subsampling_x, subsampling_y);
   3396        if (err != AOM_CODEC_OK) {
   3397          aom_internal_error(&ppi->error, err,
   3398                             "av1_check_initial_width() failed");
   3399        }
   3400      }
   3401 
   3402      // Store the original flags in to the frame buffer. Will extract the
   3403      // key frame flag when we actually encode this frame.
   3404      if (av1_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd,
   3405                                src_time_stamp, src_end_time_stamp)) {
   3406        res = update_error_state(ctx, cpi->common.error);
   3407      }
   3408      ctx->next_frame_flags = 0;
   3409    }
   3410 
   3411    cpi_data.cx_data = ctx->cx_data;
   3412    cpi_data.cx_data_sz = ctx->cx_data_sz;
   3413 
   3414    /* Any pending invisible frames? */
   3415    if (ctx->pending_cx_data_sz) {
   3416      cpi_data.cx_data += ctx->pending_cx_data_sz;
   3417      cpi_data.cx_data_sz -= ctx->pending_cx_data_sz;
   3418 
   3419      /* TODO: this is a minimal check, the underlying codec doesn't respect
   3420       * the buffer size anyway.
   3421       */
   3422      if (cpi_data.cx_data_sz < ctx->cx_data_sz / 2) {
   3423        aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
   3424                           "Compressed data buffer too small");
   3425      }
   3426    }
   3427 
   3428    int is_frame_visible = 0;
   3429    int has_no_show_keyframe = 0;
   3430    int num_workers = 0;
   3431 
   3432    if (cpi->oxcf.pass == AOM_RC_FIRST_PASS) {
   3433 #if !CONFIG_REALTIME_ONLY
   3434      num_workers = ppi->p_mt_info.num_mod_workers[MOD_FP] =
   3435          av1_fp_compute_num_enc_workers(cpi);
   3436 #endif
   3437    } else {
   3438      av1_compute_num_workers_for_mt(cpi);
   3439      num_workers = av1_get_max_num_workers(cpi);
   3440    }
   3441    if (num_workers > 1 && ppi->p_mt_info.num_workers < num_workers) {
   3442      // Obtain the maximum no. of frames that can be supported in a parallel
   3443      // encode set.
   3444      if (is_stat_consumption_stage(cpi)) {
   3445        ppi->num_fp_contexts = av1_compute_num_fp_contexts(ppi, &cpi->oxcf);
   3446      }
   3447      if (ppi->p_mt_info.num_workers > 0) {
   3448        av1_terminate_workers(ppi);
   3449        free_thread_data(ppi);
   3450        aom_free(ppi->p_mt_info.tile_thr_data);
   3451        ppi->p_mt_info.tile_thr_data = NULL;
   3452        aom_free(ppi->p_mt_info.workers);
   3453        ppi->p_mt_info.workers = NULL;
   3454        ppi->p_mt_info.num_workers = 0;
   3455        for (int j = 0; j < ppi->num_fp_contexts; j++) {
   3456          aom_free(ppi->parallel_cpi[j]->td.tctx);
   3457          ppi->parallel_cpi[j]->td.tctx = NULL;
   3458        }
   3459      }
   3460      av1_create_workers(ppi, num_workers);
   3461      av1_init_tile_thread_data(ppi, cpi->oxcf.pass == AOM_RC_FIRST_PASS);
   3462    }
   3463 
   3464    // Re-allocate thread data if workers for encoder multi-threading stage
   3465    // exceeds prev_num_enc_workers.
   3466    const int num_enc_workers =
   3467        av1_get_num_mod_workers_for_alloc(&ppi->p_mt_info, MOD_ENC);
   3468    if (ppi->p_mt_info.prev_num_enc_workers < num_enc_workers &&
   3469        num_enc_workers <= ppi->p_mt_info.num_workers) {
   3470      free_thread_data(ppi);
   3471      for (int j = 0; j < ppi->num_fp_contexts; j++) {
   3472        aom_free(ppi->parallel_cpi[j]->td.tctx);
   3473        ppi->parallel_cpi[j]->td.tctx = NULL;
   3474      }
   3475      av1_init_tile_thread_data(ppi, cpi->oxcf.pass == AOM_RC_FIRST_PASS);
   3476    }
   3477 
   3478    for (int i = 0; i < ppi->num_fp_contexts; i++) {
   3479      av1_init_frame_mt(ppi, ppi->parallel_cpi[i]);
   3480    }
   3481    if (cpi_lap != NULL) {
   3482      av1_init_frame_mt(ppi, cpi_lap);
   3483    }
   3484 #if CONFIG_MULTITHREAD
   3485    if (ppi->p_mt_info.num_workers > 1) {
   3486      for (int i = 0; i < ppi->num_fp_contexts; i++) {
   3487        av1_init_mt_sync(ppi->parallel_cpi[i],
   3488                         ppi->parallel_cpi[i]->oxcf.pass == AOM_RC_FIRST_PASS);
   3489      }
   3490      if (cpi_lap != NULL) {
   3491        av1_init_mt_sync(cpi_lap, 1);
   3492      }
   3493    }
   3494 #endif  // CONFIG_MULTITHREAD
   3495 
   3496    // Call for LAP stage
   3497    if (cpi_lap != NULL) {
   3498      AV1_COMP_DATA cpi_lap_data = { 0 };
   3499      cpi_lap_data.flush = !img;
   3500      cpi_lap_data.timestamp_ratio = &ctx->timestamp_ratio;
   3501      const int status = av1_get_compressed_data(cpi_lap, &cpi_lap_data);
   3502      if (status > AOM_CODEC_OK) {
   3503        aom_internal_error_copy(&ppi->error, cpi_lap->common.error);
   3504      }
   3505      av1_post_encode_updates(cpi_lap, &cpi_lap_data);
   3506    }
   3507 
   3508    // Recalculate the maximum number of frames that can be encoded in
   3509    // parallel at the beginning of sub gop.
   3510    if (is_stat_consumption_stage(cpi) && ppi->gf_group.size > 0 &&
   3511        cpi->gf_frame_index == ppi->gf_group.size) {
   3512      ppi->num_fp_contexts = av1_compute_num_fp_contexts(ppi, &cpi->oxcf);
   3513    }
   3514 
   3515    // Get the next visible frame. Invisible frames get packed with the next
   3516    // visible frame.
   3517    while (cpi_data.cx_data_sz >= ctx->cx_data_sz / 2 && !is_frame_visible) {
   3518      int simulate_parallel_frame = 0;
   3519      int status = -1;
   3520      cpi->do_frame_data_update = true;
   3521      cpi->ref_idx_to_skip = INVALID_IDX;
   3522      cpi->ref_refresh_index = INVALID_IDX;
   3523      cpi->refresh_idx_available = false;
   3524 
   3525 #if CONFIG_FPMT_TEST
   3526      simulate_parallel_frame =
   3527          cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE ? 1 : 0;
   3528      if (simulate_parallel_frame) {
   3529        if (ppi->num_fp_contexts > 1 && ppi->gf_group.size > 1) {
   3530          if (cpi->gf_frame_index < ppi->gf_group.size) {
   3531            calc_frame_data_update_flag(&ppi->gf_group, cpi->gf_frame_index,
   3532                                        &cpi->do_frame_data_update);
   3533          }
   3534        }
   3535        status = av1_get_compressed_data(cpi, &cpi_data);
   3536      }
   3537 
   3538 #endif  // CONFIG_FPMT_TEST
   3539      if (!simulate_parallel_frame) {
   3540        if (ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] == 0) {
   3541          status = av1_get_compressed_data(cpi, &cpi_data);
   3542        } else if (ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] ==
   3543                   1) {
   3544          // In case of an error, longjmp() would be invoked and hence "status"
   3545          // is set to AOM_CODEC_OK here.
   3546          av1_compress_parallel_frames(ppi, &cpi_data);
   3547          status = AOM_CODEC_OK;
   3548        } else {
   3549          // No possibility of failures from this function and hence "status" is
   3550          // set to AOM_CODEC_OK here.
   3551          cpi = av1_get_parallel_frame_enc_data(ppi, &cpi_data);
   3552          status = AOM_CODEC_OK;
   3553        }
   3554      }
   3555      if (status == -1) break;
   3556      if (status != AOM_CODEC_OK) {
   3557        aom_internal_error_copy(&ppi->error, cpi->common.error);
   3558      }
   3559      if (ppi->num_fp_contexts > 0 && frame_is_intra_only(&cpi->common)) {
   3560        av1_init_sc_decisions(ppi);
   3561      }
   3562 
   3563      ppi->seq_params_locked = 1;
   3564      av1_post_encode_updates(cpi, &cpi_data);
   3565 
   3566 #if CONFIG_ENTROPY_STATS
   3567      if (ppi->cpi->oxcf.pass != 1 && !cpi->common.show_existing_frame)
   3568        av1_accumulate_frame_counts(&ppi->aggregate_fc, &cpi->counts);
   3569 #endif
   3570 #if CONFIG_INTERNAL_STATS
   3571      if (ppi->cpi->oxcf.pass != 1) {
   3572        ppi->total_time_compress_data += cpi->time_compress_data;
   3573        ppi->total_recode_hits += cpi->frame_recode_hits;
   3574        ppi->total_bytes += (uint64_t)cpi->bytes;
   3575        for (int i = 0; i < MAX_MODES; i++) {
   3576          ppi->total_mode_chosen_counts[i] += cpi->mode_chosen_counts[i];
   3577        }
   3578      }
   3579 #endif  // CONFIG_INTERNAL_STATS
   3580 
   3581      if (!cpi_data.frame_size) continue;
   3582      assert(cpi_data.cx_data != NULL && cpi_data.cx_data_sz != 0);
   3583      if (cpi_data.frame_size > cpi_data.cx_data_sz) {
   3584        aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
   3585                           "cpi_data.cx_data buffer overflow");
   3586      }
   3587      const int write_temporal_delimiter =
   3588          !cpi->common.spatial_layer_id && !ctx->pending_cx_data_sz;
   3589 
   3590      if (write_temporal_delimiter) {
   3591        uint32_t obu_header_size = 1;
   3592        const uint32_t obu_payload_size = 0;
   3593        const size_t length_field_size =
   3594            aom_uleb_size_in_bytes(obu_payload_size);
   3595 
   3596        const size_t move_offset = obu_header_size + length_field_size;
   3597        assert(ctx->cx_data_sz == cpi_data.cx_data_sz);
   3598        if (move_offset > ctx->cx_data_sz - cpi_data.frame_size) {
   3599          aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
   3600                             "ctx->cx_data buffer full");
   3601        }
   3602        memmove(ctx->cx_data + move_offset, ctx->cx_data, cpi_data.frame_size);
   3603        obu_header_size = av1_write_obu_header(
   3604            &ppi->level_params, &cpi->frame_header_count,
   3605            OBU_TEMPORAL_DELIMITER,
   3606            ppi->seq_params.has_nonzero_operating_point_idc,
   3607            /*is_layer_specific_obu=*/false, 0, ctx->cx_data);
   3608        if (obu_header_size != 1) {
   3609          aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
   3610        }
   3611 
   3612        // OBUs are preceded/succeeded by an unsigned leb128 coded integer.
   3613        if (av1_write_uleb_obu_size(obu_payload_size,
   3614                                    ctx->cx_data + obu_header_size,
   3615                                    length_field_size) != AOM_CODEC_OK) {
   3616          aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
   3617        }
   3618 
   3619        cpi_data.frame_size += move_offset;
   3620      }
   3621 
   3622      if (ctx->oxcf.save_as_annexb) {
   3623        if (av1_convert_sect5obus_to_annexb(
   3624                cpi_data.cx_data, cpi_data.cx_data_sz, &cpi_data.frame_size) !=
   3625            AOM_CODEC_OK) {
   3626          aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
   3627        }
   3628 
   3629        // B_PRIME (add frame size)
   3630        const size_t length_field_size =
   3631            aom_uleb_size_in_bytes(cpi_data.frame_size);
   3632        if (length_field_size > cpi_data.cx_data_sz - cpi_data.frame_size) {
   3633          aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
   3634                             "cpi_data.cx_data buffer full");
   3635        }
   3636        memmove(cpi_data.cx_data + length_field_size, cpi_data.cx_data,
   3637                cpi_data.frame_size);
   3638        if (av1_write_uleb_obu_size(cpi_data.frame_size, cpi_data.cx_data,
   3639                                    length_field_size) != AOM_CODEC_OK) {
   3640          aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
   3641        }
   3642        cpi_data.frame_size += length_field_size;
   3643      }
   3644 
   3645      ctx->pending_cx_data_sz += cpi_data.frame_size;
   3646 
   3647      cpi_data.cx_data += cpi_data.frame_size;
   3648      cpi_data.cx_data_sz -= cpi_data.frame_size;
   3649 
   3650      is_frame_visible = cpi->common.show_frame;
   3651 
   3652      has_no_show_keyframe |=
   3653          (!is_frame_visible &&
   3654           cpi->common.current_frame.frame_type == KEY_FRAME);
   3655    }
   3656    if (is_frame_visible) {
   3657      // Add the frame packet to the list of returned packets.
   3658      aom_codec_cx_pkt_t pkt;
   3659 
   3660      // decrement frames_left counter
   3661      ppi->frames_left = AOMMAX(0, ppi->frames_left - 1);
   3662      if (ctx->oxcf.save_as_annexb) {
   3663        //  B_PRIME (add TU size)
   3664        size_t tu_size = ctx->pending_cx_data_sz;
   3665        const size_t length_field_size = aom_uleb_size_in_bytes(tu_size);
   3666        if (tu_size > ctx->cx_data_sz) {
   3667          aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
   3668                             "ctx->cx_data buffer overflow");
   3669        }
   3670        if (length_field_size > ctx->cx_data_sz - tu_size) {
   3671          aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
   3672                             "ctx->cx_data buffer full");
   3673        }
   3674        memmove(ctx->cx_data + length_field_size, ctx->cx_data, tu_size);
   3675        if (av1_write_uleb_obu_size(tu_size, ctx->cx_data, length_field_size) !=
   3676            AOM_CODEC_OK) {
   3677          aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
   3678        }
   3679        ctx->pending_cx_data_sz += length_field_size;
   3680      }
   3681 
   3682      pkt.kind = AOM_CODEC_CX_FRAME_PKT;
   3683 
   3684      pkt.data.frame.buf = ctx->cx_data;
   3685      pkt.data.frame.sz = ctx->pending_cx_data_sz;
   3686      pkt.data.frame.partition_id = -1;
   3687      pkt.data.frame.vis_frame_size = cpi_data.frame_size;
   3688 
   3689      pkt.data.frame.pts = ticks_to_timebase_units(cpi_data.timestamp_ratio,
   3690                                                   cpi_data.ts_frame_start) +
   3691                           ctx->pts_offset;
   3692      pkt.data.frame.flags = get_frame_pkt_flags(cpi, cpi_data.lib_flags);
   3693      if (has_no_show_keyframe) {
   3694        // If one of the invisible frames in the packet is a keyframe, set
   3695        // the delayed random access point flag.
   3696        pkt.data.frame.flags |= AOM_FRAME_IS_DELAYED_RANDOM_ACCESS_POINT;
   3697      }
   3698      const int64_t duration64 = ticks_to_timebase_units(
   3699          cpi_data.timestamp_ratio,
   3700          cpi_data.ts_frame_end - cpi_data.ts_frame_start);
   3701      if (duration64 > UINT32_MAX) {
   3702        aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
   3703      }
   3704      pkt.data.frame.duration = (uint32_t)duration64;
   3705 
   3706      aom_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
   3707 
   3708      ctx->pending_cx_data_sz = 0;
   3709    }
   3710  }
   3711 
   3712  ppi->error.setjmp = 0;
   3713  return res;
   3714 }
   3715 
   3716 static const aom_codec_cx_pkt_t *encoder_get_cxdata(aom_codec_alg_priv_t *ctx,
   3717                                                    aom_codec_iter_t *iter) {
   3718  return aom_codec_pkt_list_get(&ctx->pkt_list.head, iter);
   3719 }
   3720 
   3721 static aom_codec_err_t ctrl_set_reference(aom_codec_alg_priv_t *ctx,
   3722                                          va_list args) {
   3723  av1_ref_frame_t *const frame = va_arg(args, av1_ref_frame_t *);
   3724 
   3725  if (frame != NULL) {
   3726    YV12_BUFFER_CONFIG sd;
   3727 
   3728    image2yuvconfig(&frame->img, &sd);
   3729    av1_set_reference_enc(ctx->ppi->cpi, frame->idx, &sd);
   3730    return AOM_CODEC_OK;
   3731  } else {
   3732    return AOM_CODEC_INVALID_PARAM;
   3733  }
   3734 }
   3735 
   3736 static aom_codec_err_t ctrl_copy_reference(aom_codec_alg_priv_t *ctx,
   3737                                           va_list args) {
   3738  if (ctx->ppi->cpi->oxcf.algo_cfg.skip_postproc_filtering)
   3739    return AOM_CODEC_INCAPABLE;
   3740  av1_ref_frame_t *const frame = va_arg(args, av1_ref_frame_t *);
   3741 
   3742  if (frame != NULL) {
   3743    YV12_BUFFER_CONFIG sd;
   3744 
   3745    image2yuvconfig(&frame->img, &sd);
   3746    av1_copy_reference_enc(ctx->ppi->cpi, frame->idx, &sd);
   3747    return AOM_CODEC_OK;
   3748  } else {
   3749    return AOM_CODEC_INVALID_PARAM;
   3750  }
   3751 }
   3752 
   3753 static aom_codec_err_t ctrl_get_reference(aom_codec_alg_priv_t *ctx,
   3754                                          va_list args) {
   3755  if (ctx->ppi->cpi->oxcf.algo_cfg.skip_postproc_filtering)
   3756    return AOM_CODEC_INCAPABLE;
   3757  av1_ref_frame_t *const frame = va_arg(args, av1_ref_frame_t *);
   3758 
   3759  if (frame != NULL) {
   3760    YV12_BUFFER_CONFIG *fb = get_ref_frame(&ctx->ppi->cpi->common, frame->idx);
   3761    if (fb == NULL) return AOM_CODEC_ERROR;
   3762 
   3763    yuvconfig2image(&frame->img, fb, NULL);
   3764    return AOM_CODEC_OK;
   3765  } else {
   3766    return AOM_CODEC_INVALID_PARAM;
   3767  }
   3768 }
   3769 
   3770 static aom_codec_err_t ctrl_get_new_frame_image(aom_codec_alg_priv_t *ctx,
   3771                                                va_list args) {
   3772  aom_image_t *const new_img = va_arg(args, aom_image_t *);
   3773 
   3774  if (new_img != NULL) {
   3775    YV12_BUFFER_CONFIG new_frame;
   3776 
   3777    if (av1_get_last_show_frame(ctx->ppi->cpi, &new_frame) == 0) {
   3778      yuvconfig2image(new_img, &new_frame, NULL);
   3779      return AOM_CODEC_OK;
   3780    } else {
   3781      return AOM_CODEC_ERROR;
   3782    }
   3783  } else {
   3784    return AOM_CODEC_INVALID_PARAM;
   3785  }
   3786 }
   3787 
   3788 static aom_codec_err_t ctrl_copy_new_frame_image(aom_codec_alg_priv_t *ctx,
   3789                                                 va_list args) {
   3790  aom_image_t *const new_img = va_arg(args, aom_image_t *);
   3791 
   3792  if (new_img != NULL) {
   3793    YV12_BUFFER_CONFIG new_frame;
   3794 
   3795    if (av1_get_last_show_frame(ctx->ppi->cpi, &new_frame) == 0) {
   3796      YV12_BUFFER_CONFIG sd;
   3797      image2yuvconfig(new_img, &sd);
   3798      return av1_copy_new_frame_enc(&ctx->ppi->cpi->common, &new_frame, &sd);
   3799    } else {
   3800      return AOM_CODEC_ERROR;
   3801    }
   3802  } else {
   3803    return AOM_CODEC_INVALID_PARAM;
   3804  }
   3805 }
   3806 
   3807 static aom_image_t *encoder_get_preview(aom_codec_alg_priv_t *ctx) {
   3808  YV12_BUFFER_CONFIG sd;
   3809 
   3810  if (av1_get_preview_raw_frame(ctx->ppi->cpi, &sd) == 0) {
   3811    yuvconfig2image(&ctx->preview_img, &sd, NULL);
   3812    return &ctx->preview_img;
   3813  } else {
   3814    return NULL;
   3815  }
   3816 }
   3817 
   3818 static aom_codec_err_t ctrl_use_reference(aom_codec_alg_priv_t *ctx,
   3819                                          va_list args) {
   3820  const int reference_flag = va_arg(args, int);
   3821 
   3822  av1_use_as_reference(&ctx->ppi->cpi->ext_flags.ref_frame_flags,
   3823                       reference_flag);
   3824  return AOM_CODEC_OK;
   3825 }
   3826 
   3827 static aom_codec_err_t ctrl_set_roi_map(aom_codec_alg_priv_t *ctx,
   3828                                        va_list args) {
   3829  aom_roi_map_t *data = va_arg(args, aom_roi_map_t *);
   3830 
   3831  if (data) {
   3832    aom_roi_map_t *roi = data;
   3833    return av1_set_roi_map(ctx->ppi->cpi, roi->roi_map, roi->rows, roi->cols,
   3834                           roi->delta_q, roi->delta_lf, roi->skip,
   3835                           roi->ref_frame);
   3836  }
   3837  return AOM_CODEC_INVALID_PARAM;
   3838 }
   3839 
   3840 static aom_codec_err_t ctrl_set_active_map(aom_codec_alg_priv_t *ctx,
   3841                                           va_list args) {
   3842  aom_active_map_t *const map = va_arg(args, aom_active_map_t *);
   3843 
   3844  if (map) {
   3845    if (!av1_set_active_map(ctx->ppi->cpi, map->active_map, (int)map->rows,
   3846                            (int)map->cols))
   3847      return AOM_CODEC_OK;
   3848    else
   3849      return AOM_CODEC_INVALID_PARAM;
   3850  } else {
   3851    return AOM_CODEC_INVALID_PARAM;
   3852  }
   3853 }
   3854 
   3855 static aom_codec_err_t ctrl_get_active_map(aom_codec_alg_priv_t *ctx,
   3856                                           va_list args) {
   3857  aom_active_map_t *const map = va_arg(args, aom_active_map_t *);
   3858 
   3859  if (map) {
   3860    if (!av1_get_active_map(ctx->ppi->cpi, map->active_map, (int)map->rows,
   3861                            (int)map->cols))
   3862      return AOM_CODEC_OK;
   3863    else
   3864      return AOM_CODEC_INVALID_PARAM;
   3865  } else {
   3866    return AOM_CODEC_INVALID_PARAM;
   3867  }
   3868 }
   3869 
   3870 static aom_codec_err_t ctrl_set_scale_mode(aom_codec_alg_priv_t *ctx,
   3871                                           va_list args) {
   3872  aom_scaling_mode_t *const mode = va_arg(args, aom_scaling_mode_t *);
   3873 
   3874  if (mode) {
   3875    AV1EncoderConfig *const oxcf =
   3876        ctx->ppi->seq_params_locked ? &ctx->ppi->cpi->oxcf : &ctx->oxcf;
   3877    const int res =
   3878        av1_set_internal_size(oxcf, &ctx->ppi->cpi->resize_pending_params,
   3879                              mode->h_scaling_mode, mode->v_scaling_mode);
   3880    if (res == 0) {
   3881      // update_encoder_cfg() is somewhat costly and this control may be called
   3882      // multiple times, so update_encoder_cfg() is only called to ensure frame
   3883      // and superblock sizes are updated before they're fixed by the first
   3884      // encode call.
   3885      if (ctx->ppi->seq_params_locked) {
   3886        av1_check_fpmt_config(ctx->ppi, &ctx->ppi->cpi->oxcf);
   3887        return AOM_CODEC_OK;
   3888      }
   3889      return update_encoder_cfg(ctx);
   3890    }
   3891    return AOM_CODEC_INVALID_PARAM;
   3892  } else {
   3893    return AOM_CODEC_INVALID_PARAM;
   3894  }
   3895 }
   3896 
   3897 static aom_codec_err_t ctrl_set_spatial_layer_id(aom_codec_alg_priv_t *ctx,
   3898                                                 va_list args) {
   3899  const int spatial_layer_id = va_arg(args, int);
   3900  if (spatial_layer_id >= MAX_NUM_SPATIAL_LAYERS)
   3901    return AOM_CODEC_INVALID_PARAM;
   3902  ctx->ppi->cpi->common.spatial_layer_id = spatial_layer_id;
   3903  return AOM_CODEC_OK;
   3904 }
   3905 
   3906 static aom_codec_err_t ctrl_set_number_spatial_layers(aom_codec_alg_priv_t *ctx,
   3907                                                      va_list args) {
   3908  const int number_spatial_layers = va_arg(args, int);
   3909  // Note svc.use_flexible_mode is set by AV1E_SET_SVC_REF_FRAME_CONFIG. When
   3910  // it is false (the default) the actual limit is 3 for both spatial and
   3911  // temporal layers. Given the order of these calls are unpredictable the
   3912  // final check is deferred until encoder_encode() (av1_set_svc_fixed_mode()).
   3913  if (number_spatial_layers <= 0 ||
   3914      number_spatial_layers > MAX_NUM_SPATIAL_LAYERS)
   3915    return AOM_CODEC_INVALID_PARAM;
   3916  ctx->ppi->number_spatial_layers = number_spatial_layers;
   3917  // update_encoder_cfg() is somewhat costly and this control may be called
   3918  // multiple times, so update_encoder_cfg() is only called to ensure frame and
   3919  // superblock sizes are updated before they're fixed by the first encode
   3920  // call.
   3921  if (!ctx->ppi->seq_params_locked) {
   3922    return update_encoder_cfg(ctx);
   3923  }
   3924  return AOM_CODEC_OK;
   3925 }
   3926 
   3927 static aom_codec_err_t ctrl_set_layer_id(aom_codec_alg_priv_t *ctx,
   3928                                         va_list args) {
   3929  aom_svc_layer_id_t *const data = va_arg(args, aom_svc_layer_id_t *);
   3930  ctx->ppi->cpi->common.spatial_layer_id = data->spatial_layer_id;
   3931  ctx->ppi->cpi->common.temporal_layer_id = data->temporal_layer_id;
   3932  ctx->ppi->cpi->svc.spatial_layer_id = data->spatial_layer_id;
   3933  ctx->ppi->cpi->svc.temporal_layer_id = data->temporal_layer_id;
   3934  return AOM_CODEC_OK;
   3935 }
   3936 
   3937 static aom_codec_err_t ctrl_set_svc_params(aom_codec_alg_priv_t *ctx,
   3938                                           va_list args) {
   3939  AV1_PRIMARY *const ppi = ctx->ppi;
   3940  AV1_COMP *const cpi = ppi->cpi;
   3941  aom_svc_params_t *const params = va_arg(args, aom_svc_params_t *);
   3942  int64_t target_bandwidth = 0;
   3943  // Note svc.use_flexible_mode is set by AV1E_SET_SVC_REF_FRAME_CONFIG. When
   3944  // it is false (the default) the actual limit is 3 for both spatial and
   3945  // temporal layers. Given the order of these calls are unpredictable the
   3946  // final check is deferred until encoder_encode() (av1_set_svc_fixed_mode()).
   3947  if (params->number_spatial_layers <= 0 ||
   3948      params->number_spatial_layers > MAX_NUM_SPATIAL_LAYERS ||
   3949      params->number_temporal_layers <= 0 ||
   3950      params->number_temporal_layers > MAX_NUM_TEMPORAL_LAYERS) {
   3951    return AOM_CODEC_INVALID_PARAM;
   3952  }
   3953  ppi->number_spatial_layers = params->number_spatial_layers;
   3954  ppi->number_temporal_layers = params->number_temporal_layers;
   3955  cpi->svc.number_spatial_layers = params->number_spatial_layers;
   3956  cpi->svc.number_temporal_layers = params->number_temporal_layers;
   3957  // Sequence parameters (operating_points_cnt_minus_1, operating_point_idc[])
   3958  // need to be updated if the number of layers have changed.
   3959  // Force a keyframe here and update the two relevant sequence parameters.
   3960  if (cpi->svc.prev_number_temporal_layers &&
   3961      cpi->svc.prev_number_spatial_layers &&
   3962      (cpi->svc.number_temporal_layers !=
   3963           cpi->svc.prev_number_temporal_layers ||
   3964       cpi->svc.number_spatial_layers != cpi->svc.prev_number_spatial_layers)) {
   3965    SequenceHeader *const seq_params = &ppi->seq_params;
   3966    seq_params->operating_points_cnt_minus_1 =
   3967        ppi->number_spatial_layers * ppi->number_temporal_layers - 1;
   3968    ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
   3969    av1_set_svc_seq_params(ppi);
   3970    // Check for valid values for the spatial/temporal_layer_id here, since
   3971    // there has been a dynamic change in the number_spatial/temporal_layers,
   3972    // and if the ctrl_set_layer_id is not used after this call, the
   3973    // previous (last_encoded) values of spatial/temporal_layer_id will be used,
   3974    // which may be invalid.
   3975    cpi->svc.spatial_layer_id =
   3976        clamp(cpi->svc.spatial_layer_id, 0, cpi->svc.number_spatial_layers - 1);
   3977    cpi->svc.temporal_layer_id = clamp(cpi->svc.temporal_layer_id, 0,
   3978                                       cpi->svc.number_temporal_layers - 1);
   3979    cpi->common.spatial_layer_id = clamp(cpi->common.spatial_layer_id, 0,
   3980                                         cpi->svc.number_spatial_layers - 1);
   3981    cpi->common.temporal_layer_id = clamp(cpi->common.temporal_layer_id, 0,
   3982                                          cpi->svc.number_temporal_layers - 1);
   3983  }
   3984 
   3985  if (ppi->number_spatial_layers > 1 || ppi->number_temporal_layers > 1) {
   3986    unsigned int sl, tl;
   3987    ctx->ppi->use_svc = 1;
   3988    const int num_layers =
   3989        ppi->number_spatial_layers * ppi->number_temporal_layers;
   3990    for (int layer = 0; layer < num_layers; ++layer) {
   3991      if (params->max_quantizers[layer] > 63 ||
   3992          params->min_quantizers[layer] < 0 ||
   3993          params->min_quantizers[layer] > params->max_quantizers[layer]) {
   3994        return AOM_CODEC_INVALID_PARAM;
   3995      }
   3996    }
   3997    if (!av1_alloc_layer_context(cpi, num_layers)) return AOM_CODEC_MEM_ERROR;
   3998 
   3999    for (sl = 0; sl < ppi->number_spatial_layers; ++sl) {
   4000      for (tl = 0; tl < ppi->number_temporal_layers; ++tl) {
   4001        const int layer = LAYER_IDS_TO_IDX(sl, tl, ppi->number_temporal_layers);
   4002        LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
   4003        lc->max_q = params->max_quantizers[layer];
   4004        lc->min_q = params->min_quantizers[layer];
   4005        lc->scaling_factor_num = AOMMAX(1, params->scaling_factor_num[sl]);
   4006        lc->scaling_factor_den = AOMMAX(1, params->scaling_factor_den[sl]);
   4007        const int layer_target_bitrate = params->layer_target_bitrate[layer];
   4008        if (layer_target_bitrate > INT_MAX / 1000) {
   4009          lc->layer_target_bitrate = INT_MAX;
   4010        } else {
   4011          lc->layer_target_bitrate = 1000 * layer_target_bitrate;
   4012        }
   4013        lc->framerate_factor = AOMMAX(1, params->framerate_factor[tl]);
   4014        if (tl == ppi->number_temporal_layers - 1)
   4015          target_bandwidth += lc->layer_target_bitrate;
   4016      }
   4017    }
   4018 
   4019    if (ppi->seq_params_locked) {
   4020      AV1EncoderConfig *const oxcf = &cpi->oxcf;
   4021      // Keep ctx->oxcf in sync in case further codec controls are made prior
   4022      // to encoding.
   4023      ctx->oxcf.rc_cfg.target_bandwidth = oxcf->rc_cfg.target_bandwidth =
   4024          target_bandwidth;
   4025      set_primary_rc_buffer_sizes(oxcf, ppi);
   4026      av1_update_layer_context_change_config(cpi, target_bandwidth);
   4027      check_reset_rc_flag(cpi);
   4028    } else {
   4029      // Note av1_init_layer_context() relies on cpi->oxcf. The order of that
   4030      // call and the ones in the other half of this block (which
   4031      // update_encoder_cfg() transitively makes) is important. So we keep
   4032      // ctx->oxcf and cpi->oxcf in sync here as update_encoder_cfg() will
   4033      // overwrite cpi->oxcf with ctx->oxcf.
   4034      ctx->oxcf.rc_cfg.target_bandwidth = cpi->oxcf.rc_cfg.target_bandwidth =
   4035          target_bandwidth;
   4036      SequenceHeader *const seq_params = &ppi->seq_params;
   4037      seq_params->operating_points_cnt_minus_1 =
   4038          ppi->number_spatial_layers * ppi->number_temporal_layers - 1;
   4039 
   4040      av1_init_layer_context(cpi);
   4041      // update_encoder_cfg() is somewhat costly and this control may be called
   4042      // multiple times, so update_encoder_cfg() is only called to ensure frame
   4043      // and superblock sizes are updated before they're fixed by the first
   4044      // encode call.
   4045      return update_encoder_cfg(ctx);
   4046    }
   4047  } else if (!ppi->seq_params_locked) {
   4048    // Ensure frame and superblock sizes are updated.
   4049    return update_encoder_cfg(ctx);
   4050  }
   4051  av1_check_fpmt_config(ctx->ppi, &ctx->ppi->cpi->oxcf);
   4052  return AOM_CODEC_OK;
   4053 }
   4054 
   4055 static aom_codec_err_t ctrl_set_svc_ref_frame_config(aom_codec_alg_priv_t *ctx,
   4056                                                     va_list args) {
   4057  AV1_COMP *const cpi = ctx->ppi->cpi;
   4058  aom_svc_ref_frame_config_t *const data =
   4059      va_arg(args, aom_svc_ref_frame_config_t *);
   4060  cpi->ppi->rtc_ref.set_ref_frame_config = 1;
   4061  for (unsigned int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
   4062    if (data->reference[i] != 0 && data->reference[i] != 1)
   4063      return AOM_CODEC_INVALID_PARAM;
   4064    if (data->ref_idx[i] > 7 || data->ref_idx[i] < 0)
   4065      return AOM_CODEC_INVALID_PARAM;
   4066    cpi->ppi->rtc_ref.reference[i] = data->reference[i];
   4067    cpi->ppi->rtc_ref.ref_idx[i] = data->ref_idx[i];
   4068  }
   4069  for (unsigned int i = 0; i < REF_FRAMES; ++i) {
   4070    if (data->refresh[i] != 0 && data->refresh[i] != 1)
   4071      return AOM_CODEC_INVALID_PARAM;
   4072    cpi->ppi->rtc_ref.refresh[i] = data->refresh[i];
   4073  }
   4074  cpi->svc.use_flexible_mode = 1;
   4075  cpi->svc.ksvc_fixed_mode = 0;
   4076  return AOM_CODEC_OK;
   4077 }
   4078 
   4079 static aom_codec_err_t ctrl_set_svc_ref_frame_comp_pred(
   4080    aom_codec_alg_priv_t *ctx, va_list args) {
   4081  AV1_COMP *const cpi = ctx->ppi->cpi;
   4082  aom_svc_ref_frame_comp_pred_t *const data =
   4083      va_arg(args, aom_svc_ref_frame_comp_pred_t *);
   4084  cpi->ppi->rtc_ref.ref_frame_comp[0] = data->use_comp_pred[0];
   4085  cpi->ppi->rtc_ref.ref_frame_comp[1] = data->use_comp_pred[1];
   4086  cpi->ppi->rtc_ref.ref_frame_comp[2] = data->use_comp_pred[2];
   4087  return AOM_CODEC_OK;
   4088 }
   4089 
   4090 static aom_codec_err_t ctrl_set_tune_content(aom_codec_alg_priv_t *ctx,
   4091                                             va_list args) {
   4092  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4093  extra_cfg.content = CAST(AV1E_SET_TUNE_CONTENT, args);
   4094  return update_extra_cfg(ctx, &extra_cfg);
   4095 }
   4096 
   4097 static aom_codec_err_t ctrl_set_cdf_update_mode(aom_codec_alg_priv_t *ctx,
   4098                                                va_list args) {
   4099  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4100  extra_cfg.cdf_update_mode = CAST(AV1E_SET_CDF_UPDATE_MODE, args);
   4101  return update_extra_cfg(ctx, &extra_cfg);
   4102 }
   4103 
   4104 static aom_codec_err_t ctrl_set_color_primaries(aom_codec_alg_priv_t *ctx,
   4105                                                va_list args) {
   4106  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4107  extra_cfg.color_primaries = CAST(AV1E_SET_COLOR_PRIMARIES, args);
   4108  return update_extra_cfg(ctx, &extra_cfg);
   4109 }
   4110 
   4111 static aom_codec_err_t ctrl_set_transfer_characteristics(
   4112    aom_codec_alg_priv_t *ctx, va_list args) {
   4113  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4114  extra_cfg.transfer_characteristics =
   4115      CAST(AV1E_SET_TRANSFER_CHARACTERISTICS, args);
   4116  return update_extra_cfg(ctx, &extra_cfg);
   4117 }
   4118 
   4119 static aom_codec_err_t ctrl_set_matrix_coefficients(aom_codec_alg_priv_t *ctx,
   4120                                                    va_list args) {
   4121  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4122  extra_cfg.matrix_coefficients = CAST(AV1E_SET_MATRIX_COEFFICIENTS, args);
   4123  return update_extra_cfg(ctx, &extra_cfg);
   4124 }
   4125 
   4126 static aom_codec_err_t ctrl_set_chroma_sample_position(
   4127    aom_codec_alg_priv_t *ctx, va_list args) {
   4128  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4129  extra_cfg.chroma_sample_position =
   4130      CAST(AV1E_SET_CHROMA_SAMPLE_POSITION, args);
   4131  return update_extra_cfg(ctx, &extra_cfg);
   4132 }
   4133 
   4134 static aom_codec_err_t ctrl_set_color_range(aom_codec_alg_priv_t *ctx,
   4135                                            va_list args) {
   4136  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4137  extra_cfg.color_range = CAST(AV1E_SET_COLOR_RANGE, args);
   4138  return update_extra_cfg(ctx, &extra_cfg);
   4139 }
   4140 
   4141 static aom_codec_err_t ctrl_set_render_size(aom_codec_alg_priv_t *ctx,
   4142                                            va_list args) {
   4143  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4144  int *const render_size = va_arg(args, int *);
   4145  extra_cfg.render_width = render_size[0];
   4146  extra_cfg.render_height = render_size[1];
   4147  return update_extra_cfg(ctx, &extra_cfg);
   4148 }
   4149 
   4150 static aom_codec_err_t ctrl_set_superblock_size(aom_codec_alg_priv_t *ctx,
   4151                                                va_list args) {
   4152  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4153  extra_cfg.superblock_size = CAST(AV1E_SET_SUPERBLOCK_SIZE, args);
   4154  return update_extra_cfg(ctx, &extra_cfg);
   4155 }
   4156 
   4157 static aom_codec_err_t ctrl_set_chroma_subsampling_x(aom_codec_alg_priv_t *ctx,
   4158                                                     va_list args) {
   4159  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4160  extra_cfg.chroma_subsampling_x = CAST(AV1E_SET_CHROMA_SUBSAMPLING_X, args);
   4161  return update_extra_cfg(ctx, &extra_cfg);
   4162 }
   4163 
   4164 static aom_codec_err_t ctrl_set_chroma_subsampling_y(aom_codec_alg_priv_t *ctx,
   4165                                                     va_list args) {
   4166  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4167  extra_cfg.chroma_subsampling_y = CAST(AV1E_SET_CHROMA_SUBSAMPLING_Y, args);
   4168  return update_extra_cfg(ctx, &extra_cfg);
   4169 }
   4170 
   4171 static aom_codec_err_t encoder_set_option(aom_codec_alg_priv_t *ctx,
   4172                                          const char *name, const char *value) {
   4173  if (ctx == NULL || name == NULL || value == NULL)
   4174    return AOM_CODEC_INVALID_PARAM;
   4175  struct av1_extracfg extra_cfg = ctx->extra_cfg;
   4176  // Used to mock the argv with just one string "--{name}={value}"
   4177  char *argv[2] = { NULL, "" };
   4178  size_t len = strlen(name) + strlen(value) + 4;
   4179  char *const err_string = ctx->ppi->error.detail;
   4180 
   4181 #if __STDC_VERSION__ >= 201112L
   4182  // We use the keyword _Static_assert because clang-cl does not allow the
   4183  // convenience macro static_assert to be used in function scope. See
   4184  // https://bugs.llvm.org/show_bug.cgi?id=48904.
   4185  _Static_assert(sizeof(ctx->ppi->error.detail) >= ARG_ERR_MSG_MAX_LEN,
   4186                 "The size of the err_msg buffer for arg_match_helper must be "
   4187                 "at least ARG_ERR_MSG_MAX_LEN");
   4188 #else
   4189  assert(sizeof(ctx->ppi->error.detail) >= ARG_ERR_MSG_MAX_LEN);
   4190 #endif
   4191 
   4192  argv[0] = aom_malloc(len * sizeof(argv[1][0]));
   4193  if (!argv[0]) return AOM_CODEC_MEM_ERROR;
   4194  snprintf(argv[0], len, "--%s=%s", name, value);
   4195  struct arg arg;
   4196  aom_codec_err_t err = AOM_CODEC_OK;
   4197 
   4198  int match = 1;
   4199  if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_keyframe_filtering,
   4200                       argv, err_string)) {
   4201    extra_cfg.enable_keyframe_filtering =
   4202        arg_parse_uint_helper(&arg, err_string);
   4203  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.min_gf_interval, argv,
   4204                              err_string)) {
   4205    extra_cfg.min_gf_interval = arg_parse_uint_helper(&arg, err_string);
   4206  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.max_gf_interval, argv,
   4207                              err_string)) {
   4208    extra_cfg.max_gf_interval = arg_parse_uint_helper(&arg, err_string);
   4209  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.gf_min_pyr_height,
   4210                              argv, err_string)) {
   4211    extra_cfg.gf_min_pyr_height = arg_parse_uint_helper(&arg, err_string);
   4212  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.gf_max_pyr_height,
   4213                              argv, err_string)) {
   4214    extra_cfg.gf_max_pyr_height = arg_parse_uint_helper(&arg, err_string);
   4215  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.cpu_used_av1, argv,
   4216                              err_string)) {
   4217    extra_cfg.cpu_used = arg_parse_uint_helper(&arg, err_string);
   4218  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.auto_altref, argv,
   4219                              err_string)) {
   4220    extra_cfg.enable_auto_alt_ref = arg_parse_uint_helper(&arg, err_string);
   4221  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.noise_sens, argv,
   4222                              err_string)) {
   4223    extra_cfg.noise_sensitivity = arg_parse_uint_helper(&arg, err_string);
   4224  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.sharpness, argv,
   4225                              err_string)) {
   4226    extra_cfg.sharpness = arg_parse_uint_helper(&arg, err_string);
   4227  } else if (arg_match_helper(&arg,
   4228                              &g_av1_codec_arg_defs.enable_adaptive_sharpness,
   4229                              argv, err_string)) {
   4230    extra_cfg.enable_adaptive_sharpness =
   4231        arg_parse_int_helper(&arg, err_string);
   4232  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.static_thresh, argv,
   4233                              err_string)) {
   4234    extra_cfg.static_thresh = arg_parse_uint_helper(&arg, err_string);
   4235  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.rowmtarg, argv,
   4236                              err_string)) {
   4237    extra_cfg.row_mt = arg_parse_uint_helper(&arg, err_string);
   4238  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.fpmtarg, argv,
   4239                              err_string)) {
   4240    extra_cfg.fp_mt = arg_parse_uint_helper(&arg, err_string);
   4241  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.tile_cols, argv,
   4242                              err_string)) {
   4243    extra_cfg.tile_columns = arg_parse_uint_helper(&arg, err_string);
   4244    if (extra_cfg.auto_tiles) {
   4245      snprintf(err_string, ARG_ERR_MSG_MAX_LEN,
   4246               "Cannot set tile-cols because auto-tiles is already set.");
   4247      err = AOM_CODEC_INVALID_PARAM;
   4248    }
   4249  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.tile_rows, argv,
   4250                              err_string)) {
   4251    extra_cfg.tile_rows = arg_parse_uint_helper(&arg, err_string);
   4252    if (extra_cfg.auto_tiles) {
   4253      snprintf(err_string, ARG_ERR_MSG_MAX_LEN,
   4254               "Cannot set tile-rows because auto-tiles is already set.");
   4255      err = AOM_CODEC_INVALID_PARAM;
   4256    }
   4257  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.auto_tiles, argv,
   4258                              err_string)) {
   4259    extra_cfg.auto_tiles = arg_parse_uint_helper(&arg, err_string);
   4260  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_tpl_model,
   4261                              argv, err_string)) {
   4262    extra_cfg.enable_tpl_model = arg_parse_uint_helper(&arg, err_string);
   4263  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.arnr_maxframes, argv,
   4264                              err_string)) {
   4265    extra_cfg.arnr_max_frames = arg_parse_uint_helper(&arg, err_string);
   4266  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.arnr_strength, argv,
   4267                              err_string)) {
   4268    extra_cfg.arnr_strength = arg_parse_uint_helper(&arg, err_string);
   4269  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.tune_metric, argv,
   4270                              err_string)) {
   4271    extra_cfg.tuning = arg_parse_enum_helper(&arg, err_string);
   4272    err = handle_tuning(ctx, &extra_cfg);
   4273  }
   4274 #if CONFIG_TUNE_VMAF
   4275  else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.vmaf_model_path, argv,
   4276                            err_string)) {
   4277    err = allocate_and_set_string(value, default_extra_cfg.vmaf_model_path,
   4278                                  &extra_cfg.vmaf_model_path, err_string);
   4279  }
   4280 #endif
   4281  else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.partition_info_path,
   4282                            argv, err_string)) {
   4283    err = allocate_and_set_string(value, default_extra_cfg.partition_info_path,
   4284                                  &extra_cfg.partition_info_path, err_string);
   4285  } else if (arg_match_helper(&arg,
   4286                              &g_av1_codec_arg_defs.enable_rate_guide_deltaq,
   4287                              argv, err_string)) {
   4288    extra_cfg.enable_rate_guide_deltaq =
   4289        arg_parse_uint_helper(&arg, err_string);
   4290  } else if (arg_match_helper(&arg,
   4291                              &g_av1_codec_arg_defs.rate_distribution_info,
   4292                              argv, err_string)) {
   4293    err =
   4294        allocate_and_set_string(value, default_extra_cfg.rate_distribution_info,
   4295                                &extra_cfg.rate_distribution_info, err_string);
   4296  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.dist_metric, argv,
   4297                              err_string)) {
   4298    extra_cfg.dist_metric = arg_parse_enum_helper(&arg, err_string);
   4299  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.cq_level, argv,
   4300                              err_string)) {
   4301    extra_cfg.cq_level = arg_parse_uint_helper(&arg, err_string);
   4302  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.max_intra_rate_pct,
   4303                              argv, err_string)) {
   4304    extra_cfg.rc_max_intra_bitrate_pct =
   4305        arg_parse_uint_helper(&arg, err_string);
   4306  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.max_inter_rate_pct,
   4307                              argv, err_string)) {
   4308    extra_cfg.rc_max_inter_bitrate_pct =
   4309        arg_parse_uint_helper(&arg, err_string);
   4310  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.gf_cbr_boost_pct,
   4311                              argv, err_string)) {
   4312    extra_cfg.gf_cbr_boost_pct = arg_parse_uint_helper(&arg, err_string);
   4313  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.lossless, argv,
   4314                              err_string)) {
   4315    extra_cfg.lossless = arg_parse_uint_helper(&arg, err_string);
   4316  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_cdef, argv,
   4317                              err_string)) {
   4318    extra_cfg.enable_cdef = arg_parse_uint_helper(&arg, err_string);
   4319  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_restoration,
   4320                              argv, err_string)) {
   4321    extra_cfg.enable_restoration = arg_parse_uint_helper(&arg, err_string);
   4322  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.force_video_mode,
   4323                              argv, err_string)) {
   4324    extra_cfg.force_video_mode = arg_parse_uint_helper(&arg, err_string);
   4325  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_obmc, argv,
   4326                              err_string)) {
   4327    extra_cfg.enable_obmc = arg_parse_uint_helper(&arg, err_string);
   4328  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.disable_trellis_quant,
   4329                              argv, err_string)) {
   4330    extra_cfg.disable_trellis_quant = arg_parse_uint_helper(&arg, err_string);
   4331  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_qm, argv,
   4332                              err_string)) {
   4333    extra_cfg.enable_qm = arg_parse_uint_helper(&arg, err_string);
   4334  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.qm_max, argv,
   4335                              err_string)) {
   4336    extra_cfg.qm_max = arg_parse_uint_helper(&arg, err_string);
   4337  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.qm_min, argv,
   4338                              err_string)) {
   4339    extra_cfg.qm_min = arg_parse_uint_helper(&arg, err_string);
   4340  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.num_tg, argv,
   4341                              err_string)) {
   4342    extra_cfg.num_tg = arg_parse_uint_helper(&arg, err_string);
   4343  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.mtu_size, argv,
   4344                              err_string)) {
   4345    extra_cfg.mtu_size = arg_parse_uint_helper(&arg, err_string);
   4346  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.timing_info, argv,
   4347                              err_string)) {
   4348    extra_cfg.timing_info_type = arg_parse_enum_helper(&arg, err_string);
   4349  } else if (arg_match_helper(&arg,
   4350                              &g_av1_codec_arg_defs.frame_parallel_decoding,
   4351                              argv, err_string)) {
   4352    extra_cfg.frame_parallel_decoding_mode =
   4353        arg_parse_uint_helper(&arg, err_string);
   4354  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_dual_filter,
   4355                              argv, err_string)) {
   4356    extra_cfg.enable_dual_filter = arg_parse_uint_helper(&arg, err_string);
   4357  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_chroma_deltaq,
   4358                              argv, err_string)) {
   4359    extra_cfg.enable_chroma_deltaq = arg_parse_uint_helper(&arg, err_string);
   4360  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.aq_mode, argv,
   4361                              err_string)) {
   4362    extra_cfg.aq_mode = arg_parse_uint_helper(&arg, err_string);
   4363  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.deltaq_mode, argv,
   4364                              err_string)) {
   4365    extra_cfg.deltaq_mode = arg_parse_uint_helper(&arg, err_string);
   4366  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.deltaq_strength, argv,
   4367                              err_string)) {
   4368    extra_cfg.deltaq_strength = arg_parse_uint_helper(&arg, err_string);
   4369  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.deltalf_mode, argv,
   4370                              err_string)) {
   4371    extra_cfg.deltalf_mode = arg_parse_uint_helper(&arg, err_string);
   4372  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.frame_periodic_boost,
   4373                              argv, err_string)) {
   4374    extra_cfg.frame_periodic_boost = arg_parse_uint_helper(&arg, err_string);
   4375  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.tune_content, argv,
   4376                              err_string)) {
   4377    extra_cfg.content = arg_parse_enum_helper(&arg, err_string);
   4378  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.input_color_primaries,
   4379                              argv, err_string)) {
   4380    extra_cfg.color_primaries = arg_parse_enum_helper(&arg, err_string);
   4381  } else if (arg_match_helper(
   4382                 &arg, &g_av1_codec_arg_defs.input_transfer_characteristics,
   4383                 argv, err_string)) {
   4384    extra_cfg.transfer_characteristics =
   4385        arg_parse_enum_helper(&arg, err_string);
   4386  } else if (arg_match_helper(&arg,
   4387                              &g_av1_codec_arg_defs.input_matrix_coefficients,
   4388                              argv, err_string)) {
   4389    extra_cfg.matrix_coefficients = arg_parse_enum_helper(&arg, err_string);
   4390  } else if (arg_match_helper(
   4391                 &arg, &g_av1_codec_arg_defs.input_chroma_sample_position, argv,
   4392                 err_string)) {
   4393    extra_cfg.chroma_sample_position = arg_parse_enum_helper(&arg, err_string);
   4394  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.superblock_size, argv,
   4395                              err_string)) {
   4396    extra_cfg.superblock_size = arg_parse_enum_helper(&arg, err_string);
   4397  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.error_resilient_mode,
   4398                              argv, err_string)) {
   4399    extra_cfg.error_resilient_mode = arg_parse_int_helper(&arg, err_string);
   4400  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.sframe_mode, argv,
   4401                              err_string)) {
   4402    extra_cfg.s_frame_mode = arg_parse_int_helper(&arg, err_string);
   4403  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.film_grain_test, argv,
   4404                              err_string)) {
   4405    extra_cfg.film_grain_test_vector = arg_parse_int_helper(&arg, err_string);
   4406  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.film_grain_table,
   4407                              argv, err_string)) {
   4408    if (value == NULL) {
   4409      // this parameter allows NULL as its value
   4410      extra_cfg.film_grain_table_filename = value;
   4411    } else {
   4412      err = allocate_and_set_string(
   4413          value, default_extra_cfg.film_grain_table_filename,
   4414          &extra_cfg.film_grain_table_filename, err_string);
   4415    }
   4416  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.cdf_update_mode, argv,
   4417                              err_string)) {
   4418    extra_cfg.cdf_update_mode = arg_parse_int_helper(&arg, err_string);
   4419  } else if (arg_match_helper(&arg,
   4420                              &g_av1_codec_arg_defs.enable_rect_partitions,
   4421                              argv, err_string)) {
   4422    extra_cfg.enable_rect_partitions = arg_parse_int_helper(&arg, err_string);
   4423  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_ab_partitions,
   4424                              argv, err_string)) {
   4425    extra_cfg.enable_ab_partitions = arg_parse_int_helper(&arg, err_string);
   4426  } else if (arg_match_helper(&arg,
   4427                              &g_av1_codec_arg_defs.enable_1to4_partitions,
   4428                              argv, err_string)) {
   4429    extra_cfg.enable_1to4_partitions = arg_parse_int_helper(&arg, err_string);
   4430  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.min_partition_size,
   4431                              argv, err_string)) {
   4432    extra_cfg.min_partition_size = arg_parse_int_helper(&arg, err_string);
   4433  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.max_partition_size,
   4434                              argv, err_string)) {
   4435    extra_cfg.max_partition_size = arg_parse_int_helper(&arg, err_string);
   4436  } else if (arg_match_helper(&arg,
   4437                              &g_av1_codec_arg_defs.enable_intra_edge_filter,
   4438                              argv, err_string)) {
   4439    extra_cfg.enable_intra_edge_filter =
   4440        arg_parse_uint_helper(&arg, err_string);
   4441  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_order_hint,
   4442                              argv, err_string)) {
   4443    extra_cfg.enable_order_hint = arg_parse_int_helper(&arg, err_string);
   4444  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_tx64, argv,
   4445                              err_string)) {
   4446    extra_cfg.enable_tx64 = arg_parse_int_helper(&arg, err_string);
   4447  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_flip_idtx,
   4448                              argv, err_string)) {
   4449    extra_cfg.enable_flip_idtx = arg_parse_int_helper(&arg, err_string);
   4450  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_rect_tx, argv,
   4451                              err_string)) {
   4452    extra_cfg.enable_rect_tx = arg_parse_int_helper(&arg, err_string);
   4453  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_dist_wtd_comp,
   4454                              argv, err_string)) {
   4455    extra_cfg.enable_dist_wtd_comp = arg_parse_int_helper(&arg, err_string);
   4456  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.max_reference_frames,
   4457                              argv, err_string)) {
   4458    extra_cfg.max_reference_frames = arg_parse_int_helper(&arg, err_string);
   4459  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.reduced_reference_set,
   4460                              argv, err_string)) {
   4461    extra_cfg.enable_reduced_reference_set =
   4462        arg_parse_int_helper(&arg, err_string);
   4463  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_ref_frame_mvs,
   4464                              argv, err_string)) {
   4465    extra_cfg.enable_ref_frame_mvs = arg_parse_int_helper(&arg, err_string);
   4466  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_masked_comp,
   4467                              argv, err_string)) {
   4468    extra_cfg.enable_masked_comp = arg_parse_int_helper(&arg, err_string);
   4469  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_onesided_comp,
   4470                              argv, err_string)) {
   4471    extra_cfg.enable_onesided_comp = arg_parse_int_helper(&arg, err_string);
   4472  } else if (arg_match_helper(&arg,
   4473                              &g_av1_codec_arg_defs.enable_interintra_comp,
   4474                              argv, err_string)) {
   4475    extra_cfg.enable_interintra_comp = arg_parse_int_helper(&arg, err_string);
   4476  } else if (arg_match_helper(&arg,
   4477                              &g_av1_codec_arg_defs.enable_smooth_interintra,
   4478                              argv, err_string)) {
   4479    extra_cfg.enable_smooth_interintra = arg_parse_int_helper(&arg, err_string);
   4480  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_diff_wtd_comp,
   4481                              argv, err_string)) {
   4482    extra_cfg.enable_diff_wtd_comp = arg_parse_int_helper(&arg, err_string);
   4483  } else if (arg_match_helper(&arg,
   4484                              &g_av1_codec_arg_defs.enable_interinter_wedge,
   4485                              argv, err_string)) {
   4486    extra_cfg.enable_interinter_wedge = arg_parse_int_helper(&arg, err_string);
   4487  } else if (arg_match_helper(&arg,
   4488                              &g_av1_codec_arg_defs.enable_interintra_wedge,
   4489                              argv, err_string)) {
   4490    extra_cfg.enable_interintra_wedge = arg_parse_int_helper(&arg, err_string);
   4491  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_global_motion,
   4492                              argv, err_string)) {
   4493    extra_cfg.enable_global_motion = arg_parse_int_helper(&arg, err_string);
   4494  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_warped_motion,
   4495                              argv, err_string)) {
   4496    extra_cfg.enable_warped_motion = arg_parse_int_helper(&arg, err_string);
   4497  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_filter_intra,
   4498                              argv, err_string)) {
   4499    extra_cfg.enable_filter_intra = arg_parse_int_helper(&arg, err_string);
   4500  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_smooth_intra,
   4501                              argv, err_string)) {
   4502    extra_cfg.enable_smooth_intra = arg_parse_int_helper(&arg, err_string);
   4503  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_paeth_intra,
   4504                              argv, err_string)) {
   4505    extra_cfg.enable_paeth_intra = arg_parse_int_helper(&arg, err_string);
   4506  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_cfl_intra,
   4507                              argv, err_string)) {
   4508    extra_cfg.enable_cfl_intra = arg_parse_int_helper(&arg, err_string);
   4509  } else if (arg_match_helper(&arg,
   4510                              &g_av1_codec_arg_defs.enable_directional_intra,
   4511                              argv, err_string)) {
   4512    extra_cfg.enable_directional_intra = arg_parse_int_helper(&arg, err_string);
   4513  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_diagonal_intra,
   4514                              argv, err_string)) {
   4515    extra_cfg.enable_diagonal_intra = arg_parse_int_helper(&arg, err_string);
   4516  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_overlay, argv,
   4517                              err_string)) {
   4518    extra_cfg.enable_overlay = arg_parse_int_helper(&arg, err_string);
   4519  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_palette, argv,
   4520                              err_string)) {
   4521    extra_cfg.enable_palette = arg_parse_int_helper(&arg, err_string);
   4522  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_intrabc, argv,
   4523                              err_string)) {
   4524    extra_cfg.enable_intrabc = arg_parse_int_helper(&arg, err_string);
   4525  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_angle_delta,
   4526                              argv, err_string)) {
   4527    extra_cfg.enable_angle_delta = arg_parse_int_helper(&arg, err_string);
   4528  } else if (arg_match_helper(
   4529                 &arg, &g_av1_codec_arg_defs.enable_low_complexity_decode, argv,
   4530                 err_string)) {
   4531    extra_cfg.enable_low_complexity_decode =
   4532        arg_parse_int_helper(&arg, err_string);
   4533  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.reduced_tx_type_set,
   4534                              argv, err_string)) {
   4535    extra_cfg.reduced_tx_type_set = arg_parse_int_helper(&arg, err_string);
   4536  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.use_intra_dct_only,
   4537                              argv, err_string)) {
   4538    extra_cfg.use_intra_dct_only = arg_parse_int_helper(&arg, err_string);
   4539  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.use_inter_dct_only,
   4540                              argv, err_string)) {
   4541    extra_cfg.use_inter_dct_only = arg_parse_int_helper(&arg, err_string);
   4542  } else if (arg_match_helper(&arg,
   4543                              &g_av1_codec_arg_defs.use_intra_default_tx_only,
   4544                              argv, err_string)) {
   4545    extra_cfg.use_intra_default_tx_only =
   4546        arg_parse_int_helper(&arg, err_string);
   4547  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.quant_b_adapt, argv,
   4548                              err_string)) {
   4549    extra_cfg.quant_b_adapt = arg_parse_int_helper(&arg, err_string);
   4550  } else if (arg_match_helper(&arg,
   4551                              &g_av1_codec_arg_defs.vbr_corpus_complexity_lap,
   4552                              argv, err_string)) {
   4553    extra_cfg.vbr_corpus_complexity_lap =
   4554        arg_parse_uint_helper(&arg, err_string);
   4555  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.set_tier_mask, argv,
   4556                              err_string)) {
   4557    extra_cfg.tier_mask = arg_parse_uint_helper(&arg, err_string);
   4558  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.set_min_cr, argv,
   4559                              err_string)) {
   4560    extra_cfg.min_cr = arg_parse_uint_helper(&arg, err_string);
   4561  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.coeff_cost_upd_freq,
   4562                              argv, err_string)) {
   4563    extra_cfg.coeff_cost_upd_freq = arg_parse_uint_helper(&arg, err_string);
   4564  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.mode_cost_upd_freq,
   4565                              argv, err_string)) {
   4566    extra_cfg.mode_cost_upd_freq = arg_parse_uint_helper(&arg, err_string);
   4567  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.mv_cost_upd_freq,
   4568                              argv, err_string)) {
   4569    extra_cfg.mv_cost_upd_freq = arg_parse_uint_helper(&arg, err_string);
   4570  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.dv_cost_upd_freq,
   4571                              argv, err_string)) {
   4572    extra_cfg.dv_cost_upd_freq = arg_parse_uint_helper(&arg, err_string);
   4573  }
   4574 #if CONFIG_DENOISE
   4575  else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.denoise_noise_level,
   4576                            argv, err_string)) {
   4577    extra_cfg.noise_level =
   4578        (float)arg_parse_int_helper(&arg, err_string) / 10.0f;
   4579  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.denoise_block_size,
   4580                              argv, err_string)) {
   4581    extra_cfg.noise_block_size = arg_parse_uint_helper(&arg, err_string);
   4582  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.enable_dnl_denoising,
   4583                              argv, err_string)) {
   4584    extra_cfg.enable_dnl_denoising = arg_parse_uint_helper(&arg, err_string);
   4585  }
   4586 #endif
   4587  else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.target_seq_level_idx,
   4588                            argv, err_string)) {
   4589    const int val = arg_parse_int_helper(&arg, err_string);
   4590    const int level = val % 100;
   4591    const int operating_point_idx = val / 100;
   4592    if (operating_point_idx < 0 ||
   4593        operating_point_idx >= MAX_NUM_OPERATING_POINTS) {
   4594      snprintf(err_string, ARG_ERR_MSG_MAX_LEN,
   4595               "Invalid operating point index: %d", operating_point_idx);
   4596      err = AOM_CODEC_INVALID_PARAM;
   4597    } else {
   4598      extra_cfg.target_seq_level_idx[operating_point_idx] = (AV1_LEVEL)level;
   4599    }
   4600  } else if (arg_match_helper(&arg,
   4601                              &g_av1_codec_arg_defs.input_chroma_subsampling_x,
   4602                              argv, err_string)) {
   4603    extra_cfg.chroma_subsampling_x = arg_parse_uint_helper(&arg, err_string);
   4604  } else if (arg_match_helper(&arg,
   4605                              &g_av1_codec_arg_defs.input_chroma_subsampling_y,
   4606                              argv, err_string)) {
   4607    extra_cfg.chroma_subsampling_y = arg_parse_uint_helper(&arg, err_string);
   4608  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.passes, argv,
   4609                              err_string)) {
   4610    extra_cfg.passes = arg_parse_int_helper(&arg, err_string);
   4611  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.fwd_kf_dist, argv,
   4612                              err_string)) {
   4613    extra_cfg.fwd_kf_dist = arg_parse_int_helper(&arg, err_string);
   4614  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.two_pass_output, argv,
   4615                              err_string)) {
   4616    err = allocate_and_set_string(value, default_extra_cfg.two_pass_output,
   4617                                  &extra_cfg.two_pass_output, err_string);
   4618  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.second_pass_log, argv,
   4619                              err_string)) {
   4620    err = allocate_and_set_string(value, default_extra_cfg.second_pass_log,
   4621                                  &extra_cfg.second_pass_log, err_string);
   4622  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.loopfilter_control,
   4623                              argv, err_string)) {
   4624    extra_cfg.loopfilter_control = arg_parse_int_helper(&arg, err_string);
   4625  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.auto_intra_tools_off,
   4626                              argv, err_string)) {
   4627    extra_cfg.auto_intra_tools_off = arg_parse_uint_helper(&arg, err_string);
   4628  } else if (arg_match_helper(&arg,
   4629                              &g_av1_codec_arg_defs.strict_level_conformance,
   4630                              argv, err_string)) {
   4631    extra_cfg.strict_level_conformance = arg_parse_int_helper(&arg, err_string);
   4632  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.sb_qp_sweep, argv,
   4633                              err_string)) {
   4634    extra_cfg.sb_qp_sweep = arg_parse_int_helper(&arg, err_string);
   4635  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.kf_max_pyr_height,
   4636                              argv, err_string)) {
   4637    extra_cfg.kf_max_pyr_height = arg_parse_int_helper(&arg, err_string);
   4638  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.tile_width, argv,
   4639                              err_string)) {
   4640    ctx->cfg.tile_width_count = arg_parse_list_helper(
   4641        &arg, ctx->cfg.tile_widths, MAX_TILE_WIDTHS, err_string);
   4642  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.tile_height, argv,
   4643                              err_string)) {
   4644    ctx->cfg.tile_height_count = arg_parse_list_helper(
   4645        &arg, ctx->cfg.tile_heights, MAX_TILE_HEIGHTS, err_string);
   4646  } else if (arg_match_helper(&arg, &g_av1_codec_arg_defs.screen_detection_mode,
   4647                              argv, err_string)) {
   4648    extra_cfg.screen_detection_mode = arg_parse_int_helper(&arg, err_string);
   4649  } else {
   4650    match = 0;
   4651    snprintf(err_string, ARG_ERR_MSG_MAX_LEN, "Cannot find aom option %s",
   4652             name);
   4653  }
   4654  aom_free(argv[0]);
   4655 
   4656  if (err != AOM_CODEC_OK) {
   4657    ctx->base.err_detail = err_string;
   4658    return err;
   4659  }
   4660 
   4661  if (strlen(err_string) != 0) {
   4662    ctx->base.err_detail = err_string;
   4663    return AOM_CODEC_INVALID_PARAM;
   4664  }
   4665 
   4666  ctx->base.err_detail = NULL;
   4667 
   4668  if (!match) {
   4669    return AOM_CODEC_INVALID_PARAM;
   4670  }
   4671  return update_extra_cfg(ctx, &extra_cfg);
   4672 }
   4673 
   4674 static aom_codec_err_t ctrl_get_seq_level_idx(aom_codec_alg_priv_t *ctx,
   4675                                              va_list args) {
   4676  int *const arg = va_arg(args, int *);
   4677  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   4678  return av1_get_seq_level_idx(&ctx->ppi->seq_params, &ctx->ppi->level_params,
   4679                               arg);
   4680 }
   4681 
   4682 static aom_codec_err_t ctrl_get_target_seq_level_idx(aom_codec_alg_priv_t *ctx,
   4683                                                     va_list args) {
   4684  int *const arg = va_arg(args, int *);
   4685  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   4686  return av1_get_target_seq_level_idx(&ctx->ppi->seq_params,
   4687                                      &ctx->ppi->level_params, arg);
   4688 }
   4689 
   4690 static aom_codec_err_t ctrl_get_num_operating_points(aom_codec_alg_priv_t *ctx,
   4691                                                     va_list args) {
   4692  int *const arg = va_arg(args, int *);
   4693  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   4694  *arg = ctx->ppi->seq_params.operating_points_cnt_minus_1 + 1;
   4695  return AOM_CODEC_OK;
   4696 }
   4697 
   4698 static aom_codec_err_t ctrl_get_luma_cdef_strength(aom_codec_alg_priv_t *ctx,
   4699                                                   va_list args) {
   4700  int *arg = va_arg(args, int *);
   4701  AV1_COMMON const *cm = &ctx->ppi->cpi->common;
   4702  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   4703  memcpy(arg, cm->cdef_info.cdef_strengths, CDEF_MAX_STRENGTHS * sizeof(*arg));
   4704 
   4705  return AOM_CODEC_OK;
   4706 }
   4707 
   4708 static aom_codec_err_t ctrl_get_high_motion_content_screen_rtc(
   4709    aom_codec_alg_priv_t *ctx, va_list args) {
   4710  int *arg = va_arg(args, int *);
   4711  AV1_COMP *const cpi = ctx->ppi->cpi;
   4712  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
   4713  *arg = cpi->rc.high_motion_content_screen_rtc;
   4714  return AOM_CODEC_OK;
   4715 }
   4716 
   4717 static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
   4718  { AV1_COPY_REFERENCE, ctrl_copy_reference },
   4719  { AOME_USE_REFERENCE, ctrl_use_reference },
   4720 
   4721  // Setters
   4722  { AV1_SET_REFERENCE, ctrl_set_reference },
   4723  { AOME_SET_ROI_MAP, ctrl_set_roi_map },
   4724  { AOME_SET_ACTIVEMAP, ctrl_set_active_map },
   4725  { AOME_SET_SCALEMODE, ctrl_set_scale_mode },
   4726  { AOME_SET_SPATIAL_LAYER_ID, ctrl_set_spatial_layer_id },
   4727  { AOME_SET_CPUUSED, ctrl_set_cpuused },
   4728  { AOME_SET_ENABLEAUTOALTREF, ctrl_set_enable_auto_alt_ref },
   4729  { AOME_SET_ENABLEAUTOBWDREF, ctrl_set_enable_auto_bwd_ref },
   4730  { AOME_SET_SHARPNESS, ctrl_set_sharpness },
   4731  { AOME_SET_STATIC_THRESHOLD, ctrl_set_static_thresh },
   4732  { AV1E_SET_ROW_MT, ctrl_set_row_mt },
   4733  { AV1E_SET_FP_MT, ctrl_set_fp_mt },
   4734  { AV1E_SET_TILE_COLUMNS, ctrl_set_tile_columns },
   4735  { AV1E_SET_TILE_ROWS, ctrl_set_tile_rows },
   4736  { AV1E_SET_ENABLE_TPL_MODEL, ctrl_set_enable_tpl_model },
   4737  { AV1E_SET_ENABLE_KEYFRAME_FILTERING, ctrl_set_enable_keyframe_filtering },
   4738  { AOME_SET_ARNR_MAXFRAMES, ctrl_set_arnr_max_frames },
   4739  { AOME_SET_ARNR_STRENGTH, ctrl_set_arnr_strength },
   4740  { AOME_SET_TUNING, ctrl_set_tuning },
   4741  { AOME_SET_CQ_LEVEL, ctrl_set_cq_level },
   4742  { AOME_SET_MAX_INTRA_BITRATE_PCT, ctrl_set_rc_max_intra_bitrate_pct },
   4743  { AOME_SET_NUMBER_SPATIAL_LAYERS, ctrl_set_number_spatial_layers },
   4744  { AV1E_SET_MAX_INTER_BITRATE_PCT, ctrl_set_rc_max_inter_bitrate_pct },
   4745  { AV1E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct },
   4746  { AV1E_SET_LOSSLESS, ctrl_set_lossless },
   4747  { AV1E_SET_ENABLE_CDEF, ctrl_set_enable_cdef },
   4748  { AV1E_SET_ENABLE_RESTORATION, ctrl_set_enable_restoration },
   4749  { AV1E_SET_FORCE_VIDEO_MODE, ctrl_set_force_video_mode },
   4750  { AV1E_SET_ENABLE_OBMC, ctrl_set_enable_obmc },
   4751  { AV1E_SET_DISABLE_TRELLIS_QUANT, ctrl_set_disable_trellis_quant },
   4752  { AV1E_SET_ENABLE_QM, ctrl_set_enable_qm },
   4753  { AV1E_SET_QM_Y, ctrl_set_qm_y },
   4754  { AV1E_SET_QM_U, ctrl_set_qm_u },
   4755  { AV1E_SET_QM_V, ctrl_set_qm_v },
   4756  { AV1E_SET_QM_MIN, ctrl_set_qm_min },
   4757  { AV1E_SET_QM_MAX, ctrl_set_qm_max },
   4758  { AV1E_SET_NUM_TG, ctrl_set_num_tg },
   4759  { AV1E_SET_MTU, ctrl_set_mtu },
   4760  { AV1E_SET_TIMING_INFO_TYPE, ctrl_set_timing_info_type },
   4761  { AV1E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode },
   4762  { AV1E_SET_ERROR_RESILIENT_MODE, ctrl_set_error_resilient_mode },
   4763  { AV1E_SET_S_FRAME_MODE, ctrl_set_s_frame_mode },
   4764  { AV1E_SET_ENABLE_RECT_PARTITIONS, ctrl_set_enable_rect_partitions },
   4765  { AV1E_SET_ENABLE_AB_PARTITIONS, ctrl_set_enable_ab_partitions },
   4766  { AV1E_SET_ENABLE_1TO4_PARTITIONS, ctrl_set_enable_1to4_partitions },
   4767  { AV1E_SET_MIN_PARTITION_SIZE, ctrl_set_min_partition_size },
   4768  { AV1E_SET_MAX_PARTITION_SIZE, ctrl_set_max_partition_size },
   4769  { AV1E_SET_ENABLE_DUAL_FILTER, ctrl_set_enable_dual_filter },
   4770  { AV1E_SET_ENABLE_CHROMA_DELTAQ, ctrl_set_enable_chroma_deltaq },
   4771  { AV1E_SET_ENABLE_INTRA_EDGE_FILTER, ctrl_set_enable_intra_edge_filter },
   4772  { AV1E_SET_ENABLE_ORDER_HINT, ctrl_set_enable_order_hint },
   4773  { AV1E_SET_ENABLE_TX64, ctrl_set_enable_tx64 },
   4774  { AV1E_SET_ENABLE_FLIP_IDTX, ctrl_set_enable_flip_idtx },
   4775  { AV1E_SET_ENABLE_RECT_TX, ctrl_set_enable_rect_tx },
   4776  { AV1E_SET_ENABLE_DIST_WTD_COMP, ctrl_set_enable_dist_wtd_comp },
   4777  { AV1E_SET_MAX_REFERENCE_FRAMES, ctrl_set_max_reference_frames },
   4778  { AV1E_SET_REDUCED_REFERENCE_SET, ctrl_set_enable_reduced_reference_set },
   4779  { AV1E_SET_ENABLE_REF_FRAME_MVS, ctrl_set_enable_ref_frame_mvs },
   4780  { AV1E_SET_ALLOW_REF_FRAME_MVS, ctrl_set_allow_ref_frame_mvs },
   4781  { AV1E_SET_ENABLE_MASKED_COMP, ctrl_set_enable_masked_comp },
   4782  { AV1E_SET_ENABLE_ONESIDED_COMP, ctrl_set_enable_onesided_comp },
   4783  { AV1E_SET_ENABLE_INTERINTRA_COMP, ctrl_set_enable_interintra_comp },
   4784  { AV1E_SET_ENABLE_SMOOTH_INTERINTRA, ctrl_set_enable_smooth_interintra },
   4785  { AV1E_SET_ENABLE_DIFF_WTD_COMP, ctrl_set_enable_diff_wtd_comp },
   4786  { AV1E_SET_ENABLE_INTERINTER_WEDGE, ctrl_set_enable_interinter_wedge },
   4787  { AV1E_SET_ENABLE_INTERINTRA_WEDGE, ctrl_set_enable_interintra_wedge },
   4788  { AV1E_SET_ENABLE_GLOBAL_MOTION, ctrl_set_enable_global_motion },
   4789  { AV1E_SET_ENABLE_WARPED_MOTION, ctrl_set_enable_warped_motion },
   4790  { AV1E_SET_ALLOW_WARPED_MOTION, ctrl_set_allow_warped_motion },
   4791  { AV1E_SET_ENABLE_FILTER_INTRA, ctrl_set_enable_filter_intra },
   4792  { AV1E_SET_ENABLE_SMOOTH_INTRA, ctrl_set_enable_smooth_intra },
   4793  { AV1E_SET_ENABLE_PAETH_INTRA, ctrl_set_enable_paeth_intra },
   4794  { AV1E_SET_ENABLE_CFL_INTRA, ctrl_set_enable_cfl_intra },
   4795  { AV1E_SET_ENABLE_DIRECTIONAL_INTRA, ctrl_set_enable_directional_intra },
   4796  { AV1E_SET_ENABLE_DIAGONAL_INTRA, ctrl_set_enable_diagonal_intra },
   4797  { AV1E_SET_ENABLE_SUPERRES, ctrl_set_enable_superres },
   4798  { AV1E_SET_ENABLE_OVERLAY, ctrl_set_enable_overlay },
   4799  { AV1E_SET_ENABLE_PALETTE, ctrl_set_enable_palette },
   4800  { AV1E_SET_ENABLE_INTRABC, ctrl_set_enable_intrabc },
   4801  { AV1E_SET_ENABLE_ANGLE_DELTA, ctrl_set_enable_angle_delta },
   4802  { AV1E_SET_AQ_MODE, ctrl_set_aq_mode },
   4803  { AV1E_SET_REDUCED_TX_TYPE_SET, ctrl_set_reduced_tx_type_set },
   4804  { AV1E_SET_INTRA_DCT_ONLY, ctrl_set_intra_dct_only },
   4805  { AV1E_SET_INTER_DCT_ONLY, ctrl_set_inter_dct_only },
   4806  { AV1E_SET_INTRA_DEFAULT_TX_ONLY, ctrl_set_intra_default_tx_only },
   4807  { AV1E_SET_QUANT_B_ADAPT, ctrl_set_quant_b_adapt },
   4808  { AV1E_SET_COEFF_COST_UPD_FREQ, ctrl_set_coeff_cost_upd_freq },
   4809  { AV1E_SET_MODE_COST_UPD_FREQ, ctrl_set_mode_cost_upd_freq },
   4810  { AV1E_SET_MV_COST_UPD_FREQ, ctrl_set_mv_cost_upd_freq },
   4811  { AV1E_SET_DELTAQ_MODE, ctrl_set_deltaq_mode },
   4812  { AV1E_SET_DELTAQ_STRENGTH, ctrl_set_deltaq_strength },
   4813  { AV1E_SET_DELTALF_MODE, ctrl_set_deltalf_mode },
   4814  { AV1E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost },
   4815  { AV1E_SET_TUNE_CONTENT, ctrl_set_tune_content },
   4816  { AV1E_SET_CDF_UPDATE_MODE, ctrl_set_cdf_update_mode },
   4817  { AV1E_SET_COLOR_PRIMARIES, ctrl_set_color_primaries },
   4818  { AV1E_SET_TRANSFER_CHARACTERISTICS, ctrl_set_transfer_characteristics },
   4819  { AV1E_SET_MATRIX_COEFFICIENTS, ctrl_set_matrix_coefficients },
   4820  { AV1E_SET_CHROMA_SAMPLE_POSITION, ctrl_set_chroma_sample_position },
   4821  { AV1E_SET_COLOR_RANGE, ctrl_set_color_range },
   4822  { AV1E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity },
   4823  { AV1E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval },
   4824  { AV1E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval },
   4825  { AV1E_SET_GF_MIN_PYRAMID_HEIGHT, ctrl_set_gf_min_pyr_height },
   4826  { AV1E_SET_GF_MAX_PYRAMID_HEIGHT, ctrl_set_gf_max_pyr_height },
   4827  { AV1E_SET_RENDER_SIZE, ctrl_set_render_size },
   4828  { AV1E_SET_SUPERBLOCK_SIZE, ctrl_set_superblock_size },
   4829  { AV1E_SET_SINGLE_TILE_DECODING, ctrl_set_single_tile_decoding },
   4830  { AV1E_SET_VMAF_MODEL_PATH, ctrl_set_vmaf_model_path },
   4831  { AV1E_SET_PARTITION_INFO_PATH, ctrl_set_partition_info_path },
   4832  { AV1E_ENABLE_RATE_GUIDE_DELTAQ, ctrl_enable_rate_guide_deltaq },
   4833  { AV1E_SET_RATE_DISTRIBUTION_INFO, ctrl_set_rate_distribution_info },
   4834  { AV1E_SET_FILM_GRAIN_TEST_VECTOR, ctrl_set_film_grain_test_vector },
   4835  { AV1E_SET_FILM_GRAIN_TABLE, ctrl_set_film_grain_table },
   4836  { AV1E_SET_DENOISE_NOISE_LEVEL, ctrl_set_denoise_noise_level },
   4837  { AV1E_SET_DENOISE_BLOCK_SIZE, ctrl_set_denoise_block_size },
   4838  { AV1E_SET_ENABLE_DNL_DENOISING, ctrl_set_enable_dnl_denoising },
   4839  { AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
   4840  { AV1E_SET_FP_MT_UNIT_TEST, ctrl_enable_fpmt_unit_test },
   4841  { AV1E_ENABLE_EXT_TILE_DEBUG, ctrl_enable_ext_tile_debug },
   4842  { AV1E_SET_TARGET_SEQ_LEVEL_IDX, ctrl_set_target_seq_level_idx },
   4843  { AV1E_SET_TIER_MASK, ctrl_set_tier_mask },
   4844  { AV1E_SET_MIN_CR, ctrl_set_min_cr },
   4845  { AV1E_SET_SVC_LAYER_ID, ctrl_set_layer_id },
   4846  { AV1E_SET_SVC_PARAMS, ctrl_set_svc_params },
   4847  { AV1E_SET_SVC_REF_FRAME_CONFIG, ctrl_set_svc_ref_frame_config },
   4848  { AV1E_SET_SVC_REF_FRAME_COMP_PRED, ctrl_set_svc_ref_frame_comp_pred },
   4849  { AV1E_SET_VBR_CORPUS_COMPLEXITY_LAP, ctrl_set_vbr_corpus_complexity_lap },
   4850  { AV1E_ENABLE_SB_MULTIPASS_UNIT_TEST, ctrl_enable_sb_multipass_unit_test },
   4851  { AV1E_ENABLE_SB_QP_SWEEP, ctrl_enable_sb_qp_sweep },
   4852  { AV1E_SET_DV_COST_UPD_FREQ, ctrl_set_dv_cost_upd_freq },
   4853  { AV1E_SET_EXTERNAL_PARTITION, ctrl_set_external_partition },
   4854  { AV1E_SET_ENABLE_TX_SIZE_SEARCH, ctrl_set_enable_tx_size_search },
   4855  { AV1E_SET_LOOPFILTER_CONTROL, ctrl_set_loopfilter_control },
   4856  { AV1E_SET_SKIP_POSTPROC_FILTERING, ctrl_set_skip_postproc_filtering },
   4857  { AV1E_SET_AUTO_INTRA_TOOLS_OFF, ctrl_set_auto_intra_tools_off },
   4858  { AV1E_SET_RTC_EXTERNAL_RC, ctrl_set_rtc_external_rc },
   4859  { AV1E_SET_QUANTIZER_ONE_PASS, ctrl_set_quantizer_one_pass },
   4860  { AV1E_SET_BITRATE_ONE_PASS_CBR, ctrl_set_bitrate_one_pass_cbr },
   4861  { AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR, ctrl_set_max_consec_frame_drop_cbr },
   4862  { AV1E_SET_SVC_FRAME_DROP_MODE, ctrl_set_svc_frame_drop_mode },
   4863  { AV1E_SET_AUTO_TILES, ctrl_set_auto_tiles },
   4864  { AV1E_SET_POSTENCODE_DROP_RTC, ctrl_set_postencode_drop_rtc },
   4865  { AV1E_SET_MAX_CONSEC_FRAME_DROP_MS_CBR,
   4866    ctrl_set_max_consec_frame_drop_ms_cbr },
   4867  { AV1E_SET_ENABLE_LOW_COMPLEXITY_DECODE,
   4868    ctrl_set_enable_low_complexity_decode },
   4869  { AV1E_SET_SCREEN_CONTENT_DETECTION_MODE,
   4870    ctrl_set_screen_content_detection_mode },
   4871  { AV1E_SET_ENABLE_ADAPTIVE_SHARPNESS, ctrl_set_enable_adaptive_sharpness },
   4872 
   4873  // Getters
   4874  { AOME_GET_LAST_QUANTIZER, ctrl_get_quantizer },
   4875  { AOME_GET_LAST_QUANTIZER_64, ctrl_get_quantizer64 },
   4876  { AOME_GET_LOOPFILTER_LEVEL, ctrl_get_loopfilter_level },
   4877  { AV1_GET_REFERENCE, ctrl_get_reference },
   4878  { AV1E_GET_ACTIVEMAP, ctrl_get_active_map },
   4879  { AV1_GET_NEW_FRAME_IMAGE, ctrl_get_new_frame_image },
   4880  { AV1_COPY_NEW_FRAME_IMAGE, ctrl_copy_new_frame_image },
   4881  { AV1E_SET_CHROMA_SUBSAMPLING_X, ctrl_set_chroma_subsampling_x },
   4882  { AV1E_SET_CHROMA_SUBSAMPLING_Y, ctrl_set_chroma_subsampling_y },
   4883  { AV1E_GET_SEQ_LEVEL_IDX, ctrl_get_seq_level_idx },
   4884  { AV1E_GET_BASELINE_GF_INTERVAL, ctrl_get_baseline_gf_interval },
   4885  { AV1E_GET_TARGET_SEQ_LEVEL_IDX, ctrl_get_target_seq_level_idx },
   4886  { AV1E_GET_NUM_OPERATING_POINTS, ctrl_get_num_operating_points },
   4887  { AV1E_GET_LUMA_CDEF_STRENGTH, ctrl_get_luma_cdef_strength },
   4888  { AV1E_GET_HIGH_MOTION_CONTENT_SCREEN_RTC,
   4889    ctrl_get_high_motion_content_screen_rtc },
   4890 
   4891  CTRL_MAP_END,
   4892 };
   4893 
   4894 static const aom_codec_enc_cfg_t encoder_usage_cfg[] = {
   4895 #if !CONFIG_REALTIME_ONLY
   4896  {
   4897      // NOLINT
   4898      AOM_USAGE_GOOD_QUALITY,  // g_usage - non-realtime usage
   4899      0,                       // g_threads
   4900      0,                       // g_profile
   4901 
   4902      320,         // g_w
   4903      240,         // g_h
   4904      0,           // g_limit
   4905      0,           // g_forced_max_frame_width
   4906      0,           // g_forced_max_frame_height
   4907      AOM_BITS_8,  // g_bit_depth
   4908      8,           // g_input_bit_depth
   4909 
   4910      { 1, 30 },  // g_timebase
   4911 
   4912      0,  // g_error_resilient
   4913 
   4914      AOM_RC_ONE_PASS,  // g_pass
   4915 
   4916      35,  // g_lag_in_frames
   4917 
   4918      0,                // rc_dropframe_thresh
   4919      RESIZE_NONE,      // rc_resize_mode
   4920      SCALE_NUMERATOR,  // rc_resize_denominator
   4921      SCALE_NUMERATOR,  // rc_resize_kf_denominator
   4922 
   4923      AOM_SUPERRES_NONE,  // rc_superres_mode
   4924      SCALE_NUMERATOR,    // rc_superres_denominator
   4925      SCALE_NUMERATOR,    // rc_superres_kf_denominator
   4926      63,                 // rc_superres_qthresh
   4927      32,                 // rc_superres_kf_qthresh
   4928 
   4929      AOM_VBR,      // rc_end_usage
   4930      { NULL, 0 },  // rc_twopass_stats_in
   4931      { NULL, 0 },  // rc_firstpass_mb_stats_in
   4932      256,          // rc_target_bitrate
   4933      0,            // rc_min_quantizer
   4934      63,           // rc_max_quantizer
   4935      25,           // rc_undershoot_pct
   4936      25,           // rc_overshoot_pct
   4937 
   4938      6000,  // rc_buf_sz
   4939      4000,  // rc_buf_initial_sz
   4940      5000,  // rc_buf_optimal_sz
   4941 
   4942      50,    // rc_2pass_vbr_bias_pct
   4943      0,     // rc_2pass_vbr_minsection_pct
   4944      2000,  // rc_2pass_vbr_maxsection_pct
   4945 
   4946      // keyframing settings (kf)
   4947      0,                       // fwd_kf_enabled
   4948      AOM_KF_AUTO,             // kf_mode
   4949      0,                       // kf_min_dist
   4950      9999,                    // kf_max_dist
   4951      0,                       // sframe_dist
   4952      1,                       // sframe_mode
   4953      0,                       // large_scale_tile
   4954      0,                       // monochrome
   4955      0,                       // full_still_picture_hdr
   4956      0,                       // save_as_annexb
   4957      0,                       // tile_width_count
   4958      0,                       // tile_height_count
   4959      { 0 },                   // tile_widths
   4960      { 0 },                   // tile_heights
   4961      0,                       // use_fixed_qp_offsets
   4962      { -1, -1, -1, -1, -1 },  // fixed_qp_offsets
   4963      { 0, 128, 128, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   4964        0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  // encoder_cfg
   4965  },
   4966 #endif  // !CONFIG_REALTIME_ONLY
   4967  {
   4968      // NOLINT
   4969      AOM_USAGE_REALTIME,  // g_usage - real-time usage
   4970      0,                   // g_threads
   4971      0,                   // g_profile
   4972 
   4973      320,         // g_w
   4974      240,         // g_h
   4975      0,           // g_limit
   4976      0,           // g_forced_max_frame_width
   4977      0,           // g_forced_max_frame_height
   4978      AOM_BITS_8,  // g_bit_depth
   4979      8,           // g_input_bit_depth
   4980 
   4981      { 1, 30 },  // g_timebase
   4982 
   4983      0,  // g_error_resilient
   4984 
   4985      AOM_RC_ONE_PASS,  // g_pass
   4986 
   4987      0,  // g_lag_in_frames
   4988 
   4989      0,                // rc_dropframe_thresh
   4990      RESIZE_NONE,      // rc_resize_mode
   4991      SCALE_NUMERATOR,  // rc_resize_denominator
   4992      SCALE_NUMERATOR,  // rc_resize_kf_denominator
   4993 
   4994      AOM_SUPERRES_NONE,  // rc_superres_mode
   4995      SCALE_NUMERATOR,    // rc_superres_denominator
   4996      SCALE_NUMERATOR,    // rc_superres_kf_denominator
   4997      63,                 // rc_superres_qthresh
   4998      32,                 // rc_superres_kf_qthresh
   4999 
   5000      AOM_CBR,      // rc_end_usage
   5001      { NULL, 0 },  // rc_twopass_stats_in
   5002      { NULL, 0 },  // rc_firstpass_mb_stats_in
   5003      256,          // rc_target_bitrate
   5004      0,            // rc_min_quantizer
   5005      63,           // rc_max_quantizer
   5006      50,           // rc_undershoot_pct
   5007      50,           // rc_overshoot_pct
   5008 
   5009      1000,  // rc_buf_sz
   5010      600,   // rc_buf_initial_sz
   5011      600,   // rc_buf_optimal_sz
   5012 
   5013      50,    // rc_2pass_vbr_bias_pct
   5014      0,     // rc_2pass_vbr_minsection_pct
   5015      2000,  // rc_2pass_vbr_maxsection_pct
   5016 
   5017      // keyframing settings (kf)
   5018      0,                       // fwd_kf_enabled
   5019      AOM_KF_AUTO,             // kf_mode
   5020      0,                       // kf_min_dist
   5021      9999,                    // kf_max_dist
   5022      0,                       // sframe_dist
   5023      1,                       // sframe_mode
   5024      0,                       // large_scale_tile
   5025      0,                       // monochrome
   5026      0,                       // full_still_picture_hdr
   5027      0,                       // save_as_annexb
   5028      0,                       // tile_width_count
   5029      0,                       // tile_height_count
   5030      { 0 },                   // tile_widths
   5031      { 0 },                   // tile_heights
   5032      0,                       // use_fixed_qp_offsets
   5033      { -1, -1, -1, -1, -1 },  // fixed_qp_offsets
   5034      { 0, 128, 128, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5035        0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  // encoder_cfg
   5036  },
   5037 #if !CONFIG_REALTIME_ONLY
   5038  {
   5039      // NOLINT
   5040      AOM_USAGE_ALL_INTRA,  // g_usage - all intra usage
   5041      0,                    // g_threads
   5042      0,                    // g_profile
   5043 
   5044      320,         // g_w
   5045      240,         // g_h
   5046      0,           // g_limit
   5047      0,           // g_forced_max_frame_width
   5048      0,           // g_forced_max_frame_height
   5049      AOM_BITS_8,  // g_bit_depth
   5050      8,           // g_input_bit_depth
   5051 
   5052      { 1, 30 },  // g_timebase
   5053 
   5054      0,  // g_error_resilient
   5055 
   5056      AOM_RC_ONE_PASS,  // g_pass
   5057 
   5058      0,  // g_lag_in_frames
   5059 
   5060      0,                // rc_dropframe_thresh
   5061      RESIZE_NONE,      // rc_resize_mode
   5062      SCALE_NUMERATOR,  // rc_resize_denominator
   5063      SCALE_NUMERATOR,  // rc_resize_kf_denominator
   5064 
   5065      AOM_SUPERRES_NONE,  // rc_superres_mode
   5066      SCALE_NUMERATOR,    // rc_superres_denominator
   5067      SCALE_NUMERATOR,    // rc_superres_kf_denominator
   5068      63,                 // rc_superres_qthresh
   5069      32,                 // rc_superres_kf_qthresh
   5070 
   5071      AOM_Q,        // rc_end_usage
   5072      { NULL, 0 },  // rc_twopass_stats_in
   5073      { NULL, 0 },  // rc_firstpass_mb_stats_in
   5074      256,          // rc_target_bitrate
   5075      0,            // rc_min_quantizer
   5076      63,           // rc_max_quantizer
   5077      25,           // rc_undershoot_pct
   5078      25,           // rc_overshoot_pct
   5079 
   5080      6000,  // rc_buf_sz
   5081      4000,  // rc_buf_initial_sz
   5082      5000,  // rc_buf_optimal_sz
   5083 
   5084      50,    // rc_2pass_vbr_bias_pct
   5085      0,     // rc_2pass_vbr_minsection_pct
   5086      2000,  // rc_2pass_vbr_maxsection_pct
   5087 
   5088      // keyframing settings (kf)
   5089      0,                       // fwd_kf_enabled
   5090      AOM_KF_DISABLED,         // kf_mode
   5091      0,                       // kf_min_dist
   5092      0,                       // kf_max_dist
   5093      0,                       // sframe_dist
   5094      1,                       // sframe_mode
   5095      0,                       // large_scale_tile
   5096      0,                       // monochrome
   5097      0,                       // full_still_picture_hdr
   5098      0,                       // save_as_annexb
   5099      0,                       // tile_width_count
   5100      0,                       // tile_height_count
   5101      { 0 },                   // tile_widths
   5102      { 0 },                   // tile_heights
   5103      0,                       // use_fixed_qp_offsets
   5104      { -1, -1, -1, -1, -1 },  // fixed_qp_offsets
   5105      { 0, 128, 128, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5106        0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  // encoder_cfg
   5107  },
   5108 #endif  // !CONFIG_REALTIME_ONLY
   5109 };
   5110 
   5111 // This data structure and function are exported in aom/aomcx.h
   5112 #ifndef VERSION_STRING
   5113 #define VERSION_STRING
   5114 #endif
   5115 aom_codec_iface_t aom_codec_av1_cx_algo = {
   5116  "AOMedia Project AV1 Encoder" VERSION_STRING,
   5117  AOM_CODEC_INTERNAL_ABI_VERSION,
   5118  (CONFIG_AV1_HIGHBITDEPTH ? AOM_CODEC_CAP_HIGHBITDEPTH : 0) |
   5119      AOM_CODEC_CAP_ENCODER | AOM_CODEC_CAP_PSNR,  // aom_codec_caps_t
   5120  encoder_init,                                    // aom_codec_init_fn_t
   5121  encoder_destroy,                                 // aom_codec_destroy_fn_t
   5122  encoder_ctrl_maps,                               // aom_codec_ctrl_fn_map_t
   5123  {
   5124      // NOLINT
   5125      NULL,  // aom_codec_peek_si_fn_t
   5126      NULL,  // aom_codec_get_si_fn_t
   5127      NULL,  // aom_codec_decode_fn_t
   5128      NULL,  // aom_codec_get_frame_fn_t
   5129      NULL   // aom_codec_set_fb_fn_t
   5130  },
   5131  {
   5132      // NOLINT
   5133      NELEMENTS(encoder_usage_cfg),  // cfg_count
   5134      encoder_usage_cfg,             // aom_codec_enc_cfg_t
   5135      encoder_encode,                // aom_codec_encode_fn_t
   5136      encoder_get_cxdata,            // aom_codec_get_cx_data_fn_t
   5137      encoder_set_config,            // aom_codec_enc_config_set_fn_t
   5138      encoder_get_global_headers,    // aom_codec_get_global_headers_fn_t
   5139      encoder_get_preview            // aom_codec_get_preview_frame_fn_t
   5140  },
   5141  encoder_set_option  // aom_codec_set_option_fn_t
   5142 };
   5143 
   5144 aom_codec_iface_t *aom_codec_av1_cx(void) { return &aom_codec_av1_cx_algo; }