2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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.
14 #include "vpx/vpx_codec.h"
15 #include "vpx/internal/vpx_codec_internal.h"
16 #include "./vpx_version.h"
17 #include "vp9/encoder/vp9_encoder.h"
18 #include "vpx/vp8cx.h"
19 #include "vp9/encoder/vp9_firstpass.h"
20 #include "vp9/vp9_iface_common.h"
23 struct vpx_codec_pkt_list *pkt_list;
24 int cpu_used; // available cpu percentage in 1/16
25 unsigned int enable_auto_alt_ref;
26 unsigned int noise_sensitivity;
27 unsigned int sharpness;
28 unsigned int static_thresh;
29 unsigned int tile_columns;
30 unsigned int tile_rows;
31 unsigned int arnr_max_frames;
32 unsigned int arnr_strength;
33 unsigned int arnr_type;
35 unsigned int cq_level; // constrained quality level
36 unsigned int rc_max_intra_bitrate_pct;
37 unsigned int lossless;
38 unsigned int frame_parallel_decoding_mode;
40 unsigned int frame_periodic_boost;
44 struct extraconfig_map {
46 struct vp9_extracfg cfg;
49 static const struct extraconfig_map extracfg_map[] = {
55 1, // enable_auto_alt_ref
56 0, // noise_sensitivity
64 VP8_TUNE_PSNR, // tuning
66 0, // rc_max_intra_bitrate_pct
68 0, // frame_parallel_decoding_mode
70 0, // frame_periodic_delta_q
76 struct vpx_codec_alg_priv {
77 vpx_codec_priv_t base;
78 vpx_codec_enc_cfg_t cfg;
79 struct vp9_extracfg extra_cfg;
80 VP9EncoderConfig oxcf;
82 unsigned char *cx_data;
84 unsigned char *pending_cx_data;
85 size_t pending_cx_data_sz;
86 int pending_frame_count;
87 size_t pending_frame_sizes[8];
88 size_t pending_frame_magnitude;
89 vpx_image_t preview_img;
90 vp8_postproc_cfg_t preview_ppcfg;
91 vpx_codec_pkt_list_decl(128) pkt_list;
92 unsigned int fixed_kf_cntr;
95 static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
100 return VP9_GOLD_FLAG;
104 assert(0 && "Invalid Reference Frame");
105 return VP9_LAST_FLAG;
108 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
109 const struct vpx_internal_error_info *error) {
110 const vpx_codec_err_t res = error->error_code;
112 if (res != VPX_CODEC_OK)
113 ctx->base.err_detail = error->has_detail ? error->detail : NULL;
120 #define ERROR(str) do {\
121 ctx->base.err_detail = str;\
122 return VPX_CODEC_INVALID_PARAM;\
125 #define RANGE_CHECK(p, memb, lo, hi) do {\
126 if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
127 ERROR(#memb " out of range ["#lo".."#hi"]");\
130 #define RANGE_CHECK_HI(p, memb, hi) do {\
131 if (!((p)->memb <= (hi))) \
132 ERROR(#memb " out of range [.."#hi"]");\
135 #define RANGE_CHECK_LO(p, memb, lo) do {\
136 if (!((p)->memb >= (lo))) \
137 ERROR(#memb " out of range ["#lo"..]");\
140 #define RANGE_CHECK_BOOL(p, memb) do {\
141 if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
144 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
145 const vpx_codec_enc_cfg_t *cfg,
146 const struct vp9_extracfg *extra_cfg) {
147 RANGE_CHECK(cfg, g_w, 1, 65535); // 16 bits available
148 RANGE_CHECK(cfg, g_h, 1, 65535); // 16 bits available
149 RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
150 RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
151 RANGE_CHECK_HI(cfg, g_profile, 3);
153 RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
154 RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
155 RANGE_CHECK_BOOL(extra_cfg, lossless);
156 RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1);
157 RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
158 RANGE_CHECK_HI(cfg, g_threads, 64);
159 RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
160 RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
161 RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
162 RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
163 RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
164 RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
165 RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
166 RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
167 RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
168 RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
169 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
171 if (cfg->rc_resize_allowed == 1) {
172 RANGE_CHECK(cfg, rc_scaled_width, 1, cfg->g_w);
173 RANGE_CHECK(cfg, rc_scaled_height, 1, cfg->g_h);
176 RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
177 RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
178 if (cfg->ts_number_layers > 1) {
180 for (i = 1; i < cfg->ts_number_layers; ++i)
181 if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i - 1])
182 ERROR("ts_target_bitrate entries are not increasing");
184 RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
185 for (i = cfg->ts_number_layers - 2; i > 0; --i)
186 if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i])
187 ERROR("ts_rate_decimator factors are not powers of 2");
190 // VP9 does not support a lower bound on the keyframe interval in
191 // automatic keyframe placement mode.
192 if (cfg->kf_mode != VPX_KF_DISABLED &&
193 cfg->kf_min_dist != cfg->kf_max_dist &&
194 cfg->kf_min_dist > 0)
195 ERROR("kf_min_dist not supported in auto mode, use 0 "
196 "or kf_max_dist instead.");
198 RANGE_CHECK_BOOL(extra_cfg, enable_auto_alt_ref);
199 RANGE_CHECK(extra_cfg, cpu_used, -16, 16);
200 RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
201 RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
202 RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
203 RANGE_CHECK_HI(extra_cfg, sharpness, 7);
204 RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
205 RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
206 RANGE_CHECK(extra_cfg, arnr_type, 1, 3);
207 RANGE_CHECK(extra_cfg, cq_level, 0, 63);
209 // TODO(yaowu): remove this when ssim tuning is implemented for vp9
210 if (extra_cfg->tuning == VP8_TUNE_SSIM)
211 ERROR("Option --tune=ssim is not currently supported in VP9.");
213 if (cfg->g_pass == VPX_RC_LAST_PASS) {
214 const size_t packet_sz = sizeof(FIRSTPASS_STATS);
215 const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
216 const FIRSTPASS_STATS *stats;
218 if (cfg->rc_twopass_stats_in.buf == NULL)
219 ERROR("rc_twopass_stats_in.buf not set.");
221 if (cfg->rc_twopass_stats_in.sz % packet_sz)
222 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
224 if (cfg->ss_number_layers > 1) {
226 unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = {0};
228 stats = cfg->rc_twopass_stats_in.buf;
229 for (i = 0; i < n_packets; ++i) {
230 const int layer_id = (int)stats[i].spatial_layer_id;
231 if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
232 ++n_packets_per_layer[layer_id];
236 for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
237 unsigned int layer_id;
238 if (n_packets_per_layer[i] < 2) {
239 ERROR("rc_twopass_stats_in requires at least two packets for each "
243 stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
244 n_packets - cfg->ss_number_layers + i;
245 layer_id = (int)stats->spatial_layer_id;
247 if (layer_id >= cfg->ss_number_layers
248 ||(unsigned int)(stats->count + 0.5) !=
249 n_packets_per_layer[layer_id] - 1)
250 ERROR("rc_twopass_stats_in missing EOS stats packet");
253 if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
254 ERROR("rc_twopass_stats_in requires at least two packets.");
257 (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
259 if ((int)(stats->count + 0.5) != n_packets - 1)
260 ERROR("rc_twopass_stats_in missing EOS stats packet");
263 if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
264 extra_cfg->bit_depth > BITS_8)
265 ERROR("High bit-depth not supported in profile < 2");
266 if (cfg->g_profile > (unsigned int)PROFILE_1 &&
267 extra_cfg->bit_depth == BITS_8)
268 ERROR("Bit-depth 8 not supported in profile > 1");
274 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
275 const vpx_image_t *img) {
277 case VPX_IMG_FMT_YV12:
278 case VPX_IMG_FMT_I420:
279 case VPX_IMG_FMT_I422:
280 case VPX_IMG_FMT_I444:
283 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
287 if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
288 ERROR("Image size must match encoder init configuration size");
294 static vpx_codec_err_t set_encoder_config(
295 VP9EncoderConfig *oxcf,
296 const vpx_codec_enc_cfg_t *cfg,
297 const struct vp9_extracfg *extra_cfg) {
298 oxcf->profile = cfg->g_profile;
299 oxcf->width = cfg->g_w;
300 oxcf->height = cfg->g_h;
301 oxcf->bit_depth = extra_cfg->bit_depth;
302 // guess a frame rate if out of whack, use 30
303 oxcf->framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
304 if (oxcf->framerate > 180)
305 oxcf->framerate = 30;
307 switch (cfg->g_pass) {
308 case VPX_RC_ONE_PASS:
309 oxcf->mode = ONE_PASS_GOOD;
311 case VPX_RC_FIRST_PASS:
312 oxcf->mode = TWO_PASS_FIRST;
314 case VPX_RC_LAST_PASS:
315 oxcf->mode = TWO_PASS_SECOND_BEST;
319 oxcf->lag_in_frames = cfg->g_pass == VPX_RC_FIRST_PASS ? 0
320 : cfg->g_lag_in_frames;
321 oxcf->rc_mode = cfg->rc_end_usage;
323 // Convert target bandwidth from Kbit/s to Bit/s
324 oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
325 oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
327 oxcf->best_allowed_q =
328 extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_min_quantizer);
329 oxcf->worst_allowed_q =
330 extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_max_quantizer);
331 oxcf->cq_level = vp9_quantizer_to_qindex(extra_cfg->cq_level);
334 oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
335 oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
337 oxcf->allow_spatial_resampling = cfg->rc_resize_allowed;
338 oxcf->scaled_frame_width = cfg->rc_scaled_width;
339 oxcf->scaled_frame_height = cfg->rc_scaled_height;
341 oxcf->maximum_buffer_size_ms = cfg->rc_buf_sz;
342 oxcf->starting_buffer_level_ms = cfg->rc_buf_initial_sz;
343 oxcf->optimal_buffer_level_ms = cfg->rc_buf_optimal_sz;
345 oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
347 oxcf->two_pass_vbrbias = cfg->rc_2pass_vbr_bias_pct;
348 oxcf->two_pass_vbrmin_section = cfg->rc_2pass_vbr_minsection_pct;
349 oxcf->two_pass_vbrmax_section = cfg->rc_2pass_vbr_maxsection_pct;
351 oxcf->auto_key = cfg->kf_mode == VPX_KF_AUTO &&
352 cfg->kf_min_dist != cfg->kf_max_dist;
354 oxcf->key_freq = cfg->kf_max_dist;
356 oxcf->speed = clamp(abs(extra_cfg->cpu_used), 0, 7);
357 oxcf->encode_breakout = extra_cfg->static_thresh;
358 oxcf->play_alternate = extra_cfg->enable_auto_alt_ref;
359 oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
360 oxcf->sharpness = extra_cfg->sharpness;
362 oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
363 oxcf->output_pkt_list = extra_cfg->pkt_list;
365 oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
366 oxcf->arnr_strength = extra_cfg->arnr_strength;
367 oxcf->arnr_type = extra_cfg->arnr_type;
369 oxcf->tuning = extra_cfg->tuning;
371 oxcf->tile_columns = extra_cfg->tile_columns;
372 oxcf->tile_rows = extra_cfg->tile_rows;
374 oxcf->error_resilient_mode = cfg->g_error_resilient;
375 oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
377 oxcf->aq_mode = extra_cfg->aq_mode;
379 oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
381 oxcf->ss_number_layers = cfg->ss_number_layers;
383 if (oxcf->ss_number_layers > 1) {
385 for (i = 0; i < VPX_SS_MAX_LAYERS; ++i)
386 oxcf->ss_target_bitrate[i] = 1000 * cfg->ss_target_bitrate[i];
387 } else if (oxcf->ss_number_layers == 1) {
388 oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
391 oxcf->ts_number_layers = cfg->ts_number_layers;
393 if (oxcf->ts_number_layers > 1) {
395 for (i = 0; i < VPX_TS_MAX_LAYERS; ++i) {
396 oxcf->ts_target_bitrate[i] = 1000 * cfg->ts_target_bitrate[i];
397 oxcf->ts_rate_decimator[i] = cfg->ts_rate_decimator[i];
399 } else if (oxcf->ts_number_layers == 1) {
400 oxcf->ts_target_bitrate[0] = (int)oxcf->target_bandwidth;
401 oxcf->ts_rate_decimator[0] = 1;
405 printf("Current VP9 Settings: \n");
406 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
407 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
408 printf("sharpness: %d\n", oxcf->sharpness);
409 printf("cpu_used: %d\n", oxcf->cpu_used);
410 printf("Mode: %d\n", oxcf->mode);
411 printf("auto_key: %d\n", oxcf->auto_key);
412 printf("key_freq: %d\n", oxcf->key_freq);
413 printf("end_usage: %d\n", oxcf->end_usage);
414 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
415 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
416 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
417 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
418 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
419 printf("fixed_q: %d\n", oxcf->fixed_q);
420 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
421 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
422 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
423 printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
424 printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
425 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
426 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
427 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
428 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
429 printf("play_alternate: %d\n", oxcf->play_alternate);
430 printf("Version: %d\n", oxcf->Version);
431 printf("encode_breakout: %d\n", oxcf->encode_breakout);
432 printf("error resilient: %d\n", oxcf->error_resilient_mode);
433 printf("frame parallel detokenization: %d\n",
434 oxcf->frame_parallel_decoding_mode);
439 static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
440 const vpx_codec_enc_cfg_t *cfg) {
443 if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h)
444 ERROR("Cannot change width or height after initialization");
446 // Prevent increasing lag_in_frames. This check is stricter than it needs
447 // to be -- the limit is not increasing past the first lag_in_frames
448 // value, but we don't track the initial config, only the last successful
450 if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
451 ERROR("Cannot increase lag_in_frames");
453 res = validate_config(ctx, cfg, &ctx->extra_cfg);
455 if (res == VPX_CODEC_OK) {
457 set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
458 vp9_change_config(ctx->cpi, &ctx->oxcf);
464 static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
466 int *const arg = va_arg(args, int *);
468 return VPX_CODEC_INVALID_PARAM;
469 *arg = vp9_get_quantizer(ctx->cpi);
473 static vpx_codec_err_t ctrl_get_quantizer64(vpx_codec_alg_priv_t *ctx,
475 int *const arg = va_arg(args, int *);
477 return VPX_CODEC_INVALID_PARAM;
478 *arg = vp9_qindex_to_quantizer(vp9_get_quantizer(ctx->cpi));
482 static vpx_codec_err_t update_extra_cfg(vpx_codec_alg_priv_t *ctx,
483 const struct vp9_extracfg *extra_cfg) {
484 const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
485 if (res == VPX_CODEC_OK) {
486 ctx->extra_cfg = *extra_cfg;
487 set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
488 vp9_change_config(ctx->cpi, &ctx->oxcf);
493 static vpx_codec_err_t ctrl_set_cpuused(vpx_codec_alg_priv_t *ctx,
495 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
496 extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
497 return update_extra_cfg(ctx, &extra_cfg);
500 static vpx_codec_err_t ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
502 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
503 extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
504 return update_extra_cfg(ctx, &extra_cfg);
507 static vpx_codec_err_t ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
509 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
510 extra_cfg.noise_sensitivity = CAST(VP8E_SET_NOISE_SENSITIVITY, args);
511 return update_extra_cfg(ctx, &extra_cfg);
514 static vpx_codec_err_t ctrl_set_sharpness(vpx_codec_alg_priv_t *ctx,
516 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
517 extra_cfg.sharpness = CAST(VP8E_SET_SHARPNESS, args);
518 return update_extra_cfg(ctx, &extra_cfg);
521 static vpx_codec_err_t ctrl_set_static_thresh(vpx_codec_alg_priv_t *ctx,
523 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
524 extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
525 return update_extra_cfg(ctx, &extra_cfg);
528 static vpx_codec_err_t ctrl_set_tile_columns(vpx_codec_alg_priv_t *ctx,
530 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
531 extra_cfg.tile_columns = CAST(VP9E_SET_TILE_COLUMNS, args);
532 return update_extra_cfg(ctx, &extra_cfg);
535 static vpx_codec_err_t ctrl_set_tile_rows(vpx_codec_alg_priv_t *ctx,
537 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
538 extra_cfg.tile_rows = CAST(VP9E_SET_TILE_ROWS, args);
539 return update_extra_cfg(ctx, &extra_cfg);
542 static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
544 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
545 extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
546 return update_extra_cfg(ctx, &extra_cfg);
549 static vpx_codec_err_t ctrl_set_arnr_strength(vpx_codec_alg_priv_t *ctx,
551 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
552 extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
553 return update_extra_cfg(ctx, &extra_cfg);
556 static vpx_codec_err_t ctrl_set_arnr_type(vpx_codec_alg_priv_t *ctx,
558 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
559 extra_cfg.arnr_type = CAST(VP8E_SET_ARNR_TYPE, args);
560 return update_extra_cfg(ctx, &extra_cfg);
563 static vpx_codec_err_t ctrl_set_tuning(vpx_codec_alg_priv_t *ctx,
565 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
566 extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
567 return update_extra_cfg(ctx, &extra_cfg);
570 static vpx_codec_err_t ctrl_set_cq_level(vpx_codec_alg_priv_t *ctx,
572 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
573 extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
574 return update_extra_cfg(ctx, &extra_cfg);
577 static vpx_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
578 vpx_codec_alg_priv_t *ctx, va_list args) {
579 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
580 extra_cfg.rc_max_intra_bitrate_pct =
581 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
582 return update_extra_cfg(ctx, &extra_cfg);
585 static vpx_codec_err_t ctrl_set_lossless(vpx_codec_alg_priv_t *ctx,
587 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
588 extra_cfg.lossless = CAST(VP9E_SET_LOSSLESS, args);
589 return update_extra_cfg(ctx, &extra_cfg);
592 static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
593 vpx_codec_alg_priv_t *ctx, va_list args) {
594 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
595 extra_cfg.frame_parallel_decoding_mode =
596 CAST(VP9E_SET_FRAME_PARALLEL_DECODING, args);
597 return update_extra_cfg(ctx, &extra_cfg);
600 static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx,
602 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
603 extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
604 return update_extra_cfg(ctx, &extra_cfg);
607 static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
609 struct vp9_extracfg extra_cfg = ctx->extra_cfg;
610 extra_cfg.frame_periodic_boost = CAST(VP9E_SET_FRAME_PERIODIC_BOOST, args);
611 return update_extra_cfg(ctx, &extra_cfg);
614 static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
615 vpx_codec_priv_enc_mr_cfg_t *data) {
616 vpx_codec_err_t res = VPX_CODEC_OK;
619 if (ctx->priv == NULL) {
621 vpx_codec_enc_cfg_t *cfg;
622 struct vpx_codec_alg_priv *priv = calloc(1, sizeof(*priv));
625 return VPX_CODEC_MEM_ERROR;
627 ctx->priv = &priv->base;
628 ctx->priv->sz = sizeof(*ctx->priv);
629 ctx->priv->iface = ctx->iface;
630 ctx->priv->alg_priv = priv;
631 ctx->priv->init_flags = ctx->init_flags;
632 ctx->priv->enc.total_encoders = 1;
634 if (ctx->config.enc) {
635 // Update the reference to the config structure to an internal copy.
636 ctx->priv->alg_priv->cfg = *ctx->config.enc;
637 ctx->config.enc = &ctx->priv->alg_priv->cfg;
640 cfg = &ctx->priv->alg_priv->cfg;
642 // Select the extra vp6 configuration table based on the current
643 // usage value. If the current usage value isn't found, use the
644 // values for usage case 0.
646 extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
649 priv->extra_cfg = extracfg_map[i].cfg;
650 priv->extra_cfg.pkt_list = &priv->pkt_list.head;
651 // Maximum buffer size approximated based on having multiple ARF.
652 priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
654 if (priv->cx_data_sz < 4096)
655 priv->cx_data_sz = 4096;
657 priv->cx_data = (unsigned char *)malloc(priv->cx_data_sz);
658 if (priv->cx_data == NULL)
659 return VPX_CODEC_MEM_ERROR;
661 vp9_initialize_enc();
663 res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
665 if (res == VPX_CODEC_OK) {
667 set_encoder_config(&ctx->priv->alg_priv->oxcf,
668 &ctx->priv->alg_priv->cfg,
669 &ctx->priv->alg_priv->extra_cfg);
670 cpi = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
672 res = VPX_CODEC_MEM_ERROR;
674 ctx->priv->alg_priv->cpi = cpi;
681 static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
683 vp9_remove_compressor(ctx->cpi);
688 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
689 unsigned long duration,
690 unsigned long deadline) {
691 // Use best quality mode if no deadline is given.
692 MODE new_qc = ONE_PASS_BEST;
695 // Convert duration parameter from stream timebase to microseconds
696 const uint64_t duration_us = (uint64_t)duration * 1000000 *
697 (uint64_t)ctx->cfg.g_timebase.num /
698 (uint64_t)ctx->cfg.g_timebase.den;
700 // If the deadline is more that the duration this frame is to be shown,
701 // use good quality mode. Otherwise use realtime mode.
702 new_qc = (deadline > duration_us) ? ONE_PASS_GOOD : REALTIME;
705 if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
706 new_qc = TWO_PASS_FIRST;
707 else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
708 new_qc = (new_qc == ONE_PASS_BEST) ? TWO_PASS_SECOND_BEST
709 : TWO_PASS_SECOND_GOOD;
711 if (ctx->oxcf.mode != new_qc) {
712 ctx->oxcf.mode = new_qc;
713 vp9_change_config(ctx->cpi, &ctx->oxcf);
717 // Turn on to test if supplemental superframe data breaks decoding
718 // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
719 static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
720 uint8_t marker = 0xc0;
724 assert(ctx->pending_frame_count);
725 assert(ctx->pending_frame_count <= 8);
727 // Add the number of frames to the marker byte
728 marker |= ctx->pending_frame_count - 1;
730 // Choose the magnitude
731 for (mag = 0, mask = 0xff; mag < 4; mag++) {
732 if (ctx->pending_frame_magnitude < mask)
740 index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
741 if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
742 uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
744 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
745 uint8_t marker_test = 0xc0;
746 int mag_test = 2; // 1 - 4
747 int frames_test = 4; // 1 - 8
748 int index_sz_test = 2 + mag_test * frames_test;
749 marker_test |= frames_test - 1;
750 marker_test |= (mag_test - 1) << 3;
752 for (i = 0; i < mag_test * frames_test; ++i)
753 *x++ = 0; // fill up with arbitrary data
755 ctx->pending_cx_data_sz += index_sz_test;
756 printf("Added supplemental superframe data\n");
760 for (i = 0; i < ctx->pending_frame_count; i++) {
761 unsigned int this_sz = (unsigned int)ctx->pending_frame_sizes[i];
763 for (j = 0; j <= mag; j++) {
764 *x++ = this_sz & 0xff;
769 ctx->pending_cx_data_sz += index_sz;
770 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
771 index_sz += index_sz_test;
777 static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
778 const vpx_image_t *img,
780 unsigned long duration,
781 vpx_enc_frame_flags_t flags,
782 unsigned long deadline) {
783 vpx_codec_err_t res = VPX_CODEC_OK;
786 res = validate_img(ctx, img);
788 pick_quickcompress_mode(ctx, duration, deadline);
789 vpx_codec_pkt_list_init(&ctx->pkt_list);
792 if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
793 ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
794 ctx->base.err_detail = "Conflicting flags.";
795 return VPX_CODEC_INVALID_PARAM;
798 vp9_apply_encoding_flags(ctx->cpi, flags);
800 // Handle fixed keyframe intervals
801 if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
802 ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
803 if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
804 flags |= VPX_EFLAG_FORCE_KF;
805 ctx->fixed_kf_cntr = 1;
809 // Initialize the encoder instance on the first frame.
810 if (res == VPX_CODEC_OK && ctx->cpi != NULL) {
811 unsigned int lib_flags = 0;
812 YV12_BUFFER_CONFIG sd;
813 int64_t dst_time_stamp, dst_end_time_stamp;
814 size_t size, cx_data_sz;
815 unsigned char *cx_data;
817 // Set up internal flags
818 if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
819 ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
821 /* vp9 use 10,000,000 ticks/second as time stamp */
822 dst_time_stamp = (pts * 10000000 * ctx->cfg.g_timebase.num)
823 / ctx->cfg.g_timebase.den;
824 dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num /
825 ctx->cfg.g_timebase.den;
828 res = image2yuvconfig(img, &sd);
830 // Store the original flags in to the frame buffer. Will extract the
831 // key frame flag when we actually encode this frame.
832 if (vp9_receive_raw_frame(ctx->cpi, flags,
833 &sd, dst_time_stamp, dst_end_time_stamp)) {
834 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
835 res = update_error_state(ctx, &cpi->common.error);
839 cx_data = ctx->cx_data;
840 cx_data_sz = ctx->cx_data_sz;
842 /* Any pending invisible frames? */
843 if (ctx->pending_cx_data) {
844 memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
845 ctx->pending_cx_data = cx_data;
846 cx_data += ctx->pending_cx_data_sz;
847 cx_data_sz -= ctx->pending_cx_data_sz;
849 /* TODO: this is a minimal check, the underlying codec doesn't respect
850 * the buffer size anyway.
852 if (cx_data_sz < ctx->cx_data_sz / 2) {
853 ctx->base.err_detail = "Compressed data buffer too small";
854 return VPX_CODEC_ERROR;
858 while (cx_data_sz >= ctx->cx_data_sz / 2 &&
859 -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size,
860 cx_data, &dst_time_stamp,
861 &dst_end_time_stamp, !img)) {
863 vpx_codec_pts_t round, delta;
864 vpx_codec_cx_pkt_t pkt;
865 VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
867 // Pack invisible frames with the next visible frame
868 if (cpi->common.show_frame == 0
869 #ifdef CONFIG_SPATIAL_SVC
870 || (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
871 cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
874 if (ctx->pending_cx_data == 0)
875 ctx->pending_cx_data = cx_data;
876 ctx->pending_cx_data_sz += size;
877 ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
878 ctx->pending_frame_magnitude |= size;
884 // Add the frame packet to the list of returned packets.
885 round = (vpx_codec_pts_t)10000000 * ctx->cfg.g_timebase.num / 2 - 1;
886 delta = (dst_end_time_stamp - dst_time_stamp);
887 pkt.kind = VPX_CODEC_CX_FRAME_PKT;
889 (dst_time_stamp * ctx->cfg.g_timebase.den + round)
890 / ctx->cfg.g_timebase.num / 10000000;
891 pkt.data.frame.duration = (unsigned long)
892 ((delta * ctx->cfg.g_timebase.den + round)
893 / ctx->cfg.g_timebase.num / 10000000);
894 pkt.data.frame.flags = lib_flags << 16;
896 if (lib_flags & FRAMEFLAGS_KEY
897 #ifdef CONFIG_SPATIAL_SVC
898 || (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
899 cpi->svc.layer_context[0].is_key_frame)
902 pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
904 if (cpi->common.show_frame == 0) {
905 pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
907 // This timestamp should be as close as possible to the
908 // prior PTS so that if a decoder uses pts to schedule when
909 // to do this, we start right after last frame was decoded.
910 // Invisible frames have no duration.
911 pkt.data.frame.pts = ((cpi->last_time_stamp_seen
912 * ctx->cfg.g_timebase.den + round)
913 / ctx->cfg.g_timebase.num / 10000000) + 1;
914 pkt.data.frame.duration = 0;
918 pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
920 if (ctx->pending_cx_data) {
921 ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
922 ctx->pending_frame_magnitude |= size;
923 ctx->pending_cx_data_sz += size;
924 size += write_superframe_index(ctx);
925 pkt.data.frame.buf = ctx->pending_cx_data;
926 pkt.data.frame.sz = ctx->pending_cx_data_sz;
927 ctx->pending_cx_data = NULL;
928 ctx->pending_cx_data_sz = 0;
929 ctx->pending_frame_count = 0;
930 ctx->pending_frame_magnitude = 0;
932 pkt.data.frame.buf = cx_data;
933 pkt.data.frame.sz = size;
935 pkt.data.frame.partition_id = -1;
936 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
946 static const vpx_codec_cx_pkt_t *encoder_get_cxdata(vpx_codec_alg_priv_t *ctx,
947 vpx_codec_iter_t *iter) {
948 return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
951 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
953 vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
956 YV12_BUFFER_CONFIG sd;
958 image2yuvconfig(&frame->img, &sd);
959 vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
963 return VPX_CODEC_INVALID_PARAM;
967 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
969 vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
972 YV12_BUFFER_CONFIG sd;
974 image2yuvconfig(&frame->img, &sd);
975 vp9_copy_reference_enc(ctx->cpi,
976 ref_frame_to_vp9_reframe(frame->frame_type), &sd);
979 return VPX_CODEC_INVALID_PARAM;
983 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
985 vp9_ref_frame_t *const frame = va_arg(args, vp9_ref_frame_t *);
988 YV12_BUFFER_CONFIG *fb;
990 vp9_get_reference_enc(ctx->cpi, frame->idx, &fb);
991 yuvconfig2image(&frame->img, fb, NULL);
994 return VPX_CODEC_INVALID_PARAM;
998 static vpx_codec_err_t ctrl_set_previewpp(vpx_codec_alg_priv_t *ctx,
1000 #if CONFIG_VP9_POSTPROC
1001 vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
1002 if (config != NULL) {
1003 ctx->preview_ppcfg = *config;
1004 return VPX_CODEC_OK;
1006 return VPX_CODEC_INVALID_PARAM;
1011 return VPX_CODEC_INCAPABLE;
1016 static vpx_image_t *encoder_get_preview(vpx_codec_alg_priv_t *ctx) {
1017 YV12_BUFFER_CONFIG sd;
1018 vp9_ppflags_t flags;
1021 if (ctx->preview_ppcfg.post_proc_flag) {
1022 flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
1023 flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
1024 flags.noise_level = ctx->preview_ppcfg.noise_level;
1027 if (vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags) == 0) {
1028 yuvconfig2image(&ctx->preview_img, &sd, NULL);
1029 return &ctx->preview_img;
1035 static vpx_codec_err_t ctrl_update_entropy(vpx_codec_alg_priv_t *ctx,
1037 const int update = va_arg(args, int);
1039 vp9_update_entropy(ctx->cpi, update);
1040 return VPX_CODEC_OK;
1043 static vpx_codec_err_t ctrl_update_reference(vpx_codec_alg_priv_t *ctx,
1045 const int ref_frame_flags = va_arg(args, int);
1047 vp9_update_reference(ctx->cpi, ref_frame_flags);
1048 return VPX_CODEC_OK;
1051 static vpx_codec_err_t ctrl_use_reference(vpx_codec_alg_priv_t *ctx,
1053 const int reference_flag = va_arg(args, int);
1055 vp9_use_as_reference(ctx->cpi, reference_flag);
1056 return VPX_CODEC_OK;
1059 static vpx_codec_err_t ctrl_set_roi_map(vpx_codec_alg_priv_t *ctx,
1064 // TODO(yaowu): Need to re-implement and test for VP9.
1065 return VPX_CODEC_INVALID_PARAM;
1069 static vpx_codec_err_t ctrl_set_active_map(vpx_codec_alg_priv_t *ctx,
1071 vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
1074 if (!vp9_set_active_map(ctx->cpi, map->active_map,
1075 (int)map->rows, (int)map->cols))
1076 return VPX_CODEC_OK;
1078 return VPX_CODEC_INVALID_PARAM;
1080 return VPX_CODEC_INVALID_PARAM;
1084 static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
1086 vpx_scaling_mode_t *const mode = va_arg(args, vpx_scaling_mode_t *);
1089 const int res = vp9_set_internal_size(ctx->cpi,
1090 (VPX_SCALING)mode->h_scaling_mode,
1091 (VPX_SCALING)mode->v_scaling_mode);
1092 return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
1094 return VPX_CODEC_INVALID_PARAM;
1098 static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
1099 int data = va_arg(args, int);
1100 const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
1102 vp9_set_svc(ctx->cpi, data);
1103 // CBR or two pass mode for SVC with both temporal and spatial layers
1104 // not yet supported.
1106 (cfg->rc_end_usage == VPX_CBR ||
1107 cfg->g_pass == VPX_RC_FIRST_PASS ||
1108 cfg->g_pass == VPX_RC_LAST_PASS) &&
1109 cfg->ss_number_layers > 1 &&
1110 cfg->ts_number_layers > 1) {
1111 return VPX_CODEC_INVALID_PARAM;
1113 return VPX_CODEC_OK;
1116 static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
1118 vpx_svc_layer_id_t *const data = va_arg(args, vpx_svc_layer_id_t *);
1119 VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
1120 SVC *const svc = &cpi->svc;
1122 svc->spatial_layer_id = data->spatial_layer_id;
1123 svc->temporal_layer_id = data->temporal_layer_id;
1124 // Checks on valid layer_id input.
1125 if (svc->temporal_layer_id < 0 ||
1126 svc->temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
1127 return VPX_CODEC_INVALID_PARAM;
1129 if (svc->spatial_layer_id < 0 ||
1130 svc->spatial_layer_id >= (int)ctx->cfg.ss_number_layers) {
1131 return VPX_CODEC_INVALID_PARAM;
1133 return VPX_CODEC_OK;
1136 static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
1138 VP9_COMP *const cpi = ctx->cpi;
1139 vpx_svc_parameters_t *const params = va_arg(args, vpx_svc_parameters_t *);
1141 if (params == NULL || params->spatial_layer < 0 ||
1142 params->spatial_layer >= cpi->svc.number_spatial_layers)
1143 return VPX_CODEC_INVALID_PARAM;
1145 if (params->spatial_layer == 0) {
1147 for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
1148 cpi->svc.layer_context[i].svc_params_received.spatial_layer = -1;
1152 cpi->svc.layer_context[params->spatial_layer].svc_params_received =
1155 return VPX_CODEC_OK;
1158 static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
1159 {VP8_COPY_REFERENCE, ctrl_copy_reference},
1160 {VP8E_UPD_ENTROPY, ctrl_update_entropy},
1161 {VP8E_UPD_REFERENCE, ctrl_update_reference},
1162 {VP8E_USE_REFERENCE, ctrl_use_reference},
1165 {VP8_SET_REFERENCE, ctrl_set_reference},
1166 {VP8_SET_POSTPROC, ctrl_set_previewpp},
1167 {VP8E_SET_ROI_MAP, ctrl_set_roi_map},
1168 {VP8E_SET_ACTIVEMAP, ctrl_set_active_map},
1169 {VP8E_SET_SCALEMODE, ctrl_set_scale_mode},
1170 {VP8E_SET_CPUUSED, ctrl_set_cpuused},
1171 {VP8E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
1172 {VP8E_SET_ENABLEAUTOALTREF, ctrl_set_enable_auto_alt_ref},
1173 {VP8E_SET_SHARPNESS, ctrl_set_sharpness},
1174 {VP8E_SET_STATIC_THRESHOLD, ctrl_set_static_thresh},
1175 {VP9E_SET_TILE_COLUMNS, ctrl_set_tile_columns},
1176 {VP9E_SET_TILE_ROWS, ctrl_set_tile_rows},
1177 {VP8E_SET_ARNR_MAXFRAMES, ctrl_set_arnr_max_frames},
1178 {VP8E_SET_ARNR_STRENGTH, ctrl_set_arnr_strength},
1179 {VP8E_SET_ARNR_TYPE, ctrl_set_arnr_type},
1180 {VP8E_SET_TUNING, ctrl_set_tuning},
1181 {VP8E_SET_CQ_LEVEL, ctrl_set_cq_level},
1182 {VP8E_SET_MAX_INTRA_BITRATE_PCT, ctrl_set_rc_max_intra_bitrate_pct},
1183 {VP9E_SET_LOSSLESS, ctrl_set_lossless},
1184 {VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode},
1185 {VP9E_SET_AQ_MODE, ctrl_set_aq_mode},
1186 {VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost},
1187 {VP9E_SET_SVC, ctrl_set_svc},
1188 {VP9E_SET_SVC_PARAMETERS, ctrl_set_svc_parameters},
1189 {VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id},
1192 {VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer},
1193 {VP8E_GET_LAST_QUANTIZER_64, ctrl_get_quantizer64},
1194 {VP9_GET_REFERENCE, ctrl_get_reference},
1199 static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
1209 {1, 30}, // g_timebase
1211 0, // g_error_resilient
1213 VPX_RC_ONE_PASS, // g_pass
1215 25, // g_lag_in_frames
1217 0, // rc_dropframe_thresh
1218 0, // rc_resize_allowed
1219 1, // rc_scaled_width
1220 1, // rc_scaled_height
1221 60, // rc_resize_down_thresold
1222 30, // rc_resize_up_thresold
1224 VPX_VBR, // rc_end_usage
1225 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1226 {NULL, 0}, // rc_twopass_stats_in
1228 256, // rc_target_bandwidth
1229 0, // rc_min_quantizer
1230 63, // rc_max_quantizer
1231 100, // rc_undershoot_pct
1232 100, // rc_overshoot_pct
1234 6000, // rc_max_buffer_size
1235 4000, // rc_buffer_initial_size
1236 5000, // rc_buffer_optimal_size
1238 50, // rc_two_pass_vbrbias
1239 0, // rc_two_pass_vbrmin_section
1240 2000, // rc_two_pass_vbrmax_section
1242 // keyframing settings (kf)
1243 VPX_KF_AUTO, // g_kfmode
1245 9999, // kf_max_dist
1247 VPX_SS_DEFAULT_LAYERS, // ss_number_layers
1248 {0}, // ss_target_bitrate
1249 1, // ts_number_layers
1250 {0}, // ts_target_bitrate
1251 {0}, // ts_rate_decimator
1252 0, // ts_periodicity
1254 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1255 "vp8.fpf" // first pass filename
1259 { -1, {NOT_IMPLEMENTED}}
1262 #ifndef VERSION_STRING
1263 #define VERSION_STRING
1265 CODEC_INTERFACE(vpx_codec_vp9_cx) = {
1266 "WebM Project VP9 Encoder" VERSION_STRING,
1267 VPX_CODEC_INTERNAL_ABI_VERSION,
1268 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR, // vpx_codec_caps_t
1269 encoder_init, // vpx_codec_init_fn_t
1270 encoder_destroy, // vpx_codec_destroy_fn_t
1271 encoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t
1272 NOT_IMPLEMENTED, // vpx_codec_get_mmap_fn_t
1273 NOT_IMPLEMENTED, // vpx_codec_set_mmap_fn_t
1275 NOT_IMPLEMENTED, // vpx_codec_peek_si_fn_t
1276 NOT_IMPLEMENTED, // vpx_codec_get_si_fn_t
1277 NOT_IMPLEMENTED, // vpx_codec_decode_fn_t
1278 NOT_IMPLEMENTED, // vpx_codec_frame_get_fn_t
1279 NOT_IMPLEMENTED // vpx_codec_set_fb_fn_t
1282 encoder_usage_cfg_map, // vpx_codec_enc_cfg_map_t
1283 encoder_encode, // vpx_codec_encode_fn_t
1284 encoder_get_cxdata, // vpx_codec_get_cx_data_fn_t
1285 encoder_set_config, // vpx_codec_enc_config_set_fn_t
1286 NOT_IMPLEMENTED, // vpx_codec_get_global_headers_fn_t
1287 encoder_get_preview, // vpx_codec_get_preview_frame_fn_t
1288 NOT_IMPLEMENTED // vpx_codec_enc_mr_get_mem_loc_fn_t