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