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);