1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  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.
9 */
10
11
12#include "vpx/vpx_codec.h"
13#include "vpx/internal/vpx_codec_internal.h"
14#include "vpx_version.h"
15#include "vp9/encoder/vp9_onyx_int.h"
16#include "vpx/vp8cx.h"
17#include "vp9/encoder/vp9_firstpass.h"
18#include "vp9/common/vp9_onyx.h"
19#include "vp9/vp9_iface_common.h"
20#include <stdlib.h>
21#include <string.h>
22
23struct vp9_extracfg {
24  struct vpx_codec_pkt_list *pkt_list;
25  int                         cpu_used;                    /** available cpu percentage in 1/16*/
26  unsigned int                enable_auto_alt_ref;           /** if encoder decides to uses alternate reference frame */
27  unsigned int                noise_sensitivity;
28  unsigned int                Sharpness;
29  unsigned int                static_thresh;
30  unsigned int                tile_columns;
31  unsigned int                tile_rows;
32  unsigned int                arnr_max_frames;    /* alt_ref Noise Reduction Max Frame Count */
33  unsigned int                arnr_strength;    /* alt_ref Noise Reduction Strength */
34  unsigned int                arnr_type;        /* alt_ref filter type */
35  unsigned int                experimental;
36  vp8e_tuning                 tuning;
37  unsigned int                cq_level;         /* constrained quality level */
38  unsigned int                rc_max_intra_bitrate_pct;
39  unsigned int                lossless;
40  unsigned int                frame_parallel_decoding_mode;
41};
42
43struct extraconfig_map {
44  int                 usage;
45  struct vp9_extracfg cfg;
46};
47
48static const struct extraconfig_map extracfg_map[] = {
49  {
50    0,
51    {
52      NULL,
53      0,                          /* cpu_used      */
54      1,                          /* enable_auto_alt_ref */
55      0,                          /* noise_sensitivity */
56      0,                          /* Sharpness */
57      0,                          /* static_thresh */
58      0,                          /* tile_columns */
59      0,                          /* tile_rows */
60      7,                          /* arnr_max_frames */
61      5,                          /* arnr_strength */
62      3,                          /* arnr_type*/
63      0,                          /* experimental mode */
64      0,                          /* tuning*/
65      10,                         /* cq_level */
66      0,                          /* rc_max_intra_bitrate_pct */
67      0,                          /* lossless */
68      0,                          /* frame_parallel_decoding_mode */
69    }
70  }
71};
72
73struct vpx_codec_alg_priv {
74  vpx_codec_priv_t        base;
75  vpx_codec_enc_cfg_t     cfg;
76  struct vp9_extracfg     vp8_cfg;
77  VP9_CONFIG              oxcf;
78  VP9_PTR             cpi;
79  unsigned char          *cx_data;
80  unsigned int            cx_data_sz;
81  unsigned char          *pending_cx_data;
82  unsigned int            pending_cx_data_sz;
83  int                     pending_frame_count;
84  uint32_t                pending_frame_sizes[8];
85  uint32_t                pending_frame_magnitude;
86  vpx_image_t             preview_img;
87  vp8_postproc_cfg_t      preview_ppcfg;
88  vpx_codec_pkt_list_decl(64) pkt_list;              // changed to accomendate the maximum number of lagged frames allowed
89  unsigned int                fixed_kf_cntr;
90};
91
92static const VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
93  switch (frame) {
94    case VP8_LAST_FRAME:
95      return VP9_LAST_FLAG;
96    case VP8_GOLD_FRAME:
97      return VP9_GOLD_FLAG;
98    case VP8_ALTR_FRAME:
99      return VP9_ALT_FLAG;
100  }
101  assert(!"Invalid Reference Frame");
102  return VP9_LAST_FLAG;
103}
104
105static vpx_codec_err_t
106update_error_state(vpx_codec_alg_priv_t                 *ctx,
107                   const struct vpx_internal_error_info *error) {
108  vpx_codec_err_t res;
109
110  if ((res = error->error_code))
111    ctx->base.err_detail = error->has_detail
112                           ? error->detail
113                           : NULL;
114
115  return res;
116}
117
118
119#undef ERROR
120#define ERROR(str) do {\
121    ctx->base.err_detail = str;\
122    return VPX_CODEC_INVALID_PARAM;\
123  } while(0)
124
125#define RANGE_CHECK(p,memb,lo,hi) do {\
126    if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
127      ERROR(#memb " out of range ["#lo".."#hi"]");\
128  } while(0)
129
130#define RANGE_CHECK_HI(p,memb,hi) do {\
131    if(!((p)->memb <= (hi))) \
132      ERROR(#memb " out of range [.."#hi"]");\
133  } while(0)
134
135#define RANGE_CHECK_LO(p,memb,lo) do {\
136    if(!((p)->memb >= (lo))) \
137      ERROR(#memb " out of range ["#lo"..]");\
138  } while(0)
139
140#define RANGE_CHECK_BOOL(p,memb) do {\
141    if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
142  } while(0)
143
144static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
145                                       const vpx_codec_enc_cfg_t *cfg,
146                                       const struct vp9_extracfg *vp8_cfg) {
147  RANGE_CHECK(cfg, g_w,                   1, 65535); /* 16 bits available */
148  RANGE_CHECK(cfg, g_h,                   1, 65535); /* 16 bits available */
149  RANGE_CHECK(cfg, g_timebase.den,        1, 1000000000);
150  RANGE_CHECK(cfg, g_timebase.num,        1, cfg->g_timebase.den);
151  RANGE_CHECK_HI(cfg, g_profile,          3);
152
153  RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
154  RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
155  RANGE_CHECK_BOOL(vp8_cfg, lossless);
156  if (vp8_cfg->lossless) {
157    RANGE_CHECK_HI(cfg, rc_max_quantizer, 0);
158    RANGE_CHECK_HI(cfg, rc_min_quantizer, 0);
159  }
160
161  RANGE_CHECK_HI(cfg, g_threads,          64);
162  RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
163  RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
164  RANGE_CHECK_HI(cfg, rc_undershoot_pct,  1000);
165  RANGE_CHECK_HI(cfg, rc_overshoot_pct,   1000);
166  RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
167  RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
168  // RANGE_CHECK_BOOL(cfg,                 g_delete_firstpassfile);
169  RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);
170  RANGE_CHECK_HI(cfg, rc_dropframe_thresh,   100);
171  RANGE_CHECK_HI(cfg, rc_resize_up_thresh,   100);
172  RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
173  RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
174
175  RANGE_CHECK(cfg, ss_number_layers,      1,
176              VPX_SS_MAX_LAYERS); /*Spatial layers max */
177  /* VP8 does not support a lower bound on the keyframe interval in
178   * automatic keyframe placement mode.
179   */
180  if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
181      && cfg->kf_min_dist > 0)
182    ERROR("kf_min_dist not supported in auto mode, use 0 "
183          "or kf_max_dist instead.");
184
185  RANGE_CHECK_BOOL(vp8_cfg,               enable_auto_alt_ref);
186  RANGE_CHECK(vp8_cfg, cpu_used,           -16, 16);
187
188  RANGE_CHECK_HI(vp8_cfg, noise_sensitivity,  6);
189
190  RANGE_CHECK(vp8_cfg, tile_columns, 0, 6);
191  RANGE_CHECK(vp8_cfg, tile_rows, 0, 2);
192  RANGE_CHECK_HI(vp8_cfg, Sharpness,       7);
193  RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
194  RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
195  RANGE_CHECK(vp8_cfg, arnr_type,       1, 3);
196  RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
197
198  if (cfg->g_pass == VPX_RC_LAST_PASS) {
199    size_t           packet_sz = sizeof(FIRSTPASS_STATS);
200    int              n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
201    FIRSTPASS_STATS *stats;
202
203    if (!cfg->rc_twopass_stats_in.buf)
204      ERROR("rc_twopass_stats_in.buf not set.");
205
206    if (cfg->rc_twopass_stats_in.sz % packet_sz)
207      ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
208
209    if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
210      ERROR("rc_twopass_stats_in requires at least two packets.");
211
212    stats = (void *)((char *)cfg->rc_twopass_stats_in.buf
213                     + (n_packets - 1) * packet_sz);
214
215    if ((int)(stats->count + 0.5) != n_packets - 1)
216      ERROR("rc_twopass_stats_in missing EOS stats packet");
217  }
218
219  return VPX_CODEC_OK;
220}
221
222
223static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
224                                    const vpx_image_t    *img) {
225  switch (img->fmt) {
226    case VPX_IMG_FMT_YV12:
227    case VPX_IMG_FMT_I420:
228    case VPX_IMG_FMT_I422:
229    case VPX_IMG_FMT_I444:
230      break;
231    default:
232      ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
233            "supported.");
234  }
235
236  if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
237    ERROR("Image size must match encoder init configuration size");
238
239  return VPX_CODEC_OK;
240}
241
242
243static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
244                                       vpx_codec_enc_cfg_t cfg,
245                                       struct vp9_extracfg vp8_cfg) {
246  oxcf->version = cfg.g_profile | (vp8_cfg.experimental ? 0x4 : 0);
247  oxcf->width   = cfg.g_w;
248  oxcf->height  = cfg.g_h;
249  /* guess a frame rate if out of whack, use 30 */
250  oxcf->framerate             = (double)(cfg.g_timebase.den) / (double)(cfg.g_timebase.num);
251
252  if (oxcf->framerate > 180) {
253    oxcf->framerate = 30;
254  }
255
256  switch (cfg.g_pass) {
257    case VPX_RC_ONE_PASS:
258      oxcf->Mode = MODE_BESTQUALITY;
259      break;
260    case VPX_RC_FIRST_PASS:
261      oxcf->Mode = MODE_FIRSTPASS;
262      break;
263    case VPX_RC_LAST_PASS:
264      oxcf->Mode = MODE_SECONDPASS_BEST;
265      break;
266  }
267
268  if (cfg.g_pass == VPX_RC_FIRST_PASS) {
269    oxcf->allow_lag              = 0;
270    oxcf->lag_in_frames           = 0;
271  } else {
272    oxcf->allow_lag              = (cfg.g_lag_in_frames) > 0;
273    oxcf->lag_in_frames           = cfg.g_lag_in_frames;
274  }
275
276  // VBR only supported for now.
277  // CBR code has been deprectated for experimental phase.
278  // CQ mode not yet tested
279  oxcf->end_usage        = USAGE_LOCAL_FILE_PLAYBACK;
280  /*
281  if (cfg.rc_end_usage == VPX_CQ)
282    oxcf->end_usage      = USAGE_CONSTRAINED_QUALITY;
283    */
284  if (cfg.rc_end_usage == VPX_Q)
285    oxcf->end_usage      = USAGE_CONSTANT_QUALITY;
286
287  oxcf->target_bandwidth        = cfg.rc_target_bitrate;
288  oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
289
290  oxcf->best_allowed_q          = cfg.rc_min_quantizer;
291  oxcf->worst_allowed_q         = cfg.rc_max_quantizer;
292  oxcf->cq_level                = vp8_cfg.cq_level;
293  oxcf->fixed_q = -1;
294
295  oxcf->under_shoot_pct         = cfg.rc_undershoot_pct;
296  oxcf->over_shoot_pct          = cfg.rc_overshoot_pct;
297
298  oxcf->maximum_buffer_size     = cfg.rc_buf_sz;
299  oxcf->starting_buffer_level   = cfg.rc_buf_initial_sz;
300  oxcf->optimal_buffer_level    = cfg.rc_buf_optimal_sz;
301
302  oxcf->two_pass_vbrbias        = cfg.rc_2pass_vbr_bias_pct;
303  oxcf->two_pass_vbrmin_section  = cfg.rc_2pass_vbr_minsection_pct;
304  oxcf->two_pass_vbrmax_section  = cfg.rc_2pass_vbr_maxsection_pct;
305
306  oxcf->auto_key               = cfg.kf_mode == VPX_KF_AUTO
307                                 && cfg.kf_min_dist != cfg.kf_max_dist;
308  // oxcf->kf_min_dist         = cfg.kf_min_dis;
309  oxcf->key_freq               = cfg.kf_max_dist;
310
311  // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
312  // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
313
314  oxcf->cpu_used               =  vp8_cfg.cpu_used;
315  oxcf->encode_breakout        =  vp8_cfg.static_thresh;
316  oxcf->play_alternate         =  vp8_cfg.enable_auto_alt_ref;
317  oxcf->noise_sensitivity      =  vp8_cfg.noise_sensitivity;
318  oxcf->Sharpness             =  vp8_cfg.Sharpness;
319
320  oxcf->two_pass_stats_in        =  cfg.rc_twopass_stats_in;
321  oxcf->output_pkt_list         =  vp8_cfg.pkt_list;
322
323  oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
324  oxcf->arnr_strength =  vp8_cfg.arnr_strength;
325  oxcf->arnr_type =      vp8_cfg.arnr_type;
326
327  oxcf->tuning = vp8_cfg.tuning;
328
329  oxcf->tile_columns = vp8_cfg.tile_columns;
330  oxcf->tile_rows = vp8_cfg.tile_rows;
331
332  oxcf->lossless = vp8_cfg.lossless;
333
334  oxcf->error_resilient_mode = cfg.g_error_resilient;
335  oxcf->frame_parallel_decoding_mode = vp8_cfg.frame_parallel_decoding_mode;
336
337  oxcf->ss_number_layers = cfg.ss_number_layers;
338  /*
339  printf("Current VP9 Settings: \n");
340  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
341  printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
342  printf("Sharpness: %d\n",    oxcf->Sharpness);
343  printf("cpu_used: %d\n",  oxcf->cpu_used);
344  printf("Mode: %d\n",     oxcf->Mode);
345  // printf("delete_first_pass_file: %d\n",  oxcf->delete_first_pass_file);
346  printf("auto_key: %d\n",  oxcf->auto_key);
347  printf("key_freq: %d\n", oxcf->key_freq);
348  printf("end_usage: %d\n", oxcf->end_usage);
349  printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
350  printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
351  printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
352  printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
353  printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
354  printf("fixed_q: %d\n",  oxcf->fixed_q);
355  printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
356  printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
357  printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
358  printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
359  printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
360  printf("allow_lag: %d\n", oxcf->allow_lag);
361  printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
362  printf("play_alternate: %d\n", oxcf->play_alternate);
363  printf("Version: %d\n", oxcf->Version);
364  printf("encode_breakout: %d\n", oxcf->encode_breakout);
365  printf("error resilient: %d\n", oxcf->error_resilient_mode);
366  printf("frame parallel detokenization: %d\n",
367         oxcf->frame_parallel_decoding_mode);
368  */
369  return VPX_CODEC_OK;
370}
371
372static vpx_codec_err_t vp9e_set_config(vpx_codec_alg_priv_t       *ctx,
373                                       const vpx_codec_enc_cfg_t  *cfg) {
374  vpx_codec_err_t res;
375
376  if ((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
377    ERROR("Cannot change width or height after initialization");
378
379  /* Prevent increasing lag_in_frames. This check is stricter than it needs
380   * to be -- the limit is not increasing past the first lag_in_frames
381   * value, but we don't track the initial config, only the last successful
382   * config.
383   */
384  if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
385    ERROR("Cannot increase lag_in_frames");
386
387  res = validate_config(ctx, cfg, &ctx->vp8_cfg);
388
389  if (!res) {
390    ctx->cfg = *cfg;
391    set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
392    vp9_change_config(ctx->cpi, &ctx->oxcf);
393  }
394
395  return res;
396}
397
398
399int vp9_reverse_trans(int q);
400
401
402static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
403                                 int                   ctrl_id,
404                                 va_list               args) {
405  void *arg = va_arg(args, void *);
406
407#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
408
409  if (!arg)
410    return VPX_CODEC_INVALID_PARAM;
411
412  switch (ctrl_id) {
413      MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
414      MAP(VP8E_GET_LAST_QUANTIZER_64,
415          vp9_reverse_trans(vp9_get_quantizer(ctx->cpi)));
416  }
417
418  return VPX_CODEC_OK;
419#undef MAP
420}
421
422
423static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
424                                 int                   ctrl_id,
425                                 va_list               args) {
426  vpx_codec_err_t     res  = VPX_CODEC_OK;
427  struct vp9_extracfg xcfg = ctx->vp8_cfg;
428
429#define MAP(id, var) case id: var = CAST(id, args); break;
430
431  switch (ctrl_id) {
432      MAP(VP8E_SET_CPUUSED,                 xcfg.cpu_used);
433      MAP(VP8E_SET_ENABLEAUTOALTREF,        xcfg.enable_auto_alt_ref);
434      MAP(VP8E_SET_NOISE_SENSITIVITY,       xcfg.noise_sensitivity);
435      MAP(VP8E_SET_SHARPNESS,               xcfg.Sharpness);
436      MAP(VP8E_SET_STATIC_THRESHOLD,        xcfg.static_thresh);
437      MAP(VP9E_SET_TILE_COLUMNS,            xcfg.tile_columns);
438      MAP(VP9E_SET_TILE_ROWS,               xcfg.tile_rows);
439      MAP(VP8E_SET_ARNR_MAXFRAMES,          xcfg.arnr_max_frames);
440      MAP(VP8E_SET_ARNR_STRENGTH,           xcfg.arnr_strength);
441      MAP(VP8E_SET_ARNR_TYPE,               xcfg.arnr_type);
442      MAP(VP8E_SET_TUNING,                  xcfg.tuning);
443      MAP(VP8E_SET_CQ_LEVEL,                xcfg.cq_level);
444      MAP(VP9E_SET_MAX_Q,                   ctx->cfg.rc_max_quantizer);
445      MAP(VP9E_SET_MIN_Q,                   ctx->cfg.rc_min_quantizer);
446      MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT,   xcfg.rc_max_intra_bitrate_pct);
447      MAP(VP9E_SET_LOSSLESS,                xcfg.lossless);
448      MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode);
449  }
450
451  res = validate_config(ctx, &ctx->cfg, &xcfg);
452
453  if (!res) {
454    ctx->vp8_cfg = xcfg;
455    set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
456    vp9_change_config(ctx->cpi, &ctx->oxcf);
457  }
458
459  return res;
460#undef MAP
461}
462
463
464static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
465                                        int              experimental) {
466  vpx_codec_err_t            res = VPX_CODEC_OK;
467  struct vpx_codec_alg_priv *priv;
468  vpx_codec_enc_cfg_t       *cfg;
469  unsigned int               i;
470
471  VP9_PTR optr;
472
473  if (!ctx->priv) {
474    priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
475
476    if (!priv) {
477      return VPX_CODEC_MEM_ERROR;
478    }
479
480    ctx->priv = &priv->base;
481    ctx->priv->sz = sizeof(*ctx->priv);
482    ctx->priv->iface = ctx->iface;
483    ctx->priv->alg_priv = priv;
484    ctx->priv->init_flags = ctx->init_flags;
485    ctx->priv->enc.total_encoders = 1;
486
487    if (ctx->config.enc) {
488      /* Update the reference to the config structure to an
489       * internal copy.
490       */
491      ctx->priv->alg_priv->cfg = *ctx->config.enc;
492      ctx->config.enc = &ctx->priv->alg_priv->cfg;
493    }
494
495    cfg =  &ctx->priv->alg_priv->cfg;
496
497    /* Select the extra vp6 configuration table based on the current
498     * usage value. If the current usage value isn't found, use the
499     * values for usage case 0.
500     */
501    for (i = 0;
502         extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
503         i++);
504
505    priv->vp8_cfg = extracfg_map[i].cfg;
506    priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
507    priv->vp8_cfg.experimental = experimental;
508
509    // TODO(agrange) Check the limits set on this buffer, or the check that is
510    // applied in vp9e_encode.
511    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
512//    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
513
514    if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
515
516    priv->cx_data = malloc(priv->cx_data_sz);
517
518    if (!priv->cx_data) {
519      return VPX_CODEC_MEM_ERROR;
520    }
521
522    vp9_initialize_enc();
523
524    res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
525
526    if (!res) {
527      set_vp9e_config(&ctx->priv->alg_priv->oxcf,
528                      ctx->priv->alg_priv->cfg,
529                      ctx->priv->alg_priv->vp8_cfg);
530      optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
531
532      if (!optr)
533        res = VPX_CODEC_MEM_ERROR;
534      else
535        ctx->priv->alg_priv->cpi = optr;
536    }
537  }
538
539  return res;
540}
541
542
543static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx,
544                                 vpx_codec_priv_enc_mr_cfg_t *data) {
545  return vp9e_common_init(ctx, 0);
546}
547
548
549#if CONFIG_EXPERIMENTAL
550static vpx_codec_err_t vp9e_exp_init(vpx_codec_ctx_t *ctx,
551                                     vpx_codec_priv_enc_mr_cfg_t *data) {
552  return vp9e_common_init(ctx, 1);
553}
554#endif
555
556
557static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) {
558
559  free(ctx->cx_data);
560  vp9_remove_compressor(&ctx->cpi);
561  free(ctx);
562  return VPX_CODEC_OK;
563}
564
565static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
566                                    unsigned long          duration,
567                                    unsigned long          deadline) {
568  unsigned int new_qc;
569
570  /* Use best quality mode if no deadline is given. */
571  if (deadline)
572    new_qc = MODE_GOODQUALITY;
573  else
574    new_qc = MODE_BESTQUALITY;
575
576  if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
577    new_qc = MODE_FIRSTPASS;
578  else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
579    new_qc = (new_qc == MODE_BESTQUALITY)
580             ? MODE_SECONDPASS_BEST
581             : MODE_SECONDPASS;
582
583  if (ctx->oxcf.Mode != new_qc) {
584    ctx->oxcf.Mode = new_qc;
585    vp9_change_config(ctx->cpi, &ctx->oxcf);
586  }
587}
588
589
590static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
591  uint8_t marker = 0xc0;
592  int mag, mask, index_sz;
593
594  assert(ctx->pending_frame_count);
595  assert(ctx->pending_frame_count <= 8);
596
597  /* Add the number of frames to the marker byte */
598  marker |= ctx->pending_frame_count - 1;
599
600  /* Choose the magnitude */
601  for (mag = 0, mask = 0xff; mag < 4; mag++) {
602    if (ctx->pending_frame_magnitude < mask)
603      break;
604    mask <<= 8;
605    mask |= 0xff;
606  }
607  marker |= mag << 3;
608
609  /* Write the index */
610  index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
611  if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
612    uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
613    int i, j;
614
615    *x++ = marker;
616    for (i = 0; i < ctx->pending_frame_count; i++) {
617      int this_sz = ctx->pending_frame_sizes[i];
618
619      for (j = 0; j <= mag; j++) {
620        *x++ = this_sz & 0xff;
621        this_sz >>= 8;
622      }
623    }
624    *x++ = marker;
625    ctx->pending_cx_data_sz += index_sz;
626  }
627  return index_sz;
628}
629
630static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t  *ctx,
631                                   const vpx_image_t     *img,
632                                   vpx_codec_pts_t        pts,
633                                   unsigned long          duration,
634                                   vpx_enc_frame_flags_t  flags,
635                                   unsigned long          deadline) {
636  vpx_codec_err_t res = VPX_CODEC_OK;
637
638  if (img)
639    res = validate_img(ctx, img);
640
641  pick_quickcompress_mode(ctx, duration, deadline);
642  vpx_codec_pkt_list_init(&ctx->pkt_list);
643
644  /* Handle Flags */
645  if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
646      || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
647    ctx->base.err_detail = "Conflicting flags.";
648    return VPX_CODEC_INVALID_PARAM;
649  }
650
651  if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
652               | VP8_EFLAG_NO_REF_ARF)) {
653    int ref = 7;
654
655    if (flags & VP8_EFLAG_NO_REF_LAST)
656      ref ^= VP9_LAST_FLAG;
657
658    if (flags & VP8_EFLAG_NO_REF_GF)
659      ref ^= VP9_GOLD_FLAG;
660
661    if (flags & VP8_EFLAG_NO_REF_ARF)
662      ref ^= VP9_ALT_FLAG;
663
664    vp9_use_as_reference(ctx->cpi, ref);
665  }
666
667  if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
668               | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
669               | VP8_EFLAG_FORCE_ARF)) {
670    int upd = 7;
671
672    if (flags & VP8_EFLAG_NO_UPD_LAST)
673      upd ^= VP9_LAST_FLAG;
674
675    if (flags & VP8_EFLAG_NO_UPD_GF)
676      upd ^= VP9_GOLD_FLAG;
677
678    if (flags & VP8_EFLAG_NO_UPD_ARF)
679      upd ^= VP9_ALT_FLAG;
680
681    vp9_update_reference(ctx->cpi, upd);
682  }
683
684  if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
685    vp9_update_entropy(ctx->cpi, 0);
686  }
687
688  /* Handle fixed keyframe intervals */
689  if (ctx->cfg.kf_mode == VPX_KF_AUTO
690      && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
691    if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
692      flags |= VPX_EFLAG_FORCE_KF;
693      ctx->fixed_kf_cntr = 1;
694    }
695  }
696
697  /* Initialize the encoder instance on the first frame*/
698  if (!res && ctx->cpi) {
699    unsigned int lib_flags;
700    YV12_BUFFER_CONFIG sd;
701    int64_t dst_time_stamp, dst_end_time_stamp;
702    unsigned long size, cx_data_sz;
703    unsigned char *cx_data;
704
705    /* Set up internal flags */
706    if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
707      ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
708
709    // if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
710    //    ((VP9_COMP *)ctx->cpi)->output_partition = 1;
711
712    /* Convert API flags to internal codec lib flags */
713    lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
714
715    /* vp8 use 10,000,000 ticks/second as time stamp */
716    dst_time_stamp    = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
717    dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
718
719    if (img != NULL) {
720      res = image2yuvconfig(img, &sd);
721
722      if (vp9_receive_raw_frame(ctx->cpi, lib_flags,
723                                &sd, dst_time_stamp, dst_end_time_stamp)) {
724        VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
725        res = update_error_state(ctx, &cpi->common.error);
726      }
727    }
728
729    cx_data = ctx->cx_data;
730    cx_data_sz = ctx->cx_data_sz;
731    lib_flags = 0;
732
733    /* Any pending invisible frames? */
734    if (ctx->pending_cx_data) {
735      memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
736      ctx->pending_cx_data = cx_data;
737      cx_data += ctx->pending_cx_data_sz;
738      cx_data_sz -= ctx->pending_cx_data_sz;
739
740      /* TODO: this is a minimal check, the underlying codec doesn't respect
741       * the buffer size anyway.
742       */
743      if (cx_data_sz < ctx->cx_data_sz / 2) {
744        ctx->base.err_detail = "Compressed data buffer too small";
745        return VPX_CODEC_ERROR;
746      }
747    }
748
749    while (cx_data_sz >= ctx->cx_data_sz / 2 &&
750           -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size,
751                                         cx_data, &dst_time_stamp,
752                                         &dst_end_time_stamp, !img)) {
753      if (size) {
754        vpx_codec_pts_t    round, delta;
755        vpx_codec_cx_pkt_t pkt;
756        VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
757
758        /* Pack invisible frames with the next visible frame */
759        if (!cpi->common.show_frame) {
760          if (!ctx->pending_cx_data)
761            ctx->pending_cx_data = cx_data;
762          ctx->pending_cx_data_sz += size;
763          ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
764          ctx->pending_frame_magnitude |= size;
765          cx_data += size;
766          cx_data_sz -= size;
767          continue;
768        }
769
770        /* Add the frame packet to the list of returned packets. */
771        round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
772        delta = (dst_end_time_stamp - dst_time_stamp);
773        pkt.kind = VPX_CODEC_CX_FRAME_PKT;
774        pkt.data.frame.pts =
775          (dst_time_stamp * ctx->cfg.g_timebase.den + round)
776          / ctx->cfg.g_timebase.num / 10000000;
777        pkt.data.frame.duration = (unsigned long)
778          ((delta * ctx->cfg.g_timebase.den + round)
779          / ctx->cfg.g_timebase.num / 10000000);
780        pkt.data.frame.flags = lib_flags << 16;
781
782        if (lib_flags & FRAMEFLAGS_KEY)
783          pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
784
785        if (!cpi->common.show_frame) {
786          pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
787
788          // This timestamp should be as close as possible to the
789          // prior PTS so that if a decoder uses pts to schedule when
790          // to do this, we start right after last frame was decoded.
791          // Invisible frames have no duration.
792          pkt.data.frame.pts = ((cpi->last_time_stamp_seen
793                                 * ctx->cfg.g_timebase.den + round)
794                                / ctx->cfg.g_timebase.num / 10000000) + 1;
795          pkt.data.frame.duration = 0;
796        }
797
798        if (cpi->droppable)
799          pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
800
801        /*if (cpi->output_partition)
802        {
803            int i;
804            const int num_partitions = 1;
805
806            pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
807
808            for (i = 0; i < num_partitions; ++i)
809            {
810                pkt.data.frame.buf = cx_data;
811                pkt.data.frame.sz = cpi->partition_sz[i];
812                pkt.data.frame.partition_id = i;
813                // don't set the fragment bit for the last partition
814                if (i == (num_partitions - 1))
815                    pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
816                vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
817                cx_data += cpi->partition_sz[i];
818                cx_data_sz -= cpi->partition_sz[i];
819            }
820        }
821        else*/
822        {
823          if (ctx->pending_cx_data) {
824            ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
825            ctx->pending_frame_magnitude |= size;
826            ctx->pending_cx_data_sz += size;
827            size += write_superframe_index(ctx);
828            pkt.data.frame.buf = ctx->pending_cx_data;
829            pkt.data.frame.sz  = ctx->pending_cx_data_sz;
830            ctx->pending_cx_data = NULL;
831            ctx->pending_cx_data_sz = 0;
832            ctx->pending_frame_count = 0;
833            ctx->pending_frame_magnitude = 0;
834          } else {
835            pkt.data.frame.buf = cx_data;
836            pkt.data.frame.sz  = size;
837          }
838          pkt.data.frame.partition_id = -1;
839          vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
840          cx_data += size;
841          cx_data_sz -= size;
842        }
843
844        // printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
845      }
846    }
847  }
848
849  return res;
850}
851
852
853static const vpx_codec_cx_pkt_t *vp9e_get_cxdata(vpx_codec_alg_priv_t  *ctx,
854                                                 vpx_codec_iter_t      *iter) {
855  return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
856}
857
858static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
859                                          int ctr_id,
860                                          va_list args) {
861  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
862
863  if (data) {
864    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
865    YV12_BUFFER_CONFIG sd;
866
867    image2yuvconfig(&frame->img, &sd);
868    vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
869                          &sd);
870    return VPX_CODEC_OK;
871  } else
872    return VPX_CODEC_INVALID_PARAM;
873
874}
875
876static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
877                                           int ctr_id,
878                                           va_list args) {
879
880  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
881
882  if (data) {
883    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
884    YV12_BUFFER_CONFIG sd;
885
886    image2yuvconfig(&frame->img, &sd);
887    vp9_copy_reference_enc(ctx->cpi,
888                           ref_frame_to_vp9_reframe(frame->frame_type), &sd);
889    return VPX_CODEC_OK;
890  } else
891    return VPX_CODEC_INVALID_PARAM;
892}
893
894static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
895                                     int ctr_id,
896                                     va_list args) {
897  vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
898
899  if (data) {
900    YV12_BUFFER_CONFIG* fb;
901
902    vp9_get_reference_enc(ctx->cpi, data->idx, &fb);
903    yuvconfig2image(&data->img, fb, NULL);
904    return VPX_CODEC_OK;
905  } else {
906    return VPX_CODEC_INVALID_PARAM;
907  }
908}
909
910static vpx_codec_err_t vp9e_set_previewpp(vpx_codec_alg_priv_t *ctx,
911                                          int ctr_id,
912                                          va_list args) {
913#if CONFIG_VP9_POSTPROC
914  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
915  (void)ctr_id;
916
917  if (data) {
918    ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
919    return VPX_CODEC_OK;
920  } else
921    return VPX_CODEC_INVALID_PARAM;
922#else
923  (void)ctx;
924  (void)ctr_id;
925  (void)args;
926  return VPX_CODEC_INCAPABLE;
927#endif
928}
929
930
931static vpx_image_t *vp9e_get_preview(vpx_codec_alg_priv_t *ctx) {
932
933  YV12_BUFFER_CONFIG sd;
934  vp9_ppflags_t flags = {0};
935
936  if (ctx->preview_ppcfg.post_proc_flag) {
937    flags.post_proc_flag        = ctx->preview_ppcfg.post_proc_flag;
938    flags.deblocking_level      = ctx->preview_ppcfg.deblocking_level;
939    flags.noise_level           = ctx->preview_ppcfg.noise_level;
940  }
941
942  if (0 == vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags)) {
943    yuvconfig2image(&ctx->preview_img, &sd, NULL);
944    return &ctx->preview_img;
945  } else
946    return NULL;
947}
948
949static vpx_codec_err_t vp9e_update_entropy(vpx_codec_alg_priv_t *ctx,
950                                           int ctr_id,
951                                           va_list args) {
952  int update = va_arg(args, int);
953  vp9_update_entropy(ctx->cpi, update);
954  return VPX_CODEC_OK;
955
956}
957
958static vpx_codec_err_t vp9e_update_reference(vpx_codec_alg_priv_t *ctx,
959                                             int ctr_id,
960                                             va_list args) {
961  int update = va_arg(args, int);
962  vp9_update_reference(ctx->cpi, update);
963  return VPX_CODEC_OK;
964}
965
966static vpx_codec_err_t vp9e_use_reference(vpx_codec_alg_priv_t *ctx,
967                                          int ctr_id,
968                                          va_list args) {
969  int reference_flag = va_arg(args, int);
970  vp9_use_as_reference(ctx->cpi, reference_flag);
971  return VPX_CODEC_OK;
972}
973
974static vpx_codec_err_t vp9e_set_roi_map(vpx_codec_alg_priv_t *ctx,
975                                        int ctr_id,
976                                        va_list args) {
977  vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
978
979  if (data) {
980    vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
981
982    if (!vp9_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols,
983                        roi->delta_q, roi->delta_lf, roi->static_threshold))
984      return VPX_CODEC_OK;
985    else
986      return VPX_CODEC_INVALID_PARAM;
987  } else
988    return VPX_CODEC_INVALID_PARAM;
989}
990
991
992static vpx_codec_err_t vp9e_set_activemap(vpx_codec_alg_priv_t *ctx,
993                                          int ctr_id,
994                                          va_list args) {
995  vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
996
997  if (data) {
998
999    vpx_active_map_t *map = (vpx_active_map_t *)data;
1000
1001    if (!vp9_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
1002      return VPX_CODEC_OK;
1003    else
1004      return VPX_CODEC_INVALID_PARAM;
1005  } else
1006    return VPX_CODEC_INVALID_PARAM;
1007}
1008
1009static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
1010                                          int ctr_id,
1011                                          va_list args) {
1012
1013  vpx_scaling_mode_t *data =  va_arg(args, vpx_scaling_mode_t *);
1014
1015  if (data) {
1016    int res;
1017    vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data;
1018    res = vp9_set_internal_size(ctx->cpi, scalemode.h_scaling_mode,
1019                                scalemode.v_scaling_mode);
1020
1021    if (!res) {
1022      return VPX_CODEC_OK;
1023    } else
1024      return VPX_CODEC_INVALID_PARAM;
1025  } else
1026    return VPX_CODEC_INVALID_PARAM;
1027}
1028
1029static vpx_codec_err_t vp9e_set_width(vpx_codec_alg_priv_t *ctx, int ctr_id,
1030                                      va_list args) {
1031  unsigned int *data = va_arg(args, unsigned int *);
1032  if (data) {
1033    int res;
1034    res = vp9_set_size_literal(ctx->cpi, *data, 0);
1035    if (!res) {
1036      return VPX_CODEC_OK;
1037    } else {
1038      return VPX_CODEC_INVALID_PARAM;
1039    }
1040  } else {
1041    return VPX_CODEC_INVALID_PARAM;
1042  }
1043}
1044
1045static vpx_codec_err_t vp9e_set_height(vpx_codec_alg_priv_t *ctx,
1046                                       int ctr_id,
1047                                       va_list args) {
1048  unsigned int *data =  va_arg(args, unsigned int *);
1049
1050  if (data) {
1051    int res;
1052    res = vp9_set_size_literal(ctx->cpi, 0, *data);
1053
1054    if (!res) {
1055      return VPX_CODEC_OK;
1056    } else {
1057      return VPX_CODEC_INVALID_PARAM;
1058    }
1059  } else {
1060    return VPX_CODEC_INVALID_PARAM;
1061  }
1062}
1063
1064static vpx_codec_err_t vp9e_set_layer(vpx_codec_alg_priv_t *ctx,
1065                                      int ctr_id,
1066                                      va_list args) {
1067  unsigned int *data =  va_arg(args, unsigned int *);
1068
1069  if (data) {
1070    int res;
1071    res = 0;
1072
1073    res = vp9_switch_layer(ctx->cpi, *data);
1074
1075    if (!res) {
1076      return VPX_CODEC_OK;
1077    } else {
1078      return VPX_CODEC_INVALID_PARAM;
1079    }
1080  } else {
1081    return VPX_CODEC_INVALID_PARAM;
1082  }
1083}
1084
1085static vpx_codec_err_t vp9e_set_svc(vpx_codec_alg_priv_t *ctx, int ctr_id,
1086                                    va_list args) {
1087  int data = va_arg(args, int);
1088  vp9_set_svc(ctx->cpi, data);
1089  return VPX_CODEC_OK;
1090}
1091
1092static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps[] = {
1093  {VP8_SET_REFERENCE,                 vp9e_set_reference},
1094  {VP8_COPY_REFERENCE,                vp9e_copy_reference},
1095  {VP8_SET_POSTPROC,                  vp9e_set_previewpp},
1096  {VP8E_UPD_ENTROPY,                  vp9e_update_entropy},
1097  {VP8E_UPD_REFERENCE,                vp9e_update_reference},
1098  {VP8E_USE_REFERENCE,                vp9e_use_reference},
1099  {VP8E_SET_ROI_MAP,                  vp9e_set_roi_map},
1100  {VP8E_SET_ACTIVEMAP,                vp9e_set_activemap},
1101  {VP8E_SET_SCALEMODE,                vp9e_set_scalemode},
1102  {VP8E_SET_CPUUSED,                  set_param},
1103  {VP8E_SET_NOISE_SENSITIVITY,        set_param},
1104  {VP8E_SET_ENABLEAUTOALTREF,         set_param},
1105  {VP8E_SET_SHARPNESS,                set_param},
1106  {VP8E_SET_STATIC_THRESHOLD,         set_param},
1107  {VP9E_SET_TILE_COLUMNS,             set_param},
1108  {VP9E_SET_TILE_ROWS,                set_param},
1109  {VP8E_GET_LAST_QUANTIZER,           get_param},
1110  {VP8E_GET_LAST_QUANTIZER_64,        get_param},
1111  {VP8E_SET_ARNR_MAXFRAMES,           set_param},
1112  {VP8E_SET_ARNR_STRENGTH,            set_param},
1113  {VP8E_SET_ARNR_TYPE,                set_param},
1114  {VP8E_SET_TUNING,                   set_param},
1115  {VP8E_SET_CQ_LEVEL,                 set_param},
1116  {VP9E_SET_MAX_Q,                    set_param},
1117  {VP9E_SET_MIN_Q,                    set_param},
1118  {VP8E_SET_MAX_INTRA_BITRATE_PCT,    set_param},
1119  {VP9E_SET_LOSSLESS,                 set_param},
1120  {VP9E_SET_FRAME_PARALLEL_DECODING,  set_param},
1121  {VP9_GET_REFERENCE,                 get_reference},
1122  {VP9E_SET_WIDTH,                    vp9e_set_width},
1123  {VP9E_SET_HEIGHT,                   vp9e_set_height},
1124  {VP9E_SET_LAYER,                    vp9e_set_layer},
1125  {VP9E_SET_SVC,                      vp9e_set_svc},
1126  { -1, NULL},
1127};
1128
1129static vpx_codec_enc_cfg_map_t vp9e_usage_cfg_map[] = {
1130  {
1131    0,
1132    {
1133      0,                  /* g_usage */
1134      0,                  /* g_threads */
1135      0,                  /* g_profile */
1136
1137      320,                /* g_width */
1138      240,                /* g_height */
1139      {1, 30},            /* g_timebase */
1140
1141      0,                  /* g_error_resilient */
1142
1143      VPX_RC_ONE_PASS,    /* g_pass */
1144
1145      25,                 /* g_lag_in_frames */
1146
1147      0,                  /* rc_dropframe_thresh */
1148      0,                  /* rc_resize_allowed */
1149      60,                 /* rc_resize_down_thresold */
1150      30,                 /* rc_resize_up_thresold */
1151
1152      VPX_VBR,            /* rc_end_usage */
1153#if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1154      {0},                /* rc_twopass_stats_in */
1155#endif
1156      256,                /* rc_target_bandwidth */
1157      0,                  /* rc_min_quantizer */
1158      63,                 /* rc_max_quantizer */
1159      100,                /* rc_undershoot_pct */
1160      100,                /* rc_overshoot_pct */
1161
1162      6000,               /* rc_max_buffer_size */
1163      4000,               /* rc_buffer_initial_size; */
1164      5000,               /* rc_buffer_optimal_size; */
1165
1166      50,                 /* rc_two_pass_vbrbias  */
1167      0,                  /* rc_two_pass_vbrmin_section */
1168      2000,               /* rc_two_pass_vbrmax_section */
1169
1170      /* keyframing settings (kf) */
1171      VPX_KF_AUTO,        /* g_kfmode*/
1172      0,                  /* kf_min_dist */
1173      9999,               /* kf_max_dist */
1174
1175      VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
1176
1177#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1178      1,                  /* g_delete_first_pass_file */
1179      "vp8.fpf"           /* first pass filename */
1180#endif
1181    }
1182  },
1183  { -1, {NOT_IMPLEMENTED}}
1184};
1185
1186
1187#ifndef VERSION_STRING
1188#define VERSION_STRING
1189#endif
1190CODEC_INTERFACE(vpx_codec_vp9_cx) = {
1191  "WebM Project VP9 Encoder" VERSION_STRING,
1192  VPX_CODEC_INTERNAL_ABI_VERSION,
1193  VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
1194  VPX_CODEC_CAP_OUTPUT_PARTITION,
1195  /* vpx_codec_caps_t          caps; */
1196  vp9e_init,          /* vpx_codec_init_fn_t       init; */
1197  vp9e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
1198  vp9e_ctf_maps,      /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
1199  NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
1200  NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
1201  {
1202    NOT_IMPLEMENTED,    /* vpx_codec_peek_si_fn_t    peek_si; */
1203    NOT_IMPLEMENTED,    /* vpx_codec_get_si_fn_t     get_si; */
1204    NOT_IMPLEMENTED,    /* vpx_codec_decode_fn_t     decode; */
1205    NOT_IMPLEMENTED,    /* vpx_codec_frame_get_fn_t  frame_get; */
1206  },
1207  {
1208    vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
1209    vp9e_encode,        /* vpx_codec_encode_fn_t      encode; */
1210    vp9e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
1211    vp9e_set_config,
1212    NOT_IMPLEMENTED,
1213    vp9e_get_preview,
1214  } /* encoder functions */
1215};
1216
1217
1218#if CONFIG_EXPERIMENTAL
1219
1220CODEC_INTERFACE(vpx_codec_vp9x_cx) = {
1221  "VP8 Experimental Encoder" VERSION_STRING,
1222  VPX_CODEC_INTERNAL_ABI_VERSION,
1223  VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
1224  /* vpx_codec_caps_t          caps; */
1225  vp9e_exp_init,      /* vpx_codec_init_fn_t       init; */
1226  vp9e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
1227  vp9e_ctf_maps,      /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
1228  NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
1229  NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
1230  {
1231    NOT_IMPLEMENTED,    /* vpx_codec_peek_si_fn_t    peek_si; */
1232    NOT_IMPLEMENTED,    /* vpx_codec_get_si_fn_t     get_si; */
1233    NOT_IMPLEMENTED,    /* vpx_codec_decode_fn_t     decode; */
1234    NOT_IMPLEMENTED,    /* vpx_codec_frame_get_fn_t  frame_get; */
1235  },
1236  {
1237    vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
1238    vp9e_encode,        /* vpx_codec_encode_fn_t      encode; */
1239    vp9e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
1240    vp9e_set_config,
1241    NOT_IMPLEMENTED,
1242    vp9e_get_preview,
1243  } /* encoder functions */
1244};
1245#endif
1246