av1_cx_iface.c 49.2 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11 12 13 14
 */

#include <stdlib.h>
#include <string.h>

Adrian Grange's avatar
Adrian Grange committed
15 16 17 18 19
#include "./aom_config.h"
#include "aom/aom_encoder.h"
#include "aom_ports/aom_once.h"
#include "aom/internal/aom_codec_internal.h"
#include "./aom_version.h"
Yaowu Xu's avatar
Yaowu Xu committed
20
#include "av1/encoder/encoder.h"
Adrian Grange's avatar
Adrian Grange committed
21
#include "aom/aomcx.h"
Yaowu Xu's avatar
Yaowu Xu committed
22
#include "av1/encoder/firstpass.h"
Yaowu Xu's avatar
Yaowu Xu committed
23
#include "av1/av1_iface_common.h"
Jingning Han's avatar
Jingning Han committed
24

25
struct av1_extracfg {
clang-format's avatar
clang-format committed
26 27 28 29 30 31 32 33 34 35 36
  int cpu_used;  // available cpu percentage in 1/16
  unsigned int enable_auto_alt_ref;
  unsigned int noise_sensitivity;
  unsigned int sharpness;
  unsigned int static_thresh;
  unsigned int tile_columns;
  unsigned int tile_rows;
  unsigned int arnr_max_frames;
  unsigned int arnr_strength;
  unsigned int min_gf_interval;
  unsigned int max_gf_interval;
Adrian Grange's avatar
Adrian Grange committed
37
  aom_tune_metric tuning;
clang-format's avatar
clang-format committed
38 39 40 41 42
  unsigned int cq_level;  // constrained quality level
  unsigned int rc_max_intra_bitrate_pct;
  unsigned int rc_max_inter_bitrate_pct;
  unsigned int gf_cbr_boost_pct;
  unsigned int lossless;
43 44
#if CONFIG_AOM_QM
  unsigned int enable_qm;
45 46
  unsigned int qm_min;
  unsigned int qm_max;
47
#endif
clang-format's avatar
clang-format committed
48 49 50
  unsigned int frame_parallel_decoding_mode;
  AQ_MODE aq_mode;
  unsigned int frame_periodic_boost;
Adrian Grange's avatar
Adrian Grange committed
51 52 53
  aom_bit_depth_t bit_depth;
  aom_tune_content content;
  aom_color_space_t color_space;
clang-format's avatar
clang-format committed
54 55 56
  int color_range;
  int render_width;
  int render_height;
Jingning Han's avatar
Jingning Han committed
57 58
};

59
static struct av1_extracfg default_extra_cfg = {
60 61 62 63 64 65 66 67 68 69 70
  0,              // cpu_used
  1,              // enable_auto_alt_ref
  0,              // noise_sensitivity
  0,              // sharpness
  0,              // static_thresh
  6,              // tile_columns
  0,              // tile_rows
  7,              // arnr_max_frames
  5,              // arnr_strength
  0,              // min_gf_interval; 0 -> default decision
  0,              // max_gf_interval; 0 -> default decision
Adrian Grange's avatar
Adrian Grange committed
71
  AOM_TUNE_PSNR,  // tuning
72 73 74 75 76
  10,             // cq_level
  0,              // rc_max_intra_bitrate_pct
  0,              // rc_max_inter_bitrate_pct
  0,              // gf_cbr_boost_pct
  0,              // lossless
77
#if CONFIG_AOM_QM
78 79 80
  0,                 // enable_qm
  DEFAULT_QM_FIRST,  // qm_min
  DEFAULT_QM_LAST,   // qm_max
81
#endif
clang-format's avatar
clang-format committed
82 83 84
  1,                    // frame_parallel_decoding_mode
  NO_AQ,                // aq_mode
  0,                    // frame_periodic_delta_q
Adrian Grange's avatar
Adrian Grange committed
85 86 87
  AOM_BITS_8,           // Bit depth
  AOM_CONTENT_DEFAULT,  // content
  AOM_CS_UNKNOWN,       // color space
clang-format's avatar
clang-format committed
88 89 90
  0,                    // color range
  0,                    // render width
  0,                    // render height
Jingning Han's avatar
Jingning Han committed
91 92
};

Adrian Grange's avatar
Adrian Grange committed
93 94 95
struct aom_codec_alg_priv {
  aom_codec_priv_t base;
  aom_codec_enc_cfg_t cfg;
96 97 98
  struct av1_extracfg extra_cfg;
  AV1EncoderConfig oxcf;
  AV1_COMP *cpi;
clang-format's avatar
clang-format committed
99 100 101 102 103 104
  unsigned char *cx_data;
  size_t cx_data_sz;
  unsigned char *pending_cx_data;
  size_t pending_cx_data_sz;
  int pending_frame_count;
  size_t pending_frame_sizes[8];
105
#if !CONFIG_MISC_FIXES
clang-format's avatar
clang-format committed
106
  size_t pending_frame_magnitude;
107
#endif
Adrian Grange's avatar
Adrian Grange committed
108 109
  aom_image_t preview_img;
  aom_enc_frame_flags_t next_frame_flags;
Adrian Grange's avatar
Adrian Grange committed
110
  aom_postproc_cfg_t preview_ppcfg;
Adrian Grange's avatar
Adrian Grange committed
111
  aom_codec_pkt_list_decl(256) pkt_list;
clang-format's avatar
clang-format committed
112
  unsigned int fixed_kf_cntr;
Adrian Grange's avatar
Adrian Grange committed
113
  aom_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb;
Jingning Han's avatar
Jingning Han committed
114
  // BufferPool that holds all reference frames.
clang-format's avatar
clang-format committed
115
  BufferPool *buffer_pool;
Jingning Han's avatar
Jingning Han committed
116 117
};

Adrian Grange's avatar
Adrian Grange committed
118
static AOM_REFFRAME ref_frame_to_av1_reframe(aom_ref_frame_type_t frame) {
Jingning Han's avatar
Jingning Han committed
119
  switch (frame) {
Adrian Grange's avatar
Adrian Grange committed
120 121 122
    case AOM_LAST_FRAME: return AOM_LAST_FLAG;
    case AOM_GOLD_FRAME: return AOM_GOLD_FLAG;
    case AOM_ALTR_FRAME: return AOM_ALT_FLAG;
Jingning Han's avatar
Jingning Han committed
123 124
  }
  assert(0 && "Invalid Reference Frame");
Adrian Grange's avatar
Adrian Grange committed
125
  return AOM_LAST_FLAG;
Jingning Han's avatar
Jingning Han committed
126 127
}

Adrian Grange's avatar
Adrian Grange committed
128 129 130
static aom_codec_err_t update_error_state(
    aom_codec_alg_priv_t *ctx, const struct aom_internal_error_info *error) {
  const aom_codec_err_t res = error->error_code;
Jingning Han's avatar
Jingning Han committed
131

Adrian Grange's avatar
Adrian Grange committed
132
  if (res != AOM_CODEC_OK)
Jingning Han's avatar
Jingning Han committed
133 134 135 136 137 138
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;

  return res;
}

#undef ERROR
clang-format's avatar
clang-format committed
139 140 141
#define ERROR(str)                  \
  do {                              \
    ctx->base.err_detail = str;     \
Adrian Grange's avatar
Adrian Grange committed
142
    return AOM_CODEC_INVALID_PARAM; \
Jingning Han's avatar
Jingning Han committed
143 144
  } while (0)

clang-format's avatar
clang-format committed
145 146
#define RANGE_CHECK(p, memb, lo, hi)                                 \
  do {                                                               \
Jingning Han's avatar
Jingning Han committed
147
    if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
clang-format's avatar
clang-format committed
148
      ERROR(#memb " out of range [" #lo ".." #hi "]");               \
Jingning Han's avatar
Jingning Han committed
149 150
  } while (0)

clang-format's avatar
clang-format committed
151 152 153
#define RANGE_CHECK_HI(p, memb, hi)                                     \
  do {                                                                  \
    if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \
Jingning Han's avatar
Jingning Han committed
154 155
  } while (0)

clang-format's avatar
clang-format committed
156 157 158
#define RANGE_CHECK_LO(p, memb, lo)                                     \
  do {                                                                  \
    if (!((p)->memb >= (lo))) ERROR(#memb " out of range [" #lo "..]"); \
Jingning Han's avatar
Jingning Han committed
159 160
  } while (0)

clang-format's avatar
clang-format committed
161 162 163
#define RANGE_CHECK_BOOL(p, memb)                                     \
  do {                                                                \
    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
Jingning Han's avatar
Jingning Han committed
164 165
  } while (0)

Adrian Grange's avatar
Adrian Grange committed
166 167
static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
                                       const aom_codec_enc_cfg_t *cfg,
168
                                       const struct av1_extracfg *extra_cfg) {
clang-format's avatar
clang-format committed
169 170 171 172 173 174 175 176
  RANGE_CHECK(cfg, g_w, 1, 65535);  // 16 bits available
  RANGE_CHECK(cfg, g_h, 1, 65535);  // 16 bits available
  RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
  RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
  RANGE_CHECK_HI(cfg, g_profile, 3);

  RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
  RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
Jingning Han's avatar
Jingning Han committed
177
  RANGE_CHECK_BOOL(extra_cfg, lossless);
clang-format's avatar
clang-format committed
178
  RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1);
Jingning Han's avatar
Jingning Han committed
179
  RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
clang-format's avatar
clang-format committed
180 181
  RANGE_CHECK_HI(cfg, g_threads, 64);
  RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
Adrian Grange's avatar
Adrian Grange committed
182
  RANGE_CHECK(cfg, rc_end_usage, AOM_VBR, AOM_Q);
clang-format's avatar
clang-format committed
183 184
  RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
  RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
Jingning Han's avatar
Jingning Han committed
185
  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
Adrian Grange's avatar
Adrian Grange committed
186
  RANGE_CHECK(cfg, kf_mode, AOM_KF_DISABLED, AOM_KF_AUTO);
clang-format's avatar
clang-format committed
187 188 189
  RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
  RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
  RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
Jingning Han's avatar
Jingning Han committed
190
  RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
Adrian Grange's avatar
Adrian Grange committed
191
  RANGE_CHECK(cfg, g_pass, AOM_RC_ONE_PASS, AOM_RC_LAST_PASS);
Jingning Han's avatar
Jingning Han committed
192 193 194 195 196 197 198
  RANGE_CHECK(extra_cfg, min_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
  RANGE_CHECK(extra_cfg, max_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
  if (extra_cfg->max_gf_interval > 0) {
    RANGE_CHECK(extra_cfg, max_gf_interval, 2, (MAX_LAG_BUFFERS - 1));
  }
  if (extra_cfg->min_gf_interval > 0 && extra_cfg->max_gf_interval > 0) {
    RANGE_CHECK(extra_cfg, max_gf_interval, extra_cfg->min_gf_interval,
clang-format's avatar
clang-format committed
199
                (MAX_LAG_BUFFERS - 1));
Jingning Han's avatar
Jingning Han committed
200 201 202 203 204 205 206
  }

  if (cfg->rc_resize_allowed == 1) {
    RANGE_CHECK(cfg, rc_scaled_width, 0, cfg->g_w);
    RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
  }

207
  // Spatial/temporal scalability are not yet supported in AV1.
Yunqing Wang's avatar
Yunqing Wang committed
208 209 210
  // Only accept the default value for range checking.
  RANGE_CHECK(cfg, ss_number_layers, 1, 1);
  RANGE_CHECK(cfg, ts_number_layers, 1, 1);
211
  // AV1 does not support a lower bound on the keyframe interval in
Jingning Han's avatar
Jingning Han committed
212
  // automatic keyframe placement mode.
Adrian Grange's avatar
Adrian Grange committed
213
  if (cfg->kf_mode != AOM_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
Jingning Han's avatar
Jingning Han committed
214
      cfg->kf_min_dist > 0)
clang-format's avatar
clang-format committed
215 216 217
    ERROR(
        "kf_min_dist not supported in auto mode, use 0 "
        "or kf_max_dist instead.");
Jingning Han's avatar
Jingning Han committed
218 219 220 221 222 223 224 225 226 227

  RANGE_CHECK(extra_cfg, enable_auto_alt_ref, 0, 2);
  RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
  RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
  RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
  RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
  RANGE_CHECK_HI(extra_cfg, sharpness, 7);
  RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
  RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
  RANGE_CHECK(extra_cfg, cq_level, 0, 63);
Adrian Grange's avatar
Adrian Grange committed
228
  RANGE_CHECK(cfg, g_bit_depth, AOM_BITS_8, AOM_BITS_12);
Jingning Han's avatar
Jingning Han committed
229
  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
Adrian Grange's avatar
Adrian Grange committed
230
  RANGE_CHECK(extra_cfg, content, AOM_CONTENT_DEFAULT, AOM_CONTENT_INVALID - 1);
Jingning Han's avatar
Jingning Han committed
231

232
  // TODO(yaowu): remove this when ssim tuning is implemented for av1
Adrian Grange's avatar
Adrian Grange committed
233
  if (extra_cfg->tuning == AOM_TUNE_SSIM)
234
    ERROR("Option --tune=ssim is not currently supported in AV1.");
Jingning Han's avatar
Jingning Han committed
235

Adrian Grange's avatar
Adrian Grange committed
236
  if (cfg->g_pass == AOM_RC_LAST_PASS) {
Jingning Han's avatar
Jingning Han committed
237 238 239 240 241 242 243 244 245 246
    const size_t packet_sz = sizeof(FIRSTPASS_STATS);
    const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
    const FIRSTPASS_STATS *stats;

    if (cfg->rc_twopass_stats_in.buf == NULL)
      ERROR("rc_twopass_stats_in.buf not set.");

    if (cfg->rc_twopass_stats_in.sz % packet_sz)
      ERROR("rc_twopass_stats_in.sz indicates truncated packet.");

Yunqing Wang's avatar
Yunqing Wang committed
247 248
    if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
      ERROR("rc_twopass_stats_in requires at least two packets.");
Jingning Han's avatar
Jingning Han committed
249

Yunqing Wang's avatar
Yunqing Wang committed
250 251
    stats =
        (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
Jingning Han's avatar
Jingning Han committed
252

Yunqing Wang's avatar
Yunqing Wang committed
253 254
    if ((int)(stats->count + 0.5) != n_packets - 1)
      ERROR("rc_twopass_stats_in missing EOS stats packet");
Jingning Han's avatar
Jingning Han committed
255 256
  }

257
#if !CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
258 259 260 261 262
  if (cfg->g_profile > (unsigned int)PROFILE_1) {
    ERROR("Profile > 1 not supported in this build configuration");
  }
#endif
  if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
Adrian Grange's avatar
Adrian Grange committed
263
      cfg->g_bit_depth > AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
264 265
    ERROR("Codec high bit-depth not supported in profile < 2");
  }
clang-format's avatar
clang-format committed
266
  if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
Jingning Han's avatar
Jingning Han committed
267 268 269
    ERROR("Source high bit-depth not supported in profile < 2");
  }
  if (cfg->g_profile > (unsigned int)PROFILE_1 &&
Adrian Grange's avatar
Adrian Grange committed
270
      cfg->g_bit_depth == AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
271 272
    ERROR("Codec bit-depth 8 not supported in profile > 1");
  }
Adrian Grange's avatar
Adrian Grange committed
273
  RANGE_CHECK(extra_cfg, color_space, AOM_CS_UNKNOWN, AOM_CS_SRGB);
274
  RANGE_CHECK(extra_cfg, color_range, 0, 1);
Adrian Grange's avatar
Adrian Grange committed
275
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
276 277
}

Adrian Grange's avatar
Adrian Grange committed
278 279
static aom_codec_err_t validate_img(aom_codec_alg_priv_t *ctx,
                                    const aom_image_t *img) {
Jingning Han's avatar
Jingning Han committed
280
  switch (img->fmt) {
Adrian Grange's avatar
Adrian Grange committed
281 282 283 284 285 286
    case AOM_IMG_FMT_YV12:
    case AOM_IMG_FMT_I420:
    case AOM_IMG_FMT_I42016: break;
    case AOM_IMG_FMT_I422:
    case AOM_IMG_FMT_I444:
    case AOM_IMG_FMT_I440:
Jingning Han's avatar
Jingning Han committed
287
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
clang-format's avatar
clang-format committed
288 289 290
        ERROR(
            "Invalid image format. I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
291 292
      }
      break;
Adrian Grange's avatar
Adrian Grange committed
293 294 295
    case AOM_IMG_FMT_I42216:
    case AOM_IMG_FMT_I44416:
    case AOM_IMG_FMT_I44016:
Jingning Han's avatar
Jingning Han committed
296 297
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
          ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
clang-format's avatar
clang-format committed
298 299 300
        ERROR(
            "Invalid image format. 16-bit I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
301 302 303
      }
      break;
    default:
clang-format's avatar
clang-format committed
304 305 306
      ERROR(
          "Invalid image format. Only YV12, I420, I422, I444 images are "
          "supported.");
Jingning Han's avatar
Jingning Han committed
307 308 309 310 311 312
      break;
  }

  if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
    ERROR("Image size must match encoder init configuration size");

Adrian Grange's avatar
Adrian Grange committed
313
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
314 315
}

Adrian Grange's avatar
Adrian Grange committed
316
static int get_image_bps(const aom_image_t *img) {
Jingning Han's avatar
Jingning Han committed
317
  switch (img->fmt) {
Adrian Grange's avatar
Adrian Grange committed
318 319 320 321 322 323 324 325 326
    case AOM_IMG_FMT_YV12:
    case AOM_IMG_FMT_I420: return 12;
    case AOM_IMG_FMT_I422: return 16;
    case AOM_IMG_FMT_I444: return 24;
    case AOM_IMG_FMT_I440: return 16;
    case AOM_IMG_FMT_I42016: return 24;
    case AOM_IMG_FMT_I42216: return 32;
    case AOM_IMG_FMT_I44416: return 48;
    case AOM_IMG_FMT_I44016: return 32;
Jingning Han's avatar
Jingning Han committed
327 328 329 330 331
    default: assert(0 && "Invalid image format"); break;
  }
  return 0;
}

Adrian Grange's avatar
Adrian Grange committed
332
static aom_codec_err_t set_encoder_config(
333 334
    AV1EncoderConfig *oxcf, const aom_codec_enc_cfg_t *cfg,
    const struct av1_extracfg *extra_cfg) {
Adrian Grange's avatar
Adrian Grange committed
335
  const int is_vbr = cfg->rc_end_usage == AOM_VBR;
Jingning Han's avatar
Jingning Han committed
336 337
  oxcf->profile = cfg->g_profile;
  oxcf->max_threads = (int)cfg->g_threads;
clang-format's avatar
clang-format committed
338 339
  oxcf->width = cfg->g_w;
  oxcf->height = cfg->g_h;
Jingning Han's avatar
Jingning Han committed
340 341 342 343
  oxcf->bit_depth = cfg->g_bit_depth;
  oxcf->input_bit_depth = cfg->g_input_bit_depth;
  // guess a frame rate if out of whack, use 30
  oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
clang-format's avatar
clang-format committed
344
  if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
Jingning Han's avatar
Jingning Han committed
345 346 347 348

  oxcf->mode = GOOD;

  switch (cfg->g_pass) {
Adrian Grange's avatar
Adrian Grange committed
349 350 351
    case AOM_RC_ONE_PASS: oxcf->pass = 0; break;
    case AOM_RC_FIRST_PASS: oxcf->pass = 1; break;
    case AOM_RC_LAST_PASS: oxcf->pass = 2; break;
Jingning Han's avatar
Jingning Han committed
352 353
  }

clang-format's avatar
clang-format committed
354
  oxcf->lag_in_frames =
Adrian Grange's avatar
Adrian Grange committed
355
      cfg->g_pass == AOM_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
Jingning Han's avatar
Jingning Han committed
356 357 358 359 360 361 362 363 364
  oxcf->rc_mode = cfg->rc_end_usage;

  // Convert target bandwidth from Kbit/s to Bit/s
  oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
  oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
  oxcf->rc_max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct;
  oxcf->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct;

  oxcf->best_allowed_q =
365
      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_min_quantizer);
Jingning Han's avatar
Jingning Han committed
366
  oxcf->worst_allowed_q =
367 368
      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_max_quantizer);
  oxcf->cq_level = av1_quantizer_to_qindex(extra_cfg->cq_level);
Jingning Han's avatar
Jingning Han committed
369 370
  oxcf->fixed_q = -1;

371 372
#if CONFIG_AOM_QM
  oxcf->using_qm = extra_cfg->enable_qm;
373 374
  oxcf->qm_minlevel = extra_cfg->qm_min;
  oxcf->qm_maxlevel = extra_cfg->qm_max;
375 376
#endif

clang-format's avatar
clang-format committed
377 378
  oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
  oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
Jingning Han's avatar
Jingning Han committed
379

clang-format's avatar
clang-format committed
380
  oxcf->scaled_frame_width = cfg->rc_scaled_width;
Jingning Han's avatar
Jingning Han committed
381 382 383
  oxcf->scaled_frame_height = cfg->rc_scaled_height;
  if (cfg->rc_resize_allowed == 1) {
    oxcf->resize_mode =
clang-format's avatar
clang-format committed
384 385 386
        (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
            ? RESIZE_DYNAMIC
            : RESIZE_FIXED;
Jingning Han's avatar
Jingning Han committed
387 388 389 390
  } else {
    oxcf->resize_mode = RESIZE_NONE;
  }

clang-format's avatar
clang-format committed
391
  oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
Jingning Han's avatar
Jingning Han committed
392
  oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
clang-format's avatar
clang-format committed
393
  oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
Jingning Han's avatar
Jingning Han committed
394

clang-format's avatar
clang-format committed
395
  oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
Jingning Han's avatar
Jingning Han committed
396

clang-format's avatar
clang-format committed
397 398 399
  oxcf->two_pass_vbrbias = cfg->rc_2pass_vbr_bias_pct;
  oxcf->two_pass_vbrmin_section = cfg->rc_2pass_vbr_minsection_pct;
  oxcf->two_pass_vbrmax_section = cfg->rc_2pass_vbr_maxsection_pct;
Jingning Han's avatar
Jingning Han committed
400

clang-format's avatar
clang-format committed
401
  oxcf->auto_key =
Adrian Grange's avatar
Adrian Grange committed
402
      cfg->kf_mode == AOM_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
403

clang-format's avatar
clang-format committed
404
  oxcf->key_freq = cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
405

clang-format's avatar
clang-format committed
406 407 408 409 410
  oxcf->speed = abs(extra_cfg->cpu_used);
  oxcf->encode_breakout = extra_cfg->static_thresh;
  oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
  oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
  oxcf->sharpness = extra_cfg->sharpness;
Jingning Han's avatar
Jingning Han committed
411

clang-format's avatar
clang-format committed
412
  oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
Jingning Han's avatar
Jingning Han committed
413 414

#if CONFIG_FP_MB_STATS
clang-format's avatar
clang-format committed
415
  oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
Jingning Han's avatar
Jingning Han committed
416 417 418
#endif

  oxcf->color_space = extra_cfg->color_space;
419
  oxcf->color_range = extra_cfg->color_range;
clang-format's avatar
clang-format committed
420
  oxcf->render_width = extra_cfg->render_width;
421
  oxcf->render_height = extra_cfg->render_height;
Jingning Han's avatar
Jingning Han committed
422
  oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
clang-format's avatar
clang-format committed
423
  oxcf->arnr_strength = extra_cfg->arnr_strength;
Jingning Han's avatar
Jingning Han committed
424 425 426 427 428 429 430
  oxcf->min_gf_interval = extra_cfg->min_gf_interval;
  oxcf->max_gf_interval = extra_cfg->max_gf_interval;

  oxcf->tuning = extra_cfg->tuning;
  oxcf->content = extra_cfg->content;

  oxcf->tile_columns = extra_cfg->tile_columns;
clang-format's avatar
clang-format committed
431
  oxcf->tile_rows = extra_cfg->tile_rows;
Jingning Han's avatar
Jingning Han committed
432

clang-format's avatar
clang-format committed
433
  oxcf->error_resilient_mode = cfg->g_error_resilient;
Jingning Han's avatar
Jingning Han committed
434 435 436 437
  oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;

  oxcf->aq_mode = extra_cfg->aq_mode;

clang-format's avatar
clang-format committed
438
  oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
Jingning Han's avatar
Jingning Han committed
439 440

  /*
441
  printf("Current AV1 Settings: \n");
Jingning Han's avatar
Jingning Han committed
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
  printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
  printf("sharpness: %d\n",    oxcf->sharpness);
  printf("cpu_used: %d\n",  oxcf->cpu_used);
  printf("Mode: %d\n",     oxcf->mode);
  printf("auto_key: %d\n",  oxcf->auto_key);
  printf("key_freq: %d\n", oxcf->key_freq);
  printf("end_usage: %d\n", oxcf->end_usage);
  printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
  printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
  printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
  printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
  printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
  printf("fixed_q: %d\n",  oxcf->fixed_q);
  printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
  printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
  printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
  printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
  printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
  printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
  printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
  printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
  printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
  printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
  printf("Version: %d\n", oxcf->Version);
  printf("encode_breakout: %d\n", oxcf->encode_breakout);
  printf("error resilient: %d\n", oxcf->error_resilient_mode);
  printf("frame parallel detokenization: %d\n",
         oxcf->frame_parallel_decoding_mode);
  */
Adrian Grange's avatar
Adrian Grange committed
472
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
473 474
}

Adrian Grange's avatar
Adrian Grange committed
475 476 477
static aom_codec_err_t encoder_set_config(aom_codec_alg_priv_t *ctx,
                                          const aom_codec_enc_cfg_t *cfg) {
  aom_codec_err_t res;
Jingning Han's avatar
Jingning Han committed
478 479 480
  int force_key = 0;

  if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
Adrian Grange's avatar
Adrian Grange committed
481
    if (cfg->g_lag_in_frames > 1 || cfg->g_pass != AOM_RC_ONE_PASS)
Jingning Han's avatar
Jingning Han committed
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
      ERROR("Cannot change width or height after initialization");
    if (!valid_ref_frame_size(ctx->cfg.g_w, ctx->cfg.g_h, cfg->g_w, cfg->g_h) ||
        (ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
        (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
      force_key = 1;
  }

  // Prevent increasing lag_in_frames. This check is stricter than it needs
  // to be -- the limit is not increasing past the first lag_in_frames
  // value, but we don't track the initial config, only the last successful
  // config.
  if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
    ERROR("Cannot increase lag_in_frames");

  res = validate_config(ctx, cfg, &ctx->extra_cfg);

Adrian Grange's avatar
Adrian Grange committed
498
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
499 500 501 502
    ctx->cfg = *cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
    // On profile change, request a key frame
    force_key |= ctx->cpi->common.profile != ctx->oxcf.profile;
503
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
504 505
  }

Adrian Grange's avatar
Adrian Grange committed
506
  if (force_key) ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
Jingning Han's avatar
Jingning Han committed
507 508 509 510

  return res;
}

Adrian Grange's avatar
Adrian Grange committed
511
static aom_codec_err_t ctrl_get_quantizer(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
512 513
                                          va_list args) {
  int *const arg = va_arg(args, int *);
Adrian Grange's avatar
Adrian Grange committed
514
  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
515
  *arg = av1_get_quantizer(ctx->cpi);
Adrian Grange's avatar
Adrian Grange committed
516
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
517 518
}

Adrian Grange's avatar
Adrian Grange committed
519
static aom_codec_err_t ctrl_get_quantizer64(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
520 521
                                            va_list args) {
  int *const arg = va_arg(args, int *);
Adrian Grange's avatar
Adrian Grange committed
522
  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
523
  *arg = av1_qindex_to_quantizer(av1_get_quantizer(ctx->cpi));
Adrian Grange's avatar
Adrian Grange committed
524
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
525 526
}

Adrian Grange's avatar
Adrian Grange committed
527
static aom_codec_err_t update_extra_cfg(aom_codec_alg_priv_t *ctx,
528
                                        const struct av1_extracfg *extra_cfg) {
Adrian Grange's avatar
Adrian Grange committed
529
  const aom_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
Adrian Grange's avatar
Adrian Grange committed
530
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
531 532
    ctx->extra_cfg = *extra_cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
533
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
534 535 536 537
  }
  return res;
}

Adrian Grange's avatar
Adrian Grange committed
538
static aom_codec_err_t ctrl_set_cpuused(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
539
                                        va_list args) {
540
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
541
  extra_cfg.cpu_used = CAST(AOME_SET_CPUUSED, args);
Jingning Han's avatar
Jingning Han committed
542 543 544
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
545
static aom_codec_err_t ctrl_set_enable_auto_alt_ref(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
546
                                                    va_list args) {
547
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
548
  extra_cfg.enable_auto_alt_ref = CAST(AOME_SET_ENABLEAUTOALTREF, args);
Jingning Han's avatar
Jingning Han committed
549 550 551
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
552
static aom_codec_err_t ctrl_set_noise_sensitivity(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
553
                                                  va_list args) {
554
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
555
  extra_cfg.noise_sensitivity = CAST(AV1E_SET_NOISE_SENSITIVITY, args);
Jingning Han's avatar
Jingning Han committed
556 557 558
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
559
static aom_codec_err_t ctrl_set_sharpness(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
560
                                          va_list args) {
561
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
562
  extra_cfg.sharpness = CAST(AOME_SET_SHARPNESS, args);
Jingning Han's avatar
Jingning Han committed
563 564 565
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
566
static aom_codec_err_t ctrl_set_static_thresh(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
567
                                              va_list args) {
568
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
569
  extra_cfg.static_thresh = CAST(AOME_SET_STATIC_THRESHOLD, args);
Jingning Han's avatar
Jingning Han committed
570 571 572
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
573
static aom_codec_err_t ctrl_set_tile_columns(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
574
                                             va_list args) {
575
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
576
  extra_cfg.tile_columns = CAST(AV1E_SET_TILE_COLUMNS, args);
Jingning Han's avatar
Jingning Han committed
577 578 579
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
580
static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
581
                                          va_list args) {
582
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
583
  extra_cfg.tile_rows = CAST(AV1E_SET_TILE_ROWS, args);
Jingning Han's avatar
Jingning Han committed
584 585 586
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
587
static aom_codec_err_t ctrl_set_arnr_max_frames(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
588
                                                va_list args) {
589
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
590
  extra_cfg.arnr_max_frames = CAST(AOME_SET_ARNR_MAXFRAMES, args);
Jingning Han's avatar
Jingning Han committed
591 592 593
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
594
static aom_codec_err_t ctrl_set_arnr_strength(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
595
                                              va_list args) {
596
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
597
  extra_cfg.arnr_strength = CAST(AOME_SET_ARNR_STRENGTH, args);
Jingning Han's avatar
Jingning Han committed
598 599 600
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
601
static aom_codec_err_t ctrl_set_arnr_type(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
602 603 604
                                          va_list args) {
  (void)ctx;
  (void)args;
Adrian Grange's avatar
Adrian Grange committed
605
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
606 607
}

Adrian Grange's avatar
Adrian Grange committed
608
static aom_codec_err_t ctrl_set_tuning(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
609
                                       va_list args) {
610
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
611
  extra_cfg.tuning = CAST(AOME_SET_TUNING, args);
Jingning Han's avatar
Jingning Han committed
612 613 614
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
615
static aom_codec_err_t ctrl_set_cq_level(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
616
                                         va_list args) {
617
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
618
  extra_cfg.cq_level = CAST(AOME_SET_CQ_LEVEL, args);
Jingning Han's avatar
Jingning Han committed
619 620 621
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
622 623
static aom_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
    aom_codec_alg_priv_t *ctx, va_list args) {
624
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Jingning Han's avatar
Jingning Han committed
625
  extra_cfg.rc_max_intra_bitrate_pct =
Adrian Grange's avatar
Adrian Grange committed
626
      CAST(AOME_SET_MAX_INTRA_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
627 628 629
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
630 631
static aom_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
    aom_codec_alg_priv_t *ctx, va_list args) {
632
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Jingning Han's avatar
Jingning Han committed
633
  extra_cfg.rc_max_inter_bitrate_pct =
Adrian Grange's avatar
Adrian Grange committed
634
      CAST(AOME_SET_MAX_INTER_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
635 636 637
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
638
static aom_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(aom_codec_alg_priv_t *ctx,
clang-format's avatar
clang-format committed
639
                                                    va_list args) {
640
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
641
  extra_cfg.gf_cbr_boost_pct = CAST(AV1E_SET_GF_CBR_BOOST_PCT, args);
Jingning Han's avatar
Jingning Han committed
642 643 644
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
645
static aom_codec_err_t ctrl_set_lossless(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
646
                                         va_list args) {
647
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
648
  extra_cfg.lossless = CAST(AV1E_SET_LOSSLESS, args);
Jingning Han's avatar
Jingning Han committed
649 650 651
  return update_extra_cfg(ctx, &extra_cfg);
}

652
#if CONFIG_AOM_QM
Adrian Grange's avatar
Adrian Grange committed
653
static aom_codec_err_t ctrl_set_enable_qm(aom_codec_alg_priv_t *ctx,
654
                                         va_list args) {
655
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
656
  extra_cfg.enable_qm = CAST(AV1E_SET_ENABLE_QM, args);
657 658
  return update_extra_cfg(ctx, &extra_cfg);
}
659

Adrian Grange's avatar
Adrian Grange committed
660
static aom_codec_err_t ctrl_set_qm_min(aom_codec_alg_priv_t *ctx,
661
                                       va_list args) {
662
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
663
  extra_cfg.qm_min = CAST(AV1E_SET_QM_MIN, args);
664 665 666
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
667
static aom_codec_err_t ctrl_set_qm_max(aom_codec_alg_priv_t *ctx,
668
                                       va_list args) {
669
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
670
  extra_cfg.qm_max = CAST(AV1E_SET_QM_MAX, args);
671 672
  return update_extra_cfg(ctx, &extra_cfg);
}
673 674
#endif

Adrian Grange's avatar
Adrian Grange committed
675 676
static aom_codec_err_t ctrl_set_frame_parallel_decoding_mode(
    aom_codec_alg_priv_t *ctx, va_list args) {
677
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Jingning Han's avatar
Jingning Han committed
678
  extra_cfg.frame_parallel_decoding_mode =
Adrian Grange's avatar
Adrian Grange committed
679
      CAST(AV1E_SET_FRAME_PARALLEL_DECODING, args);
Jingning Han's avatar
Jingning Han committed
680 681 682
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
683
static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
684
                                        va_list args) {
685
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
686
  extra_cfg.aq_mode = CAST(AV1E_SET_AQ_MODE, args);
Jingning Han's avatar
Jingning Han committed
687 688 689
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
690
static aom_codec_err_t ctrl_set_min_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
691
                                                va_list args) {
692
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
693
  extra_cfg.min_gf_interval = CAST(AV1E_SET_MIN_GF_INTERVAL, args);
Jingning Han's avatar
Jingning Han committed
694 695 696
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
697
static aom_codec_err_t ctrl_set_max_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
698
                                                va_list args) {
699
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
700
  extra_cfg.max_gf_interval = CAST(AV1E_SET_MAX_GF_INTERVAL, args);
Jingning Han's avatar
Jingning Han committed
701 702 703
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
704
static aom_codec_err_t ctrl_set_frame_periodic_boost(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
705
                                                     va_list args) {
706
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Adrian Grange's avatar
Adrian Grange committed
707
  extra_cfg.frame_periodic_boost = CAST(AV1E_SET_FRAME_PERIODIC_BOOST, args);
Jingning Han's avatar
Jingning Han committed
708 709 710
  return update_extra_cfg(ctx, &extra_cfg);
}

Adrian Grange's avatar
Adrian Grange committed
711 712
static aom_codec_err_t encoder_init(aom_codec_ctx_t *ctx,
                                    aom_codec_priv_enc_mr_cfg_t *data) {
Adrian Grange's avatar
Adrian Grange committed
713
  aom_codec_err_t res = AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
714 715 716
  (void)data;

  if (ctx->priv == NULL) {
Adrian Grange's avatar
Adrian Grange committed
717
    aom_codec_alg_priv_t *const priv = aom_calloc(1, sizeof(*priv));
Adrian Grange's avatar
Adrian Grange committed
718
    if (priv == NULL) return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
719

Adrian Grange's avatar
Adrian Grange committed
720
    ctx->priv = (aom_codec_priv_t *)priv;
Jingning Han's avatar
Jingning Han committed
721 722
    ctx->priv->init_flags = ctx->init_flags;
    ctx->priv->enc.total_encoders = 1;
Adrian Grange's avatar
Adrian Grange committed
723
    priv->buffer_pool = (BufferPool *)aom_calloc(1, sizeof(BufferPool));
Adrian Grange's avatar
Adrian Grange committed
724
    if (priv->buffer_pool == NULL) return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
725 726 727

#if CONFIG_MULTITHREAD
    if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
Adrian Grange's avatar
Adrian Grange committed
728
      return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
729 730 731 732 733 734 735 736 737 738
    }
#endif

    if (ctx->config.enc) {
      // Update the reference to the config structure to an internal copy.
      priv->cfg = *ctx->config.enc;
      ctx->config.enc = &priv->cfg;
    }

    priv->extra_cfg = default_extra_cfg;
739
    once(av1_initialize_enc);
Jingning Han's avatar
Jingning Han committed
740 741 742

    res = validate_config(priv, &priv->cfg, &priv->extra_cfg);

Adrian Grange's avatar
Adrian Grange committed
743
    if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
744
      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
745
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
746
      priv->oxcf.use_highbitdepth =
Adrian Grange's avatar
Adrian Grange committed
747
          (ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
Jingning Han's avatar
Jingning Han committed
748
#endif
749
      priv->cpi = av1_create_compressor(&priv->oxcf, priv->buffer_pool);
Jingning Han's avatar
Jingning Han committed
750
      if (priv->cpi == NULL)
Adrian Grange's avatar
Adrian Grange committed
751
        res = AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
752 753 754 755 756 757 758 759
      else
        priv->cpi->output_pkt_list = &priv->pkt_list.head;
    }
  }

  return res;
}

Adrian Grange's avatar
Adrian Grange committed
760
static aom_codec_err_t encoder_destroy(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
761
  free(ctx->cx_data);
762
  av1_remove_compressor(ctx->cpi);
Jingning Han's avatar
Jingning Han committed
763 764 765
#if CONFIG_MULTITHREAD
  pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
#endif
Adrian Grange's avatar
Adrian Grange committed
766 767
  aom_free(ctx->buffer_pool);
  aom_free(ctx);
Adrian Grange's avatar
Adrian Grange committed
768
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
769 770
}

Adrian Grange's avatar
Adrian Grange committed
771
static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
772 773 774 775 776
                                    unsigned long duration,
                                    unsigned long deadline) {
  MODE new_mode = BEST;

  switch (ctx->cfg.g_pass) {
Adrian Grange's avatar
Adrian Grange committed
777
    case AOM_RC_ONE_PASS:
Jingning Han's avatar
Jingning Han committed
778
      if (deadline > 0) {
Adrian Grange's avatar
Adrian Grange committed
779
        const aom_codec_enc_cfg_t *const cfg = &ctx->cfg;
Jingning Han's avatar
Jingning Han committed
780 781 782

        // Convert duration parameter from stream timebase to microseconds.
        const uint64_t duration_us = (uint64_t)duration * 1000000 *
clang-format's avatar
clang-format committed
783 784
                                     (uint64_t)cfg->g_timebase.num /
                                     (uint64_t)cfg->g_timebase.den;
Jingning Han's avatar
Jingning Han committed
785 786 787 788 789 790 791 792

        // If the deadline is more that the duration this frame is to be shown,
        // use good quality mode. Otherwise use realtime mode.
        new_mode = (deadline > duration_us) ? GOOD : REALTIME;
      } else {
        new_mode = BEST;
      }
      break;
Adrian Grange's avatar
Adrian Grange committed
793 794
    case AOM_RC_FIRST_PASS: break;
    case AOM_RC_LAST_PASS: new_mode = deadline > 0 ? GOOD : BEST; break;
Jingning Han's avatar
Jingning Han committed
795 796 797 798
  }

  if (ctx->oxcf.mode != new_mode) {
    ctx->oxcf.mode = new_mode;
799
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
800 801 802 803 804
  }
}

// Turn on to test if supplemental superframe data breaks decoding
// #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
Adrian Grange's avatar
Adrian Grange committed
805
static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
806 807 808
  uint8_t marker = 0xc0;
  unsigned int mask;
  int mag, index_sz;
809 810 811 812
#if CONFIG_MISC_FIXES
  int i;
  size_t max_frame_sz = 0;
#endif
Jingning Han's avatar
Jingning Han committed
813 814 815 816 817 818

  assert(ctx->pending_frame_count);
  assert(ctx->pending_frame_count <= 8);

  // Add the number of frames to the marker byte
  marker |= ctx->pending_frame_count - 1;
819 820
#if CONFIG_MISC_FIXES
  for (i = 0; i < ctx->pending_frame_count - 1; i++) {
clang-format's avatar
clang-format committed
821
    const size_t frame_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
822 823 824
    max_frame_sz = frame_sz > max_frame_sz ? frame_sz : max_frame_sz;
  }
#endif
Jingning Han's avatar
Jingning Han committed
825 826 827

  // Choose the magnitude
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
828
#if CONFIG_MISC_FIXES
clang-format's avatar
clang-format committed
829
    if (max_frame_sz <= mask) break;
830
#else
clang-format's avatar
clang-format committed
831
    if (ctx->pending_frame_magnitude < mask) break;
832
#endif
Jingning Han's avatar
Jingning Han committed
833 834 835 836 837 838
    mask <<= 8;
    mask |= 0xff;
  }
  marker |= mag << 3;

  // Write the index
839
  index_sz = 2 + (mag + 1) * (ctx->pending_frame_count - CONFIG_MISC_FIXES);
Jingning Han's avatar
Jingning Han committed
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856