av1_cx_iface.c 52.4 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_DEBLOCKING_ACROSS_TILES
  unsigned int loop_filter_across_tiles_enabled;
#endif  // CONFIG_DEBLOCKING_ACROSS_TILES
40 41 42 43
  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
44
  aom_tune_metric tuning;
45 46 47 48 49
  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;
50 51 52 53
#if CONFIG_AOM_QM
  unsigned int enable_qm;
  unsigned int qm_min;
  unsigned int qm_max;
54 55 56 57
#endif
#if CONFIG_TILE_GROUPS
  unsigned int num_tg;
  unsigned int mtu_size;
58
#endif
59 60 61
  unsigned int frame_parallel_decoding_mode;
  AQ_MODE aq_mode;
  unsigned int frame_periodic_boost;
Yaowu Xu's avatar
Yaowu Xu committed
62 63 64
  aom_bit_depth_t bit_depth;
  aom_tune_content content;
  aom_color_space_t color_space;
65 66 67
  int color_range;
  int render_width;
  int render_height;
Yaowu Xu's avatar
Yaowu Xu committed
68
  aom_superblock_size_t superblock_size;
69 70 71
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  int ans_window_size_log2;
#endif
Jingning Han's avatar
Jingning Han committed
72 73
};

Yaowu Xu's avatar
Yaowu Xu committed
74
static struct av1_extracfg default_extra_cfg = {
75 76
  0,  // cpu_used
  1,  // enable_auto_alt_ref
77
#if CONFIG_EXT_REFS
78
  0,    // enable_auto_bwd_ref
79
#endif  // CONFIG_EXT_REFS
80 81 82
  0,    // noise_sensitivity
  0,    // sharpness
  0,    // static_thresh
83
#if CONFIG_EXT_TILE
84 85
  UINT_MAX,  // tile_columns
  UINT_MAX,  // tile_rows
86
#else
87 88
  0,  // tile_columns
  0,  // tile_rows
89 90 91 92
#endif  // CONFIG_EXT_TILE
#if CONFIG_DEBLOCKING_ACROSS_TILES
  0,              // loop_filter_across_tiles_enabled
#endif            // CONFIG_DEBLOCKING_ACROSS_TILES
93 94 95 96
  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
97
  AOM_TUNE_PSNR,  // tuning
98 99 100 101 102 103 104 105 106
  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
107 108 109 110
#endif
#if CONFIG_TILE_GROUPS
  1,  // max number of tile groups
  0,  // mtu_size
111
#endif
112 113 114 115 116 117 118 119 120 121 122 123 124
  1,                            // frame_parallel_decoding_mode
  NO_AQ,                        // aq_mode
  0,                            // frame_periodic_delta_q
  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
Jingning Han's avatar
Jingning Han committed
125 126
};

Yaowu Xu's avatar
Yaowu Xu committed
127 128 129 130 131 132
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;
133 134 135 136 137 138
  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
139 140 141 142
  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;
143
  unsigned int fixed_kf_cntr;
Jingning Han's avatar
Jingning Han committed
144
  // BufferPool that holds all reference frames.
145
  BufferPool *buffer_pool;
Jingning Han's avatar
Jingning Han committed
146 147
};

Yaowu Xu's avatar
Yaowu Xu committed
148 149 150
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
151

Yaowu Xu's avatar
Yaowu Xu committed
152
  if (res != AOM_CODEC_OK)
Jingning Han's avatar
Jingning Han committed
153 154 155 156 157 158
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;

  return res;
}

#undef ERROR
159 160 161
#define ERROR(str)                  \
  do {                              \
    ctx->base.err_detail = str;     \
Yaowu Xu's avatar
Yaowu Xu committed
162
    return AOM_CODEC_INVALID_PARAM; \
Jingning Han's avatar
Jingning Han committed
163 164
  } while (0)

165 166 167 168
#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
169 170
  } while (0)

171 172 173
#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
174 175
  } while (0)

176 177 178
#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
179 180
  } while (0)

181 182 183
#define RANGE_CHECK_BOOL(p, memb)                                     \
  do {                                                                \
    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
Jingning Han's avatar
Jingning Han committed
184 185
  } while (0)

Yaowu Xu's avatar
Yaowu Xu committed
186 187 188
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) {
189 190 191 192 193 194 195 196
  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
197
  RANGE_CHECK_BOOL(extra_cfg, lossless);
198
  RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1);
199
  RANGE_CHECK_HI(extra_cfg, frame_periodic_boost, 1);
200 201
  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
202
  RANGE_CHECK(cfg, rc_end_usage, AOM_VBR, AOM_Q);
203 204
  RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
  RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
Jingning Han's avatar
Jingning Han committed
205
  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
Yaowu Xu's avatar
Yaowu Xu committed
206
  RANGE_CHECK(cfg, kf_mode, AOM_KF_DISABLED, AOM_KF_AUTO);
207 208 209
  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
210
  RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
Yaowu Xu's avatar
Yaowu Xu committed
211
  RANGE_CHECK(cfg, g_pass, AOM_RC_ONE_PASS, AOM_RC_LAST_PASS);
212 213
  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
214 215 216 217 218
  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,
219
                (MAX_LAG_BUFFERS - 1));
Jingning Han's avatar
Jingning Han committed
220 221 222
  }

  if (cfg->rc_resize_allowed == 1) {
223 224
    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
225 226
  }

Yaowu Xu's avatar
Yaowu Xu committed
227
  // AV1 does not support a lower bound on the keyframe interval in
Jingning Han's avatar
Jingning Han committed
228
  // automatic keyframe placement mode.
Yaowu Xu's avatar
Yaowu Xu committed
229
  if (cfg->kf_mode != AOM_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
Jingning Han's avatar
Jingning Han committed
230
      cfg->kf_min_dist > 0)
231 232 233
    ERROR(
        "kf_min_dist not supported in auto mode, use 0 "
        "or kf_max_dist instead.");
Jingning Han's avatar
Jingning Han committed
234

235
  RANGE_CHECK_HI(extra_cfg, enable_auto_alt_ref, 2);
236
#if CONFIG_EXT_REFS
237
  RANGE_CHECK_HI(extra_cfg, enable_auto_bwd_ref, 2);
238
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
239 240
  RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
  RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
Yaowu Xu's avatar
Yaowu Xu committed
241 242
  RANGE_CHECK(extra_cfg, superblock_size, AOM_SUPERBLOCK_SIZE_64X64,
              AOM_SUPERBLOCK_SIZE_DYNAMIC);
243
#if CONFIG_EXT_TILE
244 245 246
// 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.
247
#if CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
248
  if (extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_64X64) {
249 250 251 252 253 254 255 256 257 258 259 260
    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);
  }
261
#else
262 263
  RANGE_CHECK_HI(extra_cfg, tile_columns, 6);
  RANGE_CHECK_HI(extra_cfg, tile_rows, 2);
264
#endif  // CONFIG_EXT_TILE
265 266 267
#if CONFIG_DEBLOCKING_ACROSS_TILES
  RANGE_CHECK_HI(extra_cfg, loop_filter_across_tiles_enabled, 1);
#endif  // CONFIG_DEBLOCKING_ACROSS_TILES
Jingning Han's avatar
Jingning Han committed
268
  RANGE_CHECK_HI(extra_cfg, sharpness, 7);
269
  RANGE_CHECK_HI(extra_cfg, arnr_max_frames, 15);
Jingning Han's avatar
Jingning Han committed
270
  RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
271
  RANGE_CHECK_HI(extra_cfg, cq_level, 63);
Yaowu Xu's avatar
Yaowu Xu committed
272
  RANGE_CHECK(cfg, g_bit_depth, AOM_BITS_8, AOM_BITS_12);
Jingning Han's avatar
Jingning Han committed
273
  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
Yaowu Xu's avatar
Yaowu Xu committed
274
  RANGE_CHECK(extra_cfg, content, AOM_CONTENT_DEFAULT, AOM_CONTENT_INVALID - 1);
Jingning Han's avatar
Jingning Han committed
275

Yaowu Xu's avatar
Yaowu Xu committed
276 277 278
  // 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
279

Yaowu Xu's avatar
Yaowu Xu committed
280
  if (cfg->g_pass == AOM_RC_LAST_PASS) {
Jingning Han's avatar
Jingning Han committed
281 282 283 284 285 286 287 288 289 290
    const size_t packet_sz = sizeof(FIRSTPASS_STATS);
    const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
    const FIRSTPASS_STATS *stats;

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

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

Yunqing Wang's avatar
Yunqing Wang committed
291 292
    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
293

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

Yunqing Wang's avatar
Yunqing Wang committed
297 298
    if ((int)(stats->count + 0.5) != n_packets - 1)
      ERROR("rc_twopass_stats_in missing EOS stats packet");
Jingning Han's avatar
Jingning Han committed
299 300
  }

Yaowu Xu's avatar
Yaowu Xu committed
301
#if !CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
302 303 304 305 306
  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
307
      cfg->g_bit_depth > AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
308 309
    ERROR("Codec high bit-depth not supported in profile < 2");
  }
310
  if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
Jingning Han's avatar
Jingning Han committed
311 312 313
    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
314
      cfg->g_bit_depth == AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
315 316
    ERROR("Codec bit-depth 8 not supported in profile > 1");
  }
Yaowu Xu's avatar
Yaowu Xu committed
317
  RANGE_CHECK(extra_cfg, color_space, AOM_CS_UNKNOWN, AOM_CS_SRGB);
318
  RANGE_CHECK(extra_cfg, color_range, 0, 1);
319 320 321
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  RANGE_CHECK(extra_cfg, ans_window_size_log2, 8, 23);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
322
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
323 324
}

Yaowu Xu's avatar
Yaowu Xu committed
325 326
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
327
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
328 329 330 331 332 333
    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
334
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
335 336 337
        ERROR(
            "Invalid image format. I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
338 339
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
340 341 342
    case AOM_IMG_FMT_I42216:
    case AOM_IMG_FMT_I44416:
    case AOM_IMG_FMT_I44016:
Jingning Han's avatar
Jingning Han committed
343 344
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
          ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
345 346 347
        ERROR(
            "Invalid image format. 16-bit I422, I444, I440 images are "
            "not supported in profile.");
Jingning Han's avatar
Jingning Han committed
348 349 350
      }
      break;
    default:
351 352 353
      ERROR(
          "Invalid image format. Only YV12, I420, I422, I444 images are "
          "supported.");
Jingning Han's avatar
Jingning Han committed
354 355 356 357 358 359
      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
360
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
361 362
}

Yaowu Xu's avatar
Yaowu Xu committed
363
static int get_image_bps(const aom_image_t *img) {
Jingning Han's avatar
Jingning Han committed
364
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
365 366 367 368 369 370 371 372 373
    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
374 375 376 377 378
    default: assert(0 && "Invalid image format"); break;
  }
  return 0;
}

Yaowu Xu's avatar
Yaowu Xu committed
379 380 381 382
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
383 384
  oxcf->profile = cfg->g_profile;
  oxcf->max_threads = (int)cfg->g_threads;
385 386
  oxcf->width = cfg->g_w;
  oxcf->height = cfg->g_h;
Jingning Han's avatar
Jingning Han committed
387 388 389 390
  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;
391
  if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
Jingning Han's avatar
Jingning Han committed
392 393 394 395

  oxcf->mode = GOOD;

  switch (cfg->g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
396 397 398
    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
399 400
  }

401
  oxcf->lag_in_frames =
Yaowu Xu's avatar
Yaowu Xu committed
402
      cfg->g_pass == AOM_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
Jingning Han's avatar
Jingning Han committed
403 404 405 406 407 408 409 410 411
  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
412
      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_min_quantizer);
Jingning Han's avatar
Jingning Han committed
413
  oxcf->worst_allowed_q =
Yaowu Xu's avatar
Yaowu Xu committed
414 415
      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
416 417
  oxcf->fixed_q = -1;

418 419 420 421 422 423
#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

424 425 426 427 428
#if CONFIG_TILE_GROUPS
  oxcf->num_tile_groups = extra_cfg->num_tg;
  oxcf->mtu = extra_cfg->mtu_size;
#endif

429 430
  oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
  oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
Jingning Han's avatar
Jingning Han committed
431

432
  oxcf->scaled_frame_width = cfg->rc_scaled_width;
Jingning Han's avatar
Jingning Han committed
433 434 435
  oxcf->scaled_frame_height = cfg->rc_scaled_height;
  if (cfg->rc_resize_allowed == 1) {
    oxcf->resize_mode =
436 437 438
        (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
            ? RESIZE_DYNAMIC
            : RESIZE_FIXED;
Jingning Han's avatar
Jingning Han committed
439 440 441 442
  } else {
    oxcf->resize_mode = RESIZE_NONE;
  }

443
  oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
Jingning Han's avatar
Jingning Han committed
444
  oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
445
  oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
Jingning Han's avatar
Jingning Han committed
446

447
  oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
Jingning Han's avatar
Jingning Han committed
448

449 450 451
  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
452

453
  oxcf->auto_key =
Yaowu Xu's avatar
Yaowu Xu committed
454
      cfg->kf_mode == AOM_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
455

456
  oxcf->key_freq = cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
457

458 459
  oxcf->speed = abs(extra_cfg->cpu_used);
  oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
460
#if CONFIG_EXT_REFS
461
  oxcf->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
462
#endif  // CONFIG_EXT_REFS
463 464
  oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
  oxcf->sharpness = extra_cfg->sharpness;
Jingning Han's avatar
Jingning Han committed
465

466
  oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
Jingning Han's avatar
Jingning Han committed
467 468

#if CONFIG_FP_MB_STATS
469
  oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
Jingning Han's avatar
Jingning Han committed
470 471 472
#endif

  oxcf->color_space = extra_cfg->color_space;
473
  oxcf->color_range = extra_cfg->color_range;
474
  oxcf->render_width = extra_cfg->render_width;
475
  oxcf->render_height = extra_cfg->render_height;
Jingning Han's avatar
Jingning Han committed
476
  oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
477
  oxcf->arnr_strength = extra_cfg->arnr_strength;
Jingning Han's avatar
Jingning Han committed
478 479 480 481 482 483
  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;

484 485 486
#if CONFIG_EXT_PARTITION
  oxcf->superblock_size = extra_cfg->superblock_size;
#endif  // CONFIG_EXT_PARTITION
487 488 489
#if CONFIG_ANS && ANS_MAX_SYMBOLS
  oxcf->ans_window_size_log2 = extra_cfg->ans_window_size_log2;
#endif  // CONFIG_ANS && ANS_MAX_SYMBOLS
490 491 492 493 494

#if CONFIG_EXT_TILE
  {
#if CONFIG_EXT_PARTITION
    const unsigned int max =
Yaowu Xu's avatar
Yaowu Xu committed
495
        extra_cfg->superblock_size == AOM_SUPERBLOCK_SIZE_64X64 ? 64 : 32;
496 497 498
#else
    const unsigned int max = 64;
#endif  // CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
499 500
    oxcf->tile_columns = AOMMIN(extra_cfg->tile_columns, max);
    oxcf->tile_rows = AOMMIN(extra_cfg->tile_rows, max);
501 502
  }
#else
Jingning Han's avatar
Jingning Han committed
503
  oxcf->tile_columns = extra_cfg->tile_columns;
504
  oxcf->tile_rows = extra_cfg->tile_rows;
505
#endif  // CONFIG_EXT_TILE
Jingning Han's avatar
Jingning Han committed
506

507 508 509 510 511
#if CONFIG_DEBLOCKING_ACROSS_TILES
  oxcf->loop_filter_across_tiles_enabled =
      extra_cfg->loop_filter_across_tiles_enabled;
#endif  // CONFIG_DEBLOCKING_ACROSS_TILES

512
  oxcf->error_resilient_mode = cfg->g_error_resilient;
Jingning Han's avatar
Jingning Han committed
513 514 515 516
  oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;

  oxcf->aq_mode = extra_cfg->aq_mode;

517
  oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
Jingning Han's avatar
Jingning Han committed
518 519

  /*
Yaowu Xu's avatar
Yaowu Xu committed
520
  printf("Current AV1 Settings: \n");
Jingning Han's avatar
Jingning Han committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
  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
550
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
551 552
}

Yaowu Xu's avatar
Yaowu Xu committed
553 554 555
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
556 557 558
  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
559
    if (cfg->g_lag_in_frames > 1 || cfg->g_pass != AOM_RC_ONE_PASS)
Jingning Han's avatar
Jingning Han committed
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
      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
576
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
577 578 579 580
    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
581
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
582 583
  }

Yaowu Xu's avatar
Yaowu Xu committed
584
  if (force_key) ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
Jingning Han's avatar
Jingning Han committed
585 586 587 588

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
589
static aom_codec_err_t ctrl_get_quantizer(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
590 591
                                          va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
592 593 594
  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
595 596
}

Yaowu Xu's avatar
Yaowu Xu committed
597
static aom_codec_err_t ctrl_get_quantizer64(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
598 599
                                            va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
600 601 602
  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
603 604
}

Yaowu Xu's avatar
Yaowu Xu committed
605 606 607 608
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
609 610
    ctx->extra_cfg = *extra_cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
Yaowu Xu's avatar
Yaowu Xu committed
611
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
612 613 614 615
  }
  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
616
static aom_codec_err_t ctrl_set_cpuused(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
617
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
618 619
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cpu_used = CAST(AOME_SET_CPUUSED, args);
Jingning Han's avatar
Jingning Han committed
620 621 622
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
623
static aom_codec_err_t ctrl_set_enable_auto_alt_ref(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
624
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
625 626
  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
627 628 629
  return update_extra_cfg(ctx, &extra_cfg);
}

630
#if CONFIG_EXT_REFS
Yaowu Xu's avatar
Yaowu Xu committed
631
static aom_codec_err_t ctrl_set_enable_auto_bwd_ref(aom_codec_alg_priv_t *ctx,
632
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
633 634
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_auto_bwd_ref = CAST(AOME_SET_ENABLEAUTOBWDREF, args);
635 636
  return update_extra_cfg(ctx, &extra_cfg);
}
637
#endif  // CONFIG_EXT_REFS
638

Yaowu Xu's avatar
Yaowu Xu committed
639
static aom_codec_err_t ctrl_set_noise_sensitivity(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
640
                                                  va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
641 642
  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
643 644 645
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
646
static aom_codec_err_t ctrl_set_sharpness(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
647
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
648 649
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.sharpness = CAST(AOME_SET_SHARPNESS, args);
Jingning Han's avatar
Jingning Han committed
650 651 652
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
653
static aom_codec_err_t ctrl_set_static_thresh(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
654
                                              va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
655 656
  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
657 658 659
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
660
static aom_codec_err_t ctrl_set_tile_columns(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
661
                                             va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
662 663
  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
664 665 666
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
667
static aom_codec_err_t ctrl_set_tile_rows(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
668
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
669 670
  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
671 672 673
  return update_extra_cfg(ctx, &extra_cfg);
}

674 675 676 677 678 679 680 681 682 683
#if CONFIG_DEBLOCKING_ACROSS_TILES
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);
}
#endif  // CONFIG_DEBLOCKING_ACROSS_TILES

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

Yaowu Xu's avatar
Yaowu Xu committed
691
static aom_codec_err_t ctrl_set_arnr_strength(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
692
                                              va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
693 694
  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
695 696 697
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
698
static aom_codec_err_t ctrl_set_tuning(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.tuning = CAST(AOME_SET_TUNING, 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_cq_level(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.cq_level = CAST(AOME_SET_CQ_LEVEL, 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 713 714
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
715
  extra_cfg.rc_max_intra_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
716
      CAST(AOME_SET_MAX_INTRA_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
717 718 719
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
720 721 722
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
723
  extra_cfg.rc_max_inter_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
724
      CAST(AOME_SET_MAX_INTER_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
725 726 727
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
728
static aom_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(aom_codec_alg_priv_t *ctx,
729
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
730 731
  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
732 733 734
  return update_extra_cfg(ctx, &extra_cfg);
}

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

742
#if CONFIG_AOM_QM
Yaowu Xu's avatar
Yaowu Xu committed
743
static aom_codec_err_t ctrl_set_enable_qm(aom_codec_alg_priv_t *ctx,
744
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
745 746
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_qm = CAST(AV1E_SET_ENABLE_QM, args);
747 748 749
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
750
static aom_codec_err_t ctrl_set_qm_min(aom_codec_alg_priv_t *ctx,
751
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
752 753
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_min = CAST(AV1E_SET_QM_MIN, args);
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_qm_max(aom_codec_alg_priv_t *ctx,
758
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
759 760
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_max = CAST(AV1E_SET_QM_MAX, args);
761 762 763 764
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif

765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
#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

Yaowu Xu's avatar
Yaowu Xu committed
780 781 782
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
783
  extra_cfg.frame_parallel_decoding_mode =
Yaowu Xu's avatar
Yaowu Xu committed
784
      CAST(AV1E_SET_FRAME_PARALLEL_DECODING, args);
Jingning Han's avatar
Jingning Han committed
785 786 787
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
788
static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
789
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
790 791
  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
792 793 794
  return update_extra_cfg(ctx, &extra_cfg);
}

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

Yaowu Xu's avatar
Yaowu Xu committed
802
static aom_codec_err_t ctrl_set_max_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
803
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
804 805
  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
806 807 808
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
809
static aom_codec_err_t ctrl_set_frame_periodic_boost(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
810
                                                     va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
811 812
  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
813 814 815
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
816 817 818
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
819 820 821
  (void)data;

  if (ctx->priv == NULL) {
Yaowu Xu's avatar
Yaowu Xu committed
822 823
    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
824

Yaowu Xu's avatar
Yaowu Xu committed
825
    ctx->priv = (aom_codec_priv_t *)priv;
Jingning Han's avatar
Jingning Han committed
826 827
    ctx->priv->init_flags = ctx->init_flags;
    ctx->priv->enc.total_encoders = 1;
Yaowu Xu's avatar
Yaowu Xu committed
828 829
    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
830 831 832

#if CONFIG_MULTITHREAD
    if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
Yaowu Xu's avatar
Yaowu Xu committed
833
      return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
834 835 836 837 838 839 840 841 842 843
    }
#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
844
    once(av1_initialize_enc);
Jingning Han's avatar
Jingning Han committed
845 846 847

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

Yaowu Xu's avatar
Yaowu Xu committed
848
    if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
849
      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
Yaowu Xu's avatar
Yaowu Xu committed
850
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
851
      priv->oxcf.use_highbitdepth =
Yaowu Xu's avatar
Yaowu Xu committed
852
          (ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
Jingning Han's avatar
Jingning Han committed
853
#endif
Yaowu Xu's avatar
Yaowu Xu committed
854
      priv->cpi = av1_create_compressor(&priv->oxcf, priv->buffer_pool);
Jingning Han's avatar
Jingning Han committed
855
      if (priv->cpi == NULL)
Yaowu Xu's avatar
Yaowu Xu committed
856
        res = AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
857 858 859 860 861 862 863 864
      else
        priv->cpi->output_pkt_list = &priv->pkt_list.head;
    }
  }

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
865
static aom_codec_err_t encoder_destroy(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
866
  free(ctx->cx_data);
Yaowu Xu's avatar
Yaowu Xu committed
867
  av1_remove_compressor(ctx->cpi);
Jingning Han's avatar
Jingning Han committed
868 869 870
#if CONFIG_MULTITHREAD
  pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
871 872 873
  aom_free(ctx->buffer_pool);
  aom_free(ctx);
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
874 875
}

Yaowu Xu's avatar
Yaowu Xu committed
876
static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
877 878 879 880
                                    unsigned long deadline) {
  MODE new_mode = BEST;

  switch (ctx->cfg.g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
881
    case AOM_RC_ONE_PASS:
882 883 884 885
      switch (deadline) {
        case AOM_DL_BEST_QUALITY: new_mode = BEST; break;
        case AOM_DL_REALTIME: new_mode = REALTIME; break;
        default: new_mode = GOOD; break;
Jingning Han's avatar
Jingning Han committed
886 887
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
888 889
    case AOM_RC_FIRST_PASS: break;
    case AOM_RC_LAST_PASS: new_mode = deadline > 0 ? GOOD : BEST; break;
Jingning Han's avatar
Jingning Han committed
890 891 892 893
  }

  if (ctx->oxcf.mode != new_mode) {
    ctx->oxcf.mode = new_mode;
Yaowu Xu's avatar
Yaowu Xu committed
894
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
895 896 897 898 899
  }
}

// Turn on to test if supplemental superframe data breaks decoding
// #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
Yaowu Xu's avatar
Yaowu Xu committed
900
static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
901 902 903
  uint8_t marker = 0xc0;
  unsigned int mask;
  int mag, index_sz;
904 905
  int i;
  size_t max_frame_sz = 0;
Jingning Han's avatar
Jingning Han committed
906 907 908 909 910 911

  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;
912
  for (i = 0; i < ctx->pending_frame_count - 1; i++) {
913
    const size_t frame_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
914 915
    max_frame_sz = frame_sz > max_frame_sz ? frame_sz : max_frame_sz;
  }
Jingning Han's avatar
Jingning Han committed
916 917 918

  // Choose the magnitude
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
919
    if (max_frame_sz <= mask) break;
Jingning Han's avatar
Jingning Han committed
920 921 922 923 924 925
    mask <<= 8;
    mask |= 0xff;
  }
  marker |= mag << 3;

  // Write the index
hui su's avatar
hui su committed
926
  index_sz = 2 + (mag + 1) * (ctx->pending_frame_count - 1);
Jingning Han's avatar
Jingning Han committed
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
  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
945
    for (i = 0; i < ctx->pending_frame_count - 1; i++) {
946
      unsigned int this_sz;
947
      int j;
Jingning Han's avatar
Jingning Han committed
948

949
      assert(ctx->pending_frame_sizes[i] > 0);
hui su's avatar
hui su committed
950
      this_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
Jingning Han's avatar
Jingning Han committed
951 952 953 954 955 956 957 958 959 960 961 962 963 964
      for (j = 0; j <= mag; j++) {
        *x++ = this_sz & 0xff;
        this_sz >>= 8;
      }
    }
    *x++ = marker;
    ctx->pending_cx_data_sz += index_sz;
#ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
    index_sz += index_sz_test;
#endif
  }
  return index_sz;
}

Yaowu Xu's avatar
Yaowu Xu committed
965
// av1 uses 10,000,000 ticks/second as time stamp
Jingning Han's avatar
Jingning Han committed
966 967
#define TICKS_PER_SEC 10000000LL

Yaowu Xu's avatar
Yaowu Xu committed
968
static int64_t timebase_units_to_ticks(const aom_rational_t *timebase,
Jingning Han's avatar
Jingning Han committed
969 970 971 972
                                       int64_t n) {
  return n * TICKS_PER_SEC * timebase->num / timebase->den;
}

Yaowu Xu's avatar
Yaowu Xu committed
973
static int64_t ticks_to_timebase_units(const aom_rational_t *timebase,
Jingning Han's avatar
Jingning Han committed
974 975 976 977 978
                                       int64_t n) {
  const int64_t round = TICKS_PER_SEC * timebase->num / 2 - 1;
  return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
}

Yaowu Xu's avatar
Yaowu Xu committed
979
static aom_codec_frame_flags_t get_frame_pkt_flags(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
980
                                                   unsigned int lib_flags) {
Yaowu Xu's avatar
Yaowu Xu committed
981
  aom_codec_frame_flags_t flags = lib_flags << 16;
Jingning Han's avatar
Jingning Han committed
982

Yaowu Xu's avatar
Yaowu Xu committed
983
  if (lib_flags & FRAMEFLAGS_KEY) flags |= AOM_FRAME_IS_KEY;
Jingning Han's avatar
Jingning Han committed
984

Yaowu Xu's avatar
Yaowu Xu committed
985
  if (cpi->droppable) flags |= AOM_FRAME_IS_DROPPABLE;
Jingning Han's avatar
Jingning Han committed
986 987 988 989

  return flags;
}

990
const size_t kMinCompressedSize = 8192;
Yaowu Xu's avatar
Yaowu Xu committed
991 992 993
static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
                                      const aom_image_t *img,
                                      aom_codec_pts_t pts,
Jingning Han's avatar
Jingning Han committed
994
                                      unsigned long duration,
Yaowu Xu's avatar
Yaowu Xu committed
995
                                      aom_enc_frame_flags_t enc_flags,
Jingning Han's avatar
Jingning Han committed
996
                                      unsigned long deadline) {
Yaowu Xu's avatar
Yaowu Xu committed
997 998 999 1000
  volatile aom_codec_err_t res = AOM_CODEC_OK;
  volatile aom_enc_frame_flags_t flags = enc_flags;
  AV1_COMP *const cpi = ctx->cpi;
  const aom_rational_t *const timebase = &ctx->cfg.g_timebase;
Jingning Han's avatar
Jingning Han committed
1001 1002
  size_t data_sz;

Yaowu Xu's avatar
Yaowu Xu committed
1003
  if (cpi == NULL) return AOM_CODEC_INVALID_PARAM;
1004

Jingning Han's avatar
Jingning Han committed
1005 1006 1007 1008
  if (img != NULL) {
    res = validate_img(ctx, img);
    // TODO(jzern) the checks related to cpi's validity should be treated as a
    // failure condition, encoder setup is done fully in init() currently.
Yaowu Xu's avatar
Yaowu Xu committed
1009
    if (res == AOM_CODEC_OK) {
1010
#if CONFIG_EXT_REFS
1011 1012
      data_sz = ALIGN_POWER_OF_TWO(ctx->cfg.g_w, 5) *
                ALIGN_POWER_OF_TWO(ctx->cfg.g_h, 5) * get_image_bps(img);
1013
#else
1014 1015
      // There's no codec control for multiple alt-refs so check the encoder
      // instance for its status to determine the compressed data size.
1016 1017
      data_sz = ALIGN_POWER_OF_TWO(ctx->cfg.g_w, 5) *
                ALIGN_POWER_OF_TWO(ctx->cfg.g_h, 5) * get_image_bps(img) / 8 *
Jingning Han's avatar
Jingning Han committed
1018
                (cpi->multi_arf_allowed ? 8 : 2);
1019
#endif  // CONFIG_EXT_REFS
1020
      if (data_sz < kMinCompressedSize) data_sz = kMinCompressedSize;
Jingning Han's avatar
Jingning Han committed
1021 1022 1023
      if (ctx->cx_data == NULL || ctx->cx_data_sz < data_sz) {
        ctx->cx_data_sz = data_sz;
        free(ctx->cx_data);
1024
        ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
Jingning Han's avatar
Jingning Han committed
1025
        if (ctx->cx_data == NULL) {
Yaowu Xu's avatar
Yaowu Xu committed
1026
          return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
1027 1028 1029 1030 1031
        }
      }
    }
  }

1032
  pick_quickcompress_mode(ctx, deadline);
Yaowu Xu's avatar
Yaowu Xu committed
1033
  aom_codec_pkt_list_init(&ctx->pkt_list);
Jingning Han's avatar
Jingning Han committed
1034 1035

  // Handle Flags
Yaowu Xu's avatar
Yaowu Xu committed
1036 1037
  if (((flags & AOM_EFLAG_NO_UPD_GF) && (flags & AOM_EFLAG_FORCE_GF)) ||
      ((flags & AOM_EFLAG_NO_UPD_ARF) && (flags & AOM_EFLAG_FORCE_ARF))) {
Jingning Han's avatar
Jingning Han committed
1038
    ctx->base.err_detail = "Conflicting flags.";
Yaowu Xu's avatar
Yaowu Xu committed
1039
    return AOM_CODEC_INVALID_PARAM;
Jingning Han's avatar
Jingning Han committed
1040 1041
  }

James Zern's avatar
James Zern committed
1042 1043 1044
  if (setjmp(cpi->common.error.jmp)) {
    cpi->common.error.setjmp = 0;
    res = update_error_state(ctx, &cpi->common.error);
Yaowu Xu's avatar
Yaowu Xu committed
1045
    aom_clear_system_state();
James Zern's avatar
James Zern committed
1046 1047 1048