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