vp9_cx_iface.c 51.6 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9
10
 */

11
12
#include <stdlib.h>
#include <string.h>
John Koleszar's avatar
John Koleszar committed
13

14
#include "./vpx_config.h"
15
16
#include "vpx/vpx_codec.h"
#include "vpx/internal/vpx_codec_internal.h"
17
#include "./vpx_version.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
18
#include "vp9/encoder/vp9_encoder.h"
John Koleszar's avatar
John Koleszar committed
19
#include "vpx/vp8cx.h"
20
#include "vp9/encoder/vp9_firstpass.h"
John Koleszar's avatar
John Koleszar committed
21
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
22

23
struct vp9_extracfg {
24
  int                         cpu_used;  // available cpu percentage in 1/16
25
  unsigned int                enable_auto_alt_ref;
John Koleszar's avatar
John Koleszar committed
26
  unsigned int                noise_sensitivity;
27
  unsigned int                sharpness;
John Koleszar's avatar
John Koleszar committed
28
  unsigned int                static_thresh;
29
  unsigned int                tile_columns;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
30
  unsigned int                tile_rows;
31
32
  unsigned int                arnr_max_frames;
  unsigned int                arnr_strength;
John Koleszar's avatar
John Koleszar committed
33
  vp8e_tuning                 tuning;
34
  unsigned int                cq_level;  // constrained quality level
John Koleszar's avatar
John Koleszar committed
35
  unsigned int                rc_max_intra_bitrate_pct;
36
  unsigned int                rc_max_inter_bitrate_pct;
37
  unsigned int                gf_cbr_boost_pct;
John Koleszar's avatar
John Koleszar committed
38
  unsigned int                lossless;
39
  unsigned int                frame_parallel_decoding_mode;
40
  AQ_MODE                     aq_mode;
41
  unsigned int                frame_periodic_boost;
42
  vpx_bit_depth_t             bit_depth;
43
  vp9e_tune_content           content;
John Koleszar's avatar
John Koleszar committed
44
45
};

46
47
48
49
50
51
52
53
54
55
56
57
58
static struct vp9_extracfg default_extra_cfg = {
  0,                          // cpu_used
  1,                          // enable_auto_alt_ref
  0,                          // noise_sensitivity
  0,                          // sharpness
  0,                          // static_thresh
  0,                          // tile_columns
  0,                          // tile_rows
  7,                          // arnr_max_frames
  5,                          // arnr_strength
  VP8_TUNE_PSNR,              // tuning
  10,                         // cq_level
  0,                          // rc_max_intra_bitrate_pct
59
  0,                          // rc_max_inter_bitrate_pct
60
  0,                          // gf_cbr_boost_pct
61
62
63
64
  0,                          // lossless
  0,                          // frame_parallel_decoding_mode
  NO_AQ,                      // aq_mode
  0,                          // frame_periodic_delta_q
65
  VPX_BITS_8,                 // Bit depth
66
  VP9E_CONTENT_DEFAULT        // content
John Koleszar's avatar
John Koleszar committed
67
68
};

John Koleszar's avatar
John Koleszar committed
69
70
71
struct vpx_codec_alg_priv {
  vpx_codec_priv_t        base;
  vpx_codec_enc_cfg_t     cfg;
72
  struct vp9_extracfg     extra_cfg;
73
  VP9EncoderConfig        oxcf;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
74
  VP9_COMP               *cpi;
John Koleszar's avatar
John Koleszar committed
75
  unsigned char          *cx_data;
76
  size_t                  cx_data_sz;
77
  unsigned char          *pending_cx_data;
78
  size_t                  pending_cx_data_sz;
John Koleszar's avatar
John Koleszar committed
79
  int                     pending_frame_count;
80
81
  size_t                  pending_frame_sizes[8];
  size_t                  pending_frame_magnitude;
John Koleszar's avatar
John Koleszar committed
82
83
  vpx_image_t             preview_img;
  vp8_postproc_cfg_t      preview_ppcfg;
84
  vpx_codec_pkt_list_decl(256) pkt_list;
85
  unsigned int                 fixed_kf_cntr;
86
  vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb;
John Koleszar's avatar
John Koleszar committed
87
88
};

89
static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
90
91
92
93
94
95
96
97
  switch (frame) {
    case VP8_LAST_FRAME:
      return VP9_LAST_FLAG;
    case VP8_GOLD_FRAME:
      return VP9_GOLD_FLAG;
    case VP8_ALTR_FRAME:
      return VP9_ALT_FLAG;
  }
James Zern's avatar
James Zern committed
98
  assert(0 && "Invalid Reference Frame");
99
100
  return VP9_LAST_FLAG;
}
John Koleszar's avatar
John Koleszar committed
101

102
103
104
static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
    const struct vpx_internal_error_info *error) {
  const vpx_codec_err_t res = error->error_code;
John Koleszar's avatar
John Koleszar committed
105

106
107
  if (res != VPX_CODEC_OK)
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;
John Koleszar's avatar
John Koleszar committed
108

John Koleszar's avatar
John Koleszar committed
109
  return res;
John Koleszar's avatar
John Koleszar committed
110
111
112
}


113
#undef ERROR
John Koleszar's avatar
John Koleszar committed
114
#define ERROR(str) do {\
John Koleszar's avatar
John Koleszar committed
115
116
    ctx->base.err_detail = str;\
    return VPX_CODEC_INVALID_PARAM;\
117
  } while (0)
John Koleszar's avatar
John Koleszar committed
118

119
120
#define RANGE_CHECK(p, memb, lo, hi) do {\
    if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
John Koleszar's avatar
John Koleszar committed
121
      ERROR(#memb " out of range ["#lo".."#hi"]");\
122
  } while (0)
John Koleszar's avatar
John Koleszar committed
123

124
125
#define RANGE_CHECK_HI(p, memb, hi) do {\
    if (!((p)->memb <= (hi))) \
John Koleszar's avatar
John Koleszar committed
126
      ERROR(#memb " out of range [.."#hi"]");\
127
  } while (0)
128

129
130
#define RANGE_CHECK_LO(p, memb, lo) do {\
    if (!((p)->memb >= (lo))) \
John Koleszar's avatar
John Koleszar committed
131
      ERROR(#memb " out of range ["#lo"..]");\
132
  } while (0)
John Koleszar's avatar
John Koleszar committed
133

134
135
136
#define RANGE_CHECK_BOOL(p, memb) do {\
    if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
  } while (0)
John Koleszar's avatar
John Koleszar committed
137

138
static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
139
                                       const vpx_codec_enc_cfg_t *cfg,
140
                                       const struct vp9_extracfg *extra_cfg) {
141
142
  RANGE_CHECK(cfg, g_w,                   1, 65535);  // 16 bits available
  RANGE_CHECK(cfg, g_h,                   1, 65535);  // 16 bits available
John Koleszar's avatar
John Koleszar committed
143
144
145
  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);
John Koleszar's avatar
John Koleszar committed
146

John Koleszar's avatar
John Koleszar committed
147
148
  RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
  RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
149
150
  RANGE_CHECK_BOOL(extra_cfg, lossless);
  RANGE_CHECK(extra_cfg, aq_mode,           0, AQ_MODE_COUNT - 1);
151
  RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
John Koleszar's avatar
John Koleszar committed
152
153
  RANGE_CHECK_HI(cfg, g_threads,          64);
  RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
154
  RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
John Koleszar's avatar
John Koleszar committed
155
156
157
158
159
160
161
162
163
164
  RANGE_CHECK_HI(cfg, rc_undershoot_pct,  1000);
  RANGE_CHECK_HI(cfg, rc_overshoot_pct,   1000);
  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
  RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
  RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);
  RANGE_CHECK_HI(cfg, rc_dropframe_thresh,   100);
  RANGE_CHECK_HI(cfg, rc_resize_up_thresh,   100);
  RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
  RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);

165
  if (cfg->rc_resize_allowed == 1) {
166
167
    RANGE_CHECK(cfg, rc_scaled_width, 0, cfg->g_w);
    RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
168
169
  }

170
  RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
171
  RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
172

173
  if (cfg->ts_number_layers > 1) {
174
    unsigned int i;
175
176
    for (i = 1; i < cfg->ts_number_layers; ++i)
      if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i - 1])
177
        ERROR("ts_target_bitrate entries are not increasing");
178
179
180
181

    RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
    for (i = cfg->ts_number_layers - 2; i > 0; --i)
      if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i])
182
183
184
        ERROR("ts_rate_decimator factors are not powers of 2");
  }

185
186
187
188
189
190
191
192
193
#if CONFIG_SPATIAL_SVC

  if ((cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) &&
      cfg->g_pass == VPX_RC_LAST_PASS) {
    unsigned int i, alt_ref_sum = 0;
    for (i = 0; i < cfg->ss_number_layers; ++i) {
      if (cfg->ss_enable_auto_alt_ref[i])
        ++alt_ref_sum;
    }
194
    if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
195
      ERROR("Not enough ref buffers for svc alt ref frames");
196
    if (cfg->ss_number_layers * cfg->ts_number_layers > 3 &&
197
        cfg->g_error_resilient == 0)
198
    ERROR("Multiple frame context are not supported for more than 3 layers");
199
200
201
  }
#endif

202
  // VP9 does not support a lower bound on the keyframe interval in
203
204
205
206
  // automatic keyframe placement mode.
  if (cfg->kf_mode != VPX_KF_DISABLED &&
      cfg->kf_min_dist != cfg->kf_max_dist &&
      cfg->kf_min_dist > 0)
John Koleszar's avatar
John Koleszar committed
207
208
209
    ERROR("kf_min_dist not supported in auto mode, use 0 "
          "or kf_max_dist instead.");

210
  RANGE_CHECK(extra_cfg, enable_auto_alt_ref, 0, 2);
211
  RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
212
213
214
215
216
217
218
  RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
  RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
  RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
  RANGE_CHECK_HI(extra_cfg, sharpness, 7);
  RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
  RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
  RANGE_CHECK(extra_cfg, cq_level, 0, 63);
219
220
  RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
221
222
  RANGE_CHECK(extra_cfg, content,
              VP9E_CONTENT_DEFAULT, VP9E_CONTENT_INVALID - 1);
John Koleszar's avatar
John Koleszar committed
223

Yaowu Xu's avatar
Yaowu Xu committed
224
  // TODO(yaowu): remove this when ssim tuning is implemented for vp9
225
  if (extra_cfg->tuning == VP8_TUNE_SSIM)
Yaowu Xu's avatar
Yaowu Xu committed
226
227
      ERROR("Option --tune=ssim is not currently supported in VP9.");

John Koleszar's avatar
John Koleszar committed
228
  if (cfg->g_pass == VPX_RC_LAST_PASS) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
229
230
    const size_t packet_sz = sizeof(FIRSTPASS_STATS);
    const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
231
    const FIRSTPASS_STATS *stats;
John Koleszar's avatar
John Koleszar committed
232

Adrian Grange's avatar
Adrian Grange committed
233
    if (cfg->rc_twopass_stats_in.buf == NULL)
John Koleszar's avatar
John Koleszar committed
234
235
236
237
238
      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.");

239
    if (cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) {
240
241
242
243
244
      int i;
      unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = {0};

      stats = cfg->rc_twopass_stats_in.buf;
      for (i = 0; i < n_packets; ++i) {
245
        const int layer_id = (int)stats[i].spatial_layer_id;
246
247
248
249
250
251
252
253
254
255
256
        if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
          ++n_packets_per_layer[layer_id];
        }
      }

      for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
        unsigned int layer_id;
        if (n_packets_per_layer[i] < 2) {
          ERROR("rc_twopass_stats_in requires at least two packets for each "
                "layer.");
        }
John Koleszar's avatar
John Koleszar committed
257

258
259
        stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
                n_packets - cfg->ss_number_layers + i;
260
        layer_id = (int)stats->spatial_layer_id;
John Koleszar's avatar
John Koleszar committed
261

262
        if (layer_id >= cfg->ss_number_layers
263
264
            ||(unsigned int)(stats->count + 0.5) !=
               n_packets_per_layer[layer_id] - 1)
265
266
267
268
269
270
271
272
273
274
275
276
          ERROR("rc_twopass_stats_in missing EOS stats packet");
      }
    } else {
      if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
        ERROR("rc_twopass_stats_in requires at least two packets.");

      stats =
          (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;

      if ((int)(stats->count + 0.5) != n_packets - 1)
        ERROR("rc_twopass_stats_in missing EOS stats packet");
    }
John Koleszar's avatar
John Koleszar committed
277
  }
278

279
#if !CONFIG_VP9_HIGHBITDEPTH
Deb Mukherjee's avatar
Deb Mukherjee committed
280
  if (cfg->g_profile > (unsigned int)PROFILE_1) {
281
    ERROR("Profile > 1 not supported in this build configuration");
Deb Mukherjee's avatar
Deb Mukherjee committed
282
  }
283
#endif
284
  if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
Deb Mukherjee's avatar
Deb Mukherjee committed
285
      cfg->g_bit_depth > VPX_BITS_8) {
286
    ERROR("Codec high bit-depth not supported in profile < 2");
Deb Mukherjee's avatar
Deb Mukherjee committed
287
288
289
290
291
  }
  if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
      cfg->g_input_bit_depth > 8) {
    ERROR("Source high bit-depth not supported in profile < 2");
  }
292
  if (cfg->g_profile > (unsigned int)PROFILE_1 &&
Deb Mukherjee's avatar
Deb Mukherjee committed
293
      cfg->g_bit_depth == VPX_BITS_8) {
294
    ERROR("Codec bit-depth 8 not supported in profile > 1");
Deb Mukherjee's avatar
Deb Mukherjee committed
295
  }
John Koleszar's avatar
John Koleszar committed
296
297

  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
298
299
300
}

static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
301
                                    const vpx_image_t *img) {
John Koleszar's avatar
John Koleszar committed
302
  switch (img->fmt) {
James Zern's avatar
James Zern committed
303
304
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_I420:
Deb Mukherjee's avatar
Deb Mukherjee committed
305
306
    case VPX_IMG_FMT_I42016:
      break;
307
308
    case VPX_IMG_FMT_I422:
    case VPX_IMG_FMT_I444:
Deb Mukherjee's avatar
Deb Mukherjee committed
309
    case VPX_IMG_FMT_I440:
Deb Mukherjee's avatar
Deb Mukherjee committed
310
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
Deb Mukherjee's avatar
Deb Mukherjee committed
311
        ERROR("Invalid image format. I422, I444, I440 images are "
Deb Mukherjee's avatar
Deb Mukherjee committed
312
313
314
315
316
              "not supported in profile.");
      }
      break;
    case VPX_IMG_FMT_I42216:
    case VPX_IMG_FMT_I44416:
Deb Mukherjee's avatar
Deb Mukherjee committed
317
    case VPX_IMG_FMT_I44016:
Deb Mukherjee's avatar
Deb Mukherjee committed
318
319
      if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
          ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
Deb Mukherjee's avatar
Deb Mukherjee committed
320
        ERROR("Invalid image format. 16-bit I422, I444, I440 images are "
Deb Mukherjee's avatar
Deb Mukherjee committed
321
322
              "not supported in profile.");
      }
John Koleszar's avatar
John Koleszar committed
323
      break;
John Koleszar's avatar
John Koleszar committed
324
    default:
325
326
      ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
            "supported.");
327
      break;
John Koleszar's avatar
John Koleszar committed
328
  }
John Koleszar's avatar
John Koleszar committed
329

330
  if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
John Koleszar's avatar
John Koleszar committed
331
    ERROR("Image size must match encoder init configuration size");
John Koleszar's avatar
John Koleszar committed
332

John Koleszar's avatar
John Koleszar committed
333
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
334
335
}

336
337
338
339
340
341
static int get_image_bps(const vpx_image_t *img) {
  switch (img->fmt) {
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_I420: return 12;
    case VPX_IMG_FMT_I422: return 16;
    case VPX_IMG_FMT_I444: return 24;
Deb Mukherjee's avatar
Deb Mukherjee committed
342
    case VPX_IMG_FMT_I440: return 16;
343
344
345
    case VPX_IMG_FMT_I42016: return 24;
    case VPX_IMG_FMT_I42216: return 32;
    case VPX_IMG_FMT_I44416: return 48;
Deb Mukherjee's avatar
Deb Mukherjee committed
346
    case VPX_IMG_FMT_I44016: return 32;
347
    default: assert(0 && "Invalid image format"); break;
348
349
350
  }
  return 0;
}
John Koleszar's avatar
John Koleszar committed
351

352
static vpx_codec_err_t set_encoder_config(
353
    VP9EncoderConfig *oxcf,
354
355
    const vpx_codec_enc_cfg_t *cfg,
    const struct vp9_extracfg *extra_cfg) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
356
  const int is_vbr = cfg->rc_end_usage == VPX_VBR;
357
  oxcf->profile = cfg->g_profile;
358
  oxcf->max_threads = (int)cfg->g_threads;
359
360
  oxcf->width   = cfg->g_w;
  oxcf->height  = cfg->g_h;
Deb Mukherjee's avatar
Deb Mukherjee committed
361
  oxcf->bit_depth = cfg->g_bit_depth;
362
  oxcf->input_bit_depth = cfg->g_input_bit_depth;
363
  // guess a frame rate if out of whack, use 30
364
365
366
  oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
  if (oxcf->init_framerate > 180)
    oxcf->init_framerate = 30;
John Koleszar's avatar
John Koleszar committed
367

368
  oxcf->mode = GOOD;
369

370
  switch (cfg->g_pass) {
John Koleszar's avatar
John Koleszar committed
371
    case VPX_RC_ONE_PASS:
372
      oxcf->pass = 0;
John Koleszar's avatar
John Koleszar committed
373
      break;
John Koleszar's avatar
John Koleszar committed
374
    case VPX_RC_FIRST_PASS:
375
      oxcf->pass = 1;
John Koleszar's avatar
John Koleszar committed
376
      break;
John Koleszar's avatar
John Koleszar committed
377
    case VPX_RC_LAST_PASS:
378
      oxcf->pass = 2;
John Koleszar's avatar
John Koleszar committed
379
380
381
      break;
  }

382
383
  oxcf->lag_in_frames = cfg->g_pass == VPX_RC_FIRST_PASS ? 0
                                                         : cfg->g_lag_in_frames;
384
  oxcf->rc_mode = cfg->rc_end_usage;
385

386
387
  // Convert target bandwidth from Kbit/s to Bit/s
  oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
388
  oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
389
  oxcf->rc_max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct;
390
  oxcf->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct;
John Koleszar's avatar
John Koleszar committed
391

392
393
394
395
  oxcf->best_allowed_q =
      extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_min_quantizer);
  oxcf->worst_allowed_q =
      extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_max_quantizer);
396
  oxcf->cq_level        = vp9_quantizer_to_qindex(extra_cfg->cq_level);
John Koleszar's avatar
John Koleszar committed
397
398
  oxcf->fixed_q = -1;

399
400
401
  oxcf->under_shoot_pct         = cfg->rc_undershoot_pct;
  oxcf->over_shoot_pct          = cfg->rc_overshoot_pct;

402
403
404
405
406
407
408
409
410
  oxcf->scaled_frame_width  = cfg->rc_scaled_width;
  oxcf->scaled_frame_height = cfg->rc_scaled_height;
  if (cfg->rc_resize_allowed == 1) {
    oxcf->resize_mode =
        (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0) ?
            RESIZE_DYNAMIC : RESIZE_FIXED;
  } else {
    oxcf->resize_mode = RESIZE_NONE;
  }
411

Dmitry Kovalev's avatar
Dmitry Kovalev committed
412
413
414
  oxcf->maximum_buffer_size_ms   = is_vbr ? 240000 : cfg->rc_buf_sz;
  oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
  oxcf->optimal_buffer_level_ms  = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
John Koleszar's avatar
John Koleszar committed
415

416
  oxcf->drop_frames_water_mark   = cfg->rc_dropframe_thresh;
John Koleszar's avatar
John Koleszar committed
417

418
419
420
  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;
421

422
423
  oxcf->auto_key               = cfg->kf_mode == VPX_KF_AUTO &&
                                 cfg->kf_min_dist != cfg->kf_max_dist;
John Koleszar's avatar
John Koleszar committed
424

425
  oxcf->key_freq               = cfg->kf_max_dist;
John Koleszar's avatar
John Koleszar committed
426

427
  oxcf->speed                  =  abs(extra_cfg->cpu_used);
428
  oxcf->encode_breakout        =  extra_cfg->static_thresh;
429
  oxcf->enable_auto_arf        =  extra_cfg->enable_auto_alt_ref;
430
431
  oxcf->noise_sensitivity      =  extra_cfg->noise_sensitivity;
  oxcf->sharpness              =  extra_cfg->sharpness;
John Koleszar's avatar
John Koleszar committed
432

433
  oxcf->two_pass_stats_in      =  cfg->rc_twopass_stats_in;
John Koleszar's avatar
John Koleszar committed
434

435
436
437
438
#if CONFIG_FP_MB_STATS
  oxcf->firstpass_mb_stats_in  = cfg->rc_firstpass_mb_stats_in;
#endif

439
440
  oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
  oxcf->arnr_strength   = extra_cfg->arnr_strength;
John Koleszar's avatar
John Koleszar committed
441

442
  oxcf->tuning = extra_cfg->tuning;
443
  oxcf->content = extra_cfg->content;
John Koleszar's avatar
John Koleszar committed
444

445
446
  oxcf->tile_columns = extra_cfg->tile_columns;
  oxcf->tile_rows    = extra_cfg->tile_rows;
447

448
449
  oxcf->error_resilient_mode         = cfg->g_error_resilient;
  oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
450

451
  oxcf->aq_mode = extra_cfg->aq_mode;
452

453
454
  oxcf->frame_periodic_boost =  extra_cfg->frame_periodic_boost;

455
  oxcf->ss_number_layers = cfg->ss_number_layers;
456

457
  if (oxcf->ss_number_layers > 1) {
458
    int i;
459
    for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
460
      oxcf->ss_target_bitrate[i] =  1000 * cfg->ss_target_bitrate[i];
461
#if CONFIG_SPATIAL_SVC
462
      oxcf->ss_enable_auto_arf[i] =  cfg->ss_enable_auto_alt_ref[i];
463
464
#endif
    }
465
  } else if (oxcf->ss_number_layers == 1) {
Paul Wilkins's avatar
Paul Wilkins committed
466
    oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
467
#if CONFIG_SPATIAL_SVC
468
    oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
469
#endif
470
471
  }

472
  oxcf->ts_number_layers = cfg->ts_number_layers;
473
474

  if (oxcf->ts_number_layers > 1) {
475
476
477
478
479
    int i;
    for (i = 0; i < VPX_TS_MAX_LAYERS; ++i) {
      oxcf->ts_target_bitrate[i] = 1000 * cfg->ts_target_bitrate[i];
      oxcf->ts_rate_decimator[i] = cfg->ts_rate_decimator[i];
    }
480
  } else if (oxcf->ts_number_layers == 1) {
481
    oxcf->ts_target_bitrate[0] = (int)oxcf->target_bandwidth;
482
483
484
    oxcf->ts_rate_decimator[0] = 1;
  }

John Koleszar's avatar
John Koleszar committed
485
  /*
486
487
488
  printf("Current VP9 Settings: \n");
  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
  printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
489
  printf("sharpness: %d\n",    oxcf->sharpness);
490
  printf("cpu_used: %d\n",  oxcf->cpu_used);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
491
  printf("Mode: %d\n",     oxcf->mode);
492
493
494
495
496
497
498
499
500
501
502
  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);
503
504
505
  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);
506
507
508
509
  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);
510
  printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
511
512
513
  printf("Version: %d\n", oxcf->Version);
  printf("encode_breakout: %d\n", oxcf->encode_breakout);
  printf("error resilient: %d\n", oxcf->error_resilient_mode);
514
515
  printf("frame parallel detokenization: %d\n",
         oxcf->frame_parallel_decoding_mode);
John Koleszar's avatar
John Koleszar committed
516
517
  */
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
518
519
}

520
521
static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
                                          const vpx_codec_enc_cfg_t  *cfg) {
John Koleszar's avatar
John Koleszar committed
522
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
523

524
  if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h)
John Koleszar's avatar
John Koleszar committed
525
    ERROR("Cannot change width or height after initialization");
John Koleszar's avatar
John Koleszar committed
526

527
528
529
530
531
  // 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)
John Koleszar's avatar
John Koleszar committed
532
    ERROR("Cannot increase lag_in_frames");
John Koleszar's avatar
John Koleszar committed
533

534
  res = validate_config(ctx, cfg, &ctx->extra_cfg);
John Koleszar's avatar
John Koleszar committed
535

Adrian Grange's avatar
Adrian Grange committed
536
  if (res == VPX_CODEC_OK) {
John Koleszar's avatar
John Koleszar committed
537
    ctx->cfg = *cfg;
538
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
539
    vp9_change_config(ctx->cpi, &ctx->oxcf);
John Koleszar's avatar
John Koleszar committed
540
  }
John Koleszar's avatar
John Koleszar committed
541

John Koleszar's avatar
John Koleszar committed
542
  return res;
John Koleszar's avatar
John Koleszar committed
543
544
}

545
546
547
548
549
550
551
552
static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
                                          va_list args) {
  int *const arg = va_arg(args, int *);
  if (arg == NULL)
    return VPX_CODEC_INVALID_PARAM;
  *arg = vp9_get_quantizer(ctx->cpi);
  return VPX_CODEC_OK;
}
John Koleszar's avatar
John Koleszar committed
553

554
555
556
static vpx_codec_err_t ctrl_get_quantizer64(vpx_codec_alg_priv_t *ctx,
                                            va_list args) {
  int *const arg = va_arg(args, int *);
557
558
  if (arg == NULL)
    return VPX_CODEC_INVALID_PARAM;
559
560
561
  *arg = vp9_qindex_to_quantizer(vp9_get_quantizer(ctx->cpi));
  return VPX_CODEC_OK;
}
John Koleszar's avatar
John Koleszar committed
562

563
564
565
566
567
568
569
static vpx_codec_err_t update_extra_cfg(vpx_codec_alg_priv_t *ctx,
                                        const struct vp9_extracfg *extra_cfg) {
  const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
  if (res == VPX_CODEC_OK) {
    ctx->extra_cfg = *extra_cfg;
    set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
    vp9_change_config(ctx->cpi, &ctx->oxcf);
John Koleszar's avatar
John Koleszar committed
570
  }
571
572
  return res;
}
John Koleszar's avatar
John Koleszar committed
573

574
575
576
577
578
static vpx_codec_err_t ctrl_set_cpuused(vpx_codec_alg_priv_t *ctx,
                                        va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
  return update_extra_cfg(ctx, &extra_cfg);
John Koleszar's avatar
John Koleszar committed
579
580
}

581
582
583
584
585
586
static vpx_codec_err_t ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
                                                    va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
587

588
589
static vpx_codec_err_t ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
                                                  va_list args) {
590
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
591
  extra_cfg.noise_sensitivity = CAST(VP9E_SET_NOISE_SENSITIVITY, args);
592
593
  return update_extra_cfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
594

595
596
597
598
599
600
static vpx_codec_err_t ctrl_set_sharpness(vpx_codec_alg_priv_t *ctx,
                                          va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.sharpness = CAST(VP8E_SET_SHARPNESS, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
601

602
603
604
605
606
607
static vpx_codec_err_t ctrl_set_static_thresh(vpx_codec_alg_priv_t *ctx,
                                              va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
608

609
610
611
612
613
614
static vpx_codec_err_t ctrl_set_tile_columns(vpx_codec_alg_priv_t *ctx,
                                             va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tile_columns = CAST(VP9E_SET_TILE_COLUMNS, args);
  return update_extra_cfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
static vpx_codec_err_t ctrl_set_tile_rows(vpx_codec_alg_priv_t *ctx,
                                          va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tile_rows = CAST(VP9E_SET_TILE_ROWS, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
                                                va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_arnr_strength(vpx_codec_alg_priv_t *ctx,
                                              va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_arnr_type(vpx_codec_alg_priv_t *ctx,
                                          va_list args) {
639
640
641
  (void)ctx;
  (void)args;
  return VPX_CODEC_OK;
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
}

static vpx_codec_err_t ctrl_set_tuning(vpx_codec_alg_priv_t *ctx,
                                       va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_cq_level(vpx_codec_alg_priv_t *ctx,
                                         va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
    vpx_codec_alg_priv_t *ctx, va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.rc_max_intra_bitrate_pct =
      CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

666
667
668
669
670
671
672
673
static vpx_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
    vpx_codec_alg_priv_t *ctx, va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.rc_max_inter_bitrate_pct =
      CAST(VP8E_SET_MAX_INTER_BITRATE_PCT, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

674
675
676
677
678
679
680
681
static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(
    vpx_codec_alg_priv_t *ctx, va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.gf_cbr_boost_pct =
      CAST(VP8E_SET_GF_CBR_BOOST_PCT, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
static vpx_codec_err_t ctrl_set_lossless(vpx_codec_alg_priv_t *ctx,
                                         va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.lossless = CAST(VP9E_SET_LOSSLESS, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
    vpx_codec_alg_priv_t *ctx, va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.frame_parallel_decoding_mode =
      CAST(VP9E_SET_FRAME_PARALLEL_DECODING, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx,
                                        va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
  return update_extra_cfg(ctx, &extra_cfg);
}

static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
                                                     va_list args) {
  struct vp9_extracfg extra_cfg = ctx->extra_cfg;
  extra_cfg.frame_periodic_boost = CAST(VP9E_SET_FRAME_PERIODIC_BOOST, args);
  return update_extra_cfg(ctx, &extra_cfg);
John Koleszar's avatar
John Koleszar committed
709
}
710

711
712
static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
                                    vpx_codec_priv_enc_mr_cfg_t *data) {
713
  vpx_codec_err_t res = VPX_CODEC_OK;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
714
  (void)data;
John Koleszar's avatar
John Koleszar committed
715

Adrian Grange's avatar
Adrian Grange committed
716
  if (ctx->priv == NULL) {
717
718
    vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
    if (priv == NULL)
719
      return VPX_CODEC_MEM_ERROR;
720

721
    ctx->priv = (vpx_codec_priv_t *)priv;
John Koleszar's avatar
John Koleszar committed
722
    ctx->priv->init_flags = ctx->init_flags;
John Koleszar's avatar
John Koleszar committed
723
    ctx->priv->enc.total_encoders = 1;
John Koleszar's avatar
John Koleszar committed
724
725

    if (ctx->config.enc) {
726
      // Update the reference to the config structure to an internal copy.
727
728
      priv->cfg = *ctx->config.enc;
      ctx->config.enc = &priv->cfg;
John Koleszar's avatar
John Koleszar committed
729
    }
730

731
    priv->extra_cfg = default_extra_cfg;
732
    vp9_initialize_enc();
John Koleszar's avatar
John Koleszar committed
733

734
    res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
John Koleszar's avatar
John Koleszar committed
735

Adrian Grange's avatar
Adrian Grange committed
736
    if (res == VPX_CODEC_OK) {
737
      set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
738
739
740
741
#if CONFIG_VP9_HIGHBITDEPTH
      priv->oxcf.use_highbitdepth =
          (ctx->init_flags & VPX_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
#endif
742
743
      priv->cpi = vp9_create_compressor(&priv->oxcf);
      if (priv->cpi == NULL)
John Koleszar's avatar
John Koleszar committed
744
        res = VPX_CODEC_MEM_ERROR;
745
      else
746
        priv->cpi->output_pkt_list = &priv->pkt_list.head;
John Koleszar's avatar
John Koleszar committed
747
    }
John Koleszar's avatar
John Koleszar committed
748
  }
John Koleszar's avatar
John Koleszar committed
749

John Koleszar's avatar
John Koleszar committed
750
  return res;
John Koleszar's avatar
John Koleszar committed
751
752
}

753
static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
754
  free(ctx->cx_data);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
755
  vp9_remove_compressor(ctx->cpi);
756
  vpx_free(ctx);
John Koleszar's avatar
John Koleszar committed
757
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
758
759
}

760
static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
761
762
                                    unsigned long duration,
                                    unsigned long deadline) {
763
  MODE new_mode = BEST;
John Koleszar's avatar
John Koleszar committed
764

765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
  switch (ctx->cfg.g_pass) {
    case VPX_RC_ONE_PASS:
      if (deadline > 0) {
        const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg;

        // Convert duration parameter from stream timebase to microseconds.
        const uint64_t duration_us = (uint64_t)duration * 1000000 *
           (uint64_t)cfg->g_timebase.num /(uint64_t)cfg->g_timebase.den;

        // If the deadline is more that the duration this frame is to be shown,
        // use good quality mode. Otherwise use realtime mode.
        new_mode = (deadline > duration_us) ? GOOD : REALTIME;
      } else {
        new_mode = BEST;
      }
      break;
    case VPX_RC_FIRST_PASS:
      break;
    case VPX_RC_LAST_PASS:
      new_mode = deadline > 0 ? GOOD : BEST;
      break;
  }
John Koleszar's avatar
John Koleszar committed
787

788
789
  if (ctx->oxcf.mode != new_mode) {
    ctx->oxcf.mode = new_mode;
790
    vp9_change_config(ctx->cpi, &ctx->oxcf);
John Koleszar's avatar
John Koleszar committed
791
  }
John Koleszar's avatar
John Koleszar committed
792
793
}

794
795
// Turn on to test if supplemental superframe data breaks decoding
// #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
796
static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
797
  uint8_t marker = 0xc0;
Yaowu Xu's avatar
Yaowu Xu committed
798
799
  unsigned int mask;
  int mag, index_sz;
John Koleszar's avatar
John Koleszar committed
800
801
802
803

  assert(ctx->pending_frame_count);
  assert(ctx->pending_frame_count <= 8);

804
  // Add the number of frames to the marker byte
John Koleszar's avatar
John Koleszar committed
805
806
  marker |= ctx->pending_frame_count - 1;

807
  // Choose the magnitude
John Koleszar's avatar
John Koleszar committed
808
809
810
811
812
813
814
815
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
    if (ctx->pending_frame_magnitude < mask)
      break;
    mask <<= 8;
    mask |= 0xff;
  }
  marker |= mag << 3;

816
  // Write the index
John Koleszar's avatar
John Koleszar committed
817
818
819
820
  index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
  if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
    uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
    int i, j;
821
822
823
824
825
826
827
828
829
830
831
832
833
834
#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
John Koleszar's avatar
John Koleszar committed
835
836
837

    *x++ = marker;
    for (i = 0; i < ctx->pending_frame_count; i++) {
838
      unsigned int this_sz = (unsigned int)ctx->pending_frame_sizes[i];
John Koleszar's avatar
John Koleszar committed
839
840
841
842
843
844
845
846

      for (j = 0; j <= mag; j++) {
        *x++ = this_sz & 0xff;
        this_sz >>= 8;
      }
    }
    *x++ = marker;
    ctx->pending_cx_data_sz += index_sz;
847
848
849
#ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
    index_sz += index_sz_test;
#endif
John Koleszar's avatar
John Koleszar committed
850
  }
851
  return index_sz;
John Koleszar's avatar
John Koleszar committed
852
853
}

854
// vp9 uses 10,000,000 ticks/second as time stamp
Yaowu Xu's avatar
Yaowu Xu committed
855
#define TICKS_PER_SEC 10000000LL
856
857
858
859
860
861
862
863
864
865
866
867

static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
                                       int64_t n) {
  return n * TICKS_PER_SEC * timebase->num / timebase->den;
}

static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase,
                                       int64_t n) {
  const int64_t round = TICKS_PER_SEC * timebase->num / 2 - 1;
  return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
}

868
869
870
871
872
873
static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi,
                                                   unsigned int lib_flags) {
  vpx_codec_frame_flags_t flags = lib_flags << 16;

  if (lib_flags & FRAMEFLAGS_KEY
#if CONFIG_SPATIAL_SVC
874
      || (is_two_pass_svc(cpi) && cpi->svc.layer_context[0].is_key_frame)
875
876
877
878
879
880
881
882
883
884
#endif
        )
    flags |= VPX_FRAME_IS_KEY;

  if (cpi->droppable)
    flags |= VPX_FRAME_IS_DROPPABLE;

  return flags;
}

885
886
887
888
889
890
static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
                                      const vpx_image_t *img,
                                      vpx_codec_pts_t pts,
                                      unsigned long duration,
                                      vpx_enc_frame_flags_t flags,
                                      unsigned long deadline) {
John Koleszar's avatar
John Koleszar committed
891
  vpx_codec_err_t res = VPX_CODEC_OK;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
892
  VP9_COMP *const cpi = ctx->cpi;
893
  const vpx_rational_t *const timebase = &ctx->cfg.g_timebase;
John Koleszar's avatar
John Koleszar committed
894

895
  if (img != NULL) {
John Koleszar's avatar
John Koleszar committed
896
    res = validate_img(ctx, img);
897
898
    // TODO(jzern) the checks related to cpi's validity should be treated as a
    // failure condition, encoder setup is done fully in init() currently.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
899
    if (res == VPX_CODEC_OK && cpi != NULL && ctx->cx_data == NULL) {
900
901
902
903
      // There's no codec control for multiple alt-refs so check the encoder
      // instance for its status to determine the compressed data size.
      ctx->cx_data_sz = ctx->cfg.g_w * ctx->cfg.g_h *
                        get_image_bps(img) / 8 *
Dmitry Kovalev's avatar
Dmitry Kovalev committed
904
                        (cpi->multi_arf_allowed ? 8 : 2);
905
906
907
908
909
910
911
912
      if (ctx->cx_data_sz < 4096) ctx->cx_data_sz = 4096;

      ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
      if (ctx->cx_data == NULL) {
        return VPX_CODEC_MEM_ERROR;
      }
    }
  }
John Koleszar's avatar
John Koleszar committed
913

John Koleszar's avatar
John Koleszar committed
914
915
  pick_quickcompress_mode(ctx, duration, deadline);
  vpx_codec_pkt_list_init(&ctx->pkt_list);
John Koleszar's avatar
John Koleszar committed
916

917
918
919
  // Handle Flags
  if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
       ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
John Koleszar's avatar
John Koleszar committed
920
921
922
    ctx->base.err_detail = "Conflicting flags.";
    return VPX_CODEC_INVALID_PARAM;
  }
John Koleszar's avatar
John Koleszar committed
923

Dmitry Kovalev's avatar
Dmitry Kovalev committed
924
  vp9_apply_encoding_flags(cpi, flags);
John Koleszar's avatar
John Koleszar committed
925

926
927
928
  // Handle fixed keyframe intervals
  if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
      ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
John Koleszar's avatar
John Koleszar committed
929
930
931
    if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
      flags |= VPX_EFLAG_FORCE_KF;
      ctx->fixed_kf_cntr = 1;