av1_cx_iface.c 58 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
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>

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

Yaowu Xu's avatar
Yaowu Xu committed
26
struct av1_extracfg {
27 28
  int cpu_used;  // available cpu percentage in 1/16
  unsigned int enable_auto_alt_ref;
29
#if CONFIG_EXT_REFS
30
  unsigned int enable_auto_bwd_ref;
31
#endif  // CONFIG_EXT_REFS
32 33 34 35 36
  unsigned int noise_sensitivity;
  unsigned int sharpness;
  unsigned int static_thresh;
  unsigned int tile_columns;
  unsigned int tile_rows;
37 38 39
#if CONFIG_DEPENDENT_HORZTILES
  unsigned int dependent_horz_tiles;
#endif
40
#if CONFIG_LOOPFILTERING_ACROSS_TILES
41
  unsigned int loop_filter_across_tiles_enabled;
42
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
43 44 45 46
  unsigned int arnr_max_frames;
  unsigned int arnr_strength;
  unsigned int min_gf_interval;
  unsigned int max_gf_interval;
Yaowu Xu's avatar
Yaowu Xu committed
47
  aom_tune_metric tuning;
48 49 50 51 52
  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;
53 54 55 56
#if CONFIG_AOM_QM
  unsigned int enable_qm;
  unsigned int qm_min;
  unsigned int qm_max;
57 58 59 60
#endif
#if CONFIG_TILE_GROUPS
  unsigned int num_tg;
  unsigned int mtu_size;
61 62 63
#endif
#if CONFIG_TEMPMV_SIGNALING
  unsigned int disable_tempmv;
64
#endif
65 66
  unsigned int frame_parallel_decoding_mode;
  AQ_MODE aq_mode;
Fangwen Fu's avatar
Fangwen Fu committed
67 68 69
#if CONFIG_EXT_DELTA_Q
  DELTAQ_MODE deltaq_mode;
#endif
70
  unsigned int frame_periodic_boost;
Yaowu Xu's avatar
Yaowu Xu committed
71 72 73
  aom_bit_depth_t bit_depth;
  aom_tune_content content;
  aom_color_space_t color_space;
74 75 76 77
#if CONFIG_COLORSPACE_HEADERS
  aom_transfer_function_t transfer_function;
  aom_chroma_sample_position_t chroma_sample_position;
#endif
78 79 80
  int color_range;
  int render_width;
  int render_height;
Yaowu Xu's avatar
Yaowu Xu committed
81
  aom_superblock_size_t superblock_size;
82 83 84
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  int ans_window_size_log2;
#endif
85 86 87
#if CONFIG_EXT_TILE
  unsigned int tile_encoding_mode;
#endif  // CONFIG_EXT_TILE
Yunqing Wang's avatar
Yunqing Wang committed
88 89

  unsigned int motion_vector_unit_test;
Jingning Han's avatar
Jingning Han committed
90 91
};

Yaowu Xu's avatar
Yaowu Xu committed
92
static struct av1_extracfg default_extra_cfg = {
93 94
  0,  // cpu_used
  1,  // enable_auto_alt_ref
95
#if CONFIG_EXT_REFS
96
  0,    // enable_auto_bwd_ref
97
#endif  // CONFIG_EXT_REFS
98 99 100
  0,    // noise_sensitivity
  0,    // sharpness
  0,    // static_thresh
101
#if CONFIG_EXT_TILE
102 103
  UINT_MAX,  // tile_columns
  UINT_MAX,  // tile_rows
104
#else
105 106
  0,  // tile_columns
  0,  // tile_rows
107
#endif  // CONFIG_EXT_TILE
108
#if CONFIG_DEPENDENT_HORZTILES
109
  0,  // Dependent Horizontal tiles
110
#endif
111
#if CONFIG_LOOPFILTERING_ACROSS_TILES
112
  1,              // loop_filter_across_tiles_enabled
113
#endif            // CONFIG_LOOPFILTERING_ACROSS_TILES
114 115 116 117
  7,              // arnr_max_frames
  5,              // arnr_strength
  0,              // min_gf_interval; 0 -> default decision
  0,              // max_gf_interval; 0 -> default decision
Yaowu Xu's avatar
Yaowu Xu committed
118
  AOM_TUNE_PSNR,  // tuning
119 120 121 122 123 124 125 126 127
  10,             // cq_level
  0,              // rc_max_intra_bitrate_pct
  0,              // rc_max_inter_bitrate_pct
  0,              // gf_cbr_boost_pct
  0,              // lossless
#if CONFIG_AOM_QM
  0,                 // enable_qm
  DEFAULT_QM_FIRST,  // qm_min
  DEFAULT_QM_LAST,   // qm_max
128 129 130 131
#endif
#if CONFIG_TILE_GROUPS
  1,  // max number of tile groups
  0,  // mtu_size
132 133 134
#endif
#if CONFIG_TEMPMV_SIGNALING
  0,  // disable temporal mv prediction
135
#endif
Fangwen Fu's avatar
Fangwen Fu committed
136 137 138 139 140
  1,      // frame_parallel_decoding_mode
  NO_AQ,  // aq_mode
#if CONFIG_EXT_DELTA_Q
  NO_DELTA_Q,  // deltaq_mode
#endif
141 142 143 144 145 146 147 148
  CONFIG_XIPHRC,        // frame_periodic_delta_q
  AOM_BITS_8,           // Bit depth
  AOM_CONTENT_DEFAULT,  // content
  AOM_CS_UNKNOWN,       // color space
#if CONFIG_COLORSPACE_HEADERS
  AOM_TF_UNKNOWN,   // transfer function
  AOM_CSP_UNKNOWN,  // chroma sample position
#endif
149 150 151 152 153 154 155
  0,                            // color range
  0,                            // render width
  0,                            // render height
  AOM_SUPERBLOCK_SIZE_DYNAMIC,  // superblock_size
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  23,  // ans_window_size_log2
#endif
156 157 158
#if CONFIG_EXT_TILE
  0,    // Tile encoding mode is TILE_NORMAL by default.
#endif  // CONFIG_EXT_TILE
Yunqing Wang's avatar
Yunqing Wang committed
159 160

  0,  // motion_vector_unit_test
Jingning Han's avatar
Jingning Han committed
161 162
};

Yaowu Xu's avatar
Yaowu Xu committed
163 164 165 166 167 168
struct aom_codec_alg_priv {
  aom_codec_priv_t base;
  aom_codec_enc_cfg_t cfg;
  struct av1_extracfg extra_cfg;
  AV1EncoderConfig oxcf;
  AV1_COMP *cpi;
169 170 171 172 173 174
  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];
Yaowu Xu's avatar
Yaowu Xu committed
175 176 177 178
  aom_image_t preview_img;
  aom_enc_frame_flags_t next_frame_flags;
  aom_postproc_cfg_t preview_ppcfg;
  aom_codec_pkt_list_decl(256) pkt_list;
179
  unsigned int fixed_kf_cntr;
Jingning Han's avatar
Jingning Han committed
180
  // BufferPool that holds all reference frames.
181
  BufferPool *buffer_pool;
Jingning Han's avatar
Jingning Han committed
182 183
};

Yaowu Xu's avatar
Yaowu Xu committed
184 185 186
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
187

Yaowu Xu's avatar
Yaowu Xu committed
188
  if (res != AOM_CODEC_OK)
Jingning Han's avatar
Jingning Han committed
189 190 191 192 193 194
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;

  return res;
}

#undef ERROR
195 196 197
#define ERROR(str)                  \
  do {                              \
    ctx->base.err_detail = str;     \
Yaowu Xu's avatar
Yaowu Xu committed
198
    return AOM_CODEC_INVALID_PARAM; \
Jingning Han's avatar
Jingning Han committed
199 200
  } while (0)

201 202 203 204
#define RANGE_CHECK(p, memb, lo, hi)                   \
  do {                                                 \
    if (!((p)->memb >= (lo) && (p)->memb <= (hi)))     \
      ERROR(#memb " out of range [" #lo ".." #hi "]"); \
Jingning Han's avatar
Jingning Han committed
205 206
  } while (0)

207 208 209
#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
210 211
  } while (0)

212 213 214
#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
215 216
  } while (0)

217 218 219
#define RANGE_CHECK_BOOL(p, memb)                                     \
  do {                                                                \
    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
Jingning Han's avatar
Jingning Han committed
220 221
  } while (0)

Yaowu Xu's avatar
Yaowu Xu committed
222 223 224
static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
                                       const aom_codec_enc_cfg_t *cfg,
                                       const struct av1_extracfg *extra_cfg) {
225 226 227 228 229 230 231 232
  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
233
  RANGE_CHECK_BOOL(extra_cfg, lossless);
234
  RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1);
Fangwen Fu's avatar
Fangwen Fu committed
235 236 237
#if CONFIG_EXT_DELTA_Q
  RANGE_CHECK(extra_cfg, deltaq_mode, 0, DELTAQ_MODE_COUNT - 1);
#endif
238
  RANGE_CHECK_HI(extra_cfg, frame_periodic_boost, 1);
239 240
  RANGE_CHECK_HI(cfg, g_threads, 64);
  RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
Yaowu Xu's avatar
Yaowu Xu committed
241
  RANGE_CHECK(cfg, rc_end_usage, AOM_VBR, AOM_Q);
242 243
  RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
  RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
Jingning Han's avatar
Jingning Han committed
244
  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
Yaowu Xu's avatar
Yaowu Xu committed
245
  RANGE_CHECK(cfg, kf_mode, AOM_KF_DISABLED, AOM_KF_AUTO);
246 247 248
  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
249
  RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
Yaowu Xu's avatar
Yaowu Xu committed
250
  RANGE_CHECK(cfg, g_pass, AOM_RC_ONE_PASS, AOM_RC_LAST_PASS);
251 252
  RANGE_CHECK_HI(extra_cfg, min_gf_interval, MAX_LAG_BUFFERS - 1);
  RANGE_CHECK_HI(extra_cfg, max_gf_interval, MAX_LAG_BUFFERS - 1);
Jingning Han's avatar
Jingning Han committed
253 254 255 256 257
  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,
258
                (MAX_LAG_BUFFERS - 1));
Jingning Han's avatar
Jingning Han committed
259 260 261
  }

  if (cfg->rc_resize_allowed == 1) {
262 263
    RANGE_CHECK_HI(cfg, rc_scaled_width, cfg->g_w);
    RANGE_CHECK_HI(cfg, rc_scaled_height, cfg->g_h);
Jingning Han's avatar
Jingning Han committed
264 265
  }

266 267 268 269 270 271
#if CONFIG_FRAME_SUPERRES
  RANGE_CHECK_HI(cfg, rc_superres_mode, SUPERRES_DYNAMIC);
  RANGE_CHECK(cfg, rc_superres_numerator, SUPERRES_SCALE_DENOMINATOR / 2,
              SUPERRES_SCALE_DENOMINATOR);
#endif  // CONFIG_FRAME_SUPERRES

Yaowu Xu's avatar
Yaowu Xu committed
272
  // AV1 does not support a lower bound on the keyframe interval in
Jingning Han's avatar
Jingning Han committed
273
  // automatic keyframe placement mode.
Yaowu Xu's avatar
Yaowu Xu committed
274
  if (cfg->kf_mode != AOM_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
Jingning Han's avatar
Jingning Han committed
275
      cfg->kf_min_dist > 0)
276 277 278
    ERROR(
        "kf_min_dist not supported in auto mode, use 0 "
        "or kf_max_dist instead.");
Jingning Han's avatar
Jingning Han committed
279

Yunqing Wang's avatar
Yunqing Wang committed
280
  RANGE_CHECK_HI(extra_cfg, motion_vector_unit_test, 2);
281
  RANGE_CHECK_HI(extra_cfg, enable_auto_alt_ref, 2);
282
#if CONFIG_EXT_REFS
283
  RANGE_CHECK_HI(extra_cfg, enable_auto_bwd_ref, 2);
284
#endif  // CONFIG_EXT_REFS
285
  RANGE_CHECK(extra_cfg, cpu_used, 0, 8);
Jingning Han's avatar
Jingning Han committed
286
  RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
Yaowu Xu's avatar
Yaowu Xu committed
287 288
  RANGE_CHECK(extra_cfg, superblock_size, AOM_SUPERBLOCK_SIZE_64X64,
              AOM_SUPERBLOCK_SIZE_DYNAMIC);
289
#if CONFIG_EXT_TILE
290 291 292
// TODO(any): Waring. If CONFIG_EXT_TILE is true, tile_columns really
// means tile_width, and tile_rows really means tile_hight. The interface
// should be sanitized.
293
#if CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
294
  if (extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_64X64) {
295 296 297 298 299 300 301 302 303 304 305 306
    if (extra_cfg->tile_columns != UINT_MAX)
      RANGE_CHECK(extra_cfg, tile_columns, 1, 32);
    if (extra_cfg->tile_rows != UINT_MAX)
      RANGE_CHECK(extra_cfg, tile_rows, 1, 32);
  } else
#endif  // CONFIG_EXT_PARTITION
  {
    if (extra_cfg->tile_columns != UINT_MAX)
      RANGE_CHECK(extra_cfg, tile_columns, 1, 64);
    if (extra_cfg->tile_rows != UINT_MAX)
      RANGE_CHECK(extra_cfg, tile_rows, 1, 64);
  }
307
  RANGE_CHECK_HI(extra_cfg, tile_encoding_mode, 1);
308
#else
309 310
  RANGE_CHECK_HI(extra_cfg, tile_columns, 6);
  RANGE_CHECK_HI(extra_cfg, tile_rows, 2);
311
#endif  // CONFIG_EXT_TILE
312 313 314
#if CONFIG_DEPENDENT_HORZTILES
  RANGE_CHECK_HI(extra_cfg, dependent_horz_tiles, 1);
#endif
315
#if CONFIG_LOOPFILTERING_ACROSS_TILES
316
  RANGE_CHECK_HI(extra_cfg, loop_filter_across_tiles_enabled, 1);
317
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
Jingning Han's avatar
Jingning Han committed
318
  RANGE_CHECK_HI(extra_cfg, sharpness, 7);
319
  RANGE_CHECK_HI(extra_cfg, arnr_max_frames, 15);
Jingning Han's avatar
Jingning Han committed
320
  RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
321
  RANGE_CHECK_HI(extra_cfg, cq_level, 63);
Yaowu Xu's avatar
Yaowu Xu committed
322
  RANGE_CHECK(cfg, g_bit_depth, AOM_BITS_8, AOM_BITS_12);
Jingning Han's avatar
Jingning Han committed
323
  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
Yaowu Xu's avatar
Yaowu Xu committed
324
  RANGE_CHECK(extra_cfg, content, AOM_CONTENT_DEFAULT, AOM_CONTENT_INVALID - 1);
Jingning Han's avatar
Jingning Han committed
325

Yaowu Xu's avatar
Yaowu Xu committed
326 327 328
  // TODO(yaowu): remove this when ssim tuning is implemented for av1
  if (extra_cfg->tuning == AOM_TUNE_SSIM)
    ERROR("Option --tune=ssim is not currently supported in AV1.");
Jingning Han's avatar
Jingning Han committed
329

Yaowu Xu's avatar
Yaowu Xu committed
330
  if (cfg->g_pass == AOM_RC_LAST_PASS) {
331
#if !CONFIG_XIPHRC
Jingning Han's avatar
Jingning Han committed
332 333 334
    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;
335
#endif
Jingning Han's avatar
Jingning Han committed
336 337 338 339

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

340
#if !CONFIG_XIPHRC
Jingning Han's avatar
Jingning Han committed
341 342 343
    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
344 345
    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
346

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

Yunqing Wang's avatar
Yunqing Wang committed
350 351
    if ((int)(stats->count + 0.5) != n_packets - 1)
      ERROR("rc_twopass_stats_in missing EOS stats packet");
352
#endif
Jingning Han's avatar
Jingning Han committed
353 354
  }

355
#if !CONFIG_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
356 357 358 359 360
  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 &&
Yaowu Xu's avatar
Yaowu Xu committed
361
      cfg->g_bit_depth > AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
362 363
    ERROR("Codec high bit-depth not supported in profile < 2");
  }
364
  if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
Jingning Han's avatar
Jingning Han committed
365 366 367
    ERROR("Source high bit-depth not supported in profile < 2");
  }
  if (cfg->g_profile > (unsigned int)PROFILE_1 &&
Yaowu Xu's avatar
Yaowu Xu committed
368
      cfg->g_bit_depth == AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
369 370
    ERROR("Codec bit-depth 8 not supported in profile > 1");
  }
371 372 373 374 375 376
#if CONFIG_COLORSPACE_HEADERS
  RANGE_CHECK(extra_cfg, color_space, AOM_CS_UNKNOWN, AOM_CS_ICTCP);
  RANGE_CHECK(extra_cfg, transfer_function, AOM_TF_UNKNOWN, AOM_TF_HLG);
  RANGE_CHECK(extra_cfg, chroma_sample_position, AOM_CSP_UNKNOWN,
              AOM_CSP_COLOCATED);
#else
Yaowu Xu's avatar
Yaowu Xu committed
377
  RANGE_CHECK(extra_cfg, color_space, AOM_CS_UNKNOWN, AOM_CS_SRGB);
378
#endif
379
  RANGE_CHECK(extra_cfg, color_range, 0, 1);
380 381 382
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  RANGE_CHECK(extra_cfg, ans_window_size_log2, 8, 23);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
383
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
384 385
}

Yaowu Xu's avatar
Yaowu Xu committed
386 387
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
388
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
389 390 391 392 393 394
    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
395
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
396 397 398
        ERROR(
            "Invalid image format. I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
399 400
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
401 402 403
    case AOM_IMG_FMT_I42216:
    case AOM_IMG_FMT_I44416:
    case AOM_IMG_FMT_I44016:
Jingning Han's avatar
Jingning Han committed
404 405
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
          ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
406 407 408
        ERROR(
            "Invalid image format. 16-bit I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
409 410 411
      }
      break;
    default:
412 413 414
      ERROR(
          "Invalid image format. Only YV12, I420, I422, I444 images are "
          "supported.");
Jingning Han's avatar
Jingning Han committed
415 416 417 418 419 420
      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");

Yaowu Xu's avatar
Yaowu Xu committed
421
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
422 423
}

Yaowu Xu's avatar
Yaowu Xu committed
424
static int get_image_bps(const aom_image_t *img) {
Jingning Han's avatar
Jingning Han committed
425
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
426 427 428 429 430 431 432 433 434
    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
435 436 437 438 439
    default: assert(0 && "Invalid image format"); break;
  }
  return 0;
}

Yaowu Xu's avatar
Yaowu Xu committed
440 441 442 443
static aom_codec_err_t set_encoder_config(
    AV1EncoderConfig *oxcf, const aom_codec_enc_cfg_t *cfg,
    const struct av1_extracfg *extra_cfg) {
  const int is_vbr = cfg->rc_end_usage == AOM_VBR;
Jingning Han's avatar
Jingning Han committed
444 445
  oxcf->profile = cfg->g_profile;
  oxcf->max_threads = (int)cfg->g_threads;
446 447
  oxcf->width = cfg->g_w;
  oxcf->height = cfg->g_h;
Jingning Han's avatar
Jingning Han committed
448 449 450 451
  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;
452
  if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
Jingning Han's avatar
Jingning Han committed
453 454 455 456

  oxcf->mode = GOOD;

  switch (cfg->g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
457 458 459
    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
460 461
  }

462
  oxcf->lag_in_frames =
Yaowu Xu's avatar
Yaowu Xu committed
463
      cfg->g_pass == AOM_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
Jingning Han's avatar
Jingning Han committed
464 465 466 467 468 469 470 471 472
  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 =
Yaowu Xu's avatar
Yaowu Xu committed
473
      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_min_quantizer);
Jingning Han's avatar
Jingning Han committed
474
  oxcf->worst_allowed_q =
Yaowu Xu's avatar
Yaowu Xu committed
475 476
      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
477 478
  oxcf->fixed_q = -1;

479 480 481 482 483 484
#if CONFIG_AOM_QM
  oxcf->using_qm = extra_cfg->enable_qm;
  oxcf->qm_minlevel = extra_cfg->qm_min;
  oxcf->qm_maxlevel = extra_cfg->qm_max;
#endif

485 486 487 488 489
#if CONFIG_TILE_GROUPS
  oxcf->num_tile_groups = extra_cfg->num_tg;
  oxcf->mtu = extra_cfg->mtu_size;
#endif

490 491 492
#if CONFIG_TEMPMV_SIGNALING
  oxcf->disable_tempmv = extra_cfg->disable_tempmv;
#endif
493 494
  oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
  oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
Jingning Han's avatar
Jingning Han committed
495

496
  oxcf->scaled_frame_width = cfg->rc_scaled_width;
Jingning Han's avatar
Jingning Han committed
497 498 499
  oxcf->scaled_frame_height = cfg->rc_scaled_height;
  if (cfg->rc_resize_allowed == 1) {
    oxcf->resize_mode =
500 501 502
        (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
            ? RESIZE_DYNAMIC
            : RESIZE_FIXED;
Jingning Han's avatar
Jingning Han committed
503 504 505 506
  } else {
    oxcf->resize_mode = RESIZE_NONE;
  }

507 508 509 510 511 512 513
  // Initialize to input resolution if not specified.
  if (oxcf->resize_mode != RESIZE_FIXED) {
    oxcf->scaled_frame_width = oxcf->width;
    oxcf->scaled_frame_height = oxcf->height;
  }

#if CONFIG_FRAME_SUPERRES
514 515 516 517 518 519
  oxcf->superres_mode = (SUPERRES_MODE)cfg->rc_superres_mode;
  oxcf->superres_scale_numerator = (uint8_t)cfg->rc_superres_numerator;
  if (oxcf->superres_mode == SUPERRES_FIXED &&
      oxcf->superres_scale_numerator == SUPERRES_SCALE_DENOMINATOR)
    oxcf->superres_mode = SUPERRES_NONE;
#endif  // CONFIG_FRAME_SUPERRES
520

521
  oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
Jingning Han's avatar
Jingning Han committed
522
  oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
523
  oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
Jingning Han's avatar
Jingning Han committed
524

525
  oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
Jingning Han's avatar
Jingning Han committed
526

527 528 529
  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
530

531
  oxcf->auto_key =
Yaowu Xu's avatar
Yaowu Xu committed
532
      cfg->kf_mode == AOM_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
533

534
  oxcf->key_freq = cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
535

536
  oxcf->speed = extra_cfg->cpu_used;
537
  oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
538
#if CONFIG_EXT_REFS
539
  oxcf->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
540
#endif  // CONFIG_EXT_REFS
541 542
  oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
  oxcf->sharpness = extra_cfg->sharpness;
Jingning Han's avatar
Jingning Han committed
543

544
  oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
Jingning Han's avatar
Jingning Han committed
545 546

#if CONFIG_FP_MB_STATS
547
  oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
Jingning Han's avatar
Jingning Han committed
548 549 550
#endif

  oxcf->color_space = extra_cfg->color_space;
551 552 553 554
#if CONFIG_COLORSPACE_HEADERS
  oxcf->transfer_function = extra_cfg->transfer_function;
  oxcf->chroma_sample_position = extra_cfg->chroma_sample_position;
#endif
555
  oxcf->color_range = extra_cfg->color_range;
556
  oxcf->render_width = extra_cfg->render_width;
557
  oxcf->render_height = extra_cfg->render_height;
Jingning Han's avatar
Jingning Han committed
558
  oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
559
  oxcf->arnr_strength = extra_cfg->arnr_strength;
Jingning Han's avatar
Jingning Han committed
560 561 562 563 564 565
  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;

566 567 568
#if CONFIG_EXT_PARTITION
  oxcf->superblock_size = extra_cfg->superblock_size;
#endif  // CONFIG_EXT_PARTITION
569 570 571
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  oxcf->ans_window_size_log2 = extra_cfg->ans_window_size_log2;
#endif  // CONFIG_ANS && ANS_MAX_SYMBOLS
572 573 574 575 576

#if CONFIG_EXT_TILE
  {
#if CONFIG_EXT_PARTITION
    const unsigned int max =
Yaowu Xu's avatar
Yaowu Xu committed
577
        extra_cfg->superblock_size == AOM_SUPERBLOCK_SIZE_64X64 ? 64 : 32;
578 579 580
#else
    const unsigned int max = 64;
#endif  // CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
581 582
    oxcf->tile_columns = AOMMIN(extra_cfg->tile_columns, max);
    oxcf->tile_rows = AOMMIN(extra_cfg->tile_rows, max);
583
    oxcf->tile_encoding_mode = extra_cfg->tile_encoding_mode;
584 585
  }
#else
Jingning Han's avatar
Jingning Han committed
586
  oxcf->tile_columns = extra_cfg->tile_columns;
587
  oxcf->tile_rows = extra_cfg->tile_rows;
588
#endif  // CONFIG_EXT_TILE
589 590 591
#if CONFIG_DEPENDENT_HORZTILES
  oxcf->dependent_horz_tiles = extra_cfg->dependent_horz_tiles;
#endif
592
#if CONFIG_LOOPFILTERING_ACROSS_TILES
593 594
  oxcf->loop_filter_across_tiles_enabled =
      extra_cfg->loop_filter_across_tiles_enabled;
595
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
596
  oxcf->error_resilient_mode = cfg->g_error_resilient;
Jingning Han's avatar
Jingning Han committed
597 598 599
  oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;

  oxcf->aq_mode = extra_cfg->aq_mode;
Fangwen Fu's avatar
Fangwen Fu committed
600 601 602
#if CONFIG_EXT_DELTA_Q
  oxcf->deltaq_mode = extra_cfg->deltaq_mode;
#endif
Jingning Han's avatar
Jingning Han committed
603

604
  oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
Jingning Han's avatar
Jingning Han committed
605

Yunqing Wang's avatar
Yunqing Wang committed
606
  oxcf->motion_vector_unit_test = extra_cfg->motion_vector_unit_test;
Jingning Han's avatar
Jingning Han committed
607
  /*
Yaowu Xu's avatar
Yaowu Xu committed
608
  printf("Current AV1 Settings: \n");
Jingning Han's avatar
Jingning Han committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
  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("error resilient: %d\n", oxcf->error_resilient_mode);
  printf("frame parallel detokenization: %d\n",
         oxcf->frame_parallel_decoding_mode);
  */
Yaowu Xu's avatar
Yaowu Xu committed
638
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
639 640
}

Yaowu Xu's avatar
Yaowu Xu committed
641 642 643
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
644 645 646
  int force_key = 0;

  if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
Yaowu Xu's avatar
Yaowu Xu committed
647
    if (cfg->g_lag_in_frames > 1 || cfg->g_pass != AOM_RC_ONE_PASS)
Jingning Han's avatar
Jingning Han committed
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
      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);

Yaowu Xu's avatar
Yaowu Xu committed
664
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
665 666 667 668
    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;
Yaowu Xu's avatar
Yaowu Xu committed
669
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
670 671
  }

Yaowu Xu's avatar
Yaowu Xu committed
672
  if (force_key) ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
Jingning Han's avatar
Jingning Han committed
673 674 675 676

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
677
static aom_codec_err_t ctrl_get_quantizer(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
678 679
                                          va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
680 681 682
  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
  *arg = av1_get_quantizer(ctx->cpi);
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
683 684
}

Yaowu Xu's avatar
Yaowu Xu committed
685
static aom_codec_err_t ctrl_get_quantizer64(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
686 687
                                            va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
688 689 690
  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
  *arg = av1_qindex_to_quantizer(av1_get_quantizer(ctx->cpi));
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
691 692
}

Yaowu Xu's avatar
Yaowu Xu committed
693 694 695 696
static aom_codec_err_t update_extra_cfg(aom_codec_alg_priv_t *ctx,
                                        const struct av1_extracfg *extra_cfg) {
  const aom_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
697 698
    ctx->extra_cfg = *extra_cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
Yaowu Xu's avatar
Yaowu Xu committed
699
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
700 701 702 703
  }
  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
704
static aom_codec_err_t ctrl_set_cpuused(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
705
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
706 707
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cpu_used = CAST(AOME_SET_CPUUSED, args);
Jingning Han's avatar
Jingning Han committed
708 709 710
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
711
static aom_codec_err_t ctrl_set_enable_auto_alt_ref(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
712
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
713 714
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_auto_alt_ref = CAST(AOME_SET_ENABLEAUTOALTREF, args);
Jingning Han's avatar
Jingning Han committed
715 716 717
  return update_extra_cfg(ctx, &extra_cfg);
}

718
#if CONFIG_EXT_REFS
Yaowu Xu's avatar
Yaowu Xu committed
719
static aom_codec_err_t ctrl_set_enable_auto_bwd_ref(aom_codec_alg_priv_t *ctx,
720
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
721 722
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_auto_bwd_ref = CAST(AOME_SET_ENABLEAUTOBWDREF, args);
723 724
  return update_extra_cfg(ctx, &extra_cfg);
}
725
#endif  // CONFIG_EXT_REFS
726

Yaowu Xu's avatar
Yaowu Xu committed
727
static aom_codec_err_t ctrl_set_noise_sensitivity(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
728
                                                  va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
729 730
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.noise_sensitivity = CAST(AV1E_SET_NOISE_SENSITIVITY, args);
Jingning Han's avatar
Jingning Han committed
731 732 733
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
734
static aom_codec_err_t ctrl_set_sharpness(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
735
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
736 737
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.sharpness = CAST(AOME_SET_SHARPNESS, args);
Jingning Han's avatar
Jingning Han committed
738 739 740
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
741
static aom_codec_err_t ctrl_set_static_thresh(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
742
                                              va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
743 744
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.static_thresh = CAST(AOME_SET_STATIC_THRESHOLD, args);
Jingning Han's avatar
Jingning Han committed
745 746 747
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
748
static aom_codec_err_t ctrl_set_tile_columns(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
749
                                             va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
750 751
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tile_columns = CAST(AV1E_SET_TILE_COLUMNS, args);
Jingning Han's avatar
Jingning Han committed
752 753 754
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
755
static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
756
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
757 758
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tile_rows = CAST(AV1E_SET_TILE_ROWS, args);
Jingning Han's avatar
Jingning Han committed
759 760
  return update_extra_cfg(ctx, &extra_cfg);
}
761 762 763 764 765 766 767 768
#if CONFIG_DEPENDENT_HORZTILES
static aom_codec_err_t ctrl_set_tile_dependent_rows(aom_codec_alg_priv_t *ctx,
                                                    va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.dependent_horz_tiles = CAST(AV1E_SET_TILE_DEPENDENT_ROWS, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif
769
#if CONFIG_LOOPFILTERING_ACROSS_TILES
770 771 772 773 774 775 776
static aom_codec_err_t ctrl_set_tile_loopfilter(aom_codec_alg_priv_t *ctx,
                                                va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.loop_filter_across_tiles_enabled =
      CAST(AV1E_SET_TILE_LOOPFILTER, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
777
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
778

Yaowu Xu's avatar
Yaowu Xu committed
779
static aom_codec_err_t ctrl_set_arnr_max_frames(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
780
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
781 782
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.arnr_max_frames = CAST(AOME_SET_ARNR_MAXFRAMES, args);
Jingning Han's avatar
Jingning Han committed
783 784 785
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
786
static aom_codec_err_t ctrl_set_arnr_strength(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
787
                                              va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
788 789
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.arnr_strength = CAST(AOME_SET_ARNR_STRENGTH, args);
Jingning Han's avatar
Jingning Han committed
790 791 792
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
793
static aom_codec_err_t ctrl_set_tuning(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
794
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
795 796
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tuning = CAST(AOME_SET_TUNING, args);
Jingning Han's avatar
Jingning Han committed
797 798 799
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
800
static aom_codec_err_t ctrl_set_cq_level(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
801
                                         va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
802 803
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cq_level = CAST(AOME_SET_CQ_LEVEL, args);
Jingning Han's avatar
Jingning Han committed
804 805 806
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
807 808 809
static aom_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
    aom_codec_alg_priv_t *ctx, va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Jingning Han's avatar
Jingning Han committed
810
  extra_cfg.rc_max_intra_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
811
      CAST(AOME_SET_MAX_INTRA_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
812 813 814
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
815 816 817
static aom_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
    aom_codec_alg_priv_t *ctx, va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Jingning Han's avatar
Jingning Han committed
818
  extra_cfg.rc_max_inter_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
819
      CAST(AOME_SET_MAX_INTER_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
820 821 822
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
823
static aom_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(aom_codec_alg_priv_t *ctx,
824
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
825 826
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.gf_cbr_boost_pct = CAST(AV1E_SET_GF_CBR_BOOST_PCT, args);
Jingning Han's avatar
Jingning Han committed
827 828 829
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
830
static aom_codec_err_t ctrl_set_lossless(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
831
                                         va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
832 833
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.lossless = CAST(AV1E_SET_LOSSLESS, args);
Jingning Han's avatar
Jingning Han committed
834 835 836
  return update_extra_cfg(ctx, &extra_cfg);
}

837
#if CONFIG_AOM_QM
Yaowu Xu's avatar
Yaowu Xu committed
838
static aom_codec_err_t ctrl_set_enable_qm(aom_codec_alg_priv_t *ctx,
839
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
840 841
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_qm = CAST(AV1E_SET_ENABLE_QM, args);
842 843 844
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
845
static aom_codec_err_t ctrl_set_qm_min(aom_codec_alg_priv_t *ctx,
846
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
847 848
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_min = CAST(AV1E_SET_QM_MIN, args);
849 850 851
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
852
static aom_codec_err_t ctrl_set_qm_max(aom_codec_alg_priv_t *ctx,
853
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
854 855
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_max = CAST(AV1E_SET_QM_MAX, args);
856 857 858 859
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif

860 861 862 863 864 865 866 867 868 869 870 871 872 873
#if CONFIG_TILE_GROUPS
static aom_codec_err_t ctrl_set_num_tg(aom_codec_alg_priv_t *ctx,
                                       va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.num_tg = CAST(AV1E_SET_NUM_TG, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static aom_codec_err_t ctrl_set_mtu(aom_codec_alg_priv_t *ctx, va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.mtu_size = CAST(AV1E_SET_MTU, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif
874 875 876 877 878 879 880 881
#if CONFIG_TEMPMV_SIGNALING
static aom_codec_err_t ctrl_set_disable_tempmv(aom_codec_alg_priv_t *ctx,
                                               va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.disable_tempmv = CAST(AV1E_SET_DISABLE_TEMPMV, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif
Yaowu Xu's avatar
Yaowu Xu committed
882 883 884
static aom_codec_err_t ctrl_set_frame_parallel_decoding_mode(
    aom_codec_alg_priv_t *ctx, va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
Jingning Han's avatar
Jingning Han committed
885
  extra_cfg.frame_parallel_decoding_mode =
Yaowu Xu's avatar
Yaowu Xu committed
886
      CAST(AV1E_SET_FRAME_PARALLEL_DECODING, args);
Jingning Han's avatar
Jingning Han committed
887 888 889
  return update_extra_cfg(ctx, &extra_cfg);
}

890 891 892 893 894 895 896 897 898
#if CONFIG_EXT_TILE
static aom_codec_err_t ctrl_set_tile_encoding_mode(aom_codec_alg_priv_t *ctx,
                                                   va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tile_encoding_mode = CAST(AV1E_SET_TILE_ENCODING_MODE, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif  // CONFIG_EXT_TILE

Yaowu Xu's avatar
Yaowu Xu committed
899
static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
900
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
901 902
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.aq_mode = CAST(AV1E_SET_AQ_MODE, args);
Jingning Han's avatar
Jingning Han committed
903 904 905
  return update_extra_cfg(ctx, &extra_cfg);
}

Fangwen Fu's avatar
Fangwen Fu committed
906 907 908 909 910 911 912 913
#if CONFIG_EXT_DELTA_Q
static aom_codec_err_t ctrl_set_deltaq_mode(aom_codec_alg_priv_t *ctx,
                                            va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.deltaq_mode = CAST(AV1E_SET_DELTAQ_MODE, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif
Yaowu Xu's avatar
Yaowu Xu committed
914
static aom_codec_err_t ctrl_set_min_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
915
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
916 917
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.min_gf_interval = CAST(AV1E_SET_MIN_GF_INTERVAL, args);
Jingning Han's avatar
Jingning Han committed
918 919 920
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
921
static aom_codec_err_t ctrl_set_max_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
922
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
923 924
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.max_gf_interval = CAST(AV1E_SET_MAX_GF_INTERVAL, args);
Jingning Han's avatar
Jingning Han committed
925 926 927
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
928
static aom_codec_err_t ctrl_set_frame_periodic_boost(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
929
                                                     va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
930 931
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.frame_periodic_boost = CAST(AV1E_SET_FRAME_PERIODIC_BOOST, args);
Jingning Han's avatar
Jingning Han committed
932 933 934
  return update_extra_cfg(ctx, &extra_cfg);
}

Yunqing Wang's avatar
Yunqing Wang committed
935 936 937 938 939 940 941 942
static aom_codec_err_t ctrl_enable_motion_vector_unit_test(
    aom_codec_alg_priv_t *ctx, va_list args) {
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.motion_vector_unit_test =
      CAST(AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
943 944 945
static aom_codec_err_t encoder_init(aom_codec_ctx_t *ctx,
                                    aom_codec_priv_enc_mr_cfg_t *data) {
  aom_codec_err_t res = AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
946 947 948
  (void)data;

  if (ctx->priv == NULL) {
Yaowu Xu's avatar
Yaowu Xu committed
949 950
    aom_codec_alg_priv_t *const priv = aom_calloc(1, sizeof(*priv));
    if (priv == NULL) return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
951

Yaowu Xu's avatar
Yaowu Xu committed
952
    ctx->priv = (aom_codec_priv_t *)priv;
Jingning Han's avatar
Jingning Han committed
953 954
    ctx->priv->init_flags = ctx->init_flags;
    ctx->priv->enc.total_encoders = 1;
Yaowu Xu's avatar
Yaowu Xu committed
955 956
    priv->buffer_pool = (BufferPool *)aom_calloc(1, sizeof(BufferPool));
    if (priv->buffer_pool == NULL) return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
957 958 959

#if CONFIG_MULTITHREAD
    if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
Yaowu Xu's avatar
Yaowu Xu committed
960
      return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
961 962 963 964 965 966 967 968 969 970
    }
#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;
Yaowu Xu's avatar
Yaowu Xu committed
971
    once(av1_initialize_enc);
Jingning Han's avatar
Jingning Han committed
972 973 974

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

Yaowu Xu's avatar
Yaowu Xu committed
975
    if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
976
      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
977
#if CONFIG_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
978
      priv->oxcf.use_highbitdepth =
Yaowu Xu's avatar
Yaowu Xu committed
979
          (ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
Jingning Han's avatar
Jingning Han committed
980
#endif
Yaowu Xu's avatar
Yaowu Xu committed
981
      priv->cpi = av1_create_compressor(&priv->oxcf, priv->buffer_pool);
Jingning Han's avatar
Jingning Han committed
982
      if (priv->cpi == NULL)
Yaowu Xu's avatar
Yaowu Xu committed
983
        res = AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
984 985 986 987 988 989 990 991
      else
        priv->cpi->output_pkt_list = &priv->pkt_list.head;
    }
  }

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
992
static aom_codec_err_t encoder_destroy(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
993
  free(ctx->cx_data);
Yaowu Xu's avatar
Yaowu Xu committed
994
  av1_remove_compressor(ctx->cpi);
Jingning Han's avatar
Jingning Han committed
995 996 997
#if CONFIG_MULTITHREAD
  pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
998 999 1000
  aom_free(ctx->buffer_pool);
  aom_free(ctx);
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
1001 1002
}

Yaowu Xu's avatar
Yaowu Xu committed
1003
static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
1004
                                    unsigned long deadline) {
1005
  MODE new_mode = GOOD;
Jingning Han's avatar
Jingning Han committed
1006 1007

  switch (ctx->cfg.g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
1008
    case AOM_RC_ONE_PASS:
1009 1010
      switch (deadline) {
        default: new_mode = GOOD; break;
Jingning Han's avatar
Jingning Han committed
1011 1012
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
1013
    case AOM_RC_FIRST_PASS: break;
1014
    case AOM_RC_LAST_PASS: new_mode = GOOD;
Jingning Han's avatar
Jingning Han committed
1015 1016 1017 1018
  }

  if (ctx->oxcf.mode != new_mode) {
    ctx->oxcf.mode = new_mode;
Yaowu Xu's avatar
Yaowu Xu committed
1019
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
1020 1021 1022 1023 1024
  }
}

// Turn on to test if supplemental superframe data breaks decoding
// #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
Yaowu Xu's avatar
Yaowu Xu committed
1025
static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
1026 1027 1028
  uint8_t marker = 0xc0;
  unsigned int mask;
  int mag, index_sz;
1029 1030
  int i;
  size_t max_frame_sz = 0;
Jingning Han's avatar
Jingning Han committed
1031 1032 1033 1034 1035 1036

  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;
1037
  for (i = 0; i < ctx->pending_frame_count - 1; i++) {
1038
    const size_t frame_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
1039 1040
    max_frame_sz = frame_sz > max_frame_sz ? frame_sz : max_frame_sz;
  }
Jingning Han's avatar
Jingning Han committed
1041 1042 1043

  // Choose the magnitude
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
1044
    if (max_frame_sz <= mask) break;
Jingning Han's avatar
Jingning Han committed
1045