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