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