vp8_cx_iface.c (51372B)
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 <assert.h> 12 #include <limits.h> 13 #include <stdint.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #include "./vpx_config.h" 18 #include "./vp8_rtcd.h" 19 #include "./vpx_dsp_rtcd.h" 20 #include "./vpx_scale_rtcd.h" 21 #include "vpx/vpx_encoder.h" 22 #include "vpx/internal/vpx_codec_internal.h" 23 #include "vpx_version.h" 24 #include "vpx_mem/vpx_mem.h" 25 #include "vpx_ports/static_assert.h" 26 #include "vpx_ports/system_state.h" 27 #include "vpx_util/vpx_timestamp.h" 28 #if CONFIG_MULTITHREAD 29 #include "vp8/encoder/ethreading.h" 30 #endif 31 #include "vp8/encoder/onyx_int.h" 32 #include "vpx/vp8cx.h" 33 #include "vp8/encoder/firstpass.h" 34 #include "vp8/common/onyx.h" 35 #include "vp8/common/common.h" 36 37 struct vp8_extracfg { 38 struct vpx_codec_pkt_list *pkt_list; 39 int cpu_used; /** available cpu percentage in 1/16*/ 40 /** if encoder decides to uses alternate reference frame */ 41 unsigned int enable_auto_alt_ref; 42 unsigned int noise_sensitivity; 43 unsigned int Sharpness; 44 unsigned int static_thresh; 45 unsigned int token_partitions; 46 unsigned int arnr_max_frames; /* alt_ref Noise Reduction Max Frame Count */ 47 unsigned int arnr_strength; /* alt_ref Noise Reduction Strength */ 48 unsigned int arnr_type; /* alt_ref filter type */ 49 vp8e_tuning tuning; 50 unsigned int cq_level; /* constrained quality level */ 51 unsigned int rc_max_intra_bitrate_pct; 52 unsigned int gf_cbr_boost_pct; 53 unsigned int screen_content_mode; 54 }; 55 56 static struct vp8_extracfg default_extracfg = { 57 NULL, 58 #if !(CONFIG_REALTIME_ONLY) 59 0, /* cpu_used */ 60 #else 61 4, /* cpu_used */ 62 #endif 63 0, /* enable_auto_alt_ref */ 64 0, /* noise_sensitivity */ 65 0, /* Sharpness */ 66 0, /* static_thresh */ 67 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) 68 VP8_EIGHT_TOKENPARTITION, 69 #else 70 VP8_ONE_TOKENPARTITION, /* token_partitions */ 71 #endif 72 0, /* arnr_max_frames */ 73 3, /* arnr_strength */ 74 3, /* arnr_type*/ 75 0, /* tuning*/ 76 10, /* cq_level */ 77 0, /* rc_max_intra_bitrate_pct */ 78 0, /* gf_cbr_boost_pct */ 79 0, /* screen_content_mode */ 80 }; 81 82 struct vpx_codec_alg_priv { 83 vpx_codec_priv_t base; 84 vpx_codec_enc_cfg_t cfg; 85 struct vp8_extracfg vp8_cfg; 86 vpx_rational64_t timestamp_ratio; 87 vpx_codec_pts_t pts_offset; 88 unsigned char pts_offset_initialized; 89 VP8_CONFIG oxcf; 90 struct VP8_COMP *cpi; 91 unsigned char *cx_data; 92 unsigned int cx_data_sz; 93 vpx_image_t preview_img; 94 unsigned int next_frame_flag; 95 vp8_postproc_cfg_t preview_ppcfg; 96 /* pkt_list size depends on the maximum number of lagged frames allowed. */ 97 vpx_codec_pkt_list_decl(64) pkt_list; 98 unsigned int fixed_kf_cntr; 99 vpx_enc_frame_flags_t control_frame_flags; 100 }; 101 102 // Called by vp8e_set_config() and vp8e_encode() only. Must not be called 103 // by vp8e_init() because the `error` paramerer (cpi->common.error) will be 104 // destroyed by vpx_codec_enc_init_ver() after vp8e_init() returns an error. 105 // See the "IMPORTANT" comment in vpx_codec_enc_init_ver(). 106 static vpx_codec_err_t update_error_state( 107 vpx_codec_alg_priv_t *ctx, 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 #undef ERROR 117 #define ERROR(str) \ 118 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) \ 124 do { \ 125 if (!(((p)->memb == (lo) || (p)->memb > (lo)) && (p)->memb <= (hi))) \ 126 ERROR(#memb " out of range [" #lo ".." #hi "]"); \ 127 } while (0) 128 129 #define RANGE_CHECK_HI(p, memb, hi) \ 130 do { \ 131 if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \ 132 } while (0) 133 134 #define RANGE_CHECK_LO(p, memb, lo) \ 135 do { \ 136 if (!((p)->memb >= (lo))) ERROR(#memb " out of range [" #lo "..]"); \ 137 } while (0) 138 139 #define RANGE_CHECK_BOOL(p, memb) \ 140 do { \ 141 if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \ 142 } while (0) 143 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 vp8_extracfg *vp8_cfg, 147 int finalize) { 148 RANGE_CHECK(cfg, g_w, 1, 16383); /* 14 bits available */ 149 RANGE_CHECK(cfg, g_h, 1, 16383); /* 14 bits available */ 150 RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000); 151 RANGE_CHECK(cfg, g_timebase.num, 1, 1000000000); 152 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_HI(cfg, g_threads, 64); 156 #if CONFIG_REALTIME_ONLY 157 RANGE_CHECK_HI(cfg, g_lag_in_frames, 0); 158 #elif CONFIG_MULTI_RES_ENCODING 159 if (ctx->base.enc.total_encoders > 1) RANGE_CHECK_HI(cfg, g_lag_in_frames, 0); 160 #else 161 RANGE_CHECK_HI(cfg, g_lag_in_frames, 25); 162 #endif 163 RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q); 164 RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100); 165 RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100); 166 RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100); 167 RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO); 168 169 /* TODO: add spatial re-sampling support and frame dropping in 170 * multi-res-encoder.*/ 171 #if CONFIG_MULTI_RES_ENCODING 172 if (ctx->base.enc.total_encoders > 1) 173 RANGE_CHECK_HI(cfg, rc_resize_allowed, 0); 174 #else 175 RANGE_CHECK_BOOL(cfg, rc_resize_allowed); 176 #endif 177 RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100); 178 RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100); 179 RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100); 180 181 #if CONFIG_REALTIME_ONLY 182 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS); 183 #elif CONFIG_MULTI_RES_ENCODING 184 if (ctx->base.enc.total_encoders > 1) 185 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS); 186 #else 187 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS); 188 #endif 189 190 /* VP8 does not support a lower bound on the keyframe interval in 191 * automatic keyframe placement mode. 192 */ 193 if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist && 194 cfg->kf_min_dist > 0) 195 ERROR( 196 "kf_min_dist not supported in auto mode, use 0 " 197 "or kf_max_dist instead."); 198 199 RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref); 200 RANGE_CHECK(vp8_cfg, cpu_used, -16, 16); 201 202 #if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING 203 RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0); 204 #else 205 RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6); 206 #endif 207 208 RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION, 209 VP8_EIGHT_TOKENPARTITION); 210 RANGE_CHECK_HI(vp8_cfg, Sharpness, 7); 211 RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15); 212 RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6); 213 RANGE_CHECK(vp8_cfg, arnr_type, 1, 3); 214 RANGE_CHECK(vp8_cfg, cq_level, 0, 63); 215 RANGE_CHECK_HI(vp8_cfg, screen_content_mode, 2); 216 if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q)) 217 RANGE_CHECK(vp8_cfg, cq_level, cfg->rc_min_quantizer, 218 cfg->rc_max_quantizer); 219 220 #if !(CONFIG_REALTIME_ONLY) 221 if (cfg->g_pass == VPX_RC_LAST_PASS) { 222 size_t packet_sz = sizeof(FIRSTPASS_STATS); 223 int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz); 224 FIRSTPASS_STATS *stats; 225 226 if (!cfg->rc_twopass_stats_in.buf) 227 ERROR("rc_twopass_stats_in.buf not set."); 228 229 if (cfg->rc_twopass_stats_in.sz % packet_sz) 230 ERROR("rc_twopass_stats_in.sz indicates truncated packet."); 231 232 if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz) 233 ERROR("rc_twopass_stats_in requires at least two packets."); 234 235 stats = (void *)((char *)cfg->rc_twopass_stats_in.buf + 236 (n_packets - 1) * packet_sz); 237 238 if ((int)(stats->count + 0.5) != n_packets - 1) 239 ERROR("rc_twopass_stats_in missing EOS stats packet"); 240 } 241 #endif 242 243 RANGE_CHECK(cfg, ts_number_layers, 1, 5); 244 245 if (cfg->ts_number_layers > 1) { 246 unsigned int i; 247 RANGE_CHECK_HI(cfg, ts_periodicity, 16); 248 249 for (i = 1; i < cfg->ts_number_layers; ++i) { 250 if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i - 1] && 251 cfg->rc_target_bitrate > 0) 252 ERROR("ts_target_bitrate entries are not strictly increasing"); 253 } 254 255 RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1); 256 for (i = cfg->ts_number_layers - 2; i > 0; i--) { 257 if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i]) 258 ERROR("ts_rate_decimator factors are not powers of 2"); 259 } 260 261 RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers - 1); 262 } 263 264 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) 265 if (cfg->g_threads > (1 << vp8_cfg->token_partitions)) 266 ERROR("g_threads cannot be bigger than number of token partitions"); 267 #endif 268 269 // The range below shall be further tuned. 270 RANGE_CHECK(cfg, use_vizier_rc_params, 0, 1); 271 RANGE_CHECK(cfg, active_wq_factor.den, 1, 1000); 272 RANGE_CHECK(cfg, err_per_mb_factor.den, 1, 1000); 273 RANGE_CHECK(cfg, sr_default_decay_limit.den, 1, 1000); 274 RANGE_CHECK(cfg, sr_diff_factor.den, 1, 1000); 275 RANGE_CHECK(cfg, kf_err_per_mb_factor.den, 1, 1000); 276 RANGE_CHECK(cfg, kf_frame_min_boost_factor.den, 1, 1000); 277 RANGE_CHECK(cfg, kf_frame_max_boost_subs_factor.den, 1, 1000); 278 RANGE_CHECK(cfg, kf_max_total_boost_factor.den, 1, 1000); 279 RANGE_CHECK(cfg, gf_max_total_boost_factor.den, 1, 1000); 280 RANGE_CHECK(cfg, gf_frame_max_boost_factor.den, 1, 1000); 281 RANGE_CHECK(cfg, zm_factor.den, 1, 1000); 282 RANGE_CHECK(cfg, rd_mult_inter_qp_fac.den, 1, 1000); 283 RANGE_CHECK(cfg, rd_mult_arf_qp_fac.den, 1, 1000); 284 RANGE_CHECK(cfg, rd_mult_key_qp_fac.den, 1, 1000); 285 286 return VPX_CODEC_OK; 287 } 288 289 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, 290 const vpx_image_t *img) { 291 switch (img->fmt) { 292 case VPX_IMG_FMT_YV12: 293 case VPX_IMG_FMT_I420: 294 case VPX_IMG_FMT_NV12: break; 295 default: 296 ERROR( 297 "Invalid image format. Only YV12, I420 and NV12 images are " 298 "supported"); 299 } 300 301 if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h)) 302 ERROR("Image size must match encoder init configuration size"); 303 304 return VPX_CODEC_OK; 305 } 306 307 static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf, 308 vpx_codec_enc_cfg_t cfg, 309 struct vp8_extracfg vp8_cfg, 310 vpx_codec_priv_enc_mr_cfg_t *mr_cfg) { 311 oxcf->multi_threaded = cfg.g_threads; 312 oxcf->Version = cfg.g_profile; 313 314 oxcf->Width = cfg.g_w; 315 oxcf->Height = cfg.g_h; 316 oxcf->timebase = cfg.g_timebase; 317 318 oxcf->error_resilient_mode = cfg.g_error_resilient; 319 320 switch (cfg.g_pass) { 321 case VPX_RC_ONE_PASS: oxcf->Mode = MODE_BESTQUALITY; break; 322 case VPX_RC_FIRST_PASS: oxcf->Mode = MODE_FIRSTPASS; break; 323 case VPX_RC_LAST_PASS: oxcf->Mode = MODE_SECONDPASS_BEST; break; 324 } 325 326 if (cfg.g_pass == VPX_RC_FIRST_PASS || cfg.g_pass == VPX_RC_ONE_PASS) { 327 oxcf->allow_lag = 0; 328 oxcf->lag_in_frames = 0; 329 } else { 330 oxcf->allow_lag = (cfg.g_lag_in_frames) > 0; 331 oxcf->lag_in_frames = cfg.g_lag_in_frames; 332 } 333 334 oxcf->allow_df = (cfg.rc_dropframe_thresh > 0); 335 oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh; 336 337 oxcf->allow_spatial_resampling = cfg.rc_resize_allowed; 338 oxcf->resample_up_water_mark = cfg.rc_resize_up_thresh; 339 oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh; 340 341 if (cfg.rc_end_usage == VPX_VBR) { 342 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK; 343 } else if (cfg.rc_end_usage == VPX_CBR) { 344 oxcf->end_usage = USAGE_STREAM_FROM_SERVER; 345 } else if (cfg.rc_end_usage == VPX_CQ) { 346 oxcf->end_usage = USAGE_CONSTRAINED_QUALITY; 347 } else if (cfg.rc_end_usage == VPX_Q) { 348 oxcf->end_usage = USAGE_CONSTANT_QUALITY; 349 } 350 351 // Cap the target rate to 1000 Mbps to avoid some integer overflows in 352 // target bandwidth calculations. 353 oxcf->target_bandwidth = VPXMIN(cfg.rc_target_bitrate, 1000000); 354 oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct; 355 oxcf->gf_cbr_boost_pct = vp8_cfg.gf_cbr_boost_pct; 356 357 oxcf->best_allowed_q = cfg.rc_min_quantizer; 358 oxcf->worst_allowed_q = cfg.rc_max_quantizer; 359 oxcf->cq_level = vp8_cfg.cq_level; 360 oxcf->fixed_q = -1; 361 362 oxcf->under_shoot_pct = cfg.rc_undershoot_pct; 363 oxcf->over_shoot_pct = cfg.rc_overshoot_pct; 364 365 oxcf->maximum_buffer_size_in_ms = cfg.rc_buf_sz; 366 oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz; 367 oxcf->optimal_buffer_level_in_ms = cfg.rc_buf_optimal_sz; 368 369 oxcf->maximum_buffer_size = cfg.rc_buf_sz; 370 oxcf->starting_buffer_level = cfg.rc_buf_initial_sz; 371 oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz; 372 373 oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct; 374 oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct; 375 oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct; 376 377 oxcf->auto_key = 378 cfg.kf_mode == VPX_KF_AUTO && cfg.kf_min_dist != cfg.kf_max_dist; 379 oxcf->key_freq = cfg.kf_max_dist; 380 381 oxcf->number_of_layers = cfg.ts_number_layers; 382 oxcf->periodicity = cfg.ts_periodicity; 383 384 if (oxcf->number_of_layers > 1) { 385 memcpy(oxcf->target_bitrate, cfg.ts_target_bitrate, 386 sizeof(cfg.ts_target_bitrate)); 387 memcpy(oxcf->rate_decimator, cfg.ts_rate_decimator, 388 sizeof(cfg.ts_rate_decimator)); 389 memcpy(oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id)); 390 } 391 392 #if CONFIG_MULTI_RES_ENCODING 393 /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id 394 * are both memset to 0, which ensures the correct logic under this 395 * situation. 396 */ 397 if (mr_cfg) { 398 oxcf->mr_total_resolutions = mr_cfg->mr_total_resolutions; 399 oxcf->mr_encoder_id = mr_cfg->mr_encoder_id; 400 oxcf->mr_down_sampling_factor = mr_cfg->mr_down_sampling_factor; 401 oxcf->mr_low_res_mode_info = mr_cfg->mr_low_res_mode_info; 402 } 403 #else 404 (void)mr_cfg; 405 #endif 406 407 oxcf->cpu_used = vp8_cfg.cpu_used; 408 if (cfg.g_pass == VPX_RC_FIRST_PASS) { 409 oxcf->cpu_used = VPXMAX(4, oxcf->cpu_used); 410 } 411 oxcf->encode_breakout = vp8_cfg.static_thresh; 412 oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref; 413 oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity; 414 oxcf->Sharpness = vp8_cfg.Sharpness; 415 oxcf->token_partitions = vp8_cfg.token_partitions; 416 417 oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in; 418 oxcf->output_pkt_list = vp8_cfg.pkt_list; 419 420 oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames; 421 oxcf->arnr_strength = vp8_cfg.arnr_strength; 422 oxcf->arnr_type = vp8_cfg.arnr_type; 423 424 oxcf->tuning = vp8_cfg.tuning; 425 426 oxcf->screen_content_mode = vp8_cfg.screen_content_mode; 427 428 /* 429 printf("Current VP8 Settings: \n"); 430 printf("target_bandwidth: %d\n", oxcf->target_bandwidth); 431 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity); 432 printf("Sharpness: %d\n", oxcf->Sharpness); 433 printf("cpu_used: %d\n", oxcf->cpu_used); 434 printf("Mode: %d\n", oxcf->Mode); 435 printf("auto_key: %d\n", oxcf->auto_key); 436 printf("key_freq: %d\n", oxcf->key_freq); 437 printf("end_usage: %d\n", oxcf->end_usage); 438 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct); 439 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct); 440 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level); 441 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level); 442 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size); 443 printf("fixed_q: %d\n", oxcf->fixed_q); 444 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q); 445 printf("best_allowed_q: %d\n", oxcf->best_allowed_q); 446 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling); 447 printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark); 448 printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark); 449 printf("allow_df: %d\n", oxcf->allow_df); 450 printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark); 451 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias); 452 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section); 453 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section); 454 printf("allow_lag: %d\n", oxcf->allow_lag); 455 printf("lag_in_frames: %d\n", oxcf->lag_in_frames); 456 printf("play_alternate: %d\n", oxcf->play_alternate); 457 printf("Version: %d\n", oxcf->Version); 458 printf("multi_threaded: %d\n", oxcf->multi_threaded); 459 printf("encode_breakout: %d\n", oxcf->encode_breakout); 460 */ 461 return VPX_CODEC_OK; 462 } 463 464 static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t *ctx, 465 const vpx_codec_enc_cfg_t *cfg) { 466 vpx_codec_err_t res; 467 468 if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) { 469 if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS) 470 ERROR("Cannot change width or height after initialization"); 471 if ((ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) || 472 (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height)) 473 ERROR("Cannot increase width or height larger than their initial values"); 474 } 475 476 /* Prevent increasing lag_in_frames. This check is stricter than it needs 477 * to be -- the limit is not increasing past the first lag_in_frames 478 * value, but we don't track the initial config, only the last successful 479 * config. 480 */ 481 if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)) 482 ERROR("Cannot increase lag_in_frames"); 483 484 res = validate_config(ctx, cfg, &ctx->vp8_cfg, 0); 485 if (res != VPX_CODEC_OK) return res; 486 487 if (setjmp(ctx->cpi->common.error.jmp)) { 488 const vpx_codec_err_t codec_err = 489 update_error_state(ctx, &ctx->cpi->common.error); 490 ctx->cpi->common.error.setjmp = 0; 491 vpx_clear_system_state(); 492 assert(codec_err != VPX_CODEC_OK); 493 return codec_err; 494 } 495 496 ctx->cpi->common.error.setjmp = 1; 497 ctx->cfg = *cfg; 498 set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL); 499 vp8_change_config(ctx->cpi, &ctx->oxcf); 500 #if CONFIG_MULTITHREAD 501 if (vp8cx_create_encoder_threads(ctx->cpi)) { 502 ctx->cpi->common.error.setjmp = 0; 503 return VPX_CODEC_ERROR; 504 } 505 #endif 506 ctx->cpi->common.error.setjmp = 0; 507 return VPX_CODEC_OK; 508 } 509 510 static vpx_codec_err_t get_quantizer(vpx_codec_alg_priv_t *ctx, va_list args) { 511 int *const arg = va_arg(args, int *); 512 if (arg == NULL) return VPX_CODEC_INVALID_PARAM; 513 *arg = vp8_get_quantizer(ctx->cpi); 514 return VPX_CODEC_OK; 515 } 516 517 static vpx_codec_err_t get_quantizer64(vpx_codec_alg_priv_t *ctx, 518 va_list args) { 519 int *const arg = va_arg(args, int *); 520 if (arg == NULL) return VPX_CODEC_INVALID_PARAM; 521 *arg = vp8_reverse_trans(vp8_get_quantizer(ctx->cpi)); 522 return VPX_CODEC_OK; 523 } 524 525 static vpx_codec_err_t update_extracfg(vpx_codec_alg_priv_t *ctx, 526 const struct vp8_extracfg *extra_cfg) { 527 const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg, 0); 528 if (res == VPX_CODEC_OK) { 529 ctx->vp8_cfg = *extra_cfg; 530 set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL); 531 vp8_change_config(ctx->cpi, &ctx->oxcf); 532 } 533 return res; 534 } 535 536 static vpx_codec_err_t set_cpu_used(vpx_codec_alg_priv_t *ctx, va_list args) { 537 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 538 extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args); 539 // Use fastest speed setting (speed 16 or -16) if it's set beyond the range. 540 extra_cfg.cpu_used = VPXMIN(16, extra_cfg.cpu_used); 541 extra_cfg.cpu_used = VPXMAX(-16, extra_cfg.cpu_used); 542 return update_extracfg(ctx, &extra_cfg); 543 } 544 545 static vpx_codec_err_t set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx, 546 va_list args) { 547 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 548 extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args); 549 return update_extracfg(ctx, &extra_cfg); 550 } 551 552 static vpx_codec_err_t set_noise_sensitivity(vpx_codec_alg_priv_t *ctx, 553 va_list args) { 554 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 555 extra_cfg.noise_sensitivity = CAST(VP8E_SET_NOISE_SENSITIVITY, args); 556 return update_extracfg(ctx, &extra_cfg); 557 } 558 559 static vpx_codec_err_t set_sharpness(vpx_codec_alg_priv_t *ctx, va_list args) { 560 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 561 extra_cfg.Sharpness = CAST(VP8E_SET_SHARPNESS, args); 562 return update_extracfg(ctx, &extra_cfg); 563 } 564 565 static vpx_codec_err_t set_static_thresh(vpx_codec_alg_priv_t *ctx, 566 va_list args) { 567 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 568 extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args); 569 return update_extracfg(ctx, &extra_cfg); 570 } 571 572 static vpx_codec_err_t set_token_partitions(vpx_codec_alg_priv_t *ctx, 573 va_list args) { 574 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 575 extra_cfg.token_partitions = CAST(VP8E_SET_TOKEN_PARTITIONS, args); 576 return update_extracfg(ctx, &extra_cfg); 577 } 578 579 static vpx_codec_err_t set_arnr_max_frames(vpx_codec_alg_priv_t *ctx, 580 va_list args) { 581 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 582 extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args); 583 return update_extracfg(ctx, &extra_cfg); 584 } 585 586 static vpx_codec_err_t set_arnr_strength(vpx_codec_alg_priv_t *ctx, 587 va_list args) { 588 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 589 extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args); 590 return update_extracfg(ctx, &extra_cfg); 591 } 592 593 static vpx_codec_err_t set_arnr_type(vpx_codec_alg_priv_t *ctx, va_list args) { 594 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 595 extra_cfg.arnr_type = CAST(VP8E_SET_ARNR_TYPE, args); 596 return update_extracfg(ctx, &extra_cfg); 597 } 598 599 static vpx_codec_err_t set_tuning(vpx_codec_alg_priv_t *ctx, va_list args) { 600 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 601 extra_cfg.tuning = CAST(VP8E_SET_TUNING, args); 602 return update_extracfg(ctx, &extra_cfg); 603 } 604 605 static vpx_codec_err_t set_cq_level(vpx_codec_alg_priv_t *ctx, va_list args) { 606 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 607 extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args); 608 return update_extracfg(ctx, &extra_cfg); 609 } 610 611 static vpx_codec_err_t set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t *ctx, 612 va_list args) { 613 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 614 extra_cfg.rc_max_intra_bitrate_pct = 615 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args); 616 return update_extracfg(ctx, &extra_cfg); 617 } 618 619 static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(vpx_codec_alg_priv_t *ctx, 620 va_list args) { 621 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 622 extra_cfg.gf_cbr_boost_pct = CAST(VP8E_SET_GF_CBR_BOOST_PCT, args); 623 return update_extracfg(ctx, &extra_cfg); 624 } 625 626 static vpx_codec_err_t set_screen_content_mode(vpx_codec_alg_priv_t *ctx, 627 va_list args) { 628 struct vp8_extracfg extra_cfg = ctx->vp8_cfg; 629 extra_cfg.screen_content_mode = CAST(VP8E_SET_SCREEN_CONTENT_MODE, args); 630 return update_extracfg(ctx, &extra_cfg); 631 } 632 633 static vpx_codec_err_t ctrl_set_rtc_external_ratectrl(vpx_codec_alg_priv_t *ctx, 634 va_list args) { 635 VP8_COMP *cpi = ctx->cpi; 636 const unsigned int data = CAST(VP8E_SET_RTC_EXTERNAL_RATECTRL, args); 637 if (data) { 638 cpi->cyclic_refresh_mode_enabled = 0; 639 cpi->rt_always_update_correction_factor = 1; 640 cpi->rt_drop_recode_on_overshoot = 0; 641 } 642 return VPX_CODEC_OK; 643 } 644 645 static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg, 646 void **mem_loc) { 647 vpx_codec_err_t res = VPX_CODEC_OK; 648 649 #if CONFIG_MULTI_RES_ENCODING 650 LOWER_RES_FRAME_INFO *shared_mem_loc; 651 int mb_rows = ((cfg->g_w + 15) >> 4); 652 int mb_cols = ((cfg->g_h + 15) >> 4); 653 654 shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO)); 655 if (!shared_mem_loc) { 656 return VPX_CODEC_MEM_ERROR; 657 } 658 659 shared_mem_loc->mb_info = 660 calloc(mb_rows * mb_cols, sizeof(LOWER_RES_MB_INFO)); 661 if (!(shared_mem_loc->mb_info)) { 662 free(shared_mem_loc); 663 res = VPX_CODEC_MEM_ERROR; 664 } else { 665 *mem_loc = (void *)shared_mem_loc; 666 res = VPX_CODEC_OK; 667 } 668 #else 669 (void)cfg; 670 *mem_loc = NULL; 671 #endif 672 return res; 673 } 674 675 static void vp8e_mr_free_mem(void *mem_loc) { 676 #if CONFIG_MULTI_RES_ENCODING 677 LOWER_RES_FRAME_INFO *shared_mem_loc = (LOWER_RES_FRAME_INFO *)mem_loc; 678 free(shared_mem_loc->mb_info); 679 free(mem_loc); 680 #else 681 (void)mem_loc; 682 assert(!mem_loc); 683 #endif 684 } 685 686 static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx, 687 vpx_codec_priv_enc_mr_cfg_t *mr_cfg) { 688 vpx_codec_err_t res = VPX_CODEC_OK; 689 690 vp8_rtcd(); 691 vpx_dsp_rtcd(); 692 vpx_scale_rtcd(); 693 694 if (!ctx->priv) { 695 struct vpx_codec_alg_priv *priv = 696 (struct vpx_codec_alg_priv *)vpx_calloc(1, sizeof(*priv)); 697 698 if (!priv) { 699 return VPX_CODEC_MEM_ERROR; 700 } 701 702 ctx->priv = (vpx_codec_priv_t *)priv; 703 ctx->priv->init_flags = ctx->init_flags; 704 705 if (ctx->config.enc) { 706 /* Update the reference to the config structure to an 707 * internal copy. 708 */ 709 priv->cfg = *ctx->config.enc; 710 ctx->config.enc = &priv->cfg; 711 } 712 713 priv->vp8_cfg = default_extracfg; 714 priv->vp8_cfg.pkt_list = &priv->pkt_list.head; 715 716 priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2; 717 718 if (priv->cx_data_sz < 32768) priv->cx_data_sz = 32768; 719 720 priv->cx_data = malloc(priv->cx_data_sz); 721 722 if (!priv->cx_data) { 723 priv->cx_data_sz = 0; 724 return VPX_CODEC_MEM_ERROR; 725 } 726 727 if (mr_cfg) { 728 ctx->priv->enc.total_encoders = mr_cfg->mr_total_resolutions; 729 } else { 730 ctx->priv->enc.total_encoders = 1; 731 } 732 733 vp8_initialize_enc(); 734 735 res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0); 736 737 if (!res) { 738 priv->pts_offset_initialized = 0; 739 priv->timestamp_ratio.den = priv->cfg.g_timebase.den; 740 priv->timestamp_ratio.num = (int64_t)priv->cfg.g_timebase.num; 741 priv->timestamp_ratio.num *= TICKS_PER_SEC; 742 reduce_ratio(&priv->timestamp_ratio); 743 744 set_vp8e_config(&priv->oxcf, priv->cfg, priv->vp8_cfg, mr_cfg); 745 priv->cpi = vp8_create_compressor(&priv->oxcf); 746 if (!priv->cpi) { 747 #if CONFIG_MULTI_RES_ENCODING 748 // Release ownership of mr_cfg->mr_low_res_mode_info on failure. This 749 // prevents ownership confusion with the caller and avoids a double 750 // free when vpx_codec_destroy() is called on this instance. 751 priv->oxcf.mr_total_resolutions = 0; 752 priv->oxcf.mr_encoder_id = 0; 753 priv->oxcf.mr_low_res_mode_info = NULL; 754 #endif 755 res = VPX_CODEC_MEM_ERROR; 756 } 757 } 758 } 759 760 return res; 761 } 762 763 static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx) { 764 #if CONFIG_MULTI_RES_ENCODING 765 /* Free multi-encoder shared memory */ 766 if (ctx->oxcf.mr_total_resolutions > 0 && 767 (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions - 1)) { 768 vp8e_mr_free_mem(ctx->oxcf.mr_low_res_mode_info); 769 } 770 #endif 771 772 free(ctx->cx_data); 773 vp8_remove_compressor(&ctx->cpi); 774 vpx_free(ctx); 775 return VPX_CODEC_OK; 776 } 777 778 static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, 779 YV12_BUFFER_CONFIG *yv12) { 780 const int y_w = img->d_w; 781 const int y_h = img->d_h; 782 const int uv_w = (img->d_w + 1) / 2; 783 const int uv_h = (img->d_h + 1) / 2; 784 vpx_codec_err_t res = VPX_CODEC_OK; 785 yv12->y_buffer = img->planes[VPX_PLANE_Y]; 786 yv12->u_buffer = img->planes[VPX_PLANE_U]; 787 yv12->v_buffer = img->planes[VPX_PLANE_V]; 788 789 yv12->y_crop_width = y_w; 790 yv12->y_crop_height = y_h; 791 yv12->y_width = y_w; 792 yv12->y_height = y_h; 793 yv12->uv_crop_width = uv_w; 794 yv12->uv_crop_height = uv_h; 795 yv12->uv_width = uv_w; 796 yv12->uv_height = uv_h; 797 798 yv12->y_stride = img->stride[VPX_PLANE_Y]; 799 yv12->uv_stride = img->stride[VPX_PLANE_U]; 800 801 yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2; 802 return res; 803 } 804 805 static vpx_codec_err_t pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx, 806 unsigned long duration, 807 vpx_enc_deadline_t deadline) { 808 int new_qc; 809 810 #if !(CONFIG_REALTIME_ONLY) 811 /* Use best quality mode if no deadline is given. */ 812 new_qc = MODE_BESTQUALITY; 813 814 if (deadline) { 815 /* Convert duration parameter from stream timebase to microseconds */ 816 VPX_STATIC_ASSERT(TICKS_PER_SEC > 1000000 && 817 (TICKS_PER_SEC % 1000000) == 0); 818 819 if (duration > UINT64_MAX / (uint64_t)ctx->timestamp_ratio.num) { 820 ERROR("duration is too big"); 821 } 822 uint64_t duration_us = 823 duration * (uint64_t)ctx->timestamp_ratio.num / 824 ((uint64_t)ctx->timestamp_ratio.den * (TICKS_PER_SEC / 1000000)); 825 826 /* If the deadline is more that the duration this frame is to be shown, 827 * use good quality mode. Otherwise use realtime mode. 828 */ 829 new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME; 830 } 831 832 #else 833 (void)duration; 834 new_qc = MODE_REALTIME; 835 #endif 836 837 if (deadline == VPX_DL_REALTIME) { 838 new_qc = MODE_REALTIME; 839 } else if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS) { 840 new_qc = MODE_FIRSTPASS; 841 } else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS) { 842 new_qc = 843 (new_qc == MODE_BESTQUALITY) ? MODE_SECONDPASS_BEST : MODE_SECONDPASS; 844 } 845 846 if (ctx->oxcf.Mode != new_qc) { 847 ctx->oxcf.Mode = new_qc; 848 vp8_change_config(ctx->cpi, &ctx->oxcf); 849 } 850 return VPX_CODEC_OK; 851 } 852 853 static vpx_codec_err_t set_reference_and_update(vpx_codec_alg_priv_t *ctx, 854 vpx_enc_frame_flags_t flags) { 855 /* Handle Flags */ 856 if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) || 857 ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) { 858 ctx->base.err_detail = "Conflicting flags."; 859 return VPX_CODEC_INVALID_PARAM; 860 } 861 862 if (flags & 863 (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF)) { 864 int ref = 7; 865 866 if (flags & VP8_EFLAG_NO_REF_LAST) ref ^= VP8_LAST_FRAME; 867 868 if (flags & VP8_EFLAG_NO_REF_GF) ref ^= VP8_GOLD_FRAME; 869 870 if (flags & VP8_EFLAG_NO_REF_ARF) ref ^= VP8_ALTR_FRAME; 871 872 vp8_use_as_reference(ctx->cpi, ref); 873 } 874 875 if (flags & 876 (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 877 VP8_EFLAG_FORCE_GF | VP8_EFLAG_FORCE_ARF)) { 878 int upd = 7; 879 880 if (flags & VP8_EFLAG_NO_UPD_LAST) upd ^= VP8_LAST_FRAME; 881 882 if (flags & VP8_EFLAG_NO_UPD_GF) upd ^= VP8_GOLD_FRAME; 883 884 if (flags & VP8_EFLAG_NO_UPD_ARF) upd ^= VP8_ALTR_FRAME; 885 886 vp8_update_reference(ctx->cpi, upd); 887 } 888 889 if (flags & VP8_EFLAG_NO_UPD_ENTROPY) { 890 vp8_update_entropy(ctx->cpi, 0); 891 } 892 893 return VPX_CODEC_OK; 894 } 895 896 static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, 897 const vpx_image_t *img, vpx_codec_pts_t pts, 898 unsigned long duration, 899 vpx_enc_frame_flags_t enc_flags, 900 vpx_enc_deadline_t deadline) { 901 volatile vpx_codec_err_t res = VPX_CODEC_OK; 902 // Make a copy as volatile to avoid -Wclobbered with longjmp. 903 volatile vpx_enc_frame_flags_t flags = enc_flags; 904 volatile vpx_codec_pts_t pts_val = pts; 905 906 if (!ctx->cfg.rc_target_bitrate) { 907 #if CONFIG_MULTI_RES_ENCODING 908 if (!ctx->cpi) return VPX_CODEC_ERROR; 909 if (ctx->cpi->oxcf.mr_total_resolutions > 1) { 910 LOWER_RES_FRAME_INFO *low_res_frame_info = 911 (LOWER_RES_FRAME_INFO *)ctx->cpi->oxcf.mr_low_res_mode_info; 912 if (!low_res_frame_info) return VPX_CODEC_ERROR; 913 low_res_frame_info->skip_encoding_prev_stream = 1; 914 if (ctx->cpi->oxcf.mr_encoder_id == 0) 915 low_res_frame_info->skip_encoding_base_stream = 1; 916 } 917 #endif 918 return res; 919 } 920 921 if (img) res = validate_img(ctx, img); 922 923 if (!res) res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1); 924 925 if (!res) res = pick_quickcompress_mode(ctx, duration, deadline); 926 vpx_codec_pkt_list_init(&ctx->pkt_list); 927 928 // If no flags are set in the encode call, then use the frame flags as 929 // defined via the control function: vp8e_set_frame_flags. 930 if (!flags) { 931 flags = ctx->control_frame_flags; 932 } 933 ctx->control_frame_flags = 0; 934 935 if (!res) res = set_reference_and_update(ctx, flags); 936 937 /* Handle fixed keyframe intervals */ 938 if (ctx->cfg.kf_mode == VPX_KF_AUTO && 939 ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) { 940 if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) { 941 flags |= VPX_EFLAG_FORCE_KF; 942 ctx->fixed_kf_cntr = 1; 943 } 944 } 945 946 /* Initialize the encoder instance on the first frame */ 947 if (!res && ctx->cpi) { 948 unsigned int lib_flags; 949 int64_t dst_time_stamp, dst_end_time_stamp; 950 size_t size, cx_data_sz; 951 unsigned char *cx_data; 952 unsigned char *cx_data_end; 953 int comp_data_state = 0; 954 955 if (setjmp(ctx->cpi->common.error.jmp)) { 956 ctx->cpi->common.error.setjmp = 0; 957 res = update_error_state(ctx, &ctx->cpi->common.error); 958 vpx_clear_system_state(); 959 return res; 960 } 961 ctx->cpi->common.error.setjmp = 1; 962 963 // Per-frame PSNR is not supported when g_lag_in_frames is greater than 0. 964 if ((flags & VPX_EFLAG_CALCULATE_PSNR) && ctx->cfg.g_lag_in_frames != 0) { 965 vpx_internal_error( 966 &ctx->cpi->common.error, VPX_CODEC_INCAPABLE, 967 "Cannot calculate per-frame PSNR when g_lag_in_frames is nonzero"); 968 } 969 /* Set up internal flags */ 970 #if CONFIG_INTERNAL_STATS 971 assert(((VP8_COMP *)ctx->cpi)->b_calculate_psnr == 1); 972 #else 973 ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 974 (ctx->base.init_flags & VPX_CODEC_USE_PSNR) || 975 (flags & VPX_EFLAG_CALCULATE_PSNR); 976 #endif 977 978 if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION) { 979 ((VP8_COMP *)ctx->cpi)->output_partition = 1; 980 } 981 982 /* Convert API flags to internal codec lib flags */ 983 lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0; 984 985 if (img != NULL) { 986 YV12_BUFFER_CONFIG sd; 987 988 if (!ctx->pts_offset_initialized) { 989 ctx->pts_offset = pts_val; 990 ctx->pts_offset_initialized = 1; 991 } 992 if (pts_val < ctx->pts_offset) { 993 vpx_internal_error(&ctx->cpi->common.error, VPX_CODEC_INVALID_PARAM, 994 "pts is smaller than initial pts"); 995 } 996 pts_val -= ctx->pts_offset; 997 if (pts_val > INT64_MAX / ctx->timestamp_ratio.num) { 998 vpx_internal_error( 999 &ctx->cpi->common.error, VPX_CODEC_INVALID_PARAM, 1000 "conversion of relative pts to ticks would overflow"); 1001 } 1002 dst_time_stamp = 1003 pts_val * ctx->timestamp_ratio.num / ctx->timestamp_ratio.den; 1004 #if ULONG_MAX > INT64_MAX 1005 if (duration > INT64_MAX) { 1006 vpx_internal_error(&ctx->cpi->common.error, VPX_CODEC_INVALID_PARAM, 1007 "duration is too big"); 1008 } 1009 #endif 1010 if (pts_val > INT64_MAX - (int64_t)duration) { 1011 vpx_internal_error(&ctx->cpi->common.error, VPX_CODEC_INVALID_PARAM, 1012 "relative pts + duration is too big"); 1013 } 1014 vpx_codec_pts_t pts_end = pts_val + (int64_t)duration; 1015 if (pts_end > INT64_MAX / ctx->timestamp_ratio.num) { 1016 vpx_internal_error( 1017 &ctx->cpi->common.error, VPX_CODEC_INVALID_PARAM, 1018 "conversion of relative pts + duration to ticks would overflow"); 1019 } 1020 dst_end_time_stamp = 1021 pts_end * ctx->timestamp_ratio.num / ctx->timestamp_ratio.den; 1022 1023 res = image2yuvconfig(img, &sd); 1024 1025 if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) { 1026 /* from vpx_encoder.h for g_w/g_h: 1027 "Note that the frames passed as input to the encoder must have this 1028 resolution" 1029 */ 1030 ctx->base.err_detail = "Invalid input frame resolution"; 1031 res = VPX_CODEC_INVALID_PARAM; 1032 } else { 1033 if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, 1034 &sd, dst_time_stamp, dst_end_time_stamp)) { 1035 VP8_COMP *cpi = (VP8_COMP *)ctx->cpi; 1036 res = update_error_state(ctx, &cpi->common.error); 1037 } 1038 } 1039 1040 /* reset for next frame */ 1041 ctx->next_frame_flag = 0; 1042 } 1043 1044 cx_data = ctx->cx_data; 1045 cx_data_sz = ctx->cx_data_sz; 1046 cx_data_end = ctx->cx_data + cx_data_sz; 1047 lib_flags = 0; 1048 1049 while (cx_data_sz >= ctx->cx_data_sz / 2) { 1050 comp_data_state = vp8_get_compressed_data( 1051 ctx->cpi, &lib_flags, &size, cx_data, cx_data_end, &dst_time_stamp, 1052 &dst_end_time_stamp, !img); 1053 1054 if (comp_data_state == VPX_CODEC_CORRUPT_FRAME) { 1055 ctx->cpi->common.error.setjmp = 0; 1056 return VPX_CODEC_CORRUPT_FRAME; 1057 } else if (comp_data_state == -1) { 1058 break; 1059 } 1060 1061 if (size) { 1062 vpx_codec_pts_t round, delta; 1063 vpx_codec_cx_pkt_t pkt; 1064 VP8_COMP *cpi = (VP8_COMP *)ctx->cpi; 1065 1066 /* Add the frame packet to the list of returned packets. */ 1067 round = (vpx_codec_pts_t)ctx->timestamp_ratio.num / 2; 1068 if (round > 0) --round; 1069 delta = (dst_end_time_stamp - dst_time_stamp); 1070 pkt.kind = VPX_CODEC_CX_FRAME_PKT; 1071 pkt.data.frame.pts = 1072 (dst_time_stamp * ctx->timestamp_ratio.den + round) / 1073 ctx->timestamp_ratio.num + 1074 ctx->pts_offset; 1075 pkt.data.frame.duration = 1076 (unsigned long)((delta * ctx->timestamp_ratio.den + round) / 1077 ctx->timestamp_ratio.num); 1078 pkt.data.frame.flags = lib_flags << 16; 1079 pkt.data.frame.width[0] = cpi->common.Width; 1080 pkt.data.frame.height[0] = cpi->common.Height; 1081 pkt.data.frame.spatial_layer_encoded[0] = 1; 1082 1083 if (lib_flags & FRAMEFLAGS_KEY) { 1084 pkt.data.frame.flags |= VPX_FRAME_IS_KEY; 1085 } 1086 1087 if (!cpi->common.show_frame) { 1088 pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE; 1089 1090 /* This timestamp should be as close as possible to the 1091 * prior PTS so that if a decoder uses pts to schedule when 1092 * to do this, we start right after last frame was decoded. 1093 * Invisible frames have no duration. 1094 */ 1095 pkt.data.frame.pts = 1096 ((cpi->last_time_stamp_seen * ctx->timestamp_ratio.den + round) / 1097 ctx->timestamp_ratio.num) + 1098 ctx->pts_offset + 1; 1099 pkt.data.frame.duration = 0; 1100 } 1101 1102 if (cpi->droppable) pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE; 1103 1104 if (cpi->output_partition) { 1105 int i; 1106 const int num_partitions = 1107 (1 << cpi->common.multi_token_partition) + 1; 1108 1109 pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT; 1110 1111 for (i = 0; i < num_partitions; ++i) { 1112 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING 1113 pkt.data.frame.buf = cpi->partition_d[i]; 1114 #else 1115 pkt.data.frame.buf = cx_data; 1116 cx_data += cpi->partition_sz[i]; 1117 cx_data_sz -= cpi->partition_sz[i]; 1118 #endif 1119 pkt.data.frame.sz = cpi->partition_sz[i]; 1120 pkt.data.frame.partition_id = i; 1121 /* don't set the fragment bit for the last partition */ 1122 if (i == (num_partitions - 1)) { 1123 pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT; 1124 } 1125 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); 1126 } 1127 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING 1128 /* In lagged mode the encoder can buffer multiple frames. 1129 * We don't want this in partitioned output because 1130 * partitions are spread all over the output buffer. 1131 * So, force an exit! 1132 */ 1133 cx_data_sz -= ctx->cx_data_sz / 2; 1134 #endif 1135 } else { 1136 pkt.data.frame.buf = cx_data; 1137 pkt.data.frame.sz = size; 1138 pkt.data.frame.partition_id = -1; 1139 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); 1140 cx_data += size; 1141 cx_data_sz -= size; 1142 } 1143 } 1144 } 1145 ctx->cpi->common.error.setjmp = 0; 1146 } 1147 1148 return res; 1149 } 1150 1151 static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx, 1152 vpx_codec_iter_t *iter) { 1153 return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter); 1154 } 1155 1156 static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx, 1157 va_list args) { 1158 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1159 1160 if (data) { 1161 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1162 YV12_BUFFER_CONFIG sd; 1163 1164 image2yuvconfig(&frame->img, &sd); 1165 vp8_set_reference(ctx->cpi, frame->frame_type, &sd); 1166 return VPX_CODEC_OK; 1167 } else { 1168 return VPX_CODEC_INVALID_PARAM; 1169 } 1170 } 1171 1172 static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx, 1173 va_list args) { 1174 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1175 1176 if (data) { 1177 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1178 YV12_BUFFER_CONFIG sd; 1179 1180 image2yuvconfig(&frame->img, &sd); 1181 vp8_get_reference(ctx->cpi, frame->frame_type, &sd); 1182 return VPX_CODEC_OK; 1183 } else { 1184 return VPX_CODEC_INVALID_PARAM; 1185 } 1186 } 1187 1188 static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx, 1189 va_list args) { 1190 #if CONFIG_POSTPROC 1191 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *); 1192 1193 if (data) { 1194 ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data); 1195 return VPX_CODEC_OK; 1196 } else { 1197 return VPX_CODEC_INVALID_PARAM; 1198 } 1199 #else 1200 (void)ctx; 1201 (void)args; 1202 return VPX_CODEC_INCAPABLE; 1203 #endif 1204 } 1205 1206 static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx) { 1207 YV12_BUFFER_CONFIG sd; 1208 vp8_ppflags_t flags; 1209 vp8_zero(flags); 1210 1211 if (ctx->preview_ppcfg.post_proc_flag) { 1212 flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag; 1213 flags.deblocking_level = ctx->preview_ppcfg.deblocking_level; 1214 flags.noise_level = ctx->preview_ppcfg.noise_level; 1215 } 1216 1217 if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, &flags)) { 1218 /* 1219 vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12, 1220 sd.y_width + 2*VP8BORDERINPIXELS, 1221 sd.y_height + 2*VP8BORDERINPIXELS, 1222 1, 1223 sd.buffer_alloc); 1224 vpx_img_set_rect(&ctx->preview_img, 1225 VP8BORDERINPIXELS, VP8BORDERINPIXELS, 1226 sd.y_width, sd.y_height); 1227 */ 1228 1229 ctx->preview_img.bps = 12; 1230 ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer; 1231 ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer; 1232 ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer; 1233 1234 ctx->preview_img.fmt = VPX_IMG_FMT_I420; 1235 ctx->preview_img.x_chroma_shift = 1; 1236 ctx->preview_img.y_chroma_shift = 1; 1237 1238 ctx->preview_img.d_w = sd.y_width; 1239 ctx->preview_img.d_h = sd.y_height; 1240 ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride; 1241 ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride; 1242 ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride; 1243 ctx->preview_img.w = sd.y_width; 1244 ctx->preview_img.h = sd.y_height; 1245 1246 return &ctx->preview_img; 1247 } else { 1248 return NULL; 1249 } 1250 } 1251 1252 static vpx_codec_err_t vp8e_set_frame_flags(vpx_codec_alg_priv_t *ctx, 1253 va_list args) { 1254 int frame_flags = va_arg(args, int); 1255 ctx->control_frame_flags = frame_flags; 1256 return set_reference_and_update(ctx, frame_flags); 1257 } 1258 1259 static vpx_codec_err_t vp8e_set_temporal_layer_id(vpx_codec_alg_priv_t *ctx, 1260 va_list args) { 1261 int layer_id = va_arg(args, int); 1262 if (layer_id < 0 || layer_id >= (int)ctx->cfg.ts_number_layers) { 1263 return VPX_CODEC_INVALID_PARAM; 1264 } 1265 ctx->cpi->temporal_layer_id = layer_id; 1266 return VPX_CODEC_OK; 1267 } 1268 1269 static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx, 1270 va_list args) { 1271 vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *); 1272 1273 if (data) { 1274 vpx_roi_map_t *roi = (vpx_roi_map_t *)data; 1275 1276 if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols, 1277 roi->delta_q, roi->delta_lf, roi->static_threshold)) { 1278 return VPX_CODEC_OK; 1279 } else { 1280 return VPX_CODEC_INVALID_PARAM; 1281 } 1282 } else { 1283 return VPX_CODEC_INVALID_PARAM; 1284 } 1285 } 1286 1287 static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx, 1288 va_list args) { 1289 vpx_active_map_t *data = va_arg(args, vpx_active_map_t *); 1290 1291 if (data) { 1292 vpx_active_map_t *map = (vpx_active_map_t *)data; 1293 1294 if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols)) { 1295 return VPX_CODEC_OK; 1296 } else { 1297 return VPX_CODEC_INVALID_PARAM; 1298 } 1299 } else { 1300 return VPX_CODEC_INVALID_PARAM; 1301 } 1302 } 1303 1304 static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx, 1305 va_list args) { 1306 vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *); 1307 1308 if (data) { 1309 int res; 1310 vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data; 1311 res = vp8_set_internal_size(ctx->cpi, scalemode.h_scaling_mode, 1312 scalemode.v_scaling_mode); 1313 1314 if (!res) { 1315 /*force next frame a key frame to effect scaling mode */ 1316 ctx->next_frame_flag |= FRAMEFLAGS_KEY; 1317 return VPX_CODEC_OK; 1318 } else { 1319 return VPX_CODEC_INVALID_PARAM; 1320 } 1321 } else { 1322 return VPX_CODEC_INVALID_PARAM; 1323 } 1324 } 1325 1326 static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] = { 1327 { VP8_SET_REFERENCE, vp8e_set_reference }, 1328 { VP8_COPY_REFERENCE, vp8e_get_reference }, 1329 { VP8_SET_POSTPROC, vp8e_set_previewpp }, 1330 { VP8E_SET_FRAME_FLAGS, vp8e_set_frame_flags }, 1331 { VP8E_SET_TEMPORAL_LAYER_ID, vp8e_set_temporal_layer_id }, 1332 { VP8E_SET_ROI_MAP, vp8e_set_roi_map }, 1333 { VP8E_SET_ACTIVEMAP, vp8e_set_activemap }, 1334 { VP8E_SET_SCALEMODE, vp8e_set_scalemode }, 1335 { VP8E_SET_CPUUSED, set_cpu_used }, 1336 { VP8E_SET_NOISE_SENSITIVITY, set_noise_sensitivity }, 1337 { VP8E_SET_ENABLEAUTOALTREF, set_enable_auto_alt_ref }, 1338 { VP8E_SET_SHARPNESS, set_sharpness }, 1339 { VP8E_SET_STATIC_THRESHOLD, set_static_thresh }, 1340 { VP8E_SET_TOKEN_PARTITIONS, set_token_partitions }, 1341 { VP8E_GET_LAST_QUANTIZER, get_quantizer }, 1342 { VP8E_GET_LAST_QUANTIZER_64, get_quantizer64 }, 1343 { VP8E_SET_ARNR_MAXFRAMES, set_arnr_max_frames }, 1344 { VP8E_SET_ARNR_STRENGTH, set_arnr_strength }, 1345 { VP8E_SET_ARNR_TYPE, set_arnr_type }, 1346 { VP8E_SET_TUNING, set_tuning }, 1347 { VP8E_SET_CQ_LEVEL, set_cq_level }, 1348 { VP8E_SET_MAX_INTRA_BITRATE_PCT, set_rc_max_intra_bitrate_pct }, 1349 { VP8E_SET_SCREEN_CONTENT_MODE, set_screen_content_mode }, 1350 { VP8E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct }, 1351 { VP8E_SET_RTC_EXTERNAL_RATECTRL, ctrl_set_rtc_external_ratectrl }, 1352 { -1, NULL }, 1353 }; 1354 1355 static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] = { 1356 { 0, 1357 { 1358 0, /* g_usage (unused) */ 1359 0, /* g_threads */ 1360 0, /* g_profile */ 1361 1362 320, /* g_width */ 1363 240, /* g_height */ 1364 VPX_BITS_8, /* g_bit_depth */ 1365 8, /* g_input_bit_depth */ 1366 1367 { 1, 30 }, /* g_timebase */ 1368 1369 0, /* g_error_resilient */ 1370 1371 VPX_RC_ONE_PASS, /* g_pass */ 1372 1373 0, /* g_lag_in_frames */ 1374 1375 0, /* rc_dropframe_thresh */ 1376 0, /* rc_resize_allowed */ 1377 1, /* rc_scaled_width */ 1378 1, /* rc_scaled_height */ 1379 60, /* rc_resize_down_thresh */ 1380 30, /* rc_resize_up_thresh */ 1381 1382 VPX_VBR, /* rc_end_usage */ 1383 { NULL, 0 }, /* rc_twopass_stats_in */ 1384 { NULL, 0 }, /* rc_firstpass_mb_stats_in */ 1385 256, /* rc_target_bitrate */ 1386 4, /* rc_min_quantizer */ 1387 63, /* rc_max_quantizer */ 1388 100, /* rc_undershoot_pct */ 1389 100, /* rc_overshoot_pct */ 1390 1391 6000, /* rc_max_buffer_size */ 1392 4000, /* rc_buffer_initial_size; */ 1393 5000, /* rc_buffer_optimal_size; */ 1394 1395 50, /* rc_two_pass_vbrbias */ 1396 0, /* rc_two_pass_vbrmin_section */ 1397 400, /* rc_two_pass_vbrmax_section */ 1398 0, // rc_2pass_vbr_corpus_complexity (only has meaningfull for VP9) 1399 1400 /* keyframing settings (kf) */ 1401 VPX_KF_AUTO, /* g_kfmode*/ 1402 0, /* kf_min_dist */ 1403 128, /* kf_max_dist */ 1404 1405 VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */ 1406 { 0 }, 1407 { 0 }, /* ss_target_bitrate */ 1408 1, /* ts_number_layers */ 1409 { 0 }, /* ts_target_bitrate */ 1410 { 0 }, /* ts_rate_decimator */ 1411 0, /* ts_periodicity */ 1412 { 0 }, /* ts_layer_id */ 1413 { 0 }, /* layer_target_bitrate */ 1414 0, /* temporal_layering_mode */ 1415 0, /* use_vizier_rc_params */ 1416 { 1, 1 }, /* active_wq_factor */ 1417 { 1, 1 }, /* err_per_mb_factor */ 1418 { 1, 1 }, /* sr_default_decay_limit */ 1419 { 1, 1 }, /* sr_diff_factor */ 1420 { 1, 1 }, /* kf_err_per_mb_factor */ 1421 { 1, 1 }, /* kf_frame_min_boost_factor */ 1422 { 1, 1 }, /* kf_frame_max_boost_first_factor */ 1423 { 1, 1 }, /* kf_frame_max_boost_subs_factor */ 1424 { 1, 1 }, /* kf_max_total_boost_factor */ 1425 { 1, 1 }, /* gf_max_total_boost_factor */ 1426 { 1, 1 }, /* gf_frame_max_boost_factor */ 1427 { 1, 1 }, /* zm_factor */ 1428 { 1, 1 }, /* rd_mult_inter_qp_fac */ 1429 { 1, 1 }, /* rd_mult_arf_qp_fac */ 1430 { 1, 1 }, /* rd_mult_key_qp_fac */ 1431 } }, 1432 }; 1433 1434 #ifndef VERSION_STRING 1435 #define VERSION_STRING 1436 #endif 1437 CODEC_INTERFACE(vpx_codec_vp8_cx) = { 1438 "WebM Project VP8 Encoder" VERSION_STRING, 1439 VPX_CODEC_INTERNAL_ABI_VERSION, 1440 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR | VPX_CODEC_CAP_OUTPUT_PARTITION, 1441 /* vpx_codec_caps_t caps; */ 1442 vp8e_init, /* vpx_codec_init_fn_t init; */ 1443 vp8e_destroy, /* vpx_codec_destroy_fn_t destroy; */ 1444 vp8e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 1445 { 1446 NULL, /* vpx_codec_peek_si_fn_t peek_si; */ 1447 NULL, /* vpx_codec_get_si_fn_t get_si; */ 1448 NULL, /* vpx_codec_decode_fn_t decode; */ 1449 NULL, /* vpx_codec_frame_get_fn_t frame_get; */ 1450 NULL, /* vpx_codec_set_fb_fn_t set_fb_fn; */ 1451 }, 1452 { 1453 1, /* 1 cfg map */ 1454 vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t cfg_maps; */ 1455 vp8e_encode, /* vpx_codec_encode_fn_t encode; */ 1456 vp8e_get_cxdata, /* vpx_codec_get_cx_data_fn_t get_cx_data; */ 1457 vp8e_set_config, 1458 NULL, 1459 vp8e_get_preview, 1460 vp8e_mr_alloc_mem, 1461 vp8e_mr_free_mem, 1462 } /* encoder functions */ 1463 };