Merge "configure: add --extra-cxxflags option"
[platform/upstream/libvpx.git] / vp10 / vp10_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_config.h"
15 #include "vpx/vpx_encoder.h"
16 #include "vpx_ports/vpx_once.h"
17 #include "vpx/internal/vpx_codec_internal.h"
18 #include "./vpx_version.h"
19 #include "vp10/encoder/encoder.h"
20 #include "vpx/vp8cx.h"
21 #include "vp10/encoder/firstpass.h"
22 #include "vp10/vp10_iface_common.h"
23
24 struct vp10_extracfg {
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                min_gf_interval;
35   unsigned int                max_gf_interval;
36   vp8e_tuning                 tuning;
37   unsigned int                cq_level;  // constrained quality level
38   unsigned int                rc_max_intra_bitrate_pct;
39   unsigned int                rc_max_inter_bitrate_pct;
40   unsigned int                gf_cbr_boost_pct;
41   unsigned int                lossless;
42   unsigned int                frame_parallel_decoding_mode;
43   AQ_MODE                     aq_mode;
44   unsigned int                frame_periodic_boost;
45   vpx_bit_depth_t             bit_depth;
46   vp9e_tune_content           content;
47   vpx_color_space_t           color_space;
48   int                         color_range;
49 };
50
51 static struct vp10_extracfg default_extra_cfg = {
52   0,                          // cpu_used
53   1,                          // enable_auto_alt_ref
54   0,                          // noise_sensitivity
55   0,                          // sharpness
56   0,                          // static_thresh
57   6,                          // tile_columns
58   0,                          // tile_rows
59   7,                          // arnr_max_frames
60   5,                          // arnr_strength
61   0,                          // min_gf_interval; 0 -> default decision
62   0,                          // max_gf_interval; 0 -> default decision
63   VP8_TUNE_PSNR,              // tuning
64   10,                         // cq_level
65   0,                          // rc_max_intra_bitrate_pct
66   0,                          // rc_max_inter_bitrate_pct
67   0,                          // gf_cbr_boost_pct
68   0,                          // lossless
69   1,                          // frame_parallel_decoding_mode
70   NO_AQ,                      // aq_mode
71   0,                          // frame_periodic_delta_q
72   VPX_BITS_8,                 // Bit depth
73   VP9E_CONTENT_DEFAULT,       // content
74   VPX_CS_UNKNOWN,             // color space
75   0,                          // color range
76 };
77
78 struct vpx_codec_alg_priv {
79   vpx_codec_priv_t        base;
80   vpx_codec_enc_cfg_t     cfg;
81   struct vp10_extracfg    extra_cfg;
82   VP10EncoderConfig       oxcf;
83   VP10_COMP               *cpi;
84   unsigned char           *cx_data;
85   size_t                  cx_data_sz;
86   unsigned char           *pending_cx_data;
87   size_t                  pending_cx_data_sz;
88   int                     pending_frame_count;
89   size_t                  pending_frame_sizes[8];
90   size_t                  pending_frame_magnitude;
91   vpx_image_t             preview_img;
92   vpx_enc_frame_flags_t   next_frame_flags;
93   vp8_postproc_cfg_t      preview_ppcfg;
94   vpx_codec_pkt_list_decl(256) pkt_list;
95   unsigned int            fixed_kf_cntr;
96   vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb;
97   // BufferPool that holds all reference frames.
98   BufferPool              *buffer_pool;
99 };
100
101 static VP9_REFFRAME ref_frame_to_vp10_reframe(vpx_ref_frame_type_t frame) {
102   switch (frame) {
103     case VP8_LAST_FRAME:
104       return VP9_LAST_FLAG;
105     case VP8_GOLD_FRAME:
106       return VP9_GOLD_FLAG;
107     case VP8_ALTR_FRAME:
108       return VP9_ALT_FLAG;
109   }
110   assert(0 && "Invalid Reference Frame");
111   return VP9_LAST_FLAG;
112 }
113
114 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
115     const struct vpx_internal_error_info *error) {
116   const vpx_codec_err_t res = error->error_code;
117
118   if (res != VPX_CODEC_OK)
119     ctx->base.err_detail = error->has_detail ? error->detail : NULL;
120
121   return res;
122 }
123
124
125 #undef ERROR
126 #define ERROR(str) do {\
127     ctx->base.err_detail = str;\
128     return VPX_CODEC_INVALID_PARAM;\
129   } while (0)
130
131 #define RANGE_CHECK(p, memb, lo, hi) do {\
132     if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
133       ERROR(#memb " out of range ["#lo".."#hi"]");\
134   } while (0)
135
136 #define RANGE_CHECK_HI(p, memb, hi) do {\
137     if (!((p)->memb <= (hi))) \
138       ERROR(#memb " out of range [.."#hi"]");\
139   } while (0)
140
141 #define RANGE_CHECK_LO(p, memb, lo) do {\
142     if (!((p)->memb >= (lo))) \
143       ERROR(#memb " out of range ["#lo"..]");\
144   } while (0)
145
146 #define RANGE_CHECK_BOOL(p, memb) do {\
147     if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
148   } while (0)
149
150 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
151                                        const vpx_codec_enc_cfg_t *cfg,
152                                        const struct vp10_extracfg *extra_cfg) {
153   RANGE_CHECK(cfg, g_w,                   1, 65535);  // 16 bits available
154   RANGE_CHECK(cfg, g_h,                   1, 65535);  // 16 bits available
155   RANGE_CHECK(cfg, g_timebase.den,        1, 1000000000);
156   RANGE_CHECK(cfg, g_timebase.num,        1, cfg->g_timebase.den);
157   RANGE_CHECK_HI(cfg, g_profile,          3);
158
159   RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
160   RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
161   RANGE_CHECK_BOOL(extra_cfg, lossless);
162   RANGE_CHECK(extra_cfg, aq_mode,           0, AQ_MODE_COUNT - 1);
163   RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
164   RANGE_CHECK_HI(cfg, g_threads,          64);
165   RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
166   RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
167   RANGE_CHECK_HI(cfg, rc_undershoot_pct,  100);
168   RANGE_CHECK_HI(cfg, rc_overshoot_pct,   100);
169   RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
170   RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
171   RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);
172   RANGE_CHECK_HI(cfg, rc_dropframe_thresh,   100);
173   RANGE_CHECK_HI(cfg, rc_resize_up_thresh,   100);
174   RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
175   RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
176   RANGE_CHECK(extra_cfg, min_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
177   RANGE_CHECK(extra_cfg, max_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
178   if (extra_cfg->max_gf_interval > 0) {
179     RANGE_CHECK(extra_cfg, max_gf_interval, 2, (MAX_LAG_BUFFERS - 1));
180   }
181   if (extra_cfg->min_gf_interval > 0 && extra_cfg->max_gf_interval > 0) {
182     RANGE_CHECK(extra_cfg, max_gf_interval, extra_cfg->min_gf_interval,
183       (MAX_LAG_BUFFERS - 1));
184   }
185
186   if (cfg->rc_resize_allowed == 1) {
187     RANGE_CHECK(cfg, rc_scaled_width, 0, cfg->g_w);
188     RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
189   }
190
191   // Spatial/temporal scalability are not yet supported in VP10.
192   // Only accept the default value for range checking.
193   RANGE_CHECK(cfg, ss_number_layers, 1, 1);
194   RANGE_CHECK(cfg, ts_number_layers, 1, 1);
195   // VP9 does not support a lower bound on the keyframe interval in
196   // automatic keyframe placement mode.
197   if (cfg->kf_mode != VPX_KF_DISABLED &&
198       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(extra_cfg, enable_auto_alt_ref, 0, 2);
204   RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
205   RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
206   RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
207   RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
208   RANGE_CHECK_HI(extra_cfg, sharpness, 7);
209   RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
210   RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
211   RANGE_CHECK(extra_cfg, cq_level, 0, 63);
212   RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
213   RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
214   RANGE_CHECK(extra_cfg, content,
215               VP9E_CONTENT_DEFAULT, VP9E_CONTENT_INVALID - 1);
216
217   // TODO(yaowu): remove this when ssim tuning is implemented for vp9
218   if (extra_cfg->tuning == VP8_TUNE_SSIM)
219       ERROR("Option --tune=ssim is not currently supported in VP9.");
220
221   if (cfg->g_pass == VPX_RC_LAST_PASS) {
222     const size_t packet_sz = sizeof(FIRSTPASS_STATS);
223     const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
224     const FIRSTPASS_STATS *stats;
225
226     if (cfg->rc_twopass_stats_in.buf == NULL)
227       ERROR("rc_twopass_stats_in.buf not set.");
228
229     if (cfg->rc_twopass_stats_in.sz % packet_sz)
230       ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
231
232     if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
233       ERROR("rc_twopass_stats_in requires at least two packets.");
234
235     stats =
236         (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
237
238     if ((int)(stats->count + 0.5) != n_packets - 1)
239       ERROR("rc_twopass_stats_in missing EOS stats packet");
240   }
241
242 #if !CONFIG_VP9_HIGHBITDEPTH
243   if (cfg->g_profile > (unsigned int)PROFILE_1) {
244     ERROR("Profile > 1 not supported in this build configuration");
245   }
246 #endif
247   if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
248       cfg->g_bit_depth > VPX_BITS_8) {
249     ERROR("Codec high bit-depth not supported in profile < 2");
250   }
251   if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
252       cfg->g_input_bit_depth > 8) {
253     ERROR("Source high bit-depth not supported in profile < 2");
254   }
255   if (cfg->g_profile > (unsigned int)PROFILE_1 &&
256       cfg->g_bit_depth == VPX_BITS_8) {
257     ERROR("Codec bit-depth 8 not supported in profile > 1");
258   }
259   RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB);
260   RANGE_CHECK(extra_cfg, color_range, 0, 1);
261   return VPX_CODEC_OK;
262 }
263
264 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
265                                     const vpx_image_t *img) {
266   switch (img->fmt) {
267     case VPX_IMG_FMT_YV12:
268     case VPX_IMG_FMT_I420:
269     case VPX_IMG_FMT_I42016:
270       break;
271     case VPX_IMG_FMT_I422:
272     case VPX_IMG_FMT_I444:
273     case VPX_IMG_FMT_I440:
274       if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
275         ERROR("Invalid image format. I422, I444, I440 images are "
276               "not supported in profile.");
277       }
278       break;
279     case VPX_IMG_FMT_I42216:
280     case VPX_IMG_FMT_I44416:
281     case VPX_IMG_FMT_I44016:
282       if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
283           ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
284         ERROR("Invalid image format. 16-bit I422, I444, I440 images are "
285               "not supported in profile.");
286       }
287       break;
288     default:
289       ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
290             "supported.");
291       break;
292   }
293
294   if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
295     ERROR("Image size must match encoder init configuration size");
296
297   return VPX_CODEC_OK;
298 }
299
300 static int get_image_bps(const vpx_image_t *img) {
301   switch (img->fmt) {
302     case VPX_IMG_FMT_YV12:
303     case VPX_IMG_FMT_I420: return 12;
304     case VPX_IMG_FMT_I422: return 16;
305     case VPX_IMG_FMT_I444: return 24;
306     case VPX_IMG_FMT_I440: return 16;
307     case VPX_IMG_FMT_I42016: return 24;
308     case VPX_IMG_FMT_I42216: return 32;
309     case VPX_IMG_FMT_I44416: return 48;
310     case VPX_IMG_FMT_I44016: return 32;
311     default: assert(0 && "Invalid image format"); break;
312   }
313   return 0;
314 }
315
316 static vpx_codec_err_t set_encoder_config(
317   VP10EncoderConfig *oxcf,
318   const vpx_codec_enc_cfg_t *cfg,
319   const struct vp10_extracfg *extra_cfg) {
320   const int is_vbr = cfg->rc_end_usage == VPX_VBR;
321   oxcf->profile = cfg->g_profile;
322   oxcf->max_threads = (int)cfg->g_threads;
323   oxcf->width   = cfg->g_w;
324   oxcf->height  = cfg->g_h;
325   oxcf->bit_depth = cfg->g_bit_depth;
326   oxcf->input_bit_depth = cfg->g_input_bit_depth;
327   // guess a frame rate if out of whack, use 30
328   oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
329   if (oxcf->init_framerate > 180)
330     oxcf->init_framerate = 30;
331
332   oxcf->mode = GOOD;
333
334   switch (cfg->g_pass) {
335     case VPX_RC_ONE_PASS:
336       oxcf->pass = 0;
337       break;
338     case VPX_RC_FIRST_PASS:
339       oxcf->pass = 1;
340       break;
341     case VPX_RC_LAST_PASS:
342       oxcf->pass = 2;
343       break;
344   }
345
346   oxcf->lag_in_frames = cfg->g_pass == VPX_RC_FIRST_PASS ? 0
347                                                          : cfg->g_lag_in_frames;
348   oxcf->rc_mode = cfg->rc_end_usage;
349
350   // Convert target bandwidth from Kbit/s to Bit/s
351   oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
352   oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
353   oxcf->rc_max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct;
354   oxcf->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct;
355
356   oxcf->best_allowed_q =
357       extra_cfg->lossless ? 0 : vp10_quantizer_to_qindex(cfg->rc_min_quantizer);
358   oxcf->worst_allowed_q =
359       extra_cfg->lossless ? 0 : vp10_quantizer_to_qindex(cfg->rc_max_quantizer);
360   oxcf->cq_level        = vp10_quantizer_to_qindex(extra_cfg->cq_level);
361   oxcf->fixed_q = -1;
362
363   oxcf->under_shoot_pct         = cfg->rc_undershoot_pct;
364   oxcf->over_shoot_pct          = cfg->rc_overshoot_pct;
365
366   oxcf->scaled_frame_width  = cfg->rc_scaled_width;
367   oxcf->scaled_frame_height = cfg->rc_scaled_height;
368   if (cfg->rc_resize_allowed == 1) {
369     oxcf->resize_mode =
370         (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0) ?
371             RESIZE_DYNAMIC : RESIZE_FIXED;
372   } else {
373     oxcf->resize_mode = RESIZE_NONE;
374   }
375
376   oxcf->maximum_buffer_size_ms   = is_vbr ? 240000 : cfg->rc_buf_sz;
377   oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
378   oxcf->optimal_buffer_level_ms  = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
379
380   oxcf->drop_frames_water_mark   = cfg->rc_dropframe_thresh;
381
382   oxcf->two_pass_vbrbias         = cfg->rc_2pass_vbr_bias_pct;
383   oxcf->two_pass_vbrmin_section  = cfg->rc_2pass_vbr_minsection_pct;
384   oxcf->two_pass_vbrmax_section  = cfg->rc_2pass_vbr_maxsection_pct;
385
386   oxcf->auto_key               = cfg->kf_mode == VPX_KF_AUTO &&
387                                  cfg->kf_min_dist != cfg->kf_max_dist;
388
389   oxcf->key_freq               = cfg->kf_max_dist;
390
391   oxcf->speed                  =  abs(extra_cfg->cpu_used);
392   oxcf->encode_breakout        =  extra_cfg->static_thresh;
393   oxcf->enable_auto_arf        =  extra_cfg->enable_auto_alt_ref;
394   oxcf->noise_sensitivity      =  extra_cfg->noise_sensitivity;
395   oxcf->sharpness              =  extra_cfg->sharpness;
396
397   oxcf->two_pass_stats_in      =  cfg->rc_twopass_stats_in;
398
399 #if CONFIG_FP_MB_STATS
400   oxcf->firstpass_mb_stats_in  = cfg->rc_firstpass_mb_stats_in;
401 #endif
402
403   oxcf->color_space = extra_cfg->color_space;
404   oxcf->color_range = extra_cfg->color_range;
405   oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
406   oxcf->arnr_strength   = extra_cfg->arnr_strength;
407   oxcf->min_gf_interval = extra_cfg->min_gf_interval;
408   oxcf->max_gf_interval = extra_cfg->max_gf_interval;
409
410   oxcf->tuning = extra_cfg->tuning;
411   oxcf->content = extra_cfg->content;
412
413   oxcf->tile_columns = extra_cfg->tile_columns;
414   oxcf->tile_rows    = extra_cfg->tile_rows;
415
416   oxcf->error_resilient_mode         = cfg->g_error_resilient;
417   oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
418
419   oxcf->aq_mode = extra_cfg->aq_mode;
420
421   oxcf->frame_periodic_boost =  extra_cfg->frame_periodic_boost;
422
423   /*
424   printf("Current VP9 Settings: \n");
425   printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
426   printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
427   printf("sharpness: %d\n",    oxcf->sharpness);
428   printf("cpu_used: %d\n",  oxcf->cpu_used);
429   printf("Mode: %d\n",     oxcf->mode);
430   printf("auto_key: %d\n",  oxcf->auto_key);
431   printf("key_freq: %d\n", oxcf->key_freq);
432   printf("end_usage: %d\n", oxcf->end_usage);
433   printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
434   printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
435   printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
436   printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
437   printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
438   printf("fixed_q: %d\n",  oxcf->fixed_q);
439   printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
440   printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
441   printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
442   printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
443   printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
444   printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
445   printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
446   printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
447   printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
448   printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
449   printf("Version: %d\n", oxcf->Version);
450   printf("encode_breakout: %d\n", oxcf->encode_breakout);
451   printf("error resilient: %d\n", oxcf->error_resilient_mode);
452   printf("frame parallel detokenization: %d\n",
453          oxcf->frame_parallel_decoding_mode);
454   */
455   return VPX_CODEC_OK;
456 }
457
458 static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
459                                           const vpx_codec_enc_cfg_t  *cfg) {
460   vpx_codec_err_t res;
461   int force_key = 0;
462
463   if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
464     if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)
465       ERROR("Cannot change width or height after initialization");
466     if (!valid_ref_frame_size(ctx->cfg.g_w, ctx->cfg.g_h, cfg->g_w, cfg->g_h) ||
467         (ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
468         (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
469       force_key = 1;
470   }
471
472   // Prevent increasing lag_in_frames. This check is stricter than it needs
473   // to be -- the limit is not increasing past the first lag_in_frames
474   // value, but we don't track the initial config, only the last successful
475   // config.
476   if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
477     ERROR("Cannot increase lag_in_frames");
478
479   res = validate_config(ctx, cfg, &ctx->extra_cfg);
480
481   if (res == VPX_CODEC_OK) {
482     ctx->cfg = *cfg;
483     set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
484     // On profile change, request a key frame
485     force_key |= ctx->cpi->common.profile != ctx->oxcf.profile;
486     vp10_change_config(ctx->cpi, &ctx->oxcf);
487   }
488
489   if (force_key)
490     ctx->next_frame_flags |= VPX_EFLAG_FORCE_KF;
491
492   return res;
493 }
494
495 static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
496                                           va_list args) {
497   int *const arg = va_arg(args, int *);
498   if (arg == NULL)
499     return VPX_CODEC_INVALID_PARAM;
500   *arg = vp10_get_quantizer(ctx->cpi);
501   return VPX_CODEC_OK;
502 }
503
504 static vpx_codec_err_t ctrl_get_quantizer64(vpx_codec_alg_priv_t *ctx,
505                                             va_list args) {
506   int *const arg = va_arg(args, int *);
507   if (arg == NULL)
508     return VPX_CODEC_INVALID_PARAM;
509   *arg = vp10_qindex_to_quantizer(vp10_get_quantizer(ctx->cpi));
510   return VPX_CODEC_OK;
511 }
512
513 static vpx_codec_err_t update_extra_cfg(vpx_codec_alg_priv_t *ctx,
514                                         const struct vp10_extracfg *extra_cfg) {
515   const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
516   if (res == VPX_CODEC_OK) {
517     ctx->extra_cfg = *extra_cfg;
518     set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
519     vp10_change_config(ctx->cpi, &ctx->oxcf);
520   }
521   return res;
522 }
523
524 static vpx_codec_err_t ctrl_set_cpuused(vpx_codec_alg_priv_t *ctx,
525                                         va_list args) {
526   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
527   extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
528   return update_extra_cfg(ctx, &extra_cfg);
529 }
530
531 static vpx_codec_err_t ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
532                                                     va_list args) {
533   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
534   extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
535   return update_extra_cfg(ctx, &extra_cfg);
536 }
537
538 static vpx_codec_err_t ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
539                                                   va_list args) {
540   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
541   extra_cfg.noise_sensitivity = CAST(VP9E_SET_NOISE_SENSITIVITY, args);
542   return update_extra_cfg(ctx, &extra_cfg);
543 }
544
545 static vpx_codec_err_t ctrl_set_sharpness(vpx_codec_alg_priv_t *ctx,
546                                           va_list args) {
547   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
548   extra_cfg.sharpness = CAST(VP8E_SET_SHARPNESS, args);
549   return update_extra_cfg(ctx, &extra_cfg);
550 }
551
552 static vpx_codec_err_t ctrl_set_static_thresh(vpx_codec_alg_priv_t *ctx,
553                                               va_list args) {
554   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
555   extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
556   return update_extra_cfg(ctx, &extra_cfg);
557 }
558
559 static vpx_codec_err_t ctrl_set_tile_columns(vpx_codec_alg_priv_t *ctx,
560                                              va_list args) {
561   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
562   extra_cfg.tile_columns = CAST(VP9E_SET_TILE_COLUMNS, args);
563   return update_extra_cfg(ctx, &extra_cfg);
564 }
565
566 static vpx_codec_err_t ctrl_set_tile_rows(vpx_codec_alg_priv_t *ctx,
567                                           va_list args) {
568   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
569   extra_cfg.tile_rows = CAST(VP9E_SET_TILE_ROWS, args);
570   return update_extra_cfg(ctx, &extra_cfg);
571 }
572
573 static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
574                                                 va_list args) {
575   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
576   extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
577   return update_extra_cfg(ctx, &extra_cfg);
578 }
579
580 static vpx_codec_err_t ctrl_set_arnr_strength(vpx_codec_alg_priv_t *ctx,
581                                               va_list args) {
582   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
583   extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
584   return update_extra_cfg(ctx, &extra_cfg);
585 }
586
587 static vpx_codec_err_t ctrl_set_arnr_type(vpx_codec_alg_priv_t *ctx,
588                                           va_list args) {
589   (void)ctx;
590   (void)args;
591   return VPX_CODEC_OK;
592 }
593
594 static vpx_codec_err_t ctrl_set_tuning(vpx_codec_alg_priv_t *ctx,
595                                        va_list args) {
596   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
597   extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
598   return update_extra_cfg(ctx, &extra_cfg);
599 }
600
601 static vpx_codec_err_t ctrl_set_cq_level(vpx_codec_alg_priv_t *ctx,
602                                          va_list args) {
603   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
604   extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
605   return update_extra_cfg(ctx, &extra_cfg);
606 }
607
608 static vpx_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
609     vpx_codec_alg_priv_t *ctx, va_list args) {
610   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
611   extra_cfg.rc_max_intra_bitrate_pct =
612       CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
613   return update_extra_cfg(ctx, &extra_cfg);
614 }
615
616 static vpx_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
617     vpx_codec_alg_priv_t *ctx, va_list args) {
618   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
619   extra_cfg.rc_max_inter_bitrate_pct =
620       CAST(VP8E_SET_MAX_INTER_BITRATE_PCT, args);
621   return update_extra_cfg(ctx, &extra_cfg);
622 }
623
624 static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(
625     vpx_codec_alg_priv_t *ctx, va_list args) {
626   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
627   extra_cfg.gf_cbr_boost_pct =
628       CAST(VP9E_SET_GF_CBR_BOOST_PCT, args);
629   return update_extra_cfg(ctx, &extra_cfg);
630 }
631
632 static vpx_codec_err_t ctrl_set_lossless(vpx_codec_alg_priv_t *ctx,
633                                          va_list args) {
634   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
635   extra_cfg.lossless = CAST(VP9E_SET_LOSSLESS, args);
636   return update_extra_cfg(ctx, &extra_cfg);
637 }
638
639 static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
640     vpx_codec_alg_priv_t *ctx, va_list args) {
641   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
642   extra_cfg.frame_parallel_decoding_mode =
643       CAST(VP9E_SET_FRAME_PARALLEL_DECODING, args);
644   return update_extra_cfg(ctx, &extra_cfg);
645 }
646
647 static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx,
648                                         va_list args) {
649   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
650   extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
651   return update_extra_cfg(ctx, &extra_cfg);
652 }
653
654 static vpx_codec_err_t ctrl_set_min_gf_interval(vpx_codec_alg_priv_t *ctx,
655                                                 va_list args) {
656   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
657   extra_cfg.min_gf_interval = CAST(VP9E_SET_MIN_GF_INTERVAL, args);
658   return update_extra_cfg(ctx, &extra_cfg);
659 }
660
661 static vpx_codec_err_t ctrl_set_max_gf_interval(vpx_codec_alg_priv_t *ctx,
662                                                 va_list args) {
663   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
664   extra_cfg.max_gf_interval = CAST(VP9E_SET_MAX_GF_INTERVAL, args);
665   return update_extra_cfg(ctx, &extra_cfg);
666 }
667
668 static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
669                                                      va_list args) {
670   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
671   extra_cfg.frame_periodic_boost = CAST(VP9E_SET_FRAME_PERIODIC_BOOST, args);
672   return update_extra_cfg(ctx, &extra_cfg);
673 }
674
675 static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
676                                     vpx_codec_priv_enc_mr_cfg_t *data) {
677   vpx_codec_err_t res = VPX_CODEC_OK;
678   (void)data;
679
680   if (ctx->priv == NULL) {
681     vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
682     if (priv == NULL)
683       return VPX_CODEC_MEM_ERROR;
684
685     ctx->priv = (vpx_codec_priv_t *)priv;
686     ctx->priv->init_flags = ctx->init_flags;
687     ctx->priv->enc.total_encoders = 1;
688     priv->buffer_pool =
689         (BufferPool *)vpx_calloc(1, sizeof(BufferPool));
690     if (priv->buffer_pool == NULL)
691       return VPX_CODEC_MEM_ERROR;
692
693 #if CONFIG_MULTITHREAD
694     if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
695       return VPX_CODEC_MEM_ERROR;
696     }
697 #endif
698
699     if (ctx->config.enc) {
700       // Update the reference to the config structure to an internal copy.
701       priv->cfg = *ctx->config.enc;
702       ctx->config.enc = &priv->cfg;
703     }
704
705     priv->extra_cfg = default_extra_cfg;
706     once(vp10_initialize_enc);
707
708     res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
709
710     if (res == VPX_CODEC_OK) {
711       set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
712 #if CONFIG_VP9_HIGHBITDEPTH
713       priv->oxcf.use_highbitdepth =
714           (ctx->init_flags & VPX_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
715 #endif
716       priv->cpi = vp10_create_compressor(&priv->oxcf, priv->buffer_pool);
717       if (priv->cpi == NULL)
718         res = VPX_CODEC_MEM_ERROR;
719       else
720         priv->cpi->output_pkt_list = &priv->pkt_list.head;
721     }
722   }
723
724   return res;
725 }
726
727 static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
728   free(ctx->cx_data);
729   vp10_remove_compressor(ctx->cpi);
730 #if CONFIG_MULTITHREAD
731   pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
732 #endif
733   vpx_free(ctx->buffer_pool);
734   vpx_free(ctx);
735   return VPX_CODEC_OK;
736 }
737
738 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
739                                     unsigned long duration,
740                                     unsigned long deadline) {
741   MODE new_mode = BEST;
742
743   switch (ctx->cfg.g_pass) {
744     case VPX_RC_ONE_PASS:
745       if (deadline > 0) {
746         const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg;
747
748         // Convert duration parameter from stream timebase to microseconds.
749         const uint64_t duration_us = (uint64_t)duration * 1000000 *
750            (uint64_t)cfg->g_timebase.num /(uint64_t)cfg->g_timebase.den;
751
752         // If the deadline is more that the duration this frame is to be shown,
753         // use good quality mode. Otherwise use realtime mode.
754         new_mode = (deadline > duration_us) ? GOOD : REALTIME;
755       } else {
756         new_mode = BEST;
757       }
758       break;
759     case VPX_RC_FIRST_PASS:
760       break;
761     case VPX_RC_LAST_PASS:
762       new_mode = deadline > 0 ? GOOD : BEST;
763       break;
764   }
765
766   if (ctx->oxcf.mode != new_mode) {
767     ctx->oxcf.mode = new_mode;
768     vp10_change_config(ctx->cpi, &ctx->oxcf);
769   }
770 }
771
772 // Turn on to test if supplemental superframe data breaks decoding
773 // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
774 static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
775   uint8_t marker = 0xc0;
776   unsigned int mask;
777   int mag, index_sz;
778
779   assert(ctx->pending_frame_count);
780   assert(ctx->pending_frame_count <= 8);
781
782   // Add the number of frames to the marker byte
783   marker |= ctx->pending_frame_count - 1;
784
785   // Choose the magnitude
786   for (mag = 0, mask = 0xff; mag < 4; mag++) {
787     if (ctx->pending_frame_magnitude < mask)
788       break;
789     mask <<= 8;
790     mask |= 0xff;
791   }
792   marker |= mag << 3;
793
794   // Write the index
795   index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
796   if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
797     uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
798     int i, j;
799 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
800     uint8_t marker_test = 0xc0;
801     int mag_test = 2;     // 1 - 4
802     int frames_test = 4;  // 1 - 8
803     int index_sz_test = 2 + mag_test * frames_test;
804     marker_test |= frames_test - 1;
805     marker_test |= (mag_test - 1) << 3;
806     *x++ = marker_test;
807     for (i = 0; i < mag_test * frames_test; ++i)
808       *x++ = 0;  // fill up with arbitrary data
809     *x++ = marker_test;
810     ctx->pending_cx_data_sz += index_sz_test;
811     printf("Added supplemental superframe data\n");
812 #endif
813
814     *x++ = marker;
815     for (i = 0; i < ctx->pending_frame_count; i++) {
816       unsigned int this_sz = (unsigned int)ctx->pending_frame_sizes[i];
817
818       for (j = 0; j <= mag; j++) {
819         *x++ = this_sz & 0xff;
820         this_sz >>= 8;
821       }
822     }
823     *x++ = marker;
824     ctx->pending_cx_data_sz += index_sz;
825 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
826     index_sz += index_sz_test;
827 #endif
828   }
829   return index_sz;
830 }
831
832 // vp9 uses 10,000,000 ticks/second as time stamp
833 #define TICKS_PER_SEC 10000000LL
834
835 static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
836                                        int64_t n) {
837   return n * TICKS_PER_SEC * timebase->num / timebase->den;
838 }
839
840 static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase,
841                                        int64_t n) {
842   const int64_t round = TICKS_PER_SEC * timebase->num / 2 - 1;
843   return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
844 }
845
846 static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP10_COMP *cpi,
847                                                    unsigned int lib_flags) {
848   vpx_codec_frame_flags_t flags = lib_flags << 16;
849
850   if (lib_flags & FRAMEFLAGS_KEY)
851     flags |= VPX_FRAME_IS_KEY;
852
853   if (cpi->droppable)
854     flags |= VPX_FRAME_IS_DROPPABLE;
855
856   return flags;
857 }
858
859 static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
860                                       const vpx_image_t *img,
861                                       vpx_codec_pts_t pts,
862                                       unsigned long duration,
863                                       vpx_enc_frame_flags_t flags,
864                                       unsigned long deadline) {
865   vpx_codec_err_t res = VPX_CODEC_OK;
866   VP10_COMP *const cpi = ctx->cpi;
867   const vpx_rational_t *const timebase = &ctx->cfg.g_timebase;
868   size_t data_sz;
869
870   if (img != NULL) {
871     res = validate_img(ctx, img);
872     // TODO(jzern) the checks related to cpi's validity should be treated as a
873     // failure condition, encoder setup is done fully in init() currently.
874     if (res == VPX_CODEC_OK && cpi != NULL) {
875       // There's no codec control for multiple alt-refs so check the encoder
876       // instance for its status to determine the compressed data size.
877       data_sz = ctx->cfg.g_w * ctx->cfg.g_h * get_image_bps(img) / 8 *
878                 (cpi->multi_arf_allowed ? 8 : 2);
879       if (data_sz < 4096)
880         data_sz = 4096;
881       if (ctx->cx_data == NULL || ctx->cx_data_sz < data_sz) {
882         ctx->cx_data_sz = data_sz;
883         free(ctx->cx_data);
884         ctx->cx_data = (unsigned char*)malloc(ctx->cx_data_sz);
885         if (ctx->cx_data == NULL) {
886           return VPX_CODEC_MEM_ERROR;
887         }
888       }
889     }
890   }
891
892   pick_quickcompress_mode(ctx, duration, deadline);
893   vpx_codec_pkt_list_init(&ctx->pkt_list);
894
895   // Handle Flags
896   if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
897        ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
898     ctx->base.err_detail = "Conflicting flags.";
899     return VPX_CODEC_INVALID_PARAM;
900   }
901
902   vp10_apply_encoding_flags(cpi, flags);
903
904   // Handle fixed keyframe intervals
905   if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
906       ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
907     if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
908       flags |= VPX_EFLAG_FORCE_KF;
909       ctx->fixed_kf_cntr = 1;
910     }
911   }
912
913   // Initialize the encoder instance on the first frame.
914   if (res == VPX_CODEC_OK && cpi != NULL) {
915     unsigned int lib_flags = 0;
916     YV12_BUFFER_CONFIG sd;
917     int64_t dst_time_stamp = timebase_units_to_ticks(timebase, pts);
918     int64_t dst_end_time_stamp =
919         timebase_units_to_ticks(timebase, pts + duration);
920     size_t size, cx_data_sz;
921     unsigned char *cx_data;
922
923     // Set up internal flags
924     if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
925       cpi->b_calculate_psnr = 1;
926
927     if (img != NULL) {
928       res = image2yuvconfig(img, &sd);
929
930       // Store the original flags in to the frame buffer. Will extract the
931       // key frame flag when we actually encode this frame.
932       if (vp10_receive_raw_frame(cpi, flags | ctx->next_frame_flags,
933                                 &sd, dst_time_stamp, dst_end_time_stamp)) {
934         res = update_error_state(ctx, &cpi->common.error);
935       }
936       ctx->next_frame_flags = 0;
937     }
938
939     cx_data = ctx->cx_data;
940     cx_data_sz = ctx->cx_data_sz;
941
942     /* Any pending invisible frames? */
943     if (ctx->pending_cx_data) {
944       memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
945       ctx->pending_cx_data = cx_data;
946       cx_data += ctx->pending_cx_data_sz;
947       cx_data_sz -= ctx->pending_cx_data_sz;
948
949       /* TODO: this is a minimal check, the underlying codec doesn't respect
950        * the buffer size anyway.
951        */
952       if (cx_data_sz < ctx->cx_data_sz / 2) {
953         ctx->base.err_detail = "Compressed data buffer too small";
954         return VPX_CODEC_ERROR;
955       }
956     }
957
958     while (cx_data_sz >= ctx->cx_data_sz / 2 &&
959            -1 != vp10_get_compressed_data(cpi, &lib_flags, &size,
960                                          cx_data, &dst_time_stamp,
961                                          &dst_end_time_stamp, !img)) {
962       if (size) {
963         vpx_codec_cx_pkt_t pkt;
964
965         // Pack invisible frames with the next visible frame
966         if (!cpi->common.show_frame) {
967           if (ctx->pending_cx_data == 0)
968             ctx->pending_cx_data = cx_data;
969           ctx->pending_cx_data_sz += size;
970           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
971           ctx->pending_frame_magnitude |= size;
972           cx_data += size;
973           cx_data_sz -= size;
974
975           if (ctx->output_cx_pkt_cb.output_cx_pkt) {
976             pkt.kind = VPX_CODEC_CX_FRAME_PKT;
977             pkt.data.frame.pts = ticks_to_timebase_units(timebase,
978                                                          dst_time_stamp);
979             pkt.data.frame.duration =
980                (unsigned long)ticks_to_timebase_units(timebase,
981                    dst_end_time_stamp - dst_time_stamp);
982             pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
983             pkt.data.frame.buf = ctx->pending_cx_data;
984             pkt.data.frame.sz  = size;
985             ctx->pending_cx_data = NULL;
986             ctx->pending_cx_data_sz = 0;
987             ctx->pending_frame_count = 0;
988             ctx->pending_frame_magnitude = 0;
989             ctx->output_cx_pkt_cb.output_cx_pkt(
990                 &pkt, ctx->output_cx_pkt_cb.user_priv);
991           }
992           continue;
993         }
994
995         // Add the frame packet to the list of returned packets.
996         pkt.kind = VPX_CODEC_CX_FRAME_PKT;
997         pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
998         pkt.data.frame.duration =
999            (unsigned long)ticks_to_timebase_units(timebase,
1000                dst_end_time_stamp - dst_time_stamp);
1001         pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
1002
1003         if (ctx->pending_cx_data) {
1004           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
1005           ctx->pending_frame_magnitude |= size;
1006           ctx->pending_cx_data_sz += size;
1007           // write the superframe only for the case when
1008           if (!ctx->output_cx_pkt_cb.output_cx_pkt)
1009             size += write_superframe_index(ctx);
1010           pkt.data.frame.buf = ctx->pending_cx_data;
1011           pkt.data.frame.sz  = ctx->pending_cx_data_sz;
1012           ctx->pending_cx_data = NULL;
1013           ctx->pending_cx_data_sz = 0;
1014           ctx->pending_frame_count = 0;
1015           ctx->pending_frame_magnitude = 0;
1016         } else {
1017           pkt.data.frame.buf = cx_data;
1018           pkt.data.frame.sz  = size;
1019         }
1020         pkt.data.frame.partition_id = -1;
1021
1022         if(ctx->output_cx_pkt_cb.output_cx_pkt)
1023           ctx->output_cx_pkt_cb.output_cx_pkt(&pkt,
1024                                               ctx->output_cx_pkt_cb.user_priv);
1025         else
1026           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
1027
1028         cx_data += size;
1029         cx_data_sz -= size;
1030       }
1031     }
1032   }
1033
1034   return res;
1035 }
1036
1037 static const vpx_codec_cx_pkt_t *encoder_get_cxdata(vpx_codec_alg_priv_t *ctx,
1038                                                     vpx_codec_iter_t *iter) {
1039   return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
1040 }
1041
1042 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
1043                                           va_list args) {
1044   vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
1045
1046   if (frame != NULL) {
1047     YV12_BUFFER_CONFIG sd;
1048
1049     image2yuvconfig(&frame->img, &sd);
1050     vp10_set_reference_enc(ctx->cpi, ref_frame_to_vp10_reframe(frame->frame_type),
1051                           &sd);
1052     return VPX_CODEC_OK;
1053   } else {
1054     return VPX_CODEC_INVALID_PARAM;
1055   }
1056 }
1057
1058 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
1059                                            va_list args) {
1060   vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
1061
1062   if (frame != NULL) {
1063     YV12_BUFFER_CONFIG sd;
1064
1065     image2yuvconfig(&frame->img, &sd);
1066     vp10_copy_reference_enc(ctx->cpi,
1067                            ref_frame_to_vp10_reframe(frame->frame_type), &sd);
1068     return VPX_CODEC_OK;
1069   } else {
1070     return VPX_CODEC_INVALID_PARAM;
1071   }
1072 }
1073
1074 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
1075                                           va_list args) {
1076   vp9_ref_frame_t *const frame = va_arg(args, vp9_ref_frame_t *);
1077
1078   if (frame != NULL) {
1079     YV12_BUFFER_CONFIG *fb = get_ref_frame(&ctx->cpi->common, frame->idx);
1080     if (fb == NULL) return VPX_CODEC_ERROR;
1081
1082     yuvconfig2image(&frame->img, fb, NULL);
1083     return VPX_CODEC_OK;
1084   } else {
1085     return VPX_CODEC_INVALID_PARAM;
1086   }
1087 }
1088
1089 static vpx_codec_err_t ctrl_set_previewpp(vpx_codec_alg_priv_t *ctx,
1090                                           va_list args) {
1091 #if CONFIG_VP9_POSTPROC
1092   vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
1093   if (config != NULL) {
1094     ctx->preview_ppcfg = *config;
1095     return VPX_CODEC_OK;
1096   } else {
1097     return VPX_CODEC_INVALID_PARAM;
1098   }
1099 #else
1100   (void)ctx;
1101   (void)args;
1102   return VPX_CODEC_INCAPABLE;
1103 #endif
1104 }
1105
1106
1107 static vpx_image_t *encoder_get_preview(vpx_codec_alg_priv_t *ctx) {
1108   YV12_BUFFER_CONFIG sd;
1109   vp10_ppflags_t flags;
1110   vp10_zero(flags);
1111
1112   if (ctx->preview_ppcfg.post_proc_flag) {
1113     flags.post_proc_flag   = ctx->preview_ppcfg.post_proc_flag;
1114     flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
1115     flags.noise_level      = ctx->preview_ppcfg.noise_level;
1116   }
1117
1118   if (vp10_get_preview_raw_frame(ctx->cpi, &sd, &flags) == 0) {
1119     yuvconfig2image(&ctx->preview_img, &sd, NULL);
1120     return &ctx->preview_img;
1121   } else {
1122     return NULL;
1123   }
1124 }
1125
1126 static vpx_codec_err_t ctrl_update_entropy(vpx_codec_alg_priv_t *ctx,
1127                                            va_list args) {
1128   const int update = va_arg(args, int);
1129
1130   vp10_update_entropy(ctx->cpi, update);
1131   return VPX_CODEC_OK;
1132 }
1133
1134 static vpx_codec_err_t ctrl_update_reference(vpx_codec_alg_priv_t *ctx,
1135                                              va_list args) {
1136   const int ref_frame_flags = va_arg(args, int);
1137
1138   vp10_update_reference(ctx->cpi, ref_frame_flags);
1139   return VPX_CODEC_OK;
1140 }
1141
1142 static vpx_codec_err_t ctrl_use_reference(vpx_codec_alg_priv_t *ctx,
1143                                           va_list args) {
1144   const int reference_flag = va_arg(args, int);
1145
1146   vp10_use_as_reference(ctx->cpi, reference_flag);
1147   return VPX_CODEC_OK;
1148 }
1149
1150 static vpx_codec_err_t ctrl_set_roi_map(vpx_codec_alg_priv_t *ctx,
1151                                         va_list args) {
1152   (void)ctx;
1153   (void)args;
1154
1155   // TODO(yaowu): Need to re-implement and test for VP9.
1156   return VPX_CODEC_INVALID_PARAM;
1157 }
1158
1159
1160 static vpx_codec_err_t ctrl_set_active_map(vpx_codec_alg_priv_t *ctx,
1161                                            va_list args) {
1162   vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
1163
1164   if (map) {
1165     if (!vp10_set_active_map(ctx->cpi, map->active_map,
1166                             (int)map->rows, (int)map->cols))
1167       return VPX_CODEC_OK;
1168     else
1169       return VPX_CODEC_INVALID_PARAM;
1170   } else {
1171     return VPX_CODEC_INVALID_PARAM;
1172   }
1173 }
1174
1175 static vpx_codec_err_t ctrl_get_active_map(vpx_codec_alg_priv_t *ctx,
1176                                            va_list args) {
1177   vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
1178
1179   if (map) {
1180     if (!vp10_get_active_map(ctx->cpi, map->active_map,
1181                             (int)map->rows, (int)map->cols))
1182       return VPX_CODEC_OK;
1183     else
1184       return VPX_CODEC_INVALID_PARAM;
1185   } else {
1186     return VPX_CODEC_INVALID_PARAM;
1187   }
1188 }
1189
1190 static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
1191                                            va_list args) {
1192   vpx_scaling_mode_t *const mode = va_arg(args, vpx_scaling_mode_t *);
1193
1194   if (mode) {
1195     const int res = vp10_set_internal_size(ctx->cpi,
1196                                           (VPX_SCALING)mode->h_scaling_mode,
1197                                           (VPX_SCALING)mode->v_scaling_mode);
1198     return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
1199   } else {
1200     return VPX_CODEC_INVALID_PARAM;
1201   }
1202 }
1203
1204 static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
1205                                                  va_list args) {
1206   vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
1207       (vpx_codec_priv_output_cx_pkt_cb_pair_t *)va_arg(args, void *);
1208   ctx->output_cx_pkt_cb.output_cx_pkt = cbp->output_cx_pkt;
1209   ctx->output_cx_pkt_cb.user_priv = cbp->user_priv;
1210
1211   return VPX_CODEC_OK;
1212 }
1213
1214 static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx,
1215                                              va_list args) {
1216   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
1217   extra_cfg.content = CAST(VP9E_SET_TUNE_CONTENT, args);
1218   return update_extra_cfg(ctx, &extra_cfg);
1219 }
1220
1221 static vpx_codec_err_t ctrl_set_color_space(vpx_codec_alg_priv_t *ctx,
1222                                             va_list args) {
1223   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
1224   extra_cfg.color_space = CAST(VP9E_SET_COLOR_SPACE, args);
1225   return update_extra_cfg(ctx, &extra_cfg);
1226 }
1227
1228 static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx,
1229                                             va_list args) {
1230   struct vp10_extracfg extra_cfg = ctx->extra_cfg;
1231   extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, args);
1232   return update_extra_cfg(ctx, &extra_cfg);
1233 }
1234
1235 static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
1236   {VP8_COPY_REFERENCE,                ctrl_copy_reference},
1237   {VP8E_UPD_ENTROPY,                  ctrl_update_entropy},
1238   {VP8E_UPD_REFERENCE,                ctrl_update_reference},
1239   {VP8E_USE_REFERENCE,                ctrl_use_reference},
1240
1241   // Setters
1242   {VP8_SET_REFERENCE,                 ctrl_set_reference},
1243   {VP8_SET_POSTPROC,                  ctrl_set_previewpp},
1244   {VP8E_SET_ROI_MAP,                  ctrl_set_roi_map},
1245   {VP8E_SET_ACTIVEMAP,                ctrl_set_active_map},
1246   {VP8E_SET_SCALEMODE,                ctrl_set_scale_mode},
1247   {VP8E_SET_CPUUSED,                  ctrl_set_cpuused},
1248   {VP8E_SET_ENABLEAUTOALTREF,         ctrl_set_enable_auto_alt_ref},
1249   {VP8E_SET_SHARPNESS,                ctrl_set_sharpness},
1250   {VP8E_SET_STATIC_THRESHOLD,         ctrl_set_static_thresh},
1251   {VP9E_SET_TILE_COLUMNS,             ctrl_set_tile_columns},
1252   {VP9E_SET_TILE_ROWS,                ctrl_set_tile_rows},
1253   {VP8E_SET_ARNR_MAXFRAMES,           ctrl_set_arnr_max_frames},
1254   {VP8E_SET_ARNR_STRENGTH,            ctrl_set_arnr_strength},
1255   {VP8E_SET_ARNR_TYPE,                ctrl_set_arnr_type},
1256   {VP8E_SET_TUNING,                   ctrl_set_tuning},
1257   {VP8E_SET_CQ_LEVEL,                 ctrl_set_cq_level},
1258   {VP8E_SET_MAX_INTRA_BITRATE_PCT,    ctrl_set_rc_max_intra_bitrate_pct},
1259   {VP9E_SET_MAX_INTER_BITRATE_PCT,    ctrl_set_rc_max_inter_bitrate_pct},
1260   {VP9E_SET_GF_CBR_BOOST_PCT,         ctrl_set_rc_gf_cbr_boost_pct},
1261   {VP9E_SET_LOSSLESS,                 ctrl_set_lossless},
1262   {VP9E_SET_FRAME_PARALLEL_DECODING,  ctrl_set_frame_parallel_decoding_mode},
1263   {VP9E_SET_AQ_MODE,                  ctrl_set_aq_mode},
1264   {VP9E_SET_FRAME_PERIODIC_BOOST,     ctrl_set_frame_periodic_boost},
1265   {VP9E_REGISTER_CX_CALLBACK,         ctrl_register_cx_callback},
1266   {VP9E_SET_TUNE_CONTENT,             ctrl_set_tune_content},
1267   {VP9E_SET_COLOR_SPACE,              ctrl_set_color_space},
1268   {VP9E_SET_COLOR_RANGE,              ctrl_set_color_range},
1269   {VP9E_SET_NOISE_SENSITIVITY,        ctrl_set_noise_sensitivity},
1270   {VP9E_SET_MIN_GF_INTERVAL,          ctrl_set_min_gf_interval},
1271   {VP9E_SET_MAX_GF_INTERVAL,          ctrl_set_max_gf_interval},
1272
1273   // Getters
1274   {VP8E_GET_LAST_QUANTIZER,           ctrl_get_quantizer},
1275   {VP8E_GET_LAST_QUANTIZER_64,        ctrl_get_quantizer64},
1276   {VP9_GET_REFERENCE,                 ctrl_get_reference},
1277   {VP9E_GET_ACTIVEMAP,                ctrl_get_active_map},
1278
1279   { -1, NULL},
1280 };
1281
1282 static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
1283   {
1284     0,
1285     {  // NOLINT
1286       0,                  // g_usage
1287       8,                  // g_threads
1288       0,                  // g_profile
1289
1290       320,                // g_width
1291       240,                // g_height
1292       VPX_BITS_8,         // g_bit_depth
1293       8,                  // g_input_bit_depth
1294
1295       {1, 30},            // g_timebase
1296
1297       0,                  // g_error_resilient
1298
1299       VPX_RC_ONE_PASS,    // g_pass
1300
1301       25,                 // g_lag_in_frames
1302
1303       0,                  // rc_dropframe_thresh
1304       0,                  // rc_resize_allowed
1305       0,                  // rc_scaled_width
1306       0,                  // rc_scaled_height
1307       60,                 // rc_resize_down_thresold
1308       30,                 // rc_resize_up_thresold
1309
1310       VPX_VBR,            // rc_end_usage
1311       {NULL, 0},          // rc_twopass_stats_in
1312       {NULL, 0},          // rc_firstpass_mb_stats_in
1313       256,                // rc_target_bandwidth
1314       0,                  // rc_min_quantizer
1315       63,                 // rc_max_quantizer
1316       25,                 // rc_undershoot_pct
1317       25,                 // rc_overshoot_pct
1318
1319       6000,               // rc_max_buffer_size
1320       4000,               // rc_buffer_initial_size
1321       5000,               // rc_buffer_optimal_size
1322
1323       50,                 // rc_two_pass_vbrbias
1324       0,                  // rc_two_pass_vbrmin_section
1325       2000,               // rc_two_pass_vbrmax_section
1326
1327       // keyframing settings (kf)
1328       VPX_KF_AUTO,        // g_kfmode
1329       0,                  // kf_min_dist
1330       9999,               // kf_max_dist
1331
1332       // TODO(yunqingwang): Spatial/temporal scalability are not supported
1333       // in VP10. The following 10 parameters are not used, which should
1334       // be removed later.
1335       1,                      // ss_number_layers
1336       {0},
1337       {0},                    // ss_target_bitrate
1338       1,                      // ts_number_layers
1339       {0},                    // ts_target_bitrate
1340       {0},                    // ts_rate_decimator
1341       0,                      // ts_periodicity
1342       {0},                    // ts_layer_id
1343       {0},                  // layer_taget_bitrate
1344       0                     // temporal_layering_mode
1345     }
1346   },
1347 };
1348
1349 #ifndef VERSION_STRING
1350 #define VERSION_STRING
1351 #endif
1352 CODEC_INTERFACE(vpx_codec_vp10_cx) = {
1353   "WebM Project VP10 Encoder" VERSION_STRING,
1354   VPX_CODEC_INTERNAL_ABI_VERSION,
1355 #if CONFIG_VP9_HIGHBITDEPTH
1356   VPX_CODEC_CAP_HIGHBITDEPTH |
1357 #endif
1358   VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,  // vpx_codec_caps_t
1359   encoder_init,       // vpx_codec_init_fn_t
1360   encoder_destroy,    // vpx_codec_destroy_fn_t
1361   encoder_ctrl_maps,  // vpx_codec_ctrl_fn_map_t
1362   {  // NOLINT
1363     NULL,  // vpx_codec_peek_si_fn_t
1364     NULL,  // vpx_codec_get_si_fn_t
1365     NULL,  // vpx_codec_decode_fn_t
1366     NULL,  // vpx_codec_frame_get_fn_t
1367     NULL   // vpx_codec_set_fb_fn_t
1368   },
1369   {  // NOLINT
1370     1,                      // 1 cfg map
1371     encoder_usage_cfg_map,  // vpx_codec_enc_cfg_map_t
1372     encoder_encode,         // vpx_codec_encode_fn_t
1373     encoder_get_cxdata,     // vpx_codec_get_cx_data_fn_t
1374     encoder_set_config,     // vpx_codec_enc_config_set_fn_t
1375     NULL,        // vpx_codec_get_global_headers_fn_t
1376     encoder_get_preview,    // vpx_codec_get_preview_frame_fn_t
1377     NULL         // vpx_codec_enc_mr_get_mem_loc_fn_t
1378   }
1379 };