av1_cx_iface.c 56 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
  int color_range;
  int render_width;
  int render_height;
Yaowu Xu's avatar
Yaowu Xu committed
77
  aom_superblock_size_t superblock_size;
78 79 80
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  int ans_window_size_log2;
#endif
81 82 83
#if CONFIG_EXT_TILE
  unsigned int tile_encoding_mode;
#endif  // CONFIG_EXT_TILE
Yunqing Wang's avatar
Yunqing Wang committed
84 85

  unsigned int motion_vector_unit_test;
Jingning Han's avatar
Jingning Han committed
86 87
};

Yaowu Xu's avatar
Yaowu Xu committed
88
static struct av1_extracfg default_extra_cfg = {
89 90
  0,  // cpu_used
  1,  // enable_auto_alt_ref
91
#if CONFIG_EXT_REFS
92
  0,    // enable_auto_bwd_ref
93
#endif  // CONFIG_EXT_REFS
94 95 96
  0,    // noise_sensitivity
  0,    // sharpness
  0,    // static_thresh
97
#if CONFIG_EXT_TILE
98 99
  UINT_MAX,  // tile_columns
  UINT_MAX,  // tile_rows
100
#else
101 102
  0,  // tile_columns
  0,  // tile_rows
103
#endif  // CONFIG_EXT_TILE
104 105 106
#if CONFIG_DEPENDENT_HORZTILES
  0,  // Depdendent Horizontal tiles
#endif
107
#if CONFIG_LOOPFILTERING_ACROSS_TILES
108
  1,              // loop_filter_across_tiles_enabled
109
#endif            // CONFIG_LOOPFILTERING_ACROSS_TILES
110 111 112 113
  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
114
  AOM_TUNE_PSNR,  // tuning
115 116 117 118 119 120 121 122 123
  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
124 125 126 127
#endif
#if CONFIG_TILE_GROUPS
  1,  // max number of tile groups
  0,  // mtu_size
128 129 130
#endif
#if CONFIG_TEMPMV_SIGNALING
  0,  // disable temporal mv prediction
131
#endif
Fangwen Fu's avatar
Fangwen Fu committed
132 133 134 135 136
  1,      // frame_parallel_decoding_mode
  NO_AQ,  // aq_mode
#if CONFIG_EXT_DELTA_Q
  NO_DELTA_Q,  // deltaq_mode
#endif
137
  CONFIG_XIPHRC,                // frame_periodic_delta_q
138 139 140 141 142 143 144 145 146 147
  AOM_BITS_8,                   // Bit depth
  AOM_CONTENT_DEFAULT,          // content
  AOM_CS_UNKNOWN,               // color space
  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
148 149 150
#if CONFIG_EXT_TILE
  0,    // Tile encoding mode is TILE_NORMAL by default.
#endif  // CONFIG_EXT_TILE
Yunqing Wang's avatar
Yunqing Wang committed
151 152

  0,  // motion_vector_unit_test
Jingning Han's avatar
Jingning Han committed
153 154
};

Yaowu Xu's avatar
Yaowu Xu committed
155 156 157 158 159 160
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;
161 162 163 164 165 166
  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
167 168 169 170
  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;
171
  unsigned int fixed_kf_cntr;
Jingning Han's avatar
Jingning Han committed
172
  // BufferPool that holds all reference frames.
173
  BufferPool *buffer_pool;
Jingning Han's avatar
Jingning Han committed
174 175
};

Yaowu Xu's avatar
Yaowu Xu committed
176 177 178
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
179

Yaowu Xu's avatar
Yaowu Xu committed
180
  if (res != AOM_CODEC_OK)
Jingning Han's avatar
Jingning Han committed
181 182 183 184 185 186
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;

  return res;
}

#undef ERROR
187 188 189
#define ERROR(str)                  \
  do {                              \
    ctx->base.err_detail = str;     \
Yaowu Xu's avatar
Yaowu Xu committed
190
    return AOM_CODEC_INVALID_PARAM; \
Jingning Han's avatar
Jingning Han committed
191 192
  } while (0)

193 194 195 196
#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
197 198
  } while (0)

199 200 201
#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
202 203
  } while (0)

204 205 206
#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
207 208
  } while (0)

209 210 211
#define RANGE_CHECK_BOOL(p, memb)                                     \
  do {                                                                \
    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
Jingning Han's avatar
Jingning Han committed
212 213
  } while (0)

Yaowu Xu's avatar
Yaowu Xu committed
214 215 216
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) {
217 218 219 220 221 222 223 224
  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
225
  RANGE_CHECK_BOOL(extra_cfg, lossless);
226
  RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1);
Fangwen Fu's avatar
Fangwen Fu committed
227 228 229
#if CONFIG_EXT_DELTA_Q
  RANGE_CHECK(extra_cfg, deltaq_mode, 0, DELTAQ_MODE_COUNT - 1);
#endif
230
  RANGE_CHECK_HI(extra_cfg, frame_periodic_boost, 1);
231 232
  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
233
  RANGE_CHECK(cfg, rc_end_usage, AOM_VBR, AOM_Q);
234 235
  RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
  RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
Jingning Han's avatar
Jingning Han committed
236
  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
Yaowu Xu's avatar
Yaowu Xu committed
237
  RANGE_CHECK(cfg, kf_mode, AOM_KF_DISABLED, AOM_KF_AUTO);
238 239 240
  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
241
  RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
Yaowu Xu's avatar
Yaowu Xu committed
242
  RANGE_CHECK(cfg, g_pass, AOM_RC_ONE_PASS, AOM_RC_LAST_PASS);
243 244
  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
245 246 247 248 249
  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,
250
                (MAX_LAG_BUFFERS - 1));
Jingning Han's avatar
Jingning Han committed
251 252 253
  }

  if (cfg->rc_resize_allowed == 1) {
254 255
    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
256 257
  }

Yaowu Xu's avatar
Yaowu Xu committed
258
  // AV1 does not support a lower bound on the keyframe interval in
Jingning Han's avatar
Jingning Han committed
259
  // automatic keyframe placement mode.
Yaowu Xu's avatar
Yaowu Xu committed
260
  if (cfg->kf_mode != AOM_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
Jingning Han's avatar
Jingning Han committed
261
      cfg->kf_min_dist > 0)
262 263 264
    ERROR(
        "kf_min_dist not supported in auto mode, use 0 "
        "or kf_max_dist instead.");
Jingning Han's avatar
Jingning Han committed
265

Yunqing Wang's avatar
Yunqing Wang committed
266
  RANGE_CHECK_HI(extra_cfg, motion_vector_unit_test, 2);
267
  RANGE_CHECK_HI(extra_cfg, enable_auto_alt_ref, 2);
268
#if CONFIG_EXT_REFS
269
  RANGE_CHECK_HI(extra_cfg, enable_auto_bwd_ref, 2);
270
#endif  // CONFIG_EXT_REFS
271
  RANGE_CHECK(extra_cfg, cpu_used, 0, 8);
Jingning Han's avatar
Jingning Han committed
272
  RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
Yaowu Xu's avatar
Yaowu Xu committed
273 274
  RANGE_CHECK(extra_cfg, superblock_size, AOM_SUPERBLOCK_SIZE_64X64,
              AOM_SUPERBLOCK_SIZE_DYNAMIC);
275
#if CONFIG_EXT_TILE
276 277 278
// 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.
279
#if CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
280
  if (extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_64X64) {
281 282 283 284 285 286 287 288 289 290 291 292
    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);
  }
293
  RANGE_CHECK_HI(extra_cfg, tile_encoding_mode, 1);
294
#else
295 296
  RANGE_CHECK_HI(extra_cfg, tile_columns, 6);
  RANGE_CHECK_HI(extra_cfg, tile_rows, 2);
297
#endif  // CONFIG_EXT_TILE
298 299 300
#if CONFIG_DEPENDENT_HORZTILES
  RANGE_CHECK_HI(extra_cfg, dependent_horz_tiles, 1);
#endif
301
#if CONFIG_LOOPFILTERING_ACROSS_TILES
302
  RANGE_CHECK_HI(extra_cfg, loop_filter_across_tiles_enabled, 1);
303
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
Jingning Han's avatar
Jingning Han committed
304
  RANGE_CHECK_HI(extra_cfg, sharpness, 7);
305
  RANGE_CHECK_HI(extra_cfg, arnr_max_frames, 15);
Jingning Han's avatar
Jingning Han committed
306
  RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
307
  RANGE_CHECK_HI(extra_cfg, cq_level, 63);
Yaowu Xu's avatar
Yaowu Xu committed
308
  RANGE_CHECK(cfg, g_bit_depth, AOM_BITS_8, AOM_BITS_12);
Jingning Han's avatar
Jingning Han committed
309
  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
Yaowu Xu's avatar
Yaowu Xu committed
310
  RANGE_CHECK(extra_cfg, content, AOM_CONTENT_DEFAULT, AOM_CONTENT_INVALID - 1);
Jingning Han's avatar
Jingning Han committed
311

Yaowu Xu's avatar
Yaowu Xu committed
312 313 314
  // 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
315

Yaowu Xu's avatar
Yaowu Xu committed
316
  if (cfg->g_pass == AOM_RC_LAST_PASS) {
317
#if !CONFIG_XIPHRC
Jingning Han's avatar
Jingning Han committed
318 319 320
    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;
321
#endif
Jingning Han's avatar
Jingning Han committed
322 323 324 325

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

326
#if !CONFIG_XIPHRC
Jingning Han's avatar
Jingning Han committed
327 328 329
    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
330 331
    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
332

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

Yunqing Wang's avatar
Yunqing Wang committed
336 337
    if ((int)(stats->count + 0.5) != n_packets - 1)
      ERROR("rc_twopass_stats_in missing EOS stats packet");
338
#endif
Jingning Han's avatar
Jingning Han committed
339 340
  }

341
#if !CONFIG_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
342 343 344 345 346
  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
347
      cfg->g_bit_depth > AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
348 349
    ERROR("Codec high bit-depth not supported in profile < 2");
  }
350
  if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
Jingning Han's avatar
Jingning Han committed
351 352 353
    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
354
      cfg->g_bit_depth == AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
355 356
    ERROR("Codec bit-depth 8 not supported in profile > 1");
  }
Yaowu Xu's avatar
Yaowu Xu committed
357
  RANGE_CHECK(extra_cfg, color_space, AOM_CS_UNKNOWN, AOM_CS_SRGB);
358
  RANGE_CHECK(extra_cfg, color_range, 0, 1);
359 360 361
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  RANGE_CHECK(extra_cfg, ans_window_size_log2, 8, 23);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
362
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
363 364
}

Yaowu Xu's avatar
Yaowu Xu committed
365 366
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
367
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
368 369 370 371 372 373
    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
374
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
375 376 377
        ERROR(
            "Invalid image format. I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
378 379
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
380 381 382
    case AOM_IMG_FMT_I42216:
    case AOM_IMG_FMT_I44416:
    case AOM_IMG_FMT_I44016:
Jingning Han's avatar
Jingning Han committed
383 384
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
          ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
385 386 387
        ERROR(
            "Invalid image format. 16-bit I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
388 389 390
      }
      break;
    default:
391 392 393
      ERROR(
          "Invalid image format. Only YV12, I420, I422, I444 images are "
          "supported.");
Jingning Han's avatar
Jingning Han committed
394 395 396 397 398 399
      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
400
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
401 402
}

Yaowu Xu's avatar
Yaowu Xu committed
403
static int get_image_bps(const aom_image_t *img) {
Jingning Han's avatar
Jingning Han committed
404
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
405 406 407 408 409 410 411 412 413
    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
414 415 416 417 418
    default: assert(0 && "Invalid image format"); break;
  }
  return 0;
}

Yaowu Xu's avatar
Yaowu Xu committed
419 420 421 422
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
423 424
  oxcf->profile = cfg->g_profile;
  oxcf->max_threads = (int)cfg->g_threads;
425 426
  oxcf->width = cfg->g_w;
  oxcf->height = cfg->g_h;
Jingning Han's avatar
Jingning Han committed
427 428 429 430
  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;
431
  if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
Jingning Han's avatar
Jingning Han committed
432 433 434 435

  oxcf->mode = GOOD;

  switch (cfg->g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
436 437 438
    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
439 440
  }

441
  oxcf->lag_in_frames =
Yaowu Xu's avatar
Yaowu Xu committed
442
      cfg->g_pass == AOM_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
Jingning Han's avatar
Jingning Han committed
443 444 445 446 447 448 449 450 451
  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
452
      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_min_quantizer);
Jingning Han's avatar
Jingning Han committed
453
  oxcf->worst_allowed_q =
Yaowu Xu's avatar
Yaowu Xu committed
454 455
      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
456 457
  oxcf->fixed_q = -1;

458 459 460 461 462 463
#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

464 465 466 467 468
#if CONFIG_TILE_GROUPS
  oxcf->num_tile_groups = extra_cfg->num_tg;
  oxcf->mtu = extra_cfg->mtu_size;
#endif

469 470 471
#if CONFIG_TEMPMV_SIGNALING
  oxcf->disable_tempmv = extra_cfg->disable_tempmv;
#endif
472 473
  oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
  oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
Jingning Han's avatar
Jingning Han committed
474

475
  oxcf->scaled_frame_width = cfg->rc_scaled_width;
Jingning Han's avatar
Jingning Han committed
476 477 478
  oxcf->scaled_frame_height = cfg->rc_scaled_height;
  if (cfg->rc_resize_allowed == 1) {
    oxcf->resize_mode =
479 480 481
        (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
            ? RESIZE_DYNAMIC
            : RESIZE_FIXED;
Jingning Han's avatar
Jingning Han committed
482 483 484 485
  } else {
    oxcf->resize_mode = RESIZE_NONE;
  }

486 487 488 489 490 491 492 493 494 495
  // 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
  oxcf->superres_enabled = 1;  // TODO(afergs): Check the config
#endif                         // CONFIG_FRAME_SUPERRES

496
  oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
Jingning Han's avatar
Jingning Han committed
497
  oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
498
  oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
Jingning Han's avatar
Jingning Han committed
499

500
  oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
Jingning Han's avatar
Jingning Han committed
501

502 503 504
  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
505

506
  oxcf->auto_key =
Yaowu Xu's avatar
Yaowu Xu committed
507
      cfg->kf_mode == AOM_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
508

509
  oxcf->key_freq = cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
510

511
  oxcf->speed = extra_cfg->cpu_used;
512
  oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
513
#if CONFIG_EXT_REFS
514
  oxcf->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
515
#endif  // CONFIG_EXT_REFS
516 517
  oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
  oxcf->sharpness = extra_cfg->sharpness;
Jingning Han's avatar
Jingning Han committed
518

519
  oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
Jingning Han's avatar
Jingning Han committed
520 521

#if CONFIG_FP_MB_STATS
522
  oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
Jingning Han's avatar
Jingning Han committed
523 524 525
#endif

  oxcf->color_space = extra_cfg->color_space;
526
  oxcf->color_range = extra_cfg->color_range;
527
  oxcf->render_width = extra_cfg->render_width;
528
  oxcf->render_height = extra_cfg->render_height;
Jingning Han's avatar
Jingning Han committed
529
  oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
530
  oxcf->arnr_strength = extra_cfg->arnr_strength;
Jingning Han's avatar
Jingning Han committed
531 532 533 534 535 536
  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;

537 538 539
#if CONFIG_EXT_PARTITION
  oxcf->superblock_size = extra_cfg->superblock_size;
#endif  // CONFIG_EXT_PARTITION
540 541 542
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  oxcf->ans_window_size_log2 = extra_cfg->ans_window_size_log2;
#endif  // CONFIG_ANS && ANS_MAX_SYMBOLS
543 544 545 546 547

#if CONFIG_EXT_TILE
  {
#if CONFIG_EXT_PARTITION
    const unsigned int max =
Yaowu Xu's avatar
Yaowu Xu committed
548
        extra_cfg->superblock_size == AOM_SUPERBLOCK_SIZE_64X64 ? 64 : 32;
549 550 551
#else
    const unsigned int max = 64;
#endif  // CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
552 553
    oxcf->tile_columns = AOMMIN(extra_cfg->tile_columns, max);
    oxcf->tile_rows = AOMMIN(extra_cfg->tile_rows, max);
554
    oxcf->tile_encoding_mode = extra_cfg->tile_encoding_mode;
555 556
  }
#else
Jingning Han's avatar
Jingning Han committed
557
  oxcf->tile_columns = extra_cfg->tile_columns;
558
  oxcf->tile_rows = extra_cfg->tile_rows;
559
#endif  // CONFIG_EXT_TILE
560 561 562
#if CONFIG_DEPENDENT_HORZTILES
  oxcf->dependent_horz_tiles = extra_cfg->dependent_horz_tiles;
#endif
563
#if CONFIG_LOOPFILTERING_ACROSS_TILES
564 565
  oxcf->loop_filter_across_tiles_enabled =
      extra_cfg->loop_filter_across_tiles_enabled;
566
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
567
  oxcf->error_resilient_mode = cfg->g_error_resilient;
Jingning Han's avatar
Jingning Han committed
568 569 570
  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
571 572 573
#if CONFIG_EXT_DELTA_Q
  oxcf->deltaq_mode = extra_cfg->deltaq_mode;
#endif
Jingning Han's avatar
Jingning Han committed
574

575
  oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
Jingning Han's avatar
Jingning Han committed
576

Yunqing Wang's avatar
Yunqing Wang committed
577
  oxcf->motion_vector_unit_test = extra_cfg->motion_vector_unit_test;
Jingning Han's avatar
Jingning Han committed
578
  /*
Yaowu Xu's avatar
Yaowu Xu committed
579
  printf("Current AV1 Settings: \n");
Jingning Han's avatar
Jingning Han committed
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
  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
609
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
610 611
}

Yaowu Xu's avatar
Yaowu Xu committed
612 613 614
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
615 616 617
  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
618
    if (cfg->g_lag_in_frames > 1 || cfg->g_pass != AOM_RC_ONE_PASS)
Jingning Han's avatar
Jingning Han committed
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
      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
635
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
636 637 638 639
    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
640
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
641 642
  }

Yaowu Xu's avatar
Yaowu Xu committed
643
  if (force_key) ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
Jingning Han's avatar
Jingning Han committed
644 645 646 647

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
648
static aom_codec_err_t ctrl_get_quantizer(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
649 650
                                          va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
651 652 653
  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
654 655
}

Yaowu Xu's avatar
Yaowu Xu committed
656
static aom_codec_err_t ctrl_get_quantizer64(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
657 658
                                            va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
659 660 661
  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
662 663
}

Yaowu Xu's avatar
Yaowu Xu committed
664 665 666 667
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
668 669
    ctx->extra_cfg = *extra_cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
Yaowu Xu's avatar
Yaowu Xu committed
670
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
671 672 673 674
  }
  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
675
static aom_codec_err_t ctrl_set_cpuused(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
676
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
677 678
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cpu_used = CAST(AOME_SET_CPUUSED, args);
Jingning Han's avatar
Jingning Han committed
679 680 681
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
682
static aom_codec_err_t ctrl_set_enable_auto_alt_ref(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
683
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
684 685
  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
686 687 688
  return update_extra_cfg(ctx, &extra_cfg);
}

689
#if CONFIG_EXT_REFS
Yaowu Xu's avatar
Yaowu Xu committed
690
static aom_codec_err_t ctrl_set_enable_auto_bwd_ref(aom_codec_alg_priv_t *ctx,
691
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
692 693
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_auto_bwd_ref = CAST(AOME_SET_ENABLEAUTOBWDREF, args);
694 695
  return update_extra_cfg(ctx, &extra_cfg);
}
696
#endif  // CONFIG_EXT_REFS
697

Yaowu Xu's avatar
Yaowu Xu committed
698
static aom_codec_err_t ctrl_set_noise_sensitivity(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
699
                                                  va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
700 701
  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
702 703 704
  return update_extra_cfg(ctx, &extra_cfg);
}

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

Yaowu Xu's avatar
Yaowu Xu committed
712
static aom_codec_err_t ctrl_set_static_thresh(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
713
                                              va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
714 715
  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
716 717 718
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
719
static aom_codec_err_t ctrl_set_tile_columns(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
720
                                             va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
721 722
  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
723 724 725
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
726
static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
727
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
728 729
  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
730 731
  return update_extra_cfg(ctx, &extra_cfg);
}
732 733 734 735 736 737 738 739
#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
740
#if CONFIG_LOOPFILTERING_ACROSS_TILES
741 742 743 744 745 746 747
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);
}
748
#endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
749

Yaowu Xu's avatar
Yaowu Xu committed
750
static aom_codec_err_t ctrl_set_arnr_max_frames(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
751
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
752 753
  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
754 755 756
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
757
static aom_codec_err_t ctrl_set_arnr_strength(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
758
                                              va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
759 760
  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
761 762 763
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
764
static aom_codec_err_t ctrl_set_tuning(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
765
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
766 767
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tuning = CAST(AOME_SET_TUNING, args);
Jingning Han's avatar
Jingning Han committed
768 769 770
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
771
static aom_codec_err_t ctrl_set_cq_level(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
772
                                         va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
773 774
  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
775 776 777
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
778 779 780
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
781
  extra_cfg.rc_max_intra_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
782
      CAST(AOME_SET_MAX_INTRA_BITRATE_PCT, 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 787 788
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
789
  extra_cfg.rc_max_inter_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
790
      CAST(AOME_SET_MAX_INTER_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
791 792 793
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
794
static aom_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(aom_codec_alg_priv_t *ctx,
795
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
796 797
  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
798 799 800
  return update_extra_cfg(ctx, &extra_cfg);
}

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

808
#if CONFIG_AOM_QM
Yaowu Xu's avatar
Yaowu Xu committed
809
static aom_codec_err_t ctrl_set_enable_qm(aom_codec_alg_priv_t *ctx,
810
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
811 812
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_qm = CAST(AV1E_SET_ENABLE_QM, args);
813 814 815
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
816
static aom_codec_err_t ctrl_set_qm_min(aom_codec_alg_priv_t *ctx,
817
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
818 819
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_min = CAST(AV1E_SET_QM_MIN, args);
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_qm_max(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.qm_max = CAST(AV1E_SET_QM_MAX, args);
827 828 829 830
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif

831 832 833 834 835 836 837 838 839 840 841 842 843 844
#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
845 846 847 848 849 850 851 852
#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
853 854 855
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
856
  extra_cfg.frame_parallel_decoding_mode =
Yaowu Xu's avatar
Yaowu Xu committed
857
      CAST(AV1E_SET_FRAME_PARALLEL_DECODING, args);
Jingning Han's avatar
Jingning Han committed
858 859 860
  return update_extra_cfg(ctx, &extra_cfg);
}

861 862 863 864 865 866 867 868 869
#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
870
static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
871
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
872 873
  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
874 875 876
  return update_extra_cfg(ctx, &extra_cfg);
}

Fangwen Fu's avatar
Fangwen Fu committed
877 878 879 880 881 882 883 884
#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
885
static aom_codec_err_t ctrl_set_min_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
886
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
887 888
  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
889 890 891
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
892
static aom_codec_err_t ctrl_set_max_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
893
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
894 895
  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
896 897 898
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
899
static aom_codec_err_t ctrl_set_frame_periodic_boost(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.frame_periodic_boost = CAST(AV1E_SET_FRAME_PERIODIC_BOOST, args);
Jingning Han's avatar
Jingning Han committed
903 904 905
  return update_extra_cfg(ctx, &extra_cfg);
}

Yunqing Wang's avatar
Yunqing Wang committed
906 907 908 909 910 911 912 913
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
914 915 916
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
917 918 919
  (void)data;

  if (ctx->priv == NULL) {
Yaowu Xu's avatar
Yaowu Xu committed
920 921
    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
922

Yaowu Xu's avatar
Yaowu Xu committed
923
    ctx->priv = (aom_codec_priv_t *)priv;
Jingning Han's avatar
Jingning Han committed
924 925
    ctx->priv->init_flags = ctx->init_flags;
    ctx->priv->enc.total_encoders = 1;
Yaowu Xu's avatar
Yaowu Xu committed
926 927
    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
928 929 930

#if CONFIG_MULTITHREAD
    if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
Yaowu Xu's avatar
Yaowu Xu committed
931
      return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
932 933 934 935 936 937 938 939 940 941
    }
#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
942
    once(av1_initialize_enc);
Jingning Han's avatar
Jingning Han committed
943 944 945

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

Yaowu Xu's avatar
Yaowu Xu committed
946
    if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
947
      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
948
#if CONFIG_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
949
      priv->oxcf.use_highbitdepth =
Yaowu Xu's avatar
Yaowu Xu committed
950
          (ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
Jingning Han's avatar
Jingning Han committed
951
#endif
Yaowu Xu's avatar
Yaowu Xu committed
952
      priv->cpi = av1_create_compressor(&priv->oxcf, priv->buffer_pool);
Jingning Han's avatar
Jingning Han committed
953
      if (priv->cpi == NULL)
Yaowu Xu's avatar
Yaowu Xu committed
954
        res = AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
955 956 957 958 959 960 961 962
      else
        priv->cpi->output_pkt_list = &priv->pkt_list.head;
    }
  }

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
963
static aom_codec_err_t encoder_destroy(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
964
  free(ctx->cx_data);
Yaowu Xu's avatar
Yaowu Xu committed
965
  av1_remove_compressor(ctx->cpi);
Jingning Han's avatar
Jingning Han committed
966 967 968
#if CONFIG_MULTITHREAD
  pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
969 970 971
  aom_free(ctx->buffer_pool);
  aom_free(ctx);
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
972 973
}

Yaowu Xu's avatar
Yaowu Xu committed
974
static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
975
                                    unsigned long deadline) {
976
  MODE new_mode = GOOD;
Jingning Han's avatar
Jingning Han committed
977 978

  switch (ctx->cfg.g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
979
    case AOM_RC_ONE_PASS:
980 981
      switch (deadline) {
        default: new_mode = GOOD; break;
Jingning Han's avatar
Jingning Han committed
982 983
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
984
    case AOM_RC_FIRST_PASS: break;
985
    case AOM_RC_LAST_PASS: new_mode = GOOD;
Jingning Han's avatar
Jingning Han committed
986 987 988 989
  }

  if (ctx->oxcf.mode != new_mode) {
    ctx->oxcf.mode = new_mode;
Yaowu Xu's avatar
Yaowu Xu committed
990
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
991 992 993 994 995
  }
}

// Turn on to test if supplemental superframe data breaks decoding
// #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
Yaowu Xu's avatar
Yaowu Xu committed
996
static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
997 998 999
  uint8_t marker = 0xc0;
  unsigned int mask;
  int mag, index_sz;
1000 1001
  int i;
  size_t max_frame_sz = 0;
Jingning Han's avatar
Jingning Han committed
1002 1003 1004 1005 1006 1007

  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;
1008
  for (i = 0; i < ctx->pending_frame_count - 1; i++) {
1009
    const size_t frame_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
1010 1011
    max_frame_sz = frame_sz > max_frame_sz ? frame_sz : max_frame_sz;
  }
Jingning Han's avatar
Jingning Han committed
1012 1013 1014

  // Choose the magnitude
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
1015
    if (max_frame_sz <= mask) break;
Jingning Han's avatar
Jingning Han committed
1016 1017 1018 1019 1020 1021
    mask <<= 8;
    mask |= 0xff;
  }
  marker |= mag << 3;

  // Write the index
hui su's avatar
hui su committed
1022
  index_sz = 2 + (mag + 1) * (ctx->pending_frame_count - 1);
Jingning Han's avatar
Jingning Han committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
  if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
    uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
#ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
    uint8_t marker_test = 0xc0;
    int mag_test = 2;     // 1 - 4
    int frames_test = 4;  // 1 - 8
    int index_sz_test = 2 + mag_test * frames_test;
    marker_test |= frames_test - 1;
    marker_test |= (mag_test - 1) << 3;
    *x++ = marker_test;
    for (i = 0; i < mag_test * frames_test; ++i)
      *x++ = 0;  // fill up with arbitrary data
    *x++ = marker_test;
    ctx->pending_cx_data_sz += index_sz_test;
    printf("Added supplemental superframe data\n");
#endif

    *x++ = marker;
hui su's avatar
hui su committed
1041
    for (i = 0; i < ctx->pending_frame_count - 1; i++) {
1042
      unsigned int this_sz;
1043
      int j;
Jingning Han's avatar
Jingning Han committed
1044

1045
      assert(ctx->pending_frame_sizes[i] > 0);
hui su's avatar
hui su committed
1046
      this_sz = (unsigned int