vp9_cx_iface.c 41.1 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 15
#include "vpx/vpx_codec.h"
#include "vpx/internal/vpx_codec_internal.h"
16
#include "./vpx_version.h"
17
#include "vp9/encoder/vp9_onyx_int.h"
John Koleszar's avatar
John Koleszar committed
18
#include "vpx/vp8cx.h"
19 20
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/common/vp9_onyx.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 {
John Koleszar's avatar
John Koleszar committed
24
  struct vpx_codec_pkt_list *pkt_list;
25 26
  int                         cpu_used;  /* available cpu percentage in 1/16 */
  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 34
  unsigned int                arnr_max_frames;
  unsigned int                arnr_strength;
  unsigned int                arnr_type;
John Koleszar's avatar
John Koleszar committed
35 36 37
  vp8e_tuning                 tuning;
  unsigned int                cq_level;         /* constrained quality level */
  unsigned int                rc_max_intra_bitrate_pct;
John Koleszar's avatar
John Koleszar committed
38
  unsigned int                lossless;
39
  unsigned int                frame_parallel_decoding_mode;
40
  unsigned int                aq_mode;
John Koleszar's avatar
John Koleszar committed
41 42
};

John Koleszar's avatar
John Koleszar committed
43 44
struct extraconfig_map {
  int                 usage;
45
  struct vp9_extracfg cfg;
John Koleszar's avatar
John Koleszar committed
46 47
};

John Koleszar's avatar
John Koleszar committed
48 49 50
static const struct extraconfig_map extracfg_map[] = {
  {
    0,
51
    { // NOLINT
John Koleszar's avatar
John Koleszar committed
52 53
      NULL,
      0,                          /* cpu_used      */
54
      1,                          /* enable_auto_alt_ref */
John Koleszar's avatar
John Koleszar committed
55
      0,                          /* noise_sensitivity */
56
      0,                          /* sharpness */
John Koleszar's avatar
John Koleszar committed
57
      0,                          /* static_thresh */
58
      0,                          /* tile_columns */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
59
      0,                          /* tile_rows */
60 61
      7,                          /* arnr_max_frames */
      5,                          /* arnr_strength */
John Koleszar's avatar
John Koleszar committed
62 63 64 65
      3,                          /* arnr_type*/
      0,                          /* tuning*/
      10,                         /* cq_level */
      0,                          /* rc_max_intra_bitrate_pct */
John Koleszar's avatar
John Koleszar committed
66
      0,                          /* lossless */
67
      0,                          /* frame_parallel_decoding_mode */
68
      0,                          /* aq_mode */
John Koleszar's avatar
John Koleszar committed
69
    }
John Koleszar's avatar
John Koleszar committed
70
  }
John Koleszar's avatar
John Koleszar committed
71 72
};

John Koleszar's avatar
John Koleszar committed
73 74 75
struct vpx_codec_alg_priv {
  vpx_codec_priv_t        base;
  vpx_codec_enc_cfg_t     cfg;
76
  struct vp9_extracfg     vp8_cfg;
77
  VP9_CONFIG              oxcf;
78
  VP9_PTR                 cpi;
John Koleszar's avatar
John Koleszar committed
79
  unsigned char          *cx_data;
80
  size_t                  cx_data_sz;
81
  unsigned char          *pending_cx_data;
82
  size_t                  pending_cx_data_sz;
John Koleszar's avatar
John Koleszar committed
83
  int                     pending_frame_count;
84 85
  size_t                  pending_frame_sizes[8];
  size_t                  pending_frame_magnitude;
John Koleszar's avatar
John Koleszar committed
86 87
  vpx_image_t             preview_img;
  vp8_postproc_cfg_t      preview_ppcfg;
88
  vpx_codec_pkt_list_decl(64) pkt_list;
John Koleszar's avatar
John Koleszar committed
89
  unsigned int                fixed_kf_cntr;
John Koleszar's avatar
John Koleszar committed
90 91
};

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

static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t                 *ctx,
John Koleszar's avatar
John Koleszar committed
107 108
                   const struct vpx_internal_error_info *error) {
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
109

John Koleszar's avatar
John Koleszar committed
110 111 112 113
  if ((res = error->error_code))
    ctx->base.err_detail = error->has_detail
                           ? error->detail
                           : NULL;
John Koleszar's avatar
John Koleszar committed
114

John Koleszar's avatar
John Koleszar committed
115
  return res;
John Koleszar's avatar
John Koleszar committed
116 117 118
}


119
#undef ERROR
John Koleszar's avatar
John Koleszar committed
120
#define ERROR(str) do {\
John Koleszar's avatar
John Koleszar committed
121 122
    ctx->base.err_detail = str;\
    return VPX_CODEC_INVALID_PARAM;\
123
  } while (0)
John Koleszar's avatar
John Koleszar committed
124

125 126
#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
127
      ERROR(#memb " out of range ["#lo".."#hi"]");\
128
  } while (0)
John Koleszar's avatar
John Koleszar committed
129

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

135 136
#define RANGE_CHECK_LO(p, memb, lo) do {\
    if (!((p)->memb >= (lo))) \
John Koleszar's avatar
John Koleszar committed
137
      ERROR(#memb " out of range ["#lo"..]");\
138
  } while (0)
John Koleszar's avatar
John Koleszar committed
139

140 141 142
#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
143 144 145

static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
                                       const vpx_codec_enc_cfg_t *cfg,
146
                                       const struct vp9_extracfg *vp8_cfg) {
Jingning Han's avatar
Jingning Han committed
147 148
  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
149 150 151
  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
152

John Koleszar's avatar
John Koleszar committed
153 154
  RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
  RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
John Koleszar's avatar
John Koleszar committed
155 156 157 158 159
  RANGE_CHECK_BOOL(vp8_cfg, lossless);
  if (vp8_cfg->lossless) {
    RANGE_CHECK_HI(cfg, rc_max_quantizer, 0);
    RANGE_CHECK_HI(cfg, rc_min_quantizer, 0);
  }
160
  RANGE_CHECK(vp8_cfg, aq_mode,           0, AQ_MODES_COUNT - 1);
John Koleszar's avatar
John Koleszar committed
161

John Koleszar's avatar
John Koleszar committed
162 163
  RANGE_CHECK_HI(cfg, g_threads,          64);
  RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
164
  RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
John Koleszar's avatar
John Koleszar committed
165 166 167 168 169 170 171 172 173 174 175
  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,                 g_delete_firstpassfile);
  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);

176 177
  RANGE_CHECK(cfg, ss_number_layers,      1,
              VPX_SS_MAX_LAYERS); /*Spatial layers max */
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

  RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
  if (cfg->ts_number_layers > 1) {
    int i;
    for (i = 1; i < cfg->ts_number_layers; ++i) {
      if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i-1]) {
        ERROR("ts_target_bitrate entries are not increasing");
      }
    }
    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]) {
        ERROR("ts_rate_decimator factors are not powers of 2");
      }
    }
  }

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

  RANGE_CHECK_BOOL(vp8_cfg,               enable_auto_alt_ref);
  RANGE_CHECK(vp8_cfg, cpu_used,           -16, 16);

  RANGE_CHECK_HI(vp8_cfg, noise_sensitivity,  6);

208
  RANGE_CHECK(vp8_cfg, tile_columns, 0, 6);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
209
  RANGE_CHECK(vp8_cfg, tile_rows, 0, 2);
210
  RANGE_CHECK_HI(vp8_cfg, sharpness, 7);
John Koleszar's avatar
John Koleszar committed
211 212 213 214 215
  RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
  RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
  RANGE_CHECK(vp8_cfg, arnr_type,       1, 3);
  RANGE_CHECK(vp8_cfg, cq_level, 0, 63);

Yaowu Xu's avatar
Yaowu Xu committed
216 217 218 219
  // TODO(yaowu): remove this when ssim tuning is implemented for vp9
  if (vp8_cfg->tuning == VP8_TUNE_SSIM)
      ERROR("Option --tune=ssim is not currently supported in VP9.");

John Koleszar's avatar
John Koleszar committed
220 221
  if (cfg->g_pass == VPX_RC_LAST_PASS) {
    size_t           packet_sz = sizeof(FIRSTPASS_STATS);
222
    int              n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
John Koleszar's avatar
John Koleszar committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
    FIRSTPASS_STATS *stats;

    if (!cfg->rc_twopass_stats_in.buf)
      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.");

    if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
      ERROR("rc_twopass_stats_in requires at least two packets.");

    stats = (void *)((char *)cfg->rc_twopass_stats_in.buf
                     + (n_packets - 1) * packet_sz);

    if ((int)(stats->count + 0.5) != n_packets - 1)
      ERROR("rc_twopass_stats_in missing EOS stats packet");
  }

  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
242 243 244 245
}


static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
246 247
                                    const vpx_image_t    *img) {
  switch (img->fmt) {
James Zern's avatar
James Zern committed
248 249
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_I420:
250 251
    case VPX_IMG_FMT_I422:
    case VPX_IMG_FMT_I444:
John Koleszar's avatar
John Koleszar committed
252
      break;
John Koleszar's avatar
John Koleszar committed
253
    default:
254 255
      ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
            "supported.");
John Koleszar's avatar
John Koleszar committed
256
  }
John Koleszar's avatar
John Koleszar committed
257

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

John Koleszar's avatar
John Koleszar committed
261
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
262 263 264
}


265
static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
John Koleszar's avatar
John Koleszar committed
266
                                       vpx_codec_enc_cfg_t cfg,
267
                                       struct vp9_extracfg vp8_cfg) {
268
  oxcf->version = cfg.g_profile;
269 270
  oxcf->width   = cfg.g_w;
  oxcf->height  = cfg.g_h;
John Koleszar's avatar
John Koleszar committed
271
  /* guess a frame rate if out of whack, use 30 */
272 273
  oxcf->framerate = (double)(cfg.g_timebase.den)
                    / (double)(cfg.g_timebase.num);
John Koleszar's avatar
John Koleszar committed
274

James Zern's avatar
James Zern committed
275 276
  if (oxcf->framerate > 180) {
    oxcf->framerate = 30;
John Koleszar's avatar
John Koleszar committed
277
  }
John Koleszar's avatar
John Koleszar committed
278

John Koleszar's avatar
John Koleszar committed
279
  switch (cfg.g_pass) {
John Koleszar's avatar
John Koleszar committed
280
    case VPX_RC_ONE_PASS:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
281
      oxcf->mode = MODE_GOODQUALITY;
John Koleszar's avatar
John Koleszar committed
282
      break;
John Koleszar's avatar
John Koleszar committed
283
    case VPX_RC_FIRST_PASS:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
284
      oxcf->mode = MODE_FIRSTPASS;
John Koleszar's avatar
John Koleszar committed
285
      break;
John Koleszar's avatar
John Koleszar committed
286
    case VPX_RC_LAST_PASS:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
287
      oxcf->mode = MODE_SECONDPASS_BEST;
John Koleszar's avatar
John Koleszar committed
288 289 290 291
      break;
  }

  if (cfg.g_pass == VPX_RC_FIRST_PASS) {
Jingning Han's avatar
Jingning Han committed
292 293
    oxcf->allow_lag     = 0;
    oxcf->lag_in_frames = 0;
John Koleszar's avatar
John Koleszar committed
294
  } else {
Jingning Han's avatar
Jingning Han committed
295 296
    oxcf->allow_lag     = (cfg.g_lag_in_frames) > 0;
    oxcf->lag_in_frames = cfg.g_lag_in_frames;
John Koleszar's avatar
John Koleszar committed
297 298 299 300 301
  }

  // VBR only supported for now.
  // CBR code has been deprectated for experimental phase.
  // CQ mode not yet tested
302 303 304
  oxcf->end_usage        = USAGE_LOCAL_FILE_PLAYBACK;
  if (cfg.rc_end_usage == VPX_CQ)
    oxcf->end_usage      = USAGE_CONSTRAINED_QUALITY;
305
  else if (cfg.rc_end_usage == VPX_Q)
306
    oxcf->end_usage      = USAGE_CONSTANT_QUALITY;
Marco Paniconi's avatar
Marco Paniconi committed
307 308
  else if (cfg.rc_end_usage == VPX_CBR)
    oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
309

Jingning Han's avatar
Jingning Han committed
310
  oxcf->target_bandwidth         = cfg.rc_target_bitrate;
John Koleszar's avatar
John Koleszar committed
311 312 313 314 315 316 317 318 319 320 321 322 323 324
  oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;

  oxcf->best_allowed_q          = cfg.rc_min_quantizer;
  oxcf->worst_allowed_q         = cfg.rc_max_quantizer;
  oxcf->cq_level                = vp8_cfg.cq_level;
  oxcf->fixed_q = -1;

  oxcf->under_shoot_pct         = cfg.rc_undershoot_pct;
  oxcf->over_shoot_pct          = cfg.rc_overshoot_pct;

  oxcf->maximum_buffer_size     = cfg.rc_buf_sz;
  oxcf->starting_buffer_level   = cfg.rc_buf_initial_sz;
  oxcf->optimal_buffer_level    = cfg.rc_buf_optimal_sz;

325 326
  oxcf->drop_frames_water_mark   = cfg.rc_dropframe_thresh;

Jingning Han's avatar
Jingning Han committed
327
  oxcf->two_pass_vbrbias         = cfg.rc_2pass_vbr_bias_pct;
John Koleszar's avatar
John Koleszar committed
328 329 330 331 332 333 334 335 336 337 338 339
  oxcf->two_pass_vbrmin_section  = cfg.rc_2pass_vbr_minsection_pct;
  oxcf->two_pass_vbrmax_section  = cfg.rc_2pass_vbr_maxsection_pct;

  oxcf->auto_key               = cfg.kf_mode == VPX_KF_AUTO
                                 && cfg.kf_min_dist != cfg.kf_max_dist;
  // oxcf->kf_min_dist         = cfg.kf_min_dis;
  oxcf->key_freq               = cfg.kf_max_dist;

  oxcf->cpu_used               =  vp8_cfg.cpu_used;
  oxcf->encode_breakout        =  vp8_cfg.static_thresh;
  oxcf->play_alternate         =  vp8_cfg.enable_auto_alt_ref;
  oxcf->noise_sensitivity      =  vp8_cfg.noise_sensitivity;
340
  oxcf->sharpness              =  vp8_cfg.sharpness;
John Koleszar's avatar
John Koleszar committed
341

Jingning Han's avatar
Jingning Han committed
342 343
  oxcf->two_pass_stats_in      =  cfg.rc_twopass_stats_in;
  oxcf->output_pkt_list        =  vp8_cfg.pkt_list;
John Koleszar's avatar
John Koleszar committed
344 345

  oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
Jingning Han's avatar
Jingning Han committed
346 347
  oxcf->arnr_strength   = vp8_cfg.arnr_strength;
  oxcf->arnr_type       = vp8_cfg.arnr_type;
John Koleszar's avatar
John Koleszar committed
348 349

  oxcf->tuning = vp8_cfg.tuning;
John Koleszar's avatar
John Koleszar committed
350

351
  oxcf->tile_columns = vp8_cfg.tile_columns;
Jingning Han's avatar
Jingning Han committed
352
  oxcf->tile_rows    = vp8_cfg.tile_rows;
353

John Koleszar's avatar
John Koleszar committed
354
  oxcf->lossless = vp8_cfg.lossless;
Hui Su's avatar
Hui Su committed
355

Jingning Han's avatar
Jingning Han committed
356
  oxcf->error_resilient_mode         = cfg.g_error_resilient;
357
  oxcf->frame_parallel_decoding_mode = vp8_cfg.frame_parallel_decoding_mode;
358

359 360
  oxcf->aq_mode = vp8_cfg.aq_mode;

361
  oxcf->ss_number_layers = cfg.ss_number_layers;
362 363 364 365 366 367 368 369 370 371 372 373 374

  oxcf->ts_number_layers = cfg.ts_number_layers;

  if (oxcf->ts_number_layers > 1) {
    memcpy(oxcf->ts_target_bitrate, cfg.ts_target_bitrate,
           sizeof(cfg.ts_target_bitrate));
    memcpy(oxcf->ts_rate_decimator, cfg.ts_rate_decimator,
           sizeof(cfg.ts_rate_decimator));
  } else if (oxcf->ts_number_layers == 1) {
    oxcf->ts_target_bitrate[0] = oxcf->target_bandwidth;
    oxcf->ts_rate_decimator[0] = 1;
  }

John Koleszar's avatar
John Koleszar committed
375
  /*
376 377 378
  printf("Current VP9 Settings: \n");
  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
  printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
379
  printf("sharpness: %d\n",    oxcf->sharpness);
380
  printf("cpu_used: %d\n",  oxcf->cpu_used);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
381
  printf("Mode: %d\n",     oxcf->mode);
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
  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("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("allow_lag: %d\n", oxcf->allow_lag);
  printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
  printf("play_alternate: %d\n", oxcf->play_alternate);
  printf("Version: %d\n", oxcf->Version);
  printf("encode_breakout: %d\n", oxcf->encode_breakout);
  printf("error resilient: %d\n", oxcf->error_resilient_mode);
402 403
  printf("frame parallel detokenization: %d\n",
         oxcf->frame_parallel_decoding_mode);
John Koleszar's avatar
John Koleszar committed
404 405
  */
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
406 407
}

408
static vpx_codec_err_t vp9e_set_config(vpx_codec_alg_priv_t       *ctx,
John Koleszar's avatar
John Koleszar committed
409 410
                                       const vpx_codec_enc_cfg_t  *cfg) {
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
411

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

John Koleszar's avatar
John Koleszar committed
415 416 417 418 419 420 421
  /* 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");
John Koleszar's avatar
John Koleszar committed
422

John Koleszar's avatar
John Koleszar committed
423
  res = validate_config(ctx, cfg, &ctx->vp8_cfg);
John Koleszar's avatar
John Koleszar committed
424

John Koleszar's avatar
John Koleszar committed
425 426
  if (!res) {
    ctx->cfg = *cfg;
427
    set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
428
    vp9_change_config(ctx->cpi, &ctx->oxcf);
John Koleszar's avatar
John Koleszar committed
429
  }
John Koleszar's avatar
John Koleszar committed
430

John Koleszar's avatar
John Koleszar committed
431
  return res;
John Koleszar's avatar
John Koleszar committed
432 433 434
}


435
int vp9_reverse_trans(int q);
John Koleszar's avatar
John Koleszar committed
436 437 438 439


static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
                                 int                   ctrl_id,
John Koleszar's avatar
John Koleszar committed
440 441
                                 va_list               args) {
  void *arg = va_arg(args, void *);
John Koleszar's avatar
John Koleszar committed
442 443 444

#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break

John Koleszar's avatar
John Koleszar committed
445 446
  if (!arg)
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
447

John Koleszar's avatar
John Koleszar committed
448
  switch (ctrl_id) {
449
      MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
450 451
      MAP(VP8E_GET_LAST_QUANTIZER_64,
          vp9_reverse_trans(vp9_get_quantizer(ctx->cpi)));
John Koleszar's avatar
John Koleszar committed
452
  }
John Koleszar's avatar
John Koleszar committed
453

John Koleszar's avatar
John Koleszar committed
454
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
455 456 457 458 459 460
#undef MAP
}


static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
                                 int                   ctrl_id,
John Koleszar's avatar
John Koleszar committed
461 462
                                 va_list               args) {
  vpx_codec_err_t     res  = VPX_CODEC_OK;
463
  struct vp9_extracfg xcfg = ctx->vp8_cfg;
John Koleszar's avatar
John Koleszar committed
464 465 466

#define MAP(id, var) case id: var = CAST(id, args); break;

John Koleszar's avatar
John Koleszar committed
467
  switch (ctrl_id) {
468 469 470
      MAP(VP8E_SET_CPUUSED,                 xcfg.cpu_used);
      MAP(VP8E_SET_ENABLEAUTOALTREF,        xcfg.enable_auto_alt_ref);
      MAP(VP8E_SET_NOISE_SENSITIVITY,       xcfg.noise_sensitivity);
471
      MAP(VP8E_SET_SHARPNESS,               xcfg.sharpness);
472 473 474 475 476 477 478 479 480 481
      MAP(VP8E_SET_STATIC_THRESHOLD,        xcfg.static_thresh);
      MAP(VP9E_SET_TILE_COLUMNS,            xcfg.tile_columns);
      MAP(VP9E_SET_TILE_ROWS,               xcfg.tile_rows);
      MAP(VP8E_SET_ARNR_MAXFRAMES,          xcfg.arnr_max_frames);
      MAP(VP8E_SET_ARNR_STRENGTH,           xcfg.arnr_strength);
      MAP(VP8E_SET_ARNR_TYPE,               xcfg.arnr_type);
      MAP(VP8E_SET_TUNING,                  xcfg.tuning);
      MAP(VP8E_SET_CQ_LEVEL,                xcfg.cq_level);
      MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT,   xcfg.rc_max_intra_bitrate_pct);
      MAP(VP9E_SET_LOSSLESS,                xcfg.lossless);
482
      MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode);
483
      MAP(VP9E_SET_AQ_MODE,                 xcfg.aq_mode);
John Koleszar's avatar
John Koleszar committed
484 485 486 487 488 489
  }

  res = validate_config(ctx, &ctx->cfg, &xcfg);

  if (!res) {
    ctx->vp8_cfg = xcfg;
490
    set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
491
    vp9_change_config(ctx->cpi, &ctx->oxcf);
John Koleszar's avatar
John Koleszar committed
492 493 494
  }

  return res;
John Koleszar's avatar
John Koleszar committed
495 496
#undef MAP
}
497 498


499
static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx) {
John Koleszar's avatar
John Koleszar committed
500
  vpx_codec_err_t            res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
501 502 503
  struct vpx_codec_alg_priv *priv;
  vpx_codec_enc_cfg_t       *cfg;
  unsigned int               i;
John Koleszar's avatar
John Koleszar committed
504

505
  VP9_PTR optr;
John Koleszar's avatar
John Koleszar committed
506

John Koleszar's avatar
John Koleszar committed
507 508
  if (!ctx->priv) {
    priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
John Koleszar's avatar
John Koleszar committed
509

John Koleszar's avatar
John Koleszar committed
510 511 512
    if (!priv) {
      return VPX_CODEC_MEM_ERROR;
    }
513

John Koleszar's avatar
John Koleszar committed
514 515 516 517 518
    ctx->priv = &priv->base;
    ctx->priv->sz = sizeof(*ctx->priv);
    ctx->priv->iface = ctx->iface;
    ctx->priv->alg_priv = priv;
    ctx->priv->init_flags = ctx->init_flags;
John Koleszar's avatar
John Koleszar committed
519
    ctx->priv->enc.total_encoders = 1;
John Koleszar's avatar
John Koleszar committed
520 521 522 523 524 525 526 527

    if (ctx->config.enc) {
      /* Update the reference to the config structure to an
       * internal copy.
       */
      ctx->priv->alg_priv->cfg = *ctx->config.enc;
      ctx->config.enc = &ctx->priv->alg_priv->cfg;
    }
528

John Koleszar's avatar
John Koleszar committed
529
    cfg =  &ctx->priv->alg_priv->cfg;
John Koleszar's avatar
John Koleszar committed
530

John Koleszar's avatar
John Koleszar committed
531 532 533 534 535 536
    /* Select the extra vp6 configuration table based on the current
     * usage value. If the current usage value isn't found, use the
     * values for usage case 0.
     */
    for (i = 0;
         extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
537
         i++) {}
John Koleszar's avatar
John Koleszar committed
538

John Koleszar's avatar
John Koleszar committed
539 540
    priv->vp8_cfg = extracfg_map[i].cfg;
    priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
John Koleszar's avatar
John Koleszar committed
541

542
    // Maximum buffer size approximated based on having multiple ARF.
543
    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
John Koleszar's avatar
John Koleszar committed
544

John Koleszar's avatar
John Koleszar committed
545
    if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
John Koleszar's avatar
John Koleszar committed
546

John Koleszar's avatar
John Koleszar committed
547
    priv->cx_data = malloc(priv->cx_data_sz);
John Koleszar's avatar
John Koleszar committed
548

John Koleszar's avatar
John Koleszar committed
549 550 551
    if (!priv->cx_data) {
      return VPX_CODEC_MEM_ERROR;
    }
John Koleszar's avatar
John Koleszar committed
552

553
    vp9_initialize_enc();
John Koleszar's avatar
John Koleszar committed
554

John Koleszar's avatar
John Koleszar committed
555
    res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
John Koleszar's avatar
John Koleszar committed
556

John Koleszar's avatar
John Koleszar committed
557
    if (!res) {
558
      set_vp9e_config(&ctx->priv->alg_priv->oxcf,
John Koleszar's avatar
John Koleszar committed
559 560
                      ctx->priv->alg_priv->cfg,
                      ctx->priv->alg_priv->vp8_cfg);
561
      optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
562

John Koleszar's avatar
John Koleszar committed
563 564 565 566
      if (!optr)
        res = VPX_CODEC_MEM_ERROR;
      else
        ctx->priv->alg_priv->cpi = optr;
John Koleszar's avatar
John Koleszar committed
567
    }
John Koleszar's avatar
John Koleszar committed
568
  }
John Koleszar's avatar
John Koleszar committed
569

John Koleszar's avatar
John Koleszar committed
570
  return res;
John Koleszar's avatar
John Koleszar committed
571 572
}

573

574
static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx,
John Koleszar's avatar
John Koleszar committed
575
                                 vpx_codec_priv_enc_mr_cfg_t *data) {
576
  return vp9e_common_init(ctx);
577 578
}

579
static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
580
  free(ctx->cx_data);
581
  vp9_remove_compressor(&ctx->cpi);
John Koleszar's avatar
John Koleszar committed
582 583
  free(ctx);
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
584 585 586 587
}

static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
                                    unsigned long          duration,
John Koleszar's avatar
John Koleszar committed
588 589 590 591
                                    unsigned long          deadline) {
  unsigned int new_qc;

  /* Use best quality mode if no deadline is given. */
Jim Bankoski's avatar
Jim Bankoski committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
  new_qc = MODE_BESTQUALITY;

  if (deadline) {
      uint64_t     duration_us;

      /* Convert duration parameter from stream timebase to microseconds */
      duration_us = (uint64_t)duration * 1000000
                    * (uint64_t)ctx->cfg.g_timebase.num
                    / (uint64_t)ctx->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_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
  }
John Koleszar's avatar
John Koleszar committed
607 608 609 610 611 612 613 614

  if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
    new_qc = MODE_FIRSTPASS;
  else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
    new_qc = (new_qc == MODE_BESTQUALITY)
             ? MODE_SECONDPASS_BEST
             : MODE_SECONDPASS;

Dmitry Kovalev's avatar
Dmitry Kovalev committed
615 616
  if (ctx->oxcf.mode != new_qc) {
    ctx->oxcf.mode = new_qc;
617
    vp9_change_config(ctx->cpi, &ctx->oxcf);
John Koleszar's avatar
John Koleszar committed
618
  }
John Koleszar's avatar
John Koleszar committed
619 620 621
}


622
static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
623
  uint8_t marker = 0xc0;
Yaowu Xu's avatar
Yaowu Xu committed
624 625
  unsigned int mask;
  int mag, index_sz;
John Koleszar's avatar
John Koleszar committed
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659

  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;

  /* Choose the magnitude */
  for (mag = 0, mask = 0xff; mag < 4; mag++) {
    if (ctx->pending_frame_magnitude < mask)
      break;
    mask <<= 8;
    mask |= 0xff;
  }
  marker |= mag << 3;

  /* Write the index */
  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;

    *x++ = marker;
    for (i = 0; i < ctx->pending_frame_count; i++) {
      int this_sz = ctx->pending_frame_sizes[i];

      for (j = 0; j <= mag; j++) {
        *x++ = this_sz & 0xff;
        this_sz >>= 8;
      }
    }
    *x++ = marker;
    ctx->pending_cx_data_sz += index_sz;
  }
660
  return index_sz;
John Koleszar's avatar
John Koleszar committed
661 662
}

663
static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t  *ctx,
John Koleszar's avatar
John Koleszar committed
664 665 666 667
                                   const vpx_image_t     *img,
                                   vpx_codec_pts_t        pts,
                                   unsigned long          duration,
                                   vpx_enc_frame_flags_t  flags,
John Koleszar's avatar
John Koleszar committed
668 669
                                   unsigned long          deadline) {
  vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
670

John Koleszar's avatar
John Koleszar committed
671 672
  if (img)
    res = validate_img(ctx, img);
John Koleszar's avatar
John Koleszar committed
673

John Koleszar's avatar
John Koleszar committed
674 675
  pick_quickcompress_mode(ctx, duration, deadline);
  vpx_codec_pkt_list_init(&ctx->pkt_list);
John Koleszar's avatar
John Koleszar committed
676

John Koleszar's avatar
John Koleszar committed
677 678 679 680 681 682
  /* 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))) {
    ctx->base.err_detail = "Conflicting flags.";
    return VPX_CODEC_INVALID_PARAM;
  }
John Koleszar's avatar
John Koleszar committed
683

John Koleszar's avatar
John Koleszar committed
684 685 686
  if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
               | VP8_EFLAG_NO_REF_ARF)) {
    int ref = 7;
John Koleszar's avatar
John Koleszar committed
687

John Koleszar's avatar
John Koleszar committed
688
    if (flags & VP8_EFLAG_NO_REF_LAST)
689
      ref ^= VP9_LAST_FLAG;
John Koleszar's avatar
John Koleszar committed
690

John Koleszar's avatar
John Koleszar committed
691
    if (flags & VP8_EFLAG_NO_REF_GF)
692
      ref ^= VP9_GOLD_FLAG;
John Koleszar's avatar
John Koleszar committed
693

John Koleszar's avatar
John Koleszar committed
694
    if (flags & VP8_EFLAG_NO_REF_ARF)
695
      ref ^= VP9_ALT_FLAG;
John Koleszar's avatar
John Koleszar committed
696

697
    vp9_use_as_reference(ctx->cpi, ref);
John Koleszar's avatar
John Koleszar committed
698
  }
John Koleszar's avatar
John Koleszar committed
699

John Koleszar's avatar
John Koleszar committed
700 701 702 703
  if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
               | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
               | VP8_EFLAG_FORCE_ARF)) {
    int upd = 7;
John Koleszar's avatar
John Koleszar committed
704

John Koleszar's avatar
John Koleszar committed
705
    if (flags & VP8_EFLAG_NO_UPD_LAST)
706
      upd ^= VP9_LAST_FLAG;
John Koleszar's avatar
John Koleszar committed
707

John Koleszar's avatar
John Koleszar committed
708
    if (flags & VP8_EFLAG_NO_UPD_GF)
709
      upd ^= VP9_GOLD_FLAG;
John Koleszar's avatar
John Koleszar committed
710

John Koleszar's avatar
John Koleszar committed
711
    if (flags & VP8_EFLAG_NO_UPD_ARF)
712
      upd ^= VP9_ALT_FLAG;
John Koleszar's avatar
John Koleszar committed
713

714
    vp9_update_reference(ctx->cpi, upd);
John Koleszar's avatar
John Koleszar committed
715
  }
John Koleszar's avatar
John Koleszar committed
716

John Koleszar's avatar
John Koleszar committed
717
  if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
718
    vp9_update_entropy(ctx->cpi, 0);
John Koleszar's avatar
John Koleszar committed
719
  }
John Koleszar's avatar
John Koleszar committed
720

John Koleszar's avatar
John Koleszar committed
721 722 723 724 725 726
  /* Handle fixed keyframe intervals */
  if (ctx->cfg.kf_mode == VPX_KF_AUTO
      && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
    if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
      flags |= VPX_EFLAG_FORCE_KF;
      ctx->fixed_kf_cntr = 1;
John Koleszar's avatar
John Koleszar committed
727
    }
John Koleszar's avatar
John Koleszar committed
728
  }
John Koleszar's avatar
John Koleszar committed
729

730
  /* Initialize the encoder instance on the first frame. */
John Koleszar's avatar
John Koleszar committed
731 732 733 734
  if (!res && ctx->cpi) {
    unsigned int lib_flags;
    YV12_BUFFER_CONFIG sd;
    int64_t dst_time_stamp, dst_end_time_stamp;
735
    size_t size, cx_data_sz;
John Koleszar's avatar
John Koleszar committed
736
    unsigned char *cx_data;
John Koleszar's avatar
John Koleszar committed
737

John Koleszar's avatar
John Koleszar committed
738 739
    /* Set up internal flags */
    if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
740
      ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
John Koleszar's avatar
John Koleszar committed
741

John Koleszar's avatar
John Koleszar committed
742 743
    /* Convert API flags to internal codec lib flags */
    lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
John Koleszar's avatar
John Koleszar committed
744

John Koleszar's avatar
John Koleszar committed
745
    /* vp8 use 10,000,000 ticks/second as time stamp */
746 747 748 749
    dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num
                     / ctx->cfg.g_timebase.den;
    dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num /
                         ctx->cfg.g_timebase.den;
John Koleszar's avatar
John Koleszar committed
750

John Koleszar's avatar
John Koleszar committed
751 752
    if (img != NULL) {
      res = image2yuvconfig(img, &sd);
John Koleszar's avatar
John Koleszar committed
753

754
      if (vp9_receive_raw_frame(ctx->cpi, lib_flags,
John Koleszar's avatar
John Koleszar committed
755
                                &sd, dst_time_stamp, dst_end_time_stamp)) {
756
        VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
John Koleszar's avatar
John Koleszar committed
757 758 759
        res = update_error_state(ctx, &cpi->common.error);
      }
    }
John Koleszar's avatar
John Koleszar committed
760

761 762
    cx_data = ctx->cx_data;
    cx_data_sz = ctx->cx_data_sz;
John Koleszar's avatar
John Koleszar committed
763 764
    lib_flags = 0;

765 766 767 768 769 770 771 772 773 774 775 776 777 778
    /* Any pending invisible frames? */
    if (ctx->pending_cx_data) {
      memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
      ctx->pending_cx_data = cx_data;
      cx_data += ctx->pending_cx_data_sz;
      cx_data_sz -= ctx->pending_cx_data_sz;

      /* TODO: this is a minimal check, the underlying codec doesn't respect
       * the buffer size anyway.
       */
      if (cx_data_sz < ctx->cx_data_sz / 2) {
        ctx->base.err_detail = "Compressed data buffer too small";
        return VPX_CODEC_ERROR;
      }
779 780
    }

781 782 783 784
    while (cx_data_sz >= ctx->cx_data_sz / 2 &&
           -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size,
                                         cx_data, &dst_time_stamp,
                                         &dst_end_time_stamp, !img)) {
John Koleszar's avatar
John Koleszar committed
785 786 787
      if (size) {
        vpx_codec_pts_t    round, delta;
        vpx_codec_cx_pkt_t pkt;
788
        VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
John Koleszar's avatar
John Koleszar committed
789

790
        /* Pack invisible frames with the next visible frame */
791
        if (!cpi->common.show_frame) {
792 793 794
          if (!ctx->pending_cx_data)
            ctx->pending_cx_data = cx_data;
          ctx->pending_cx_data_sz += size;
John Koleszar's avatar
John Koleszar committed
795 796
          ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
          ctx->pending_frame_magnitude |= size;
797 798 799 800 801
          cx_data += size;
          cx_data_sz -= size;
          continue;
        }

John Koleszar's avatar
John Koleszar committed
802
        /* Add the frame packet to the list of returned packets. */
Yaowu Xu's avatar
Yaowu Xu committed
803
        round = (vpx_codec_pts_t)1000000 * ctx->cfg.g_timebase.num / 2 - 1;
John Koleszar's avatar
John Koleszar committed
804 805 806 807 808
        delta = (dst_end_time_stamp - dst_time_stamp);
        pkt.kind = VPX_CODEC_CX_FRAME_PKT;
        pkt.data.frame.pts =
          (dst_time_stamp * ctx->cfg.g_timebase.den + round)
          / ctx->cfg.g_timebase.num / 10000000;
809 810 811
        pkt.data.frame.duration = (unsigned long)
          ((delta * ctx->cfg.g_timebase.den + round)
          / ctx->cfg.g_timebase.num / 10000000);
John Koleszar's avatar
John Koleszar committed
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
        pkt.data.frame.flags = lib_flags << 16;

        if (lib_flags & FRAMEFLAGS_KEY)
          pkt.data.frame.flags |= VPX_FRAME_IS_KEY;

        if (!cpi->common.show_frame) {
          pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;

          // This timestamp should be as close as possible to the
          // prior PTS so that if a decoder uses pts to schedule when
          // to do this, we start right after last frame was decoded.
          // Invisible frames have no duration.
          pkt.data.frame.pts = ((cpi->last_time_stamp_seen
                                 * ctx->cfg.g_timebase.den + round)
                                / ctx->cfg.g_timebase.num / 10000000) + 1;
          pkt.data.frame.duration = 0;
John Koleszar's avatar
John Koleszar committed
828 829
        }

John Koleszar's avatar
John Koleszar committed
830 831
        if (cpi->droppable)
          pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
John Koleszar's avatar
John Koleszar committed
832

John Koleszar's avatar
John Koleszar committed
833
        /*if (cpi->output_partition)
John Koleszar's avatar
John Koleszar committed
834
        {
John Koleszar's avatar
John Koleszar committed
835 836 837 838 839 840
            int i;
            const int num_partitions = 1;

            pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;

            for (i = 0; i < num_partitions; ++i)
John Koleszar's avatar
John Koleszar committed
841
            {
John Koleszar's avatar
John Koleszar committed
842 843 844 845 846 847 848 849 850
                pkt.data.frame.buf = cx_data;
                pkt.data.frame.sz = cpi->partition_sz[i];
                pkt.data.frame.partition_id = i;
                // don't set the fragment bit for the last partition
                if (i == (num_partitions - 1))
                    pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
                vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
                cx_data += cpi->partition_sz[i];
                cx_data_sz -= cpi->partition_sz[i];
John Koleszar's avatar
John Koleszar committed
851 852
            }
        }
John Koleszar's avatar
John Koleszar committed
853 854
        else*/
        {
855
          if (ctx->pending_cx_data) {
John Koleszar's avatar
John Koleszar committed
856 857 858
            ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
            ctx->pending_frame_magnitude |= size;
            ctx->pending_cx_data_sz += size;
859
            size += write_superframe_index(ctx);
860
            pkt.data.frame.buf = ctx->pending_cx_data;
John Koleszar's avatar
John Koleszar committed
861
            pkt.data.frame.sz  = ctx->pending_cx_data_sz;
862 863
            ctx->pending_cx_data = NULL;
            ctx->pending_cx_data_sz = 0;
John Koleszar's avatar
John Koleszar committed
864 865
            ctx->pending_frame_count = 0;
            ctx->pending_frame_magnitude = 0;
866 867
          } else {
            pkt.data.frame.buf = cx_data;
868
            pkt.data.frame.sz  = size;
869
          }
John Koleszar's avatar
John Koleszar committed
870 871 872 873 874 875
          pkt.data.frame.partition_id = -1;
          vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
          cx_data += size;
          cx_data_sz -= size;
        }
      }
John Koleszar's avatar
John Koleszar committed
876
    }
John Koleszar's avatar
John Koleszar committed
877
  }
John Koleszar's avatar
John Koleszar committed
878

John Koleszar's avatar
John Koleszar committed
879
  return res;
John Koleszar's avatar
John Koleszar committed
880 881 882
}


883
static const vpx_codec_cx_pkt_t *vp9e_get_cxdata(vpx_codec_alg_priv_t  *ctx,
John Koleszar's avatar
John Koleszar committed
884 885
                                                 vpx_codec_iter_t      *iter) {
  return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
John Koleszar's avatar
John Koleszar committed
886 887
}

888
static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
889 890 891
                                          int ctr_id,
                                          va_list args) {
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
892

John Koleszar's avatar
John Koleszar committed
893 894 895
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
896

John Koleszar's avatar
John Koleszar committed
897
    image2yuvconfig(&frame->img, &sd);
898 899
    vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
                          &sd);
John Koleszar's avatar
John Koleszar committed
900
    return VPX_CODEC_OK;
901
  } else {
John Koleszar's avatar
John Koleszar committed
902
    return VPX_CODEC_INVALID_PARAM;
903
  }
John Koleszar's avatar
John Koleszar committed
904 905
}

906
static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
907 908
                                           int ctr_id,
                                           va_list args) {
John Koleszar's avatar
John Koleszar committed
909
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
910

John Koleszar's avatar
John Koleszar committed
911 912 913
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
914

John Koleszar's avatar
John Koleszar committed
915
    image2yuvconfig(&frame->img, &sd);
916 917
    vp9_copy_reference_enc(ctx->cpi,
                           ref_frame_to_vp9_reframe(frame->frame_type), &sd);
John Koleszar's avatar
John Koleszar committed
918
    return VPX_CODEC_OK;
919
  } else {
John Koleszar's avatar
John Koleszar committed
920
    return VPX_CODEC_INVALID_PARAM;
921
  }
John Koleszar's avatar
John Koleszar committed
922 923
}

John Koleszar's avatar
John Koleszar committed
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
                                     int ctr_id,
                                     va_list args) {
  vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);

  if (data) {
    YV12_BUFFER_CONFIG* fb;

    vp9_get_reference_enc(ctx->cpi, data->idx, &fb);
    yuvconfig2image(&data->img, fb, NULL);
    return VPX_CODEC_OK;
  } else {
    return VPX_CODEC_INVALID_PARAM;
  }
}

940
static vpx_codec_err_t vp9e_set_previewpp(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
941 942
                                          int ctr_id,
                                          va_list args) {
943
#if CONFIG_VP9_POSTPROC
John Koleszar's avatar
John Koleszar committed
944 945
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
  (void)ctr_id;
John Koleszar's avatar
John Koleszar committed
946

John Koleszar's avatar
John Koleszar committed
947 948 949
  if (data) {
    ctx