LCOV - code coverage report
Current view: top level - media/libvpx/libvpx/vp9 - vp9_cx_iface.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 766 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include <stdlib.h>
      12             : #include <string.h>
      13             : 
      14             : #include "./vpx_config.h"
      15             : #include "vpx/vpx_encoder.h"
      16             : #include "vpx_ports/vpx_once.h"
      17             : #include "vpx_ports/system_state.h"
      18             : #include "vpx/internal/vpx_codec_internal.h"
      19             : #include "./vpx_version.h"
      20             : #include "vp9/encoder/vp9_encoder.h"
      21             : #include "vpx/vp8cx.h"
      22             : #include "vp9/encoder/vp9_firstpass.h"
      23             : #include "vp9/vp9_iface_common.h"
      24             : 
      25             : struct vp9_extracfg {
      26             :   int cpu_used;  // available cpu percentage in 1/16
      27             :   unsigned int enable_auto_alt_ref;
      28             :   unsigned int noise_sensitivity;
      29             :   unsigned int sharpness;
      30             :   unsigned int static_thresh;
      31             :   unsigned int tile_columns;
      32             :   unsigned int tile_rows;
      33             :   unsigned int arnr_max_frames;
      34             :   unsigned int arnr_strength;
      35             :   unsigned int min_gf_interval;
      36             :   unsigned int max_gf_interval;
      37             :   vp8e_tuning tuning;
      38             :   unsigned int cq_level;  // constrained quality level
      39             :   unsigned int rc_max_intra_bitrate_pct;
      40             :   unsigned int rc_max_inter_bitrate_pct;
      41             :   unsigned int gf_cbr_boost_pct;
      42             :   unsigned int lossless;
      43             :   unsigned int target_level;
      44             :   unsigned int frame_parallel_decoding_mode;
      45             :   AQ_MODE aq_mode;
      46             :   int alt_ref_aq;
      47             :   unsigned int frame_periodic_boost;
      48             :   vpx_bit_depth_t bit_depth;
      49             :   vp9e_tune_content content;
      50             :   vpx_color_space_t color_space;
      51             :   vpx_color_range_t color_range;
      52             :   int render_width;
      53             :   int render_height;
      54             : };
      55             : 
      56             : static struct vp9_extracfg default_extra_cfg = {
      57             :   0,                     // cpu_used
      58             :   1,                     // enable_auto_alt_ref
      59             :   0,                     // noise_sensitivity
      60             :   0,                     // sharpness
      61             :   0,                     // static_thresh
      62             :   6,                     // tile_columns
      63             :   0,                     // tile_rows
      64             :   7,                     // arnr_max_frames
      65             :   5,                     // arnr_strength
      66             :   0,                     // min_gf_interval; 0 -> default decision
      67             :   0,                     // max_gf_interval; 0 -> default decision
      68             :   VP8_TUNE_PSNR,         // tuning
      69             :   10,                    // cq_level
      70             :   0,                     // rc_max_intra_bitrate_pct
      71             :   0,                     // rc_max_inter_bitrate_pct
      72             :   0,                     // gf_cbr_boost_pct
      73             :   0,                     // lossless
      74             :   255,                   // target_level
      75             :   1,                     // frame_parallel_decoding_mode
      76             :   NO_AQ,                 // aq_mode
      77             :   0,                     // alt_ref_aq
      78             :   0,                     // frame_periodic_delta_q
      79             :   VPX_BITS_8,            // Bit depth
      80             :   VP9E_CONTENT_DEFAULT,  // content
      81             :   VPX_CS_UNKNOWN,        // color space
      82             :   0,                     // color range
      83             :   0,                     // render width
      84             :   0,                     // render height
      85             : };
      86             : 
      87             : struct vpx_codec_alg_priv {
      88             :   vpx_codec_priv_t base;
      89             :   vpx_codec_enc_cfg_t cfg;
      90             :   struct vp9_extracfg extra_cfg;
      91             :   VP9EncoderConfig oxcf;
      92             :   VP9_COMP *cpi;
      93             :   unsigned char *cx_data;
      94             :   size_t cx_data_sz;
      95             :   unsigned char *pending_cx_data;
      96             :   size_t pending_cx_data_sz;
      97             :   int pending_frame_count;
      98             :   size_t pending_frame_sizes[8];
      99             :   size_t pending_frame_magnitude;
     100             :   vpx_image_t preview_img;
     101             :   vpx_enc_frame_flags_t next_frame_flags;
     102             :   vp8_postproc_cfg_t preview_ppcfg;
     103             :   vpx_codec_pkt_list_decl(256) pkt_list;
     104             :   unsigned int fixed_kf_cntr;
     105             :   vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb;
     106             :   // BufferPool that holds all reference frames.
     107             :   BufferPool *buffer_pool;
     108             : };
     109             : 
     110           0 : static vpx_codec_err_t update_error_state(
     111             :     vpx_codec_alg_priv_t *ctx, const struct vpx_internal_error_info *error) {
     112           0 :   const vpx_codec_err_t res = error->error_code;
     113             : 
     114           0 :   if (res != VPX_CODEC_OK)
     115           0 :     ctx->base.err_detail = error->has_detail ? error->detail : NULL;
     116             : 
     117           0 :   return res;
     118             : }
     119             : 
     120             : #undef ERROR
     121             : #define ERROR(str)                  \
     122             :   do {                              \
     123             :     ctx->base.err_detail = str;     \
     124             :     return VPX_CODEC_INVALID_PARAM; \
     125             :   } while (0)
     126             : 
     127             : #define RANGE_CHECK(p, memb, lo, hi)                                 \
     128             :   do {                                                               \
     129             :     if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
     130             :       ERROR(#memb " out of range [" #lo ".." #hi "]");               \
     131             :   } while (0)
     132             : 
     133             : #define RANGE_CHECK_HI(p, memb, hi)                                     \
     134             :   do {                                                                  \
     135             :     if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \
     136             :   } while (0)
     137             : 
     138             : #define RANGE_CHECK_LO(p, memb, lo)                                     \
     139             :   do {                                                                  \
     140             :     if (!((p)->memb >= (lo))) ERROR(#memb " out of range [" #lo "..]"); \
     141             :   } while (0)
     142             : 
     143             : #define RANGE_CHECK_BOOL(p, memb)                                     \
     144             :   do {                                                                \
     145             :     if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
     146             :   } while (0)
     147             : 
     148           0 : static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
     149             :                                        const vpx_codec_enc_cfg_t *cfg,
     150             :                                        const struct vp9_extracfg *extra_cfg) {
     151           0 :   RANGE_CHECK(cfg, g_w, 1, 65535);  // 16 bits available
     152           0 :   RANGE_CHECK(cfg, g_h, 1, 65535);  // 16 bits available
     153           0 :   RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
     154           0 :   RANGE_CHECK(cfg, g_timebase.num, 1, 1000000000);
     155           0 :   RANGE_CHECK_HI(cfg, g_profile, 3);
     156             : 
     157           0 :   RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
     158           0 :   RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
     159           0 :   RANGE_CHECK_BOOL(extra_cfg, lossless);
     160           0 :   RANGE_CHECK_BOOL(extra_cfg, frame_parallel_decoding_mode);
     161           0 :   RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 2);
     162           0 :   RANGE_CHECK(extra_cfg, alt_ref_aq, 0, 1);
     163           0 :   RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
     164           0 :   RANGE_CHECK_HI(cfg, g_threads, 64);
     165           0 :   RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
     166           0 :   RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
     167           0 :   RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
     168           0 :   RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
     169           0 :   RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
     170           0 :   RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
     171           0 :   RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
     172           0 :   RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
     173           0 :   RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
     174           0 :   RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
     175           0 :   RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
     176           0 :   RANGE_CHECK(extra_cfg, min_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
     177           0 :   RANGE_CHECK(extra_cfg, max_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
     178           0 :   if (extra_cfg->max_gf_interval > 0) {
     179           0 :     RANGE_CHECK(extra_cfg, max_gf_interval, 2, (MAX_LAG_BUFFERS - 1));
     180             :   }
     181           0 :   if (extra_cfg->min_gf_interval > 0 && extra_cfg->max_gf_interval > 0) {
     182           0 :     RANGE_CHECK(extra_cfg, max_gf_interval, extra_cfg->min_gf_interval,
     183             :                 (MAX_LAG_BUFFERS - 1));
     184             :   }
     185             : 
     186           0 :   if (cfg->rc_resize_allowed == 1) {
     187           0 :     RANGE_CHECK(cfg, rc_scaled_width, 0, cfg->g_w);
     188           0 :     RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
     189             :   }
     190             : 
     191           0 :   RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
     192           0 :   RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
     193             : 
     194             :   {
     195           0 :     unsigned int level = extra_cfg->target_level;
     196           0 :     if (level != LEVEL_1 && level != LEVEL_1_1 && level != LEVEL_2 &&
     197           0 :         level != LEVEL_2_1 && level != LEVEL_3 && level != LEVEL_3_1 &&
     198           0 :         level != LEVEL_4 && level != LEVEL_4_1 && level != LEVEL_5 &&
     199           0 :         level != LEVEL_5_1 && level != LEVEL_5_2 && level != LEVEL_6 &&
     200           0 :         level != LEVEL_6_1 && level != LEVEL_6_2 && level != LEVEL_UNKNOWN &&
     201             :         level != LEVEL_MAX)
     202           0 :       ERROR("target_level is invalid");
     203             :   }
     204             : 
     205           0 :   if (cfg->ss_number_layers * cfg->ts_number_layers > VPX_MAX_LAYERS)
     206           0 :     ERROR("ss_number_layers * ts_number_layers is out of range");
     207           0 :   if (cfg->ts_number_layers > 1) {
     208             :     unsigned int sl, tl;
     209           0 :     for (sl = 1; sl < cfg->ss_number_layers; ++sl) {
     210           0 :       for (tl = 1; tl < cfg->ts_number_layers; ++tl) {
     211           0 :         const int layer = LAYER_IDS_TO_IDX(sl, tl, cfg->ts_number_layers);
     212           0 :         if (cfg->layer_target_bitrate[layer] <
     213           0 :             cfg->layer_target_bitrate[layer - 1])
     214           0 :           ERROR("ts_target_bitrate entries are not increasing");
     215             :       }
     216             :     }
     217             : 
     218           0 :     RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
     219           0 :     for (tl = cfg->ts_number_layers - 2; tl > 0; --tl)
     220           0 :       if (cfg->ts_rate_decimator[tl - 1] != 2 * cfg->ts_rate_decimator[tl])
     221           0 :         ERROR("ts_rate_decimator factors are not powers of 2");
     222             :   }
     223             : 
     224             : #if CONFIG_SPATIAL_SVC
     225             : 
     226             :   if ((cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) &&
     227             :       cfg->g_pass == VPX_RC_LAST_PASS) {
     228             :     unsigned int i, alt_ref_sum = 0;
     229             :     for (i = 0; i < cfg->ss_number_layers; ++i) {
     230             :       if (cfg->ss_enable_auto_alt_ref[i]) ++alt_ref_sum;
     231             :     }
     232             :     if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
     233             :       ERROR("Not enough ref buffers for svc alt ref frames");
     234             :     if (cfg->ss_number_layers * cfg->ts_number_layers > 3 &&
     235             :         cfg->g_error_resilient == 0)
     236             :       ERROR("Multiple frame context are not supported for more than 3 layers");
     237             :   }
     238             : #endif
     239             : 
     240             :   // VP9 does not support a lower bound on the keyframe interval in
     241             :   // automatic keyframe placement mode.
     242           0 :   if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
     243           0 :       cfg->kf_min_dist > 0)
     244           0 :     ERROR(
     245             :         "kf_min_dist not supported in auto mode, use 0 "
     246             :         "or kf_max_dist instead.");
     247             : 
     248           0 :   RANGE_CHECK(extra_cfg, enable_auto_alt_ref, 0, 2);
     249           0 :   RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
     250           0 :   RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
     251           0 :   RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
     252           0 :   RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
     253           0 :   RANGE_CHECK_HI(extra_cfg, sharpness, 7);
     254           0 :   RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
     255           0 :   RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
     256           0 :   RANGE_CHECK(extra_cfg, cq_level, 0, 63);
     257           0 :   RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
     258           0 :   RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
     259           0 :   RANGE_CHECK(extra_cfg, content, VP9E_CONTENT_DEFAULT,
     260             :               VP9E_CONTENT_INVALID - 1);
     261             : 
     262             :   // TODO(yaowu): remove this when ssim tuning is implemented for vp9
     263           0 :   if (extra_cfg->tuning == VP8_TUNE_SSIM)
     264           0 :     ERROR("Option --tune=ssim is not currently supported in VP9.");
     265             : 
     266           0 :   if (cfg->g_pass == VPX_RC_LAST_PASS) {
     267           0 :     const size_t packet_sz = sizeof(FIRSTPASS_STATS);
     268           0 :     const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
     269             :     const FIRSTPASS_STATS *stats;
     270             : 
     271           0 :     if (cfg->rc_twopass_stats_in.buf == NULL)
     272           0 :       ERROR("rc_twopass_stats_in.buf not set.");
     273             : 
     274           0 :     if (cfg->rc_twopass_stats_in.sz % packet_sz)
     275           0 :       ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
     276             : 
     277           0 :     if (cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) {
     278             :       int i;
     279           0 :       unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = { 0 };
     280             : 
     281           0 :       stats = cfg->rc_twopass_stats_in.buf;
     282           0 :       for (i = 0; i < n_packets; ++i) {
     283           0 :         const int layer_id = (int)stats[i].spatial_layer_id;
     284           0 :         if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
     285           0 :           ++n_packets_per_layer[layer_id];
     286             :         }
     287             :       }
     288             : 
     289           0 :       for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
     290             :         unsigned int layer_id;
     291           0 :         if (n_packets_per_layer[i] < 2) {
     292           0 :           ERROR(
     293             :               "rc_twopass_stats_in requires at least two packets for each "
     294             :               "layer.");
     295             :         }
     296             : 
     297           0 :         stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
     298           0 :                 n_packets - cfg->ss_number_layers + i;
     299           0 :         layer_id = (int)stats->spatial_layer_id;
     300             : 
     301           0 :         if (layer_id >= cfg->ss_number_layers ||
     302           0 :             (unsigned int)(stats->count + 0.5) !=
     303           0 :                 n_packets_per_layer[layer_id] - 1)
     304           0 :           ERROR("rc_twopass_stats_in missing EOS stats packet");
     305             :       }
     306             :     } else {
     307           0 :       if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
     308           0 :         ERROR("rc_twopass_stats_in requires at least two packets.");
     309             : 
     310           0 :       stats =
     311           0 :           (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
     312             : 
     313           0 :       if ((int)(stats->count + 0.5) != n_packets - 1)
     314           0 :         ERROR("rc_twopass_stats_in missing EOS stats packet");
     315             :     }
     316             :   }
     317             : 
     318             : #if !CONFIG_VP9_HIGHBITDEPTH
     319           0 :   if (cfg->g_profile > (unsigned int)PROFILE_1) {
     320           0 :     ERROR("Profile > 1 not supported in this build configuration");
     321             :   }
     322             : #endif
     323           0 :   if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
     324           0 :       cfg->g_bit_depth > VPX_BITS_8) {
     325           0 :     ERROR("Codec high bit-depth not supported in profile < 2");
     326             :   }
     327           0 :   if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
     328           0 :     ERROR("Source high bit-depth not supported in profile < 2");
     329             :   }
     330           0 :   if (cfg->g_profile > (unsigned int)PROFILE_1 &&
     331           0 :       cfg->g_bit_depth == VPX_BITS_8) {
     332           0 :     ERROR("Codec bit-depth 8 not supported in profile > 1");
     333             :   }
     334           0 :   RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB);
     335           0 :   RANGE_CHECK(extra_cfg, color_range, VPX_CR_STUDIO_RANGE, VPX_CR_FULL_RANGE);
     336           0 :   return VPX_CODEC_OK;
     337             : }
     338             : 
     339           0 : static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
     340             :                                     const vpx_image_t *img) {
     341           0 :   switch (img->fmt) {
     342             :     case VPX_IMG_FMT_YV12:
     343             :     case VPX_IMG_FMT_I420:
     344           0 :     case VPX_IMG_FMT_I42016: break;
     345             :     case VPX_IMG_FMT_I422:
     346             :     case VPX_IMG_FMT_I444:
     347             :     case VPX_IMG_FMT_I440:
     348           0 :       if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
     349           0 :         ERROR(
     350             :             "Invalid image format. I422, I444, I440 images are "
     351             :             "not supported in profile.");
     352             :       }
     353           0 :       break;
     354             :     case VPX_IMG_FMT_I42216:
     355             :     case VPX_IMG_FMT_I44416:
     356             :     case VPX_IMG_FMT_I44016:
     357           0 :       if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
     358           0 :           ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
     359           0 :         ERROR(
     360             :             "Invalid image format. 16-bit I422, I444, I440 images are "
     361             :             "not supported in profile.");
     362             :       }
     363           0 :       break;
     364             :     default:
     365           0 :       ERROR(
     366             :           "Invalid image format. Only YV12, I420, I422, I444 images are "
     367             :           "supported.");
     368             :       break;
     369             :   }
     370             : 
     371           0 :   if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
     372           0 :     ERROR("Image size must match encoder init configuration size");
     373             : 
     374           0 :   return VPX_CODEC_OK;
     375             : }
     376             : 
     377           0 : static int get_image_bps(const vpx_image_t *img) {
     378           0 :   switch (img->fmt) {
     379             :     case VPX_IMG_FMT_YV12:
     380           0 :     case VPX_IMG_FMT_I420: return 12;
     381           0 :     case VPX_IMG_FMT_I422: return 16;
     382           0 :     case VPX_IMG_FMT_I444: return 24;
     383           0 :     case VPX_IMG_FMT_I440: return 16;
     384           0 :     case VPX_IMG_FMT_I42016: return 24;
     385           0 :     case VPX_IMG_FMT_I42216: return 32;
     386           0 :     case VPX_IMG_FMT_I44416: return 48;
     387           0 :     case VPX_IMG_FMT_I44016: return 32;
     388           0 :     default: assert(0 && "Invalid image format"); break;
     389             :   }
     390             :   return 0;
     391             : }
     392             : 
     393             : // Modify the encoder config for the target level.
     394           0 : static void config_target_level(VP9EncoderConfig *oxcf) {
     395             :   double max_average_bitrate;  // in bits per second
     396             :   int max_over_shoot_pct;
     397           0 :   const int target_level_index = get_level_index(oxcf->target_level);
     398             : 
     399           0 :   vpx_clear_system_state();
     400           0 :   assert(target_level_index >= 0);
     401           0 :   assert(target_level_index < VP9_LEVELS);
     402             : 
     403             :   // Maximum target bit-rate is level_limit * 80%.
     404           0 :   max_average_bitrate =
     405           0 :       vp9_level_defs[target_level_index].average_bitrate * 800.0;
     406           0 :   if ((double)oxcf->target_bandwidth > max_average_bitrate)
     407           0 :     oxcf->target_bandwidth = (int64_t)(max_average_bitrate);
     408           0 :   if (oxcf->ss_number_layers == 1 && oxcf->pass != 0)
     409           0 :     oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
     410             : 
     411             :   // Adjust max over-shoot percentage.
     412           0 :   max_over_shoot_pct =
     413           0 :       (int)((max_average_bitrate * 1.10 - (double)oxcf->target_bandwidth) *
     414           0 :             100 / (double)(oxcf->target_bandwidth));
     415           0 :   if (oxcf->over_shoot_pct > max_over_shoot_pct)
     416           0 :     oxcf->over_shoot_pct = max_over_shoot_pct;
     417             : 
     418             :   // Adjust worst allowed quantizer.
     419           0 :   oxcf->worst_allowed_q = vp9_quantizer_to_qindex(63);
     420             : 
     421             :   // Adjust minimum art-ref distance.
     422           0 :   if (oxcf->min_gf_interval <
     423           0 :       (int)vp9_level_defs[target_level_index].min_altref_distance)
     424           0 :     oxcf->min_gf_interval =
     425           0 :         (int)vp9_level_defs[target_level_index].min_altref_distance;
     426             : 
     427             :   // Adjust maximum column tiles.
     428           0 :   if (vp9_level_defs[target_level_index].max_col_tiles <
     429           0 :       (1 << oxcf->tile_columns)) {
     430           0 :     while (oxcf->tile_columns > 0 &&
     431           0 :            vp9_level_defs[target_level_index].max_col_tiles <
     432           0 :                (1 << oxcf->tile_columns))
     433           0 :       --oxcf->tile_columns;
     434             :   }
     435           0 : }
     436             : 
     437           0 : static vpx_codec_err_t set_encoder_config(
     438             :     VP9EncoderConfig *oxcf, const vpx_codec_enc_cfg_t *cfg,
     439             :     const struct vp9_extracfg *extra_cfg) {
     440           0 :   const int is_vbr = cfg->rc_end_usage == VPX_VBR;
     441             :   int sl, tl;
     442           0 :   oxcf->profile = cfg->g_profile;
     443           0 :   oxcf->max_threads = (int)cfg->g_threads;
     444           0 :   oxcf->width = cfg->g_w;
     445           0 :   oxcf->height = cfg->g_h;
     446           0 :   oxcf->bit_depth = cfg->g_bit_depth;
     447           0 :   oxcf->input_bit_depth = cfg->g_input_bit_depth;
     448             :   // guess a frame rate if out of whack, use 30
     449           0 :   oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
     450           0 :   if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
     451             : 
     452           0 :   oxcf->mode = GOOD;
     453             : 
     454           0 :   switch (cfg->g_pass) {
     455           0 :     case VPX_RC_ONE_PASS: oxcf->pass = 0; break;
     456           0 :     case VPX_RC_FIRST_PASS: oxcf->pass = 1; break;
     457           0 :     case VPX_RC_LAST_PASS: oxcf->pass = 2; break;
     458             :   }
     459             : 
     460           0 :   oxcf->lag_in_frames =
     461           0 :       cfg->g_pass == VPX_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
     462           0 :   oxcf->rc_mode = cfg->rc_end_usage;
     463             : 
     464             :   // Convert target bandwidth from Kbit/s to Bit/s
     465           0 :   oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
     466           0 :   oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
     467           0 :   oxcf->rc_max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct;
     468           0 :   oxcf->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct;
     469             : 
     470           0 :   oxcf->best_allowed_q =
     471           0 :       extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_min_quantizer);
     472           0 :   oxcf->worst_allowed_q =
     473           0 :       extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_max_quantizer);
     474           0 :   oxcf->cq_level = vp9_quantizer_to_qindex(extra_cfg->cq_level);
     475           0 :   oxcf->fixed_q = -1;
     476             : 
     477           0 :   oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
     478           0 :   oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
     479             : 
     480           0 :   oxcf->scaled_frame_width = cfg->rc_scaled_width;
     481           0 :   oxcf->scaled_frame_height = cfg->rc_scaled_height;
     482           0 :   if (cfg->rc_resize_allowed == 1) {
     483           0 :     oxcf->resize_mode =
     484           0 :         (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
     485             :             ? RESIZE_DYNAMIC
     486           0 :             : RESIZE_FIXED;
     487             :   } else {
     488           0 :     oxcf->resize_mode = RESIZE_NONE;
     489             :   }
     490             : 
     491           0 :   oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
     492           0 :   oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
     493           0 :   oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
     494             : 
     495           0 :   oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
     496             : 
     497           0 :   oxcf->two_pass_vbrbias = cfg->rc_2pass_vbr_bias_pct;
     498           0 :   oxcf->two_pass_vbrmin_section = cfg->rc_2pass_vbr_minsection_pct;
     499           0 :   oxcf->two_pass_vbrmax_section = cfg->rc_2pass_vbr_maxsection_pct;
     500             : 
     501           0 :   oxcf->auto_key =
     502           0 :       cfg->kf_mode == VPX_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
     503             : 
     504           0 :   oxcf->key_freq = cfg->kf_max_dist;
     505             : 
     506           0 :   oxcf->speed = abs(extra_cfg->cpu_used);
     507           0 :   oxcf->encode_breakout = extra_cfg->static_thresh;
     508           0 :   oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
     509           0 :   oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
     510           0 :   oxcf->sharpness = extra_cfg->sharpness;
     511             : 
     512           0 :   oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
     513             : 
     514             : #if CONFIG_FP_MB_STATS
     515             :   oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
     516             : #endif
     517             : 
     518           0 :   oxcf->color_space = extra_cfg->color_space;
     519           0 :   oxcf->color_range = extra_cfg->color_range;
     520           0 :   oxcf->render_width = extra_cfg->render_width;
     521           0 :   oxcf->render_height = extra_cfg->render_height;
     522           0 :   oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
     523           0 :   oxcf->arnr_strength = extra_cfg->arnr_strength;
     524           0 :   oxcf->min_gf_interval = extra_cfg->min_gf_interval;
     525           0 :   oxcf->max_gf_interval = extra_cfg->max_gf_interval;
     526             : 
     527           0 :   oxcf->tuning = extra_cfg->tuning;
     528           0 :   oxcf->content = extra_cfg->content;
     529             : 
     530           0 :   oxcf->tile_columns = extra_cfg->tile_columns;
     531             : 
     532             :   // TODO(yunqing): The dependencies between row tiles cause error in multi-
     533             :   // threaded encoding. For now, tile_rows is forced to be 0 in this case.
     534             :   // The further fix can be done by adding synchronizations after a tile row
     535             :   // is encoded. But this will hurt multi-threaded encoder performance. So,
     536             :   // it is recommended to use tile-rows=0 while encoding with threads > 1.
     537           0 :   if (oxcf->max_threads > 1 && oxcf->tile_columns > 0)
     538           0 :     oxcf->tile_rows = 0;
     539             :   else
     540           0 :     oxcf->tile_rows = extra_cfg->tile_rows;
     541             : 
     542           0 :   oxcf->error_resilient_mode = cfg->g_error_resilient;
     543           0 :   oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
     544             : 
     545           0 :   oxcf->aq_mode = extra_cfg->aq_mode;
     546           0 :   oxcf->alt_ref_aq = extra_cfg->alt_ref_aq;
     547             : 
     548           0 :   oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
     549             : 
     550           0 :   oxcf->ss_number_layers = cfg->ss_number_layers;
     551           0 :   oxcf->ts_number_layers = cfg->ts_number_layers;
     552           0 :   oxcf->temporal_layering_mode =
     553           0 :       (enum vp9e_temporal_layering_mode)cfg->temporal_layering_mode;
     554             : 
     555           0 :   oxcf->target_level = extra_cfg->target_level;
     556             : 
     557           0 :   for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
     558             : #if CONFIG_SPATIAL_SVC
     559             :     oxcf->ss_enable_auto_arf[sl] = cfg->ss_enable_auto_alt_ref[sl];
     560             : #endif
     561           0 :     for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
     562           0 :       oxcf->layer_target_bitrate[sl * oxcf->ts_number_layers + tl] =
     563           0 :           1000 * cfg->layer_target_bitrate[sl * oxcf->ts_number_layers + tl];
     564             :     }
     565             :   }
     566           0 :   if (oxcf->ss_number_layers == 1 && oxcf->pass != 0) {
     567           0 :     oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
     568             : #if CONFIG_SPATIAL_SVC
     569             :     oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
     570             : #endif
     571             :   }
     572           0 :   if (oxcf->ts_number_layers > 1) {
     573           0 :     for (tl = 0; tl < VPX_TS_MAX_LAYERS; ++tl) {
     574           0 :       oxcf->ts_rate_decimator[tl] =
     575           0 :           cfg->ts_rate_decimator[tl] ? cfg->ts_rate_decimator[tl] : 1;
     576             :     }
     577           0 :   } else if (oxcf->ts_number_layers == 1) {
     578           0 :     oxcf->ts_rate_decimator[0] = 1;
     579             :   }
     580             : 
     581           0 :   if (get_level_index(oxcf->target_level) >= 0) config_target_level(oxcf);
     582             :   /*
     583             :   printf("Current VP9 Settings: \n");
     584             :   printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
     585             :   printf("target_level: %d\n", oxcf->target_level);
     586             :   printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
     587             :   printf("sharpness: %d\n",    oxcf->sharpness);
     588             :   printf("cpu_used: %d\n",  oxcf->cpu_used);
     589             :   printf("Mode: %d\n",     oxcf->mode);
     590             :   printf("auto_key: %d\n",  oxcf->auto_key);
     591             :   printf("key_freq: %d\n", oxcf->key_freq);
     592             :   printf("end_usage: %d\n", oxcf->end_usage);
     593             :   printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
     594             :   printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
     595             :   printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
     596             :   printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
     597             :   printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
     598             :   printf("fixed_q: %d\n",  oxcf->fixed_q);
     599             :   printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
     600             :   printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
     601             :   printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
     602             :   printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
     603             :   printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
     604             :   printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
     605             :   printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
     606             :   printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
     607             :   printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
     608             :   printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
     609             :   printf("Version: %d\n", oxcf->Version);
     610             :   printf("encode_breakout: %d\n", oxcf->encode_breakout);
     611             :   printf("error resilient: %d\n", oxcf->error_resilient_mode);
     612             :   printf("frame parallel detokenization: %d\n",
     613             :          oxcf->frame_parallel_decoding_mode);
     614             :   */
     615           0 :   return VPX_CODEC_OK;
     616             : }
     617             : 
     618           0 : static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
     619             :                                           const vpx_codec_enc_cfg_t *cfg) {
     620             :   vpx_codec_err_t res;
     621           0 :   int force_key = 0;
     622             : 
     623           0 :   if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
     624           0 :     if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)
     625           0 :       ERROR("Cannot change width or height after initialization");
     626           0 :     if (!valid_ref_frame_size(ctx->cfg.g_w, ctx->cfg.g_h, cfg->g_w, cfg->g_h) ||
     627           0 :         (ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
     628           0 :         (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
     629           0 :       force_key = 1;
     630             :   }
     631             : 
     632             :   // Prevent increasing lag_in_frames. This check is stricter than it needs
     633             :   // to be -- the limit is not increasing past the first lag_in_frames
     634             :   // value, but we don't track the initial config, only the last successful
     635             :   // config.
     636           0 :   if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
     637           0 :     ERROR("Cannot increase lag_in_frames");
     638             : 
     639           0 :   res = validate_config(ctx, cfg, &ctx->extra_cfg);
     640             : 
     641           0 :   if (res == VPX_CODEC_OK) {
     642           0 :     ctx->cfg = *cfg;
     643           0 :     set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
     644             :     // On profile change, request a key frame
     645           0 :     force_key |= ctx->cpi->common.profile != ctx->oxcf.profile;
     646           0 :     vp9_change_config(ctx->cpi, &ctx->oxcf);
     647             :   }
     648             : 
     649           0 :   if (force_key) ctx->next_frame_flags |= VPX_EFLAG_FORCE_KF;
     650             : 
     651           0 :   return res;
     652             : }
     653             : 
     654           0 : static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
     655             :                                           va_list args) {
     656           0 :   int *const arg = va_arg(args, int *);
     657           0 :   if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
     658           0 :   *arg = vp9_get_quantizer(ctx->cpi);
     659           0 :   return VPX_CODEC_OK;
     660             : }
     661             : 
     662           0 : static vpx_codec_err_t ctrl_get_quantizer64(vpx_codec_alg_priv_t *ctx,
     663             :                                             va_list args) {
     664           0 :   int *const arg = va_arg(args, int *);
     665           0 :   if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
     666           0 :   *arg = vp9_qindex_to_quantizer(vp9_get_quantizer(ctx->cpi));
     667           0 :   return VPX_CODEC_OK;
     668             : }
     669             : 
     670           0 : static vpx_codec_err_t update_extra_cfg(vpx_codec_alg_priv_t *ctx,
     671             :                                         const struct vp9_extracfg *extra_cfg) {
     672           0 :   const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
     673           0 :   if (res == VPX_CODEC_OK) {
     674           0 :     ctx->extra_cfg = *extra_cfg;
     675           0 :     set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
     676           0 :     vp9_change_config(ctx->cpi, &ctx->oxcf);
     677             :   }
     678           0 :   return res;
     679             : }
     680             : 
     681           0 : static vpx_codec_err_t ctrl_set_cpuused(vpx_codec_alg_priv_t *ctx,
     682             :                                         va_list args) {
     683           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     684           0 :   extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
     685           0 :   return update_extra_cfg(ctx, &extra_cfg);
     686             : }
     687             : 
     688           0 : static vpx_codec_err_t ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
     689             :                                                     va_list args) {
     690           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     691           0 :   extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
     692           0 :   return update_extra_cfg(ctx, &extra_cfg);
     693             : }
     694             : 
     695           0 : static vpx_codec_err_t ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
     696             :                                                   va_list args) {
     697           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     698           0 :   extra_cfg.noise_sensitivity = CAST(VP9E_SET_NOISE_SENSITIVITY, args);
     699           0 :   return update_extra_cfg(ctx, &extra_cfg);
     700             : }
     701             : 
     702           0 : static vpx_codec_err_t ctrl_set_sharpness(vpx_codec_alg_priv_t *ctx,
     703             :                                           va_list args) {
     704           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     705           0 :   extra_cfg.sharpness = CAST(VP8E_SET_SHARPNESS, args);
     706           0 :   return update_extra_cfg(ctx, &extra_cfg);
     707             : }
     708             : 
     709           0 : static vpx_codec_err_t ctrl_set_static_thresh(vpx_codec_alg_priv_t *ctx,
     710             :                                               va_list args) {
     711           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     712           0 :   extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
     713           0 :   return update_extra_cfg(ctx, &extra_cfg);
     714             : }
     715             : 
     716           0 : static vpx_codec_err_t ctrl_set_tile_columns(vpx_codec_alg_priv_t *ctx,
     717             :                                              va_list args) {
     718           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     719           0 :   extra_cfg.tile_columns = CAST(VP9E_SET_TILE_COLUMNS, args);
     720           0 :   return update_extra_cfg(ctx, &extra_cfg);
     721             : }
     722             : 
     723           0 : static vpx_codec_err_t ctrl_set_tile_rows(vpx_codec_alg_priv_t *ctx,
     724             :                                           va_list args) {
     725           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     726           0 :   extra_cfg.tile_rows = CAST(VP9E_SET_TILE_ROWS, args);
     727           0 :   return update_extra_cfg(ctx, &extra_cfg);
     728             : }
     729             : 
     730           0 : static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
     731             :                                                 va_list args) {
     732           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     733           0 :   extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
     734           0 :   return update_extra_cfg(ctx, &extra_cfg);
     735             : }
     736             : 
     737           0 : static vpx_codec_err_t ctrl_set_arnr_strength(vpx_codec_alg_priv_t *ctx,
     738             :                                               va_list args) {
     739           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     740           0 :   extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
     741           0 :   return update_extra_cfg(ctx, &extra_cfg);
     742             : }
     743             : 
     744           0 : static vpx_codec_err_t ctrl_set_arnr_type(vpx_codec_alg_priv_t *ctx,
     745             :                                           va_list args) {
     746             :   (void)ctx;
     747             :   (void)args;
     748           0 :   return VPX_CODEC_OK;
     749             : }
     750             : 
     751           0 : static vpx_codec_err_t ctrl_set_tuning(vpx_codec_alg_priv_t *ctx,
     752             :                                        va_list args) {
     753           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     754           0 :   extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
     755           0 :   return update_extra_cfg(ctx, &extra_cfg);
     756             : }
     757             : 
     758           0 : static vpx_codec_err_t ctrl_set_cq_level(vpx_codec_alg_priv_t *ctx,
     759             :                                          va_list args) {
     760           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     761           0 :   extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
     762           0 :   return update_extra_cfg(ctx, &extra_cfg);
     763             : }
     764             : 
     765           0 : static vpx_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
     766             :     vpx_codec_alg_priv_t *ctx, va_list args) {
     767           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     768           0 :   extra_cfg.rc_max_intra_bitrate_pct =
     769           0 :       CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
     770           0 :   return update_extra_cfg(ctx, &extra_cfg);
     771             : }
     772             : 
     773           0 : static vpx_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
     774             :     vpx_codec_alg_priv_t *ctx, va_list args) {
     775           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     776           0 :   extra_cfg.rc_max_inter_bitrate_pct =
     777           0 :       CAST(VP8E_SET_MAX_INTER_BITRATE_PCT, args);
     778           0 :   return update_extra_cfg(ctx, &extra_cfg);
     779             : }
     780             : 
     781           0 : static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(vpx_codec_alg_priv_t *ctx,
     782             :                                                     va_list args) {
     783           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     784           0 :   extra_cfg.gf_cbr_boost_pct = CAST(VP9E_SET_GF_CBR_BOOST_PCT, args);
     785           0 :   return update_extra_cfg(ctx, &extra_cfg);
     786             : }
     787             : 
     788           0 : static vpx_codec_err_t ctrl_set_lossless(vpx_codec_alg_priv_t *ctx,
     789             :                                          va_list args) {
     790           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     791           0 :   extra_cfg.lossless = CAST(VP9E_SET_LOSSLESS, args);
     792           0 :   return update_extra_cfg(ctx, &extra_cfg);
     793             : }
     794             : 
     795           0 : static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
     796             :     vpx_codec_alg_priv_t *ctx, va_list args) {
     797           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     798           0 :   extra_cfg.frame_parallel_decoding_mode =
     799           0 :       CAST(VP9E_SET_FRAME_PARALLEL_DECODING, args);
     800           0 :   return update_extra_cfg(ctx, &extra_cfg);
     801             : }
     802             : 
     803           0 : static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx,
     804             :                                         va_list args) {
     805           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     806           0 :   extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
     807           0 :   return update_extra_cfg(ctx, &extra_cfg);
     808             : }
     809             : 
     810           0 : static vpx_codec_err_t ctrl_set_alt_ref_aq(vpx_codec_alg_priv_t *ctx,
     811             :                                            va_list args) {
     812           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     813           0 :   extra_cfg.alt_ref_aq = CAST(VP9E_SET_ALT_REF_AQ, args);
     814           0 :   return update_extra_cfg(ctx, &extra_cfg);
     815             : }
     816             : 
     817           0 : static vpx_codec_err_t ctrl_set_min_gf_interval(vpx_codec_alg_priv_t *ctx,
     818             :                                                 va_list args) {
     819           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     820           0 :   extra_cfg.min_gf_interval = CAST(VP9E_SET_MIN_GF_INTERVAL, args);
     821           0 :   return update_extra_cfg(ctx, &extra_cfg);
     822             : }
     823             : 
     824           0 : static vpx_codec_err_t ctrl_set_max_gf_interval(vpx_codec_alg_priv_t *ctx,
     825             :                                                 va_list args) {
     826           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     827           0 :   extra_cfg.max_gf_interval = CAST(VP9E_SET_MAX_GF_INTERVAL, args);
     828           0 :   return update_extra_cfg(ctx, &extra_cfg);
     829             : }
     830             : 
     831           0 : static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
     832             :                                                      va_list args) {
     833           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     834           0 :   extra_cfg.frame_periodic_boost = CAST(VP9E_SET_FRAME_PERIODIC_BOOST, args);
     835           0 :   return update_extra_cfg(ctx, &extra_cfg);
     836             : }
     837             : 
     838           0 : static vpx_codec_err_t ctrl_set_target_level(vpx_codec_alg_priv_t *ctx,
     839             :                                              va_list args) {
     840           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
     841           0 :   extra_cfg.target_level = CAST(VP9E_SET_TARGET_LEVEL, args);
     842           0 :   return update_extra_cfg(ctx, &extra_cfg);
     843             : }
     844             : 
     845           0 : static vpx_codec_err_t ctrl_get_level(vpx_codec_alg_priv_t *ctx, va_list args) {
     846           0 :   int *const arg = va_arg(args, int *);
     847           0 :   if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
     848           0 :   *arg = (int)vp9_get_level(&ctx->cpi->level_info.level_spec);
     849           0 :   return VPX_CODEC_OK;
     850             : }
     851             : 
     852           0 : static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
     853             :                                     vpx_codec_priv_enc_mr_cfg_t *data) {
     854           0 :   vpx_codec_err_t res = VPX_CODEC_OK;
     855             :   (void)data;
     856             : 
     857           0 :   if (ctx->priv == NULL) {
     858           0 :     vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
     859           0 :     if (priv == NULL) return VPX_CODEC_MEM_ERROR;
     860             : 
     861           0 :     ctx->priv = (vpx_codec_priv_t *)priv;
     862           0 :     ctx->priv->init_flags = ctx->init_flags;
     863           0 :     ctx->priv->enc.total_encoders = 1;
     864           0 :     priv->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool));
     865           0 :     if (priv->buffer_pool == NULL) return VPX_CODEC_MEM_ERROR;
     866             : 
     867             : #if CONFIG_MULTITHREAD
     868           0 :     if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
     869           0 :       return VPX_CODEC_MEM_ERROR;
     870             :     }
     871             : #endif
     872             : 
     873           0 :     if (ctx->config.enc) {
     874             :       // Update the reference to the config structure to an internal copy.
     875           0 :       priv->cfg = *ctx->config.enc;
     876           0 :       ctx->config.enc = &priv->cfg;
     877             :     }
     878             : 
     879           0 :     priv->extra_cfg = default_extra_cfg;
     880           0 :     once(vp9_initialize_enc);
     881             : 
     882           0 :     res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
     883             : 
     884           0 :     if (res == VPX_CODEC_OK) {
     885           0 :       set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
     886             : #if CONFIG_VP9_HIGHBITDEPTH
     887             :       priv->oxcf.use_highbitdepth =
     888             :           (ctx->init_flags & VPX_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
     889             : #endif
     890           0 :       priv->cpi = vp9_create_compressor(&priv->oxcf, priv->buffer_pool);
     891           0 :       if (priv->cpi == NULL)
     892           0 :         res = VPX_CODEC_MEM_ERROR;
     893             :       else
     894           0 :         priv->cpi->output_pkt_list = &priv->pkt_list.head;
     895             :     }
     896             :   }
     897             : 
     898           0 :   return res;
     899             : }
     900             : 
     901           0 : static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
     902           0 :   free(ctx->cx_data);
     903           0 :   vp9_remove_compressor(ctx->cpi);
     904             : #if CONFIG_MULTITHREAD
     905           0 :   pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
     906             : #endif
     907           0 :   vpx_free(ctx->buffer_pool);
     908           0 :   vpx_free(ctx);
     909           0 :   return VPX_CODEC_OK;
     910             : }
     911             : 
     912           0 : static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
     913             :                                     unsigned long duration,
     914             :                                     unsigned long deadline) {
     915           0 :   MODE new_mode = BEST;
     916             : 
     917           0 :   switch (ctx->cfg.g_pass) {
     918             :     case VPX_RC_ONE_PASS:
     919           0 :       if (deadline > 0) {
     920           0 :         const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg;
     921             : 
     922             :         // Convert duration parameter from stream timebase to microseconds.
     923           0 :         const uint64_t duration_us = (uint64_t)duration * 1000000 *
     924           0 :                                      (uint64_t)cfg->g_timebase.num /
     925           0 :                                      (uint64_t)cfg->g_timebase.den;
     926             : 
     927             :         // If the deadline is more that the duration this frame is to be shown,
     928             :         // use good quality mode. Otherwise use realtime mode.
     929           0 :         new_mode = (deadline > duration_us) ? GOOD : REALTIME;
     930             :       } else {
     931           0 :         new_mode = BEST;
     932             :       }
     933           0 :       break;
     934           0 :     case VPX_RC_FIRST_PASS: break;
     935           0 :     case VPX_RC_LAST_PASS: new_mode = deadline > 0 ? GOOD : BEST; break;
     936             :   }
     937             : 
     938           0 :   if (deadline == VPX_DL_REALTIME) {
     939           0 :     ctx->oxcf.pass = 0;
     940           0 :     new_mode = REALTIME;
     941             :   }
     942             : 
     943           0 :   if (ctx->oxcf.mode != new_mode) {
     944           0 :     ctx->oxcf.mode = new_mode;
     945           0 :     vp9_change_config(ctx->cpi, &ctx->oxcf);
     946             :   }
     947           0 : }
     948             : 
     949             : // Turn on to test if supplemental superframe data breaks decoding
     950             : // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
     951           0 : static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
     952           0 :   uint8_t marker = 0xc0;
     953             :   unsigned int mask;
     954             :   int mag, index_sz;
     955             : 
     956           0 :   assert(ctx->pending_frame_count);
     957           0 :   assert(ctx->pending_frame_count <= 8);
     958             : 
     959             :   // Add the number of frames to the marker byte
     960           0 :   marker |= ctx->pending_frame_count - 1;
     961             : 
     962             :   // Choose the magnitude
     963           0 :   for (mag = 0, mask = 0xff; mag < 4; mag++) {
     964           0 :     if (ctx->pending_frame_magnitude < mask) break;
     965           0 :     mask <<= 8;
     966           0 :     mask |= 0xff;
     967             :   }
     968           0 :   marker |= mag << 3;
     969             : 
     970             :   // Write the index
     971           0 :   index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
     972           0 :   if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
     973           0 :     uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
     974             :     int i, j;
     975             : #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
     976             :     uint8_t marker_test = 0xc0;
     977             :     int mag_test = 2;     // 1 - 4
     978             :     int frames_test = 4;  // 1 - 8
     979             :     int index_sz_test = 2 + mag_test * frames_test;
     980             :     marker_test |= frames_test - 1;
     981             :     marker_test |= (mag_test - 1) << 3;
     982             :     *x++ = marker_test;
     983             :     for (i = 0; i < mag_test * frames_test; ++i)
     984             :       *x++ = 0;  // fill up with arbitrary data
     985             :     *x++ = marker_test;
     986             :     ctx->pending_cx_data_sz += index_sz_test;
     987             :     printf("Added supplemental superframe data\n");
     988             : #endif
     989             : 
     990           0 :     *x++ = marker;
     991           0 :     for (i = 0; i < ctx->pending_frame_count; i++) {
     992           0 :       unsigned int this_sz = (unsigned int)ctx->pending_frame_sizes[i];
     993             : 
     994           0 :       for (j = 0; j <= mag; j++) {
     995           0 :         *x++ = this_sz & 0xff;
     996           0 :         this_sz >>= 8;
     997             :       }
     998             :     }
     999           0 :     *x++ = marker;
    1000           0 :     ctx->pending_cx_data_sz += index_sz;
    1001             : #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
    1002             :     index_sz += index_sz_test;
    1003             : #endif
    1004             :   }
    1005           0 :   return index_sz;
    1006             : }
    1007             : 
    1008           0 : static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
    1009             :                                        int64_t n) {
    1010           0 :   return n * TICKS_PER_SEC * timebase->num / timebase->den;
    1011             : }
    1012             : 
    1013           0 : static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase,
    1014             :                                        int64_t n) {
    1015           0 :   const int64_t round = (int64_t)TICKS_PER_SEC * timebase->num / 2 - 1;
    1016           0 :   return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
    1017             : }
    1018             : 
    1019           0 : static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi,
    1020             :                                                    unsigned int lib_flags) {
    1021           0 :   vpx_codec_frame_flags_t flags = lib_flags << 16;
    1022             : 
    1023           0 :   if (lib_flags & FRAMEFLAGS_KEY ||
    1024           0 :       (cpi->use_svc &&
    1025             :        cpi->svc
    1026           0 :            .layer_context[cpi->svc.spatial_layer_id *
    1027           0 :                               cpi->svc.number_temporal_layers +
    1028           0 :                           cpi->svc.temporal_layer_id]
    1029           0 :            .is_key_frame))
    1030           0 :     flags |= VPX_FRAME_IS_KEY;
    1031             : 
    1032           0 :   if (cpi->droppable) flags |= VPX_FRAME_IS_DROPPABLE;
    1033             : 
    1034           0 :   return flags;
    1035             : }
    1036             : 
    1037             : const size_t kMinCompressedSize = 8192;
    1038           0 : static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
    1039             :                                       const vpx_image_t *img,
    1040             :                                       vpx_codec_pts_t pts,
    1041             :                                       unsigned long duration,
    1042             :                                       vpx_enc_frame_flags_t enc_flags,
    1043             :                                       unsigned long deadline) {
    1044           0 :   volatile vpx_codec_err_t res = VPX_CODEC_OK;
    1045           0 :   volatile vpx_enc_frame_flags_t flags = enc_flags;
    1046           0 :   VP9_COMP *const cpi = ctx->cpi;
    1047           0 :   const vpx_rational_t *const timebase = &ctx->cfg.g_timebase;
    1048             :   size_t data_sz;
    1049             : 
    1050           0 :   if (cpi == NULL) return VPX_CODEC_INVALID_PARAM;
    1051             : 
    1052           0 :   if (cpi->oxcf.pass == 2 && cpi->level_constraint.level_index >= 0 &&
    1053           0 :       !cpi->level_constraint.rc_config_updated) {
    1054           0 :     SVC *const svc = &cpi->svc;
    1055           0 :     const int is_two_pass_svc =
    1056           0 :         (svc->number_spatial_layers > 1) || (svc->number_temporal_layers > 1);
    1057           0 :     const VP9EncoderConfig *const oxcf = &cpi->oxcf;
    1058           0 :     TWO_PASS *const twopass = &cpi->twopass;
    1059           0 :     FIRSTPASS_STATS *stats = &twopass->total_stats;
    1060           0 :     if (is_two_pass_svc) {
    1061           0 :       const double frame_rate = 10000000.0 * stats->count / stats->duration;
    1062           0 :       vp9_update_spatial_layer_framerate(cpi, frame_rate);
    1063           0 :       twopass->bits_left =
    1064           0 :           (int64_t)(stats->duration *
    1065           0 :                     svc->layer_context[svc->spatial_layer_id].target_bandwidth /
    1066             :                     10000000.0);
    1067             :     } else {
    1068           0 :       twopass->bits_left =
    1069           0 :           (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
    1070             :     }
    1071           0 :     cpi->level_constraint.rc_config_updated = 1;
    1072             :   }
    1073             : 
    1074           0 :   if (img != NULL) {
    1075           0 :     res = validate_img(ctx, img);
    1076           0 :     if (res == VPX_CODEC_OK) {
    1077             :       // There's no codec control for multiple alt-refs so check the encoder
    1078             :       // instance for its status to determine the compressed data size.
    1079           0 :       data_sz = ctx->cfg.g_w * ctx->cfg.g_h * get_image_bps(img) / 8 *
    1080           0 :                 (cpi->multi_arf_allowed ? 8 : 2);
    1081           0 :       if (data_sz < kMinCompressedSize) data_sz = kMinCompressedSize;
    1082           0 :       if (ctx->cx_data == NULL || ctx->cx_data_sz < data_sz) {
    1083           0 :         ctx->cx_data_sz = data_sz;
    1084           0 :         free(ctx->cx_data);
    1085           0 :         ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
    1086           0 :         if (ctx->cx_data == NULL) {
    1087           0 :           return VPX_CODEC_MEM_ERROR;
    1088             :         }
    1089             :       }
    1090             :     }
    1091             :   }
    1092             : 
    1093           0 :   pick_quickcompress_mode(ctx, duration, deadline);
    1094           0 :   vpx_codec_pkt_list_init(&ctx->pkt_list);
    1095             : 
    1096             :   // Handle Flags
    1097           0 :   if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
    1098           0 :       ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
    1099           0 :     ctx->base.err_detail = "Conflicting flags.";
    1100           0 :     return VPX_CODEC_INVALID_PARAM;
    1101             :   }
    1102             : 
    1103           0 :   if (setjmp(cpi->common.error.jmp)) {
    1104           0 :     cpi->common.error.setjmp = 0;
    1105           0 :     res = update_error_state(ctx, &cpi->common.error);
    1106           0 :     vpx_clear_system_state();
    1107           0 :     return res;
    1108             :   }
    1109           0 :   cpi->common.error.setjmp = 1;
    1110             : 
    1111           0 :   vp9_apply_encoding_flags(cpi, flags);
    1112             : 
    1113             :   // Handle fixed keyframe intervals
    1114           0 :   if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
    1115           0 :       ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
    1116           0 :     if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
    1117           0 :       flags |= VPX_EFLAG_FORCE_KF;
    1118           0 :       ctx->fixed_kf_cntr = 1;
    1119             :     }
    1120             :   }
    1121             : 
    1122           0 :   if (res == VPX_CODEC_OK) {
    1123           0 :     unsigned int lib_flags = 0;
    1124             :     YV12_BUFFER_CONFIG sd;
    1125           0 :     int64_t dst_time_stamp = timebase_units_to_ticks(timebase, pts);
    1126           0 :     int64_t dst_end_time_stamp =
    1127           0 :         timebase_units_to_ticks(timebase, pts + duration);
    1128             :     size_t size, cx_data_sz;
    1129             :     unsigned char *cx_data;
    1130             : 
    1131             :     // Set up internal flags
    1132           0 :     if (ctx->base.init_flags & VPX_CODEC_USE_PSNR) cpi->b_calculate_psnr = 1;
    1133             : 
    1134           0 :     if (img != NULL) {
    1135           0 :       res = image2yuvconfig(img, &sd);
    1136             : 
    1137           0 :       if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) {
    1138             :         /* from vpx_encoder.h for g_w/g_h:
    1139             :            "Note that the frames passed as input to the encoder must have this
    1140             :            resolution"
    1141             :         */
    1142           0 :         ctx->base.err_detail = "Invalid input frame resolution";
    1143           0 :         res = VPX_CODEC_INVALID_PARAM;
    1144             :       } else {
    1145             :         // Store the original flags in to the frame buffer. Will extract the
    1146             :         // key frame flag when we actually encode this frame.
    1147           0 :         if (vp9_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd,
    1148             :                                   dst_time_stamp, dst_end_time_stamp)) {
    1149           0 :           res = update_error_state(ctx, &cpi->common.error);
    1150             :         }
    1151             :       }
    1152           0 :       ctx->next_frame_flags = 0;
    1153             :     }
    1154             : 
    1155           0 :     cx_data = ctx->cx_data;
    1156           0 :     cx_data_sz = ctx->cx_data_sz;
    1157             : 
    1158             :     /* Any pending invisible frames? */
    1159           0 :     if (ctx->pending_cx_data) {
    1160           0 :       memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
    1161           0 :       ctx->pending_cx_data = cx_data;
    1162           0 :       cx_data += ctx->pending_cx_data_sz;
    1163           0 :       cx_data_sz -= ctx->pending_cx_data_sz;
    1164             : 
    1165             :       /* TODO: this is a minimal check, the underlying codec doesn't respect
    1166             :        * the buffer size anyway.
    1167             :        */
    1168           0 :       if (cx_data_sz < ctx->cx_data_sz / 2) {
    1169           0 :         vpx_internal_error(&cpi->common.error, VPX_CODEC_ERROR,
    1170             :                            "Compressed data buffer too small");
    1171           0 :         return VPX_CODEC_ERROR;
    1172             :       }
    1173             :     }
    1174             : 
    1175           0 :     while (cx_data_sz >= ctx->cx_data_sz / 2 &&
    1176           0 :            -1 != vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data,
    1177             :                                          &dst_time_stamp, &dst_end_time_stamp,
    1178             :                                          !img)) {
    1179           0 :       if (size) {
    1180             :         vpx_codec_cx_pkt_t pkt;
    1181             : 
    1182             : #if CONFIG_SPATIAL_SVC
    1183             :         if (cpi->use_svc)
    1184             :           cpi->svc
    1185             :               .layer_context[cpi->svc.spatial_layer_id *
    1186             :                              cpi->svc.number_temporal_layers]
    1187             :               .layer_size += size;
    1188             : #endif
    1189             : 
    1190             :         // Pack invisible frames with the next visible frame
    1191           0 :         if (!cpi->common.show_frame ||
    1192           0 :             (cpi->use_svc &&
    1193           0 :              cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)) {
    1194           0 :           if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data;
    1195           0 :           ctx->pending_cx_data_sz += size;
    1196           0 :           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
    1197           0 :           ctx->pending_frame_magnitude |= size;
    1198           0 :           cx_data += size;
    1199           0 :           cx_data_sz -= size;
    1200             : 
    1201           0 :           if (ctx->output_cx_pkt_cb.output_cx_pkt) {
    1202           0 :             pkt.kind = VPX_CODEC_CX_FRAME_PKT;
    1203           0 :             pkt.data.frame.pts =
    1204           0 :                 ticks_to_timebase_units(timebase, dst_time_stamp);
    1205           0 :             pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units(
    1206             :                 timebase, dst_end_time_stamp - dst_time_stamp);
    1207           0 :             pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
    1208           0 :             pkt.data.frame.buf = ctx->pending_cx_data;
    1209           0 :             pkt.data.frame.sz = size;
    1210           0 :             ctx->pending_cx_data = NULL;
    1211           0 :             ctx->pending_cx_data_sz = 0;
    1212           0 :             ctx->pending_frame_count = 0;
    1213           0 :             ctx->pending_frame_magnitude = 0;
    1214           0 :             ctx->output_cx_pkt_cb.output_cx_pkt(
    1215             :                 &pkt, ctx->output_cx_pkt_cb.user_priv);
    1216             :           }
    1217           0 :           continue;
    1218             :         }
    1219             : 
    1220             :         // Add the frame packet to the list of returned packets.
    1221           0 :         pkt.kind = VPX_CODEC_CX_FRAME_PKT;
    1222           0 :         pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
    1223           0 :         pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units(
    1224             :             timebase, dst_end_time_stamp - dst_time_stamp);
    1225           0 :         pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
    1226             : 
    1227           0 :         if (ctx->pending_cx_data) {
    1228           0 :           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
    1229           0 :           ctx->pending_frame_magnitude |= size;
    1230           0 :           ctx->pending_cx_data_sz += size;
    1231             :           // write the superframe only for the case when
    1232           0 :           if (!ctx->output_cx_pkt_cb.output_cx_pkt)
    1233           0 :             size += write_superframe_index(ctx);
    1234           0 :           pkt.data.frame.buf = ctx->pending_cx_data;
    1235           0 :           pkt.data.frame.sz = ctx->pending_cx_data_sz;
    1236           0 :           ctx->pending_cx_data = NULL;
    1237           0 :           ctx->pending_cx_data_sz = 0;
    1238           0 :           ctx->pending_frame_count = 0;
    1239           0 :           ctx->pending_frame_magnitude = 0;
    1240             :         } else {
    1241           0 :           pkt.data.frame.buf = cx_data;
    1242           0 :           pkt.data.frame.sz = size;
    1243             :         }
    1244           0 :         pkt.data.frame.partition_id = -1;
    1245             : 
    1246           0 :         if (ctx->output_cx_pkt_cb.output_cx_pkt)
    1247           0 :           ctx->output_cx_pkt_cb.output_cx_pkt(&pkt,
    1248             :                                               ctx->output_cx_pkt_cb.user_priv);
    1249             :         else
    1250           0 :           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
    1251             : 
    1252           0 :         cx_data += size;
    1253           0 :         cx_data_sz -= size;
    1254             : #if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
    1255             : #if CONFIG_SPATIAL_SVC
    1256             :         if (cpi->use_svc && !ctx->output_cx_pkt_cb.output_cx_pkt) {
    1257             :           vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
    1258             :           int sl;
    1259             :           vp9_zero(pkt_sizes);
    1260             :           vp9_zero(pkt_psnr);
    1261             :           pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
    1262             :           pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
    1263             :           for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
    1264             :             LAYER_CONTEXT *lc =
    1265             :                 &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
    1266             :             pkt_sizes.data.layer_sizes[sl] = lc->layer_size;
    1267             :             pkt_psnr.data.layer_psnr[sl] = lc->psnr_pkt;
    1268             :             lc->layer_size = 0;
    1269             :           }
    1270             : 
    1271             :           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_sizes);
    1272             : 
    1273             :           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
    1274             :         }
    1275             : #endif
    1276             : #endif
    1277           0 :         if (is_one_pass_cbr_svc(cpi) &&
    1278           0 :             (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
    1279             :           // Encoded all spatial layers; exit loop.
    1280           0 :           break;
    1281             :         }
    1282             :       }
    1283             :     }
    1284             :   }
    1285             : 
    1286           0 :   cpi->common.error.setjmp = 0;
    1287           0 :   return res;
    1288             : }
    1289             : 
    1290           0 : static const vpx_codec_cx_pkt_t *encoder_get_cxdata(vpx_codec_alg_priv_t *ctx,
    1291             :                                                     vpx_codec_iter_t *iter) {
    1292           0 :   return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
    1293             : }
    1294             : 
    1295           0 : static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
    1296             :                                           va_list args) {
    1297           0 :   vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
    1298             : 
    1299           0 :   if (frame != NULL) {
    1300             :     YV12_BUFFER_CONFIG sd;
    1301             : 
    1302           0 :     image2yuvconfig(&frame->img, &sd);
    1303           0 :     vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
    1304             :                           &sd);
    1305           0 :     return VPX_CODEC_OK;
    1306             :   } else {
    1307           0 :     return VPX_CODEC_INVALID_PARAM;
    1308             :   }
    1309             : }
    1310             : 
    1311           0 : static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
    1312             :                                            va_list args) {
    1313           0 :   vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
    1314             : 
    1315           0 :   if (frame != NULL) {
    1316             :     YV12_BUFFER_CONFIG sd;
    1317             : 
    1318           0 :     image2yuvconfig(&frame->img, &sd);
    1319           0 :     vp9_copy_reference_enc(ctx->cpi,
    1320             :                            ref_frame_to_vp9_reframe(frame->frame_type), &sd);
    1321           0 :     return VPX_CODEC_OK;
    1322             :   } else {
    1323           0 :     return VPX_CODEC_INVALID_PARAM;
    1324             :   }
    1325             : }
    1326             : 
    1327           0 : static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
    1328             :                                           va_list args) {
    1329           0 :   vp9_ref_frame_t *const frame = va_arg(args, vp9_ref_frame_t *);
    1330             : 
    1331           0 :   if (frame != NULL) {
    1332           0 :     YV12_BUFFER_CONFIG *fb = get_ref_frame(&ctx->cpi->common, frame->idx);
    1333           0 :     if (fb == NULL) return VPX_CODEC_ERROR;
    1334             : 
    1335           0 :     yuvconfig2image(&frame->img, fb, NULL);
    1336           0 :     return VPX_CODEC_OK;
    1337             :   } else {
    1338           0 :     return VPX_CODEC_INVALID_PARAM;
    1339             :   }
    1340             : }
    1341             : 
    1342           0 : static vpx_codec_err_t ctrl_set_previewpp(vpx_codec_alg_priv_t *ctx,
    1343             :                                           va_list args) {
    1344             : #if CONFIG_VP9_POSTPROC
    1345           0 :   vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
    1346           0 :   if (config != NULL) {
    1347           0 :     ctx->preview_ppcfg = *config;
    1348           0 :     return VPX_CODEC_OK;
    1349             :   } else {
    1350           0 :     return VPX_CODEC_INVALID_PARAM;
    1351             :   }
    1352             : #else
    1353             :   (void)ctx;
    1354             :   (void)args;
    1355             :   return VPX_CODEC_INCAPABLE;
    1356             : #endif
    1357             : }
    1358             : 
    1359           0 : static vpx_image_t *encoder_get_preview(vpx_codec_alg_priv_t *ctx) {
    1360             :   YV12_BUFFER_CONFIG sd;
    1361             :   vp9_ppflags_t flags;
    1362           0 :   vp9_zero(flags);
    1363             : 
    1364           0 :   if (ctx->preview_ppcfg.post_proc_flag) {
    1365           0 :     flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
    1366           0 :     flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
    1367           0 :     flags.noise_level = ctx->preview_ppcfg.noise_level;
    1368             :   }
    1369             : 
    1370           0 :   if (vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags) == 0) {
    1371           0 :     yuvconfig2image(&ctx->preview_img, &sd, NULL);
    1372           0 :     return &ctx->preview_img;
    1373             :   } else {
    1374           0 :     return NULL;
    1375             :   }
    1376             : }
    1377             : 
    1378           0 : static vpx_codec_err_t ctrl_set_roi_map(vpx_codec_alg_priv_t *ctx,
    1379             :                                         va_list args) {
    1380             :   (void)ctx;
    1381             :   (void)args;
    1382             : 
    1383             :   // TODO(yaowu): Need to re-implement and test for VP9.
    1384           0 :   return VPX_CODEC_INVALID_PARAM;
    1385             : }
    1386             : 
    1387           0 : static vpx_codec_err_t ctrl_set_active_map(vpx_codec_alg_priv_t *ctx,
    1388             :                                            va_list args) {
    1389           0 :   vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
    1390             : 
    1391           0 :   if (map) {
    1392           0 :     if (!vp9_set_active_map(ctx->cpi, map->active_map, (int)map->rows,
    1393           0 :                             (int)map->cols))
    1394           0 :       return VPX_CODEC_OK;
    1395             :     else
    1396           0 :       return VPX_CODEC_INVALID_PARAM;
    1397             :   } else {
    1398           0 :     return VPX_CODEC_INVALID_PARAM;
    1399             :   }
    1400             : }
    1401             : 
    1402           0 : static vpx_codec_err_t ctrl_get_active_map(vpx_codec_alg_priv_t *ctx,
    1403             :                                            va_list args) {
    1404           0 :   vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
    1405             : 
    1406           0 :   if (map) {
    1407           0 :     if (!vp9_get_active_map(ctx->cpi, map->active_map, (int)map->rows,
    1408           0 :                             (int)map->cols))
    1409           0 :       return VPX_CODEC_OK;
    1410             :     else
    1411           0 :       return VPX_CODEC_INVALID_PARAM;
    1412             :   } else {
    1413           0 :     return VPX_CODEC_INVALID_PARAM;
    1414             :   }
    1415             : }
    1416             : 
    1417           0 : static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
    1418             :                                            va_list args) {
    1419           0 :   vpx_scaling_mode_t *const mode = va_arg(args, vpx_scaling_mode_t *);
    1420             : 
    1421           0 :   if (mode) {
    1422           0 :     const int res =
    1423           0 :         vp9_set_internal_size(ctx->cpi, (VPX_SCALING)mode->h_scaling_mode,
    1424           0 :                               (VPX_SCALING)mode->v_scaling_mode);
    1425           0 :     return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
    1426             :   } else {
    1427           0 :     return VPX_CODEC_INVALID_PARAM;
    1428             :   }
    1429             : }
    1430             : 
    1431           0 : static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
    1432           0 :   int data = va_arg(args, int);
    1433           0 :   const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
    1434             :   // Both one-pass and two-pass RC are supported now.
    1435             :   // User setting this has to make sure of the following.
    1436             :   // In two-pass setting: either (but not both)
    1437             :   //      cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
    1438             :   // In one-pass setting:
    1439             :   //      either or both cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
    1440             : 
    1441           0 :   vp9_set_svc(ctx->cpi, data);
    1442             : 
    1443           0 :   if (data == 1 &&
    1444           0 :       (cfg->g_pass == VPX_RC_FIRST_PASS || cfg->g_pass == VPX_RC_LAST_PASS) &&
    1445           0 :       cfg->ss_number_layers > 1 && cfg->ts_number_layers > 1) {
    1446           0 :     return VPX_CODEC_INVALID_PARAM;
    1447             :   }
    1448           0 :   return VPX_CODEC_OK;
    1449             : }
    1450             : 
    1451           0 : static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
    1452             :                                              va_list args) {
    1453           0 :   vpx_svc_layer_id_t *const data = va_arg(args, vpx_svc_layer_id_t *);
    1454           0 :   VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
    1455           0 :   SVC *const svc = &cpi->svc;
    1456             : 
    1457           0 :   svc->first_spatial_layer_to_encode = data->spatial_layer_id;
    1458           0 :   svc->spatial_layer_to_encode = data->spatial_layer_id;
    1459           0 :   svc->temporal_layer_id = data->temporal_layer_id;
    1460             :   // Checks on valid layer_id input.
    1461           0 :   if (svc->temporal_layer_id < 0 ||
    1462           0 :       svc->temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
    1463           0 :     return VPX_CODEC_INVALID_PARAM;
    1464             :   }
    1465           0 :   if (svc->first_spatial_layer_to_encode < 0 ||
    1466           0 :       svc->first_spatial_layer_to_encode >= (int)ctx->cfg.ss_number_layers) {
    1467           0 :     return VPX_CODEC_INVALID_PARAM;
    1468             :   }
    1469             :   // First spatial layer to encode not implemented for two-pass.
    1470           0 :   if (is_two_pass_svc(cpi) && svc->first_spatial_layer_to_encode > 0)
    1471           0 :     return VPX_CODEC_INVALID_PARAM;
    1472           0 :   return VPX_CODEC_OK;
    1473             : }
    1474             : 
    1475           0 : static vpx_codec_err_t ctrl_get_svc_layer_id(vpx_codec_alg_priv_t *ctx,
    1476             :                                              va_list args) {
    1477           0 :   vpx_svc_layer_id_t *data = va_arg(args, vpx_svc_layer_id_t *);
    1478           0 :   VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
    1479           0 :   SVC *const svc = &cpi->svc;
    1480             : 
    1481           0 :   data->spatial_layer_id = svc->spatial_layer_id;
    1482           0 :   data->temporal_layer_id = svc->temporal_layer_id;
    1483             : 
    1484           0 :   return VPX_CODEC_OK;
    1485             : }
    1486             : 
    1487           0 : static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
    1488             :                                                va_list args) {
    1489           0 :   VP9_COMP *const cpi = ctx->cpi;
    1490           0 :   vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
    1491             :   int sl, tl;
    1492             : 
    1493             :   // Number of temporal layers and number of spatial layers have to be set
    1494             :   // properly before calling this control function.
    1495           0 :   for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
    1496           0 :     for (tl = 0; tl < cpi->svc.number_temporal_layers; ++tl) {
    1497           0 :       const int layer =
    1498           0 :           LAYER_IDS_TO_IDX(sl, tl, cpi->svc.number_temporal_layers);
    1499           0 :       LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
    1500           0 :       lc->max_q = params->max_quantizers[layer];
    1501           0 :       lc->min_q = params->min_quantizers[layer];
    1502           0 :       lc->scaling_factor_num = params->scaling_factor_num[sl];
    1503           0 :       lc->scaling_factor_den = params->scaling_factor_den[sl];
    1504           0 :       lc->speed = params->speed_per_layer[sl];
    1505             :     }
    1506             :   }
    1507             : 
    1508           0 :   return VPX_CODEC_OK;
    1509             : }
    1510             : 
    1511           0 : static vpx_codec_err_t ctrl_set_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx,
    1512             :                                                      va_list args) {
    1513           0 :   VP9_COMP *const cpi = ctx->cpi;
    1514           0 :   vpx_svc_ref_frame_config_t *data = va_arg(args, vpx_svc_ref_frame_config_t *);
    1515             :   int sl;
    1516           0 :   for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
    1517           0 :     cpi->svc.ext_frame_flags[sl] = data->frame_flags[sl];
    1518           0 :     cpi->svc.ext_lst_fb_idx[sl] = data->lst_fb_idx[sl];
    1519           0 :     cpi->svc.ext_gld_fb_idx[sl] = data->gld_fb_idx[sl];
    1520           0 :     cpi->svc.ext_alt_fb_idx[sl] = data->alt_fb_idx[sl];
    1521             :   }
    1522           0 :   return VPX_CODEC_OK;
    1523             : }
    1524             : 
    1525           0 : static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
    1526             :                                                  va_list args) {
    1527           0 :   vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
    1528             :       (vpx_codec_priv_output_cx_pkt_cb_pair_t *)va_arg(args, void *);
    1529           0 :   ctx->output_cx_pkt_cb.output_cx_pkt = cbp->output_cx_pkt;
    1530           0 :   ctx->output_cx_pkt_cb.user_priv = cbp->user_priv;
    1531             : 
    1532           0 :   return VPX_CODEC_OK;
    1533             : }
    1534             : 
    1535           0 : static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx,
    1536             :                                              va_list args) {
    1537           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
    1538           0 :   extra_cfg.content = CAST(VP9E_SET_TUNE_CONTENT, args);
    1539           0 :   return update_extra_cfg(ctx, &extra_cfg);
    1540             : }
    1541             : 
    1542           0 : static vpx_codec_err_t ctrl_set_color_space(vpx_codec_alg_priv_t *ctx,
    1543             :                                             va_list args) {
    1544           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
    1545           0 :   extra_cfg.color_space = CAST(VP9E_SET_COLOR_SPACE, args);
    1546           0 :   return update_extra_cfg(ctx, &extra_cfg);
    1547             : }
    1548             : 
    1549           0 : static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx,
    1550             :                                             va_list args) {
    1551           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
    1552           0 :   extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, args);
    1553           0 :   return update_extra_cfg(ctx, &extra_cfg);
    1554             : }
    1555             : 
    1556           0 : static vpx_codec_err_t ctrl_set_render_size(vpx_codec_alg_priv_t *ctx,
    1557             :                                             va_list args) {
    1558           0 :   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
    1559           0 :   int *const render_size = va_arg(args, int *);
    1560           0 :   extra_cfg.render_width = render_size[0];
    1561           0 :   extra_cfg.render_height = render_size[1];
    1562           0 :   return update_extra_cfg(ctx, &extra_cfg);
    1563             : }
    1564             : 
    1565             : static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
    1566             :   { VP8_COPY_REFERENCE, ctrl_copy_reference },
    1567             : 
    1568             :   // Setters
    1569             :   { VP8_SET_REFERENCE, ctrl_set_reference },
    1570             :   { VP8_SET_POSTPROC, ctrl_set_previewpp },
    1571             :   { VP8E_SET_ROI_MAP, ctrl_set_roi_map },
    1572             :   { VP8E_SET_ACTIVEMAP, ctrl_set_active_map },
    1573             :   { VP8E_SET_SCALEMODE, ctrl_set_scale_mode },
    1574             :   { VP8E_SET_CPUUSED, ctrl_set_cpuused },
    1575             :   { VP8E_SET_ENABLEAUTOALTREF, ctrl_set_enable_auto_alt_ref },
    1576             :   { VP8E_SET_SHARPNESS, ctrl_set_sharpness },
    1577             :   { VP8E_SET_STATIC_THRESHOLD, ctrl_set_static_thresh },
    1578             :   { VP9E_SET_TILE_COLUMNS, ctrl_set_tile_columns },
    1579             :   { VP9E_SET_TILE_ROWS, ctrl_set_tile_rows },
    1580             :   { VP8E_SET_ARNR_MAXFRAMES, ctrl_set_arnr_max_frames },
    1581             :   { VP8E_SET_ARNR_STRENGTH, ctrl_set_arnr_strength },
    1582             :   { VP8E_SET_ARNR_TYPE, ctrl_set_arnr_type },
    1583             :   { VP8E_SET_TUNING, ctrl_set_tuning },
    1584             :   { VP8E_SET_CQ_LEVEL, ctrl_set_cq_level },
    1585             :   { VP8E_SET_MAX_INTRA_BITRATE_PCT, ctrl_set_rc_max_intra_bitrate_pct },
    1586             :   { VP9E_SET_MAX_INTER_BITRATE_PCT, ctrl_set_rc_max_inter_bitrate_pct },
    1587             :   { VP9E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct },
    1588             :   { VP9E_SET_LOSSLESS, ctrl_set_lossless },
    1589             :   { VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode },
    1590             :   { VP9E_SET_AQ_MODE, ctrl_set_aq_mode },
    1591             :   { VP9E_SET_ALT_REF_AQ, ctrl_set_alt_ref_aq },
    1592             :   { VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost },
    1593             :   { VP9E_SET_SVC, ctrl_set_svc },
    1594             :   { VP9E_SET_SVC_PARAMETERS, ctrl_set_svc_parameters },
    1595             :   { VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback },
    1596             :   { VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id },
    1597             :   { VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content },
    1598             :   { VP9E_SET_COLOR_SPACE, ctrl_set_color_space },
    1599             :   { VP9E_SET_COLOR_RANGE, ctrl_set_color_range },
    1600             :   { VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity },
    1601             :   { VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval },
    1602             :   { VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval },
    1603             :   { VP9E_SET_SVC_REF_FRAME_CONFIG, ctrl_set_svc_ref_frame_config },
    1604             :   { VP9E_SET_RENDER_SIZE, ctrl_set_render_size },
    1605             :   { VP9E_SET_TARGET_LEVEL, ctrl_set_target_level },
    1606             : 
    1607             :   // Getters
    1608             :   { VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer },
    1609             :   { VP8E_GET_LAST_QUANTIZER_64, ctrl_get_quantizer64 },
    1610             :   { VP9_GET_REFERENCE, ctrl_get_reference },
    1611             :   { VP9E_GET_SVC_LAYER_ID, ctrl_get_svc_layer_id },
    1612             :   { VP9E_GET_ACTIVEMAP, ctrl_get_active_map },
    1613             :   { VP9E_GET_LEVEL, ctrl_get_level },
    1614             : 
    1615             :   { -1, NULL },
    1616             : };
    1617             : 
    1618             : static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
    1619             :   { 0,
    1620             :     {
    1621             :         // NOLINT
    1622             :         0,  // g_usage
    1623             :         8,  // g_threads
    1624             :         0,  // g_profile
    1625             : 
    1626             :         320,         // g_width
    1627             :         240,         // g_height
    1628             :         VPX_BITS_8,  // g_bit_depth
    1629             :         8,           // g_input_bit_depth
    1630             : 
    1631             :         { 1, 30 },  // g_timebase
    1632             : 
    1633             :         0,  // g_error_resilient
    1634             : 
    1635             :         VPX_RC_ONE_PASS,  // g_pass
    1636             : 
    1637             :         25,  // g_lag_in_frames
    1638             : 
    1639             :         0,   // rc_dropframe_thresh
    1640             :         0,   // rc_resize_allowed
    1641             :         0,   // rc_scaled_width
    1642             :         0,   // rc_scaled_height
    1643             :         60,  // rc_resize_down_thresold
    1644             :         30,  // rc_resize_up_thresold
    1645             : 
    1646             :         VPX_VBR,      // rc_end_usage
    1647             :         { NULL, 0 },  // rc_twopass_stats_in
    1648             :         { NULL, 0 },  // rc_firstpass_mb_stats_in
    1649             :         256,          // rc_target_bandwidth
    1650             :         0,            // rc_min_quantizer
    1651             :         63,           // rc_max_quantizer
    1652             :         25,           // rc_undershoot_pct
    1653             :         25,           // rc_overshoot_pct
    1654             : 
    1655             :         6000,  // rc_max_buffer_size
    1656             :         4000,  // rc_buffer_initial_size
    1657             :         5000,  // rc_buffer_optimal_size
    1658             : 
    1659             :         50,    // rc_two_pass_vbrbias
    1660             :         0,     // rc_two_pass_vbrmin_section
    1661             :         2000,  // rc_two_pass_vbrmax_section
    1662             : 
    1663             :         // keyframing settings (kf)
    1664             :         VPX_KF_AUTO,  // g_kfmode
    1665             :         0,            // kf_min_dist
    1666             :         128,          // kf_max_dist
    1667             : 
    1668             :         VPX_SS_DEFAULT_LAYERS,  // ss_number_layers
    1669             :         { 0 },
    1670             :         { 0 },  // ss_target_bitrate
    1671             :         1,      // ts_number_layers
    1672             :         { 0 },  // ts_target_bitrate
    1673             :         { 0 },  // ts_rate_decimator
    1674             :         0,      // ts_periodicity
    1675             :         { 0 },  // ts_layer_id
    1676             :         { 0 },  // layer_taget_bitrate
    1677             :         0       // temporal_layering_mode
    1678             :     } },
    1679             : };
    1680             : 
    1681             : #ifndef VERSION_STRING
    1682             : #define VERSION_STRING
    1683             : #endif
    1684           0 : CODEC_INTERFACE(vpx_codec_vp9_cx) = {
    1685             :   "WebM Project VP9 Encoder" VERSION_STRING,
    1686             :   VPX_CODEC_INTERNAL_ABI_VERSION,
    1687             : #if CONFIG_VP9_HIGHBITDEPTH
    1688             :   VPX_CODEC_CAP_HIGHBITDEPTH |
    1689             : #endif
    1690             :       VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,  // vpx_codec_caps_t
    1691             :   encoder_init,                                    // vpx_codec_init_fn_t
    1692             :   encoder_destroy,                                 // vpx_codec_destroy_fn_t
    1693             :   encoder_ctrl_maps,                               // vpx_codec_ctrl_fn_map_t
    1694             :   {
    1695             :       // NOLINT
    1696             :       NULL,  // vpx_codec_peek_si_fn_t
    1697             :       NULL,  // vpx_codec_get_si_fn_t
    1698             :       NULL,  // vpx_codec_decode_fn_t
    1699             :       NULL,  // vpx_codec_frame_get_fn_t
    1700             :       NULL   // vpx_codec_set_fb_fn_t
    1701             :   },
    1702             :   {
    1703             :       // NOLINT
    1704             :       1,                      // 1 cfg map
    1705             :       encoder_usage_cfg_map,  // vpx_codec_enc_cfg_map_t
    1706             :       encoder_encode,         // vpx_codec_encode_fn_t
    1707             :       encoder_get_cxdata,     // vpx_codec_get_cx_data_fn_t
    1708             :       encoder_set_config,     // vpx_codec_enc_config_set_fn_t
    1709             :       NULL,                   // vpx_codec_get_global_headers_fn_t
    1710             :       encoder_get_preview,    // vpx_codec_get_preview_frame_fn_t
    1711             :       NULL                    // vpx_codec_enc_mr_get_mem_loc_fn_t
    1712             :   }
    1713             : };

Generated by: LCOV version 1.13