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
#include "vpx/vpx_codec.h"
16
#include "vpx_ports/vpx_once.h"
17
#include "vpx/internal/vpx_codec_internal.h"
18
#include "./vpx_version.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
19
#include "vp9/encoder/vp9_encoder.h"
John Koleszar's avatar
John Koleszar committed
20
#include "vpx/vp8cx.h"
21
#include "vp9/encoder/vp9_firstpass.h"
John Koleszar's avatar
John Koleszar committed
22
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
23

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

47
48
49
50
51
52
53
54
55
56
57
58
59
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
60
  0,                          // rc_max_inter_bitrate_pct
61
  0,                          // gf_cbr_boost_pct
62
63
64
65
  0,                          // lossless
  0,                          // frame_parallel_decoding_mode
  NO_AQ,                      // aq_mode
  0,                          // frame_periodic_delta_q
66
  VPX_BITS_8,                 // Bit depth
67
  VP9E_CONTENT_DEFAULT        // content
John Koleszar's avatar
John Koleszar committed
68
69
};

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

90
static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
91
92
93
94
95
96
97
98
  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
99
  assert(0 && "Invalid Reference Frame");
100
101
  return VP9_LAST_FLAG;
}
John Koleszar's avatar
John Koleszar committed
102

103
104
105
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
106

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

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


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

120
121
#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
122
      ERROR(#memb " out of range ["#lo".."#hi"]");\
123
  } while (0)
John Koleszar's avatar
John Koleszar committed
124

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

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

135
136
137
#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
138

139
static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
140
                                       const vpx_codec_enc_cfg_t *cfg,
141
                                       const struct vp9_extracfg *extra_cfg) {
142
143
  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
144
145
146
  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
147

John Koleszar's avatar
John Koleszar committed
148
149
  RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
  RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
150
151
  RANGE_CHECK_BOOL(extra_cfg, lossless);
  RANGE_CHECK(extra_cfg, aq_mode,           0, AQ_MODE_COUNT - 1);
152
  RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
John Koleszar's avatar
John Koleszar committed
153
154
  RANGE_CHECK_HI(cfg, g_threads,          64);
  RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
155
  RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
John Koleszar's avatar
John Koleszar committed
156
157
158
159
160
161
162
163
164
165
  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);

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

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

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

    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])
183
184
185
        ERROR("ts_rate_decimator factors are not powers of 2");
  }

186
187
188
189
190
191
192
193
194
#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;
    }
195
    if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
196
      ERROR("Not enough ref buffers for svc alt ref frames");
197
    if (cfg->ss_number_layers * cfg->ts_number_layers > 3 &&
198
        cfg->g_error_resilient == 0)
199
    ERROR("Multiple frame context are not supported for more than 3 layers");
200
201
202
  }
#endif

203
  // VP9 does not support a lower bound on the keyframe interval in
204
205
206
207
  // 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
208
209
210
    ERROR("kf_min_dist not supported in auto mode, use 0 "
          "or kf_max_dist instead.");

211
  RANGE_CHECK(extra_cfg, enable_auto_alt_ref, 0, 2);
212
  RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
213
214
215
216
217
218
219
  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);
220
221
  RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
  RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
222
223
  RANGE_CHECK(extra_cfg, content,
              VP9E_CONTENT_DEFAULT, VP9E_CONTENT_INVALID - 1);
John Koleszar's avatar
John Koleszar committed
224

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

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

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

240
    if (cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) {
241
242
243
244
245
      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) {
246
        const int layer_id = (int)stats[i].spatial_layer_id;
247
248
249
250
251
252
253
254
255
256
257
        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
258

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

263
        if (layer_id >= cfg->ss_number_layers
264
265
            ||(unsigned int)(stats->count + 0.5) !=
               n_packets_per_layer[layer_id] - 1)
266
267
268
269
270
271
272
273
274
275
276
277
          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
278
  }
279

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

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

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

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

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

337
338
339
340
341
342
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
343
    case VPX_IMG_FMT_I440: return 16;
344
345
346
    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
347
    case VPX_IMG_FMT_I44016: return 32;
348
    default: assert(0 && "Invalid image format"); break;
349
350
351
  }
  return 0;
}
John Koleszar's avatar
John Koleszar committed
352

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

369
  oxcf->mode = GOOD;
370

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

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

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

393
394
395
396
  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);
397
  oxcf->cq_level        = vp9_quantizer_to_qindex(extra_cfg->cq_level);
John Koleszar's avatar
John Koleszar committed
398
399
  oxcf->fixed_q = -1;

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

403
404
405
406
407
408
409
410
411
  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;
  }
412

Dmitry Kovalev's avatar
Dmitry Kovalev committed
413
414
415
  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
416

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  if (oxcf->ts_number_layers > 1) {
476
477
478
479
480
    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];
    }
481
  } else if (oxcf->ts_number_layers == 1) {
482
    oxcf->ts_target_bitrate[0] = (int)oxcf->target_bandwidth;
483
484
485
    oxcf->ts_rate_decimator[0] = 1;
  }

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

521
522
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
523
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
524

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

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

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

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

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

546
547
548
549
550
551
552
553
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
554

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

564
565
566
567
568
569
570
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
571
  }
572
573
  return res;
}
John Koleszar's avatar
John Koleszar committed
574

575
576
577
578
579
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
580
581
}

582
583
584
585
586
587
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
588

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

596
597
598
599
600
601
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
602

603
604
605
606
607
608
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
609

610
611
612
613
614
615
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
616

617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
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) {
640
641
642
  (void)ctx;
  (void)args;
  return VPX_CODEC_OK;
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
}

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

667
668
669
670
671
672
673
674
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);
}

675
676
677
678
679
680
681
682
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);
}

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
709
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
710
}
711

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

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

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

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

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

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

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

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

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

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

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
  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
788

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

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

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

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

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

817
  // Write the index
John Koleszar's avatar
John Koleszar committed
818
819
820
821
  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;
822
823
824
825
826
827
828
829
830
831
832
833
834
835
#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
836
837
838

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

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

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

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

869
870
871
872
873
874
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
875
      || (is_two_pass_svc(cpi) && cpi->svc.layer_context[0].is_key_frame)
876
877
878
879
880
881
882
883
884
885
#endif
        )
    flags |= VPX_FRAME_IS_KEY;

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

  return flags;
}

886
887
888
889
890
891
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
892
  vpx_codec_err_t res = VPX_CODEC_OK;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
893
  VP9_COMP *const cpi = ctx->cpi;
894
  const vpx_rational_t *const timebase = &ctx->cfg.g_timebase;
John Koleszar's avatar
John Koleszar committed
895

896
  if (img != NULL) {
John Koleszar's avatar
John Koleszar committed
897
    res = validate_img(ctx, img);
898
899
    // 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
900
    if (res == VPX_CODEC_OK && cpi != NULL && ctx->cx_data == NULL) {
901
902
903
904
      // 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
905
                        (cpi->multi_arf_allowed ? 8 : 2);
906
907
908
909
910
911
912
913
      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
914

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

918
919
920
  // 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
921
922
923
    ctx->base.err_detail = "Conflicting flags.";
    return VPX_CODEC_INVALID_PARAM;
  }
John Koleszar's avatar
John Koleszar committed
924

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

927
928
929
  // Handle fixed keyframe intervals
  if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
      ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {