av1_cx_iface.c 51.6 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;
Jingning Han's avatar
Jingning Han committed
69
70
};

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

Yaowu Xu's avatar
Yaowu Xu committed
121
122
123
124
125
126
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;
127
128
129
130
131
132
  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
133
134
135
136
  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;
137
  unsigned int fixed_kf_cntr;
Jingning Han's avatar
Jingning Han committed
138
  // BufferPool that holds all reference frames.
139
  BufferPool *buffer_pool;
Jingning Han's avatar
Jingning Han committed
140
141
};

Yaowu Xu's avatar
Yaowu Xu committed
142
143
144
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
145

Yaowu Xu's avatar
Yaowu Xu committed
146
  if (res != AOM_CODEC_OK)
Jingning Han's avatar
Jingning Han committed
147
148
149
150
151
152
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;

  return res;
}

#undef ERROR
153
154
155
#define ERROR(str)                  \
  do {                              \
    ctx->base.err_detail = str;     \
Yaowu Xu's avatar
Yaowu Xu committed
156
    return AOM_CODEC_INVALID_PARAM; \
Jingning Han's avatar
Jingning Han committed
157
158
  } while (0)

159
160
161
162
#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
163
164
  } while (0)

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

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

175
176
177
#define RANGE_CHECK_BOOL(p, memb)                                     \
  do {                                                                \
    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
Jingning Han's avatar
Jingning Han committed
178
179
  } while (0)

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

  if (cfg->rc_resize_allowed == 1) {
217
218
    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
219
220
  }

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

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

Yaowu Xu's avatar
Yaowu Xu committed
270
271
272
  // 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
273

Yaowu Xu's avatar
Yaowu Xu committed
274
  if (cfg->g_pass == AOM_RC_LAST_PASS) {
Jingning Han's avatar
Jingning Han committed
275
276
277
278
279
280
281
282
283
284
    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
285
286
    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
287

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

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

Yaowu Xu's avatar
Yaowu Xu committed
295
#if !CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
296
297
298
299
300
  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
301
      cfg->g_bit_depth > AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
302
303
    ERROR("Codec high bit-depth not supported in profile < 2");
  }
304
  if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
Jingning Han's avatar
Jingning Han committed
305
306
307
    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
308
      cfg->g_bit_depth == AOM_BITS_8) {
Jingning Han's avatar
Jingning Han committed
309
310
    ERROR("Codec bit-depth 8 not supported in profile > 1");
  }
Yaowu Xu's avatar
Yaowu Xu committed
311
  RANGE_CHECK(extra_cfg, color_space, AOM_CS_UNKNOWN, AOM_CS_SRGB);
312
  RANGE_CHECK(extra_cfg, color_range, 0, 1);
Yaowu Xu's avatar
Yaowu Xu committed
313
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
314
315
}

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

Yaowu Xu's avatar
Yaowu Xu committed
354
static int get_image_bps(const aom_image_t *img) {
Jingning Han's avatar
Jingning Han committed
355
  switch (img->fmt) {
Yaowu Xu's avatar
Yaowu Xu committed
356
357
358
359
360
361
362
363
364
    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
365
366
367
368
369
    default: assert(0 && "Invalid image format"); break;
  }
  return 0;
}

Yaowu Xu's avatar
Yaowu Xu committed
370
371
372
373
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
374
375
  oxcf->profile = cfg->g_profile;
  oxcf->max_threads = (int)cfg->g_threads;
376
377
  oxcf->width = cfg->g_w;
  oxcf->height = cfg->g_h;
Jingning Han's avatar
Jingning Han committed
378
379
380
381
  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;
382
  if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
Jingning Han's avatar
Jingning Han committed
383
384
385
386

  oxcf->mode = GOOD;

  switch (cfg->g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
387
388
389
    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
390
391
  }

392
  oxcf->lag_in_frames =
Yaowu Xu's avatar
Yaowu Xu committed
393
      cfg->g_pass == AOM_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
Jingning Han's avatar
Jingning Han committed
394
395
396
397
398
399
400
401
402
  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
403
      extra_cfg->lossless ? 0 : av1_quantizer_to_qindex(cfg->rc_min_quantizer);
Jingning Han's avatar
Jingning Han committed
404
  oxcf->worst_allowed_q =
Yaowu Xu's avatar
Yaowu Xu committed
405
406
      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
407
408
  oxcf->fixed_q = -1;

409
410
411
412
413
414
#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

415
416
417
418
419
#if CONFIG_TILE_GROUPS
  oxcf->num_tile_groups = extra_cfg->num_tg;
  oxcf->mtu = extra_cfg->mtu_size;
#endif

420
421
  oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
  oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
Jingning Han's avatar
Jingning Han committed
422

423
  oxcf->scaled_frame_width = cfg->rc_scaled_width;
Jingning Han's avatar
Jingning Han committed
424
425
426
  oxcf->scaled_frame_height = cfg->rc_scaled_height;
  if (cfg->rc_resize_allowed == 1) {
    oxcf->resize_mode =
427
428
429
        (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
            ? RESIZE_DYNAMIC
            : RESIZE_FIXED;
Jingning Han's avatar
Jingning Han committed
430
431
432
433
  } else {
    oxcf->resize_mode = RESIZE_NONE;
  }

434
  oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
Jingning Han's avatar
Jingning Han committed
435
  oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
436
  oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
Jingning Han's avatar
Jingning Han committed
437

438
  oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
Jingning Han's avatar
Jingning Han committed
439

440
441
442
  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
443

444
  oxcf->auto_key =
Yaowu Xu's avatar
Yaowu Xu committed
445
      cfg->kf_mode == AOM_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
446

447
  oxcf->key_freq = cfg->kf_max_dist;
Jingning Han's avatar
Jingning Han committed
448

449
450
  oxcf->speed = abs(extra_cfg->cpu_used);
  oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
451
#if CONFIG_EXT_REFS
452
  oxcf->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
453
#endif  // CONFIG_EXT_REFS
454
455
  oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
  oxcf->sharpness = extra_cfg->sharpness;
Jingning Han's avatar
Jingning Han committed
456

457
  oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
Jingning Han's avatar
Jingning Han committed
458
459

#if CONFIG_FP_MB_STATS
460
  oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
Jingning Han's avatar
Jingning Han committed
461
462
463
#endif

  oxcf->color_space = extra_cfg->color_space;
464
  oxcf->color_range = extra_cfg->color_range;
465
  oxcf->render_width = extra_cfg->render_width;
466
  oxcf->render_height = extra_cfg->render_height;
Jingning Han's avatar
Jingning Han committed
467
  oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
468
  oxcf->arnr_strength = extra_cfg->arnr_strength;
Jingning Han's avatar
Jingning Han committed
469
470
471
472
473
474
  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;

475
476
477
478
479
480
481
482
#if CONFIG_EXT_PARTITION
  oxcf->superblock_size = extra_cfg->superblock_size;
#endif  // CONFIG_EXT_PARTITION

#if CONFIG_EXT_TILE
  {
#if CONFIG_EXT_PARTITION
    const unsigned int max =
Yaowu Xu's avatar
Yaowu Xu committed
483
        extra_cfg->superblock_size == AOM_SUPERBLOCK_SIZE_64X64 ? 64 : 32;
484
485
486
#else
    const unsigned int max = 64;
#endif  // CONFIG_EXT_PARTITION
Yaowu Xu's avatar
Yaowu Xu committed
487
488
    oxcf->tile_columns = AOMMIN(extra_cfg->tile_columns, max);
    oxcf->tile_rows = AOMMIN(extra_cfg->tile_rows, max);
489
490
  }
#else
Jingning Han's avatar
Jingning Han committed
491
  oxcf->tile_columns = extra_cfg->tile_columns;
492
  oxcf->tile_rows = extra_cfg->tile_rows;
493
#endif  // CONFIG_EXT_TILE
Jingning Han's avatar
Jingning Han committed
494

495
496
497
498
499
#if CONFIG_DEBLOCKING_ACROSS_TILES
  oxcf->loop_filter_across_tiles_enabled =
      extra_cfg->loop_filter_across_tiles_enabled;
#endif  // CONFIG_DEBLOCKING_ACROSS_TILES

500
  oxcf->error_resilient_mode = cfg->g_error_resilient;
Jingning Han's avatar
Jingning Han committed
501
502
503
504
  oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;

  oxcf->aq_mode = extra_cfg->aq_mode;

505
  oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
Jingning Han's avatar
Jingning Han committed
506
507

  /*
Yaowu Xu's avatar
Yaowu Xu committed
508
  printf("Current AV1 Settings: \n");
Jingning Han's avatar
Jingning Han committed
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  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
538
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
539
540
}

Yaowu Xu's avatar
Yaowu Xu committed
541
542
543
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
544
545
546
  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
547
    if (cfg->g_lag_in_frames > 1 || cfg->g_pass != AOM_RC_ONE_PASS)
Jingning Han's avatar
Jingning Han committed
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
      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
564
  if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
565
566
567
568
    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
569
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
570
571
  }

Yaowu Xu's avatar
Yaowu Xu committed
572
  if (force_key) ctx->next_frame_flags |= AOM_EFLAG_FORCE_KF;
Jingning Han's avatar
Jingning Han committed
573
574
575
576

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
577
static aom_codec_err_t ctrl_get_quantizer(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
578
579
                                          va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
580
581
582
  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
583
584
}

Yaowu Xu's avatar
Yaowu Xu committed
585
static aom_codec_err_t ctrl_get_quantizer64(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
586
587
                                            va_list args) {
  int *const arg = va_arg(args, int *);
Yaowu Xu's avatar
Yaowu Xu committed
588
589
590
  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
591
592
}

Yaowu Xu's avatar
Yaowu Xu committed
593
594
595
596
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
597
598
    ctx->extra_cfg = *extra_cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
Yaowu Xu's avatar
Yaowu Xu committed
599
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
600
601
602
603
  }
  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
604
static aom_codec_err_t ctrl_set_cpuused(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
605
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
606
607
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cpu_used = CAST(AOME_SET_CPUUSED, args);
Jingning Han's avatar
Jingning Han committed
608
609
610
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
611
static aom_codec_err_t ctrl_set_enable_auto_alt_ref(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
612
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
613
614
  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
615
616
617
  return update_extra_cfg(ctx, &extra_cfg);
}

618
#if CONFIG_EXT_REFS
Yaowu Xu's avatar
Yaowu Xu committed
619
static aom_codec_err_t ctrl_set_enable_auto_bwd_ref(aom_codec_alg_priv_t *ctx,
620
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
621
622
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_auto_bwd_ref = CAST(AOME_SET_ENABLEAUTOBWDREF, args);
623
624
  return update_extra_cfg(ctx, &extra_cfg);
}
625
#endif  // CONFIG_EXT_REFS
626

Yaowu Xu's avatar
Yaowu Xu committed
627
static aom_codec_err_t ctrl_set_noise_sensitivity(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
628
                                                  va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
629
630
  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
631
632
633
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
634
static aom_codec_err_t ctrl_set_sharpness(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
635
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
636
637
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.sharpness = CAST(AOME_SET_SHARPNESS, args);
Jingning Han's avatar
Jingning Han committed
638
639
640
  return update_extra_cfg(ctx, &extra_cfg);
}

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

Yaowu Xu's avatar
Yaowu Xu committed
648
static aom_codec_err_t ctrl_set_tile_columns(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
649
                                             va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
650
651
  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
652
653
654
  return update_extra_cfg(ctx, &extra_cfg);
}

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

662
663
664
665
666
667
668
669
670
671
#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
672
static aom_codec_err_t ctrl_set_arnr_max_frames(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
673
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
674
675
  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
676
677
678
  return update_extra_cfg(ctx, &extra_cfg);
}

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

Yaowu Xu's avatar
Yaowu Xu committed
686
static aom_codec_err_t ctrl_set_tuning(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
687
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
688
689
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tuning = CAST(AOME_SET_TUNING, args);
Jingning Han's avatar
Jingning Han committed
690
691
692
  return update_extra_cfg(ctx, &extra_cfg);
}

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

Yaowu Xu's avatar
Yaowu Xu committed
700
701
702
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
703
  extra_cfg.rc_max_intra_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
704
      CAST(AOME_SET_MAX_INTRA_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
705
706
707
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
708
709
710
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
711
  extra_cfg.rc_max_inter_bitrate_pct =
Yaowu Xu's avatar
Yaowu Xu committed
712
      CAST(AOME_SET_MAX_INTER_BITRATE_PCT, args);
Jingning Han's avatar
Jingning Han committed
713
714
715
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
716
static aom_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(aom_codec_alg_priv_t *ctx,
717
                                                    va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
718
719
  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
720
721
722
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
723
static aom_codec_err_t ctrl_set_lossless(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
724
                                         va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
725
726
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.lossless = CAST(AV1E_SET_LOSSLESS, args);
Jingning Han's avatar
Jingning Han committed
727
728
729
  return update_extra_cfg(ctx, &extra_cfg);
}

730
#if CONFIG_AOM_QM
Yaowu Xu's avatar
Yaowu Xu committed
731
static aom_codec_err_t ctrl_set_enable_qm(aom_codec_alg_priv_t *ctx,
732
                                          va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
733
734
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_qm = CAST(AV1E_SET_ENABLE_QM, args);
735
736
737
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
738
static aom_codec_err_t ctrl_set_qm_min(aom_codec_alg_priv_t *ctx,
739
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
740
741
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_min = CAST(AV1E_SET_QM_MIN, args);
742
743
744
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
745
static aom_codec_err_t ctrl_set_qm_max(aom_codec_alg_priv_t *ctx,
746
                                       va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
747
748
  struct av1_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.qm_max = CAST(AV1E_SET_QM_MAX, args);
749
750
751
752
  return update_extra_cfg(ctx, &extra_cfg);
}
#endif

753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
#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
768
769
770
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
771
  extra_cfg.frame_parallel_decoding_mode =
Yaowu Xu's avatar
Yaowu Xu committed
772
      CAST(AV1E_SET_FRAME_PARALLEL_DECODING, args);
Jingning Han's avatar
Jingning Han committed
773
774
775
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
776
static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
777
                                        va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
778
779
  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
780
781
782
  return update_extra_cfg(ctx, &extra_cfg);
}

Yaowu Xu's avatar
Yaowu Xu committed
783
static aom_codec_err_t ctrl_set_min_gf_interval(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
784
                                                va_list args) {
Yaowu Xu's avatar
Yaowu Xu committed
785
786
  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
787
788
789
  return update_extra_cfg(ctx, &extra_cfg);
}

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

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

Yaowu Xu's avatar
Yaowu Xu committed
804
805
806
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
807
808
809
  (void)data;

  if (ctx->priv == NULL) {
Yaowu Xu's avatar
Yaowu Xu committed
810
811
    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
812

Yaowu Xu's avatar
Yaowu Xu committed
813
    ctx->priv = (aom_codec_priv_t *)priv;
Jingning Han's avatar
Jingning Han committed
814
815
    ctx->priv->init_flags = ctx->init_flags;
    ctx->priv->enc.total_encoders = 1;
Yaowu Xu's avatar
Yaowu Xu committed
816
817
    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
818
819
820

#if CONFIG_MULTITHREAD
    if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
Yaowu Xu's avatar
Yaowu Xu committed
821
      return AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
822
823
824
825
826
827
828
829
830
831
    }
#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
832
    once(av1_initialize_enc);
Jingning Han's avatar
Jingning Han committed
833
834
835

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

Yaowu Xu's avatar
Yaowu Xu committed
836
    if (res == AOM_CODEC_OK) {
Jingning Han's avatar
Jingning Han committed
837
      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
Yaowu Xu's avatar
Yaowu Xu committed
838
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
839
      priv->oxcf.use_highbitdepth =
Yaowu Xu's avatar
Yaowu Xu committed
840
          (ctx->init_flags & AOM_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
Jingning Han's avatar
Jingning Han committed
841
#endif
Yaowu Xu's avatar
Yaowu Xu committed
842
      priv->cpi = av1_create_compressor(&priv->oxcf, priv->buffer_pool);
Jingning Han's avatar
Jingning Han committed
843
      if (priv->cpi == NULL)
Yaowu Xu's avatar
Yaowu Xu committed
844
        res = AOM_CODEC_MEM_ERROR;
Jingning Han's avatar
Jingning Han committed
845
846
847
848
849
850
851
852
      else
        priv->cpi->output_pkt_list = &priv->pkt_list.head;
    }
  }

  return res;
}

Yaowu Xu's avatar
Yaowu Xu committed
853
static aom_codec_err_t encoder_destroy(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
854
  free(ctx->cx_data);
Yaowu Xu's avatar
Yaowu Xu committed
855
  av1_remove_compressor(ctx->cpi);
Jingning Han's avatar
Jingning Han committed
856
857
858
#if CONFIG_MULTITHREAD
  pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
#endif
Yaowu Xu's avatar
Yaowu Xu committed
859
860
861
  aom_free(ctx->buffer_pool);
  aom_free(ctx);
  return AOM_CODEC_OK;
Jingning Han's avatar
Jingning Han committed
862
863
}

Yaowu Xu's avatar
Yaowu Xu committed
864
static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx,
Jingning Han's avatar
Jingning Han committed
865
866
867
868
                                    unsigned long deadline) {
  MODE new_mode = BEST;

  switch (ctx->cfg.g_pass) {
Yaowu Xu's avatar
Yaowu Xu committed
869
    case AOM_RC_ONE_PASS:
870
871
872
873
      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
874
875
      }
      break;
Yaowu Xu's avatar
Yaowu Xu committed
876
877
    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
878
879
880
881
  }

  if (ctx->oxcf.mode != new_mode) {
    ctx->oxcf.mode = new_mode;
Yaowu Xu's avatar
Yaowu Xu committed
882
    av1_change_config(ctx->cpi, &ctx->oxcf);
Jingning Han's avatar
Jingning Han committed
883
884
885
886
887
  }
}

// Turn on to test if supplemental superframe data breaks decoding
// #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
Yaowu Xu's avatar
Yaowu Xu committed
888
static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
Jingning Han's avatar
Jingning Han committed
889
890
891
  uint8_t marker = 0xc0;
  unsigned int mask;
  int mag, index_sz;
892
893
  int i;
  size_t max_frame_sz = 0;
Jingning Han's avatar
Jingning Han committed
894
895
896
897
898
899

  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;
900
  for (i = 0; i < ctx->pending_frame_count - 1; i++) {
901
    const size_t frame_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
902
903
    max_frame_sz = frame_sz > max_frame_sz ? frame_sz : max_frame_sz;
  }
Jingning Han's avatar
Jingning Han committed
904
905
906

  // Choose the magnitude
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
907
    if (max_frame_sz <= mask) break;
Jingning Han's avatar
Jingning Han committed
908
909
910
911
912
913
    mask <<= 8;
    mask |= 0xff;
  }
  marker |= mag << 3;

  // Write the index
hui su's avatar
hui su committed
914
  index_sz = 2 + (mag + 1) * (ctx->pending_frame_count - 1);
Jingning Han's avatar
Jingning Han committed
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
  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
933
    for (i = 0; i < ctx->pending_frame_count - 1; i++) {
934
      unsigned int this_sz;
935
      int j;
Jingning Han's avatar
Jingning Han committed
936

937
      assert(ctx->pending_frame_sizes[i] > 0);
hui su's avatar
hui su committed
938
      this_sz = (unsigned int)ctx->pending_frame_sizes[i] - 1;
Jingning Han's avatar
Jingning Han committed
939
940
941
942
943
944
945
946
947
948
949
950
951
952
      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
953
// av1 uses 10,000,000 ticks/second as time stamp
Jingning Han's avatar
Jingning Han committed
954
955
#define TICKS_PER_SEC 10000000LL

Yaowu Xu's avatar
Yaowu Xu committed
956
static int64_t timebase_units_to_ticks(const aom_rational_t *timebase,
Jingning Han's avatar
Jingning Han committed
957
958
959
960
                                       int64_t n) {
  return n * TICKS_PER_SEC * timebase->num / timebase->den;
}

Yaowu Xu's avatar
Yaowu Xu committed
961
static int64_t ticks_to_timebase_units(const aom_rational_t *timebase,
Jingning Han's avatar
Jingning Han committed
962
963
964
965
966
                                       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
967
static aom_codec_frame_flags_t get_frame_pkt_flags(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
968
                                                   unsigned int lib_flags) {
Yaowu Xu's avatar
Yaowu Xu committed
969
  aom_codec_frame_flags_t flags = lib_flags << 16;
Jingning Han's avatar
Jingning Han committed
970

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

Yaowu Xu's avatar
Yaowu Xu committed
973
  if (cpi->droppable) flags |= AOM_FRAME_IS_DROPPABLE;
Jingning Han's avatar
Jingning Han committed
974
975
976
977

  return flags;
}

978
const size_t kMinCompressedSize = 8192;
Yaowu Xu's avatar
Yaowu Xu committed
979
980
981
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
982
                                      unsigned long duration,
Yaowu Xu's avatar
Yaowu Xu committed
983
                                      aom_enc_frame_flags_t enc_flags,
Jingning Han's avatar
Jingning Han committed
984
                                      unsigned long deadline) {
Yaowu Xu's avatar
Yaowu Xu committed
985
986
987
988
  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
989
990
  size_t data_sz;

Yaowu Xu's avatar
Yaowu Xu committed
991
  if (cpi == NULL) return AOM_CODEC_INVALID_PARAM;
992

Jingning Han's avatar
Jingning Han committed
993
994
995
996
  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
997
    if (res == AOM_CODEC_OK) {
998
#if CONFIG_EXT_REFS
999
1000
      data_sz = ALIGN_POWER_OF_TWO(ctx->cfg.g_w, 5) *
                ALIGN_POWER_OF_TWO(ctx->cfg.g_h, 5) * get_image_bps(img);
1001
#else
1002
1003
      // There's no codec control for multiple alt-refs so check the encoder
      // instance for its status to determine the compressed data size.
1004
1005
      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
1006
                (cpi->multi_arf_allowed ? 8 : 2);
1007
#endif  // CONFIG_EXT_REFS
1008
      if (data_sz < kMinCompressedSize) data_sz = kMinCompressedSize;