1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp9/vp9_cx_iface.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1203 @@ 1.4 +/* 1.5 + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 +#include <stdlib.h> 1.15 +#include <string.h> 1.16 + 1.17 +#include "vpx/vpx_codec.h" 1.18 +#include "vpx/internal/vpx_codec_internal.h" 1.19 +#include "./vpx_version.h" 1.20 +#include "vp9/encoder/vp9_onyx_int.h" 1.21 +#include "vpx/vp8cx.h" 1.22 +#include "vp9/encoder/vp9_firstpass.h" 1.23 +#include "vp9/common/vp9_onyx.h" 1.24 +#include "vp9/vp9_iface_common.h" 1.25 + 1.26 +struct vp9_extracfg { 1.27 + struct vpx_codec_pkt_list *pkt_list; 1.28 + int cpu_used; /* available cpu percentage in 1/16 */ 1.29 + unsigned int enable_auto_alt_ref; 1.30 + unsigned int noise_sensitivity; 1.31 + unsigned int Sharpness; 1.32 + unsigned int static_thresh; 1.33 + unsigned int tile_columns; 1.34 + unsigned int tile_rows; 1.35 + unsigned int arnr_max_frames; 1.36 + unsigned int arnr_strength; 1.37 + unsigned int arnr_type; 1.38 + unsigned int experimental; 1.39 + vp8e_tuning tuning; 1.40 + unsigned int cq_level; /* constrained quality level */ 1.41 + unsigned int rc_max_intra_bitrate_pct; 1.42 + unsigned int lossless; 1.43 + unsigned int frame_parallel_decoding_mode; 1.44 + unsigned int aq_mode; 1.45 +}; 1.46 + 1.47 +struct extraconfig_map { 1.48 + int usage; 1.49 + struct vp9_extracfg cfg; 1.50 +}; 1.51 + 1.52 +static const struct extraconfig_map extracfg_map[] = { 1.53 + { 1.54 + 0, 1.55 + { // NOLINT 1.56 + NULL, 1.57 + 0, /* cpu_used */ 1.58 + 1, /* enable_auto_alt_ref */ 1.59 + 0, /* noise_sensitivity */ 1.60 + 0, /* Sharpness */ 1.61 + 0, /* static_thresh */ 1.62 + 0, /* tile_columns */ 1.63 + 0, /* tile_rows */ 1.64 + 7, /* arnr_max_frames */ 1.65 + 5, /* arnr_strength */ 1.66 + 3, /* arnr_type*/ 1.67 + 0, /* experimental mode */ 1.68 + 0, /* tuning*/ 1.69 + 10, /* cq_level */ 1.70 + 0, /* rc_max_intra_bitrate_pct */ 1.71 + 0, /* lossless */ 1.72 + 0, /* frame_parallel_decoding_mode */ 1.73 + 0, /* aq_mode */ 1.74 + } 1.75 + } 1.76 +}; 1.77 + 1.78 +struct vpx_codec_alg_priv { 1.79 + vpx_codec_priv_t base; 1.80 + vpx_codec_enc_cfg_t cfg; 1.81 + struct vp9_extracfg vp8_cfg; 1.82 + VP9_CONFIG oxcf; 1.83 + VP9_PTR cpi; 1.84 + unsigned char *cx_data; 1.85 + unsigned int cx_data_sz; 1.86 + unsigned char *pending_cx_data; 1.87 + unsigned int pending_cx_data_sz; 1.88 + int pending_frame_count; 1.89 + uint32_t pending_frame_sizes[8]; 1.90 + uint32_t pending_frame_magnitude; 1.91 + vpx_image_t preview_img; 1.92 + vp8_postproc_cfg_t preview_ppcfg; 1.93 + vpx_codec_pkt_list_decl(64) pkt_list; 1.94 + unsigned int fixed_kf_cntr; 1.95 +}; 1.96 + 1.97 +static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) { 1.98 + switch (frame) { 1.99 + case VP8_LAST_FRAME: 1.100 + return VP9_LAST_FLAG; 1.101 + case VP8_GOLD_FRAME: 1.102 + return VP9_GOLD_FLAG; 1.103 + case VP8_ALTR_FRAME: 1.104 + return VP9_ALT_FLAG; 1.105 + } 1.106 + assert(!"Invalid Reference Frame"); 1.107 + return VP9_LAST_FLAG; 1.108 +} 1.109 + 1.110 +static vpx_codec_err_t 1.111 +update_error_state(vpx_codec_alg_priv_t *ctx, 1.112 + const struct vpx_internal_error_info *error) { 1.113 + vpx_codec_err_t res; 1.114 + 1.115 + if ((res = error->error_code)) 1.116 + ctx->base.err_detail = error->has_detail 1.117 + ? error->detail 1.118 + : NULL; 1.119 + 1.120 + return res; 1.121 +} 1.122 + 1.123 + 1.124 +#undef ERROR 1.125 +#define ERROR(str) do {\ 1.126 + ctx->base.err_detail = str;\ 1.127 + return VPX_CODEC_INVALID_PARAM;\ 1.128 + } while (0) 1.129 + 1.130 +#define RANGE_CHECK(p, memb, lo, hi) do {\ 1.131 + if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \ 1.132 + ERROR(#memb " out of range ["#lo".."#hi"]");\ 1.133 + } while (0) 1.134 + 1.135 +#define RANGE_CHECK_HI(p, memb, hi) do {\ 1.136 + if (!((p)->memb <= (hi))) \ 1.137 + ERROR(#memb " out of range [.."#hi"]");\ 1.138 + } while (0) 1.139 + 1.140 +#define RANGE_CHECK_LO(p, memb, lo) do {\ 1.141 + if (!((p)->memb >= (lo))) \ 1.142 + ERROR(#memb " out of range ["#lo"..]");\ 1.143 + } while (0) 1.144 + 1.145 +#define RANGE_CHECK_BOOL(p, memb) do {\ 1.146 + if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\ 1.147 + } while (0) 1.148 + 1.149 +static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, 1.150 + const vpx_codec_enc_cfg_t *cfg, 1.151 + const struct vp9_extracfg *vp8_cfg) { 1.152 + RANGE_CHECK(cfg, g_w, 1, 65535); /* 16 bits available */ 1.153 + RANGE_CHECK(cfg, g_h, 1, 65535); /* 16 bits available */ 1.154 + RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000); 1.155 + RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den); 1.156 + RANGE_CHECK_HI(cfg, g_profile, 3); 1.157 + 1.158 + RANGE_CHECK_HI(cfg, rc_max_quantizer, 63); 1.159 + RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer); 1.160 + RANGE_CHECK_BOOL(vp8_cfg, lossless); 1.161 + if (vp8_cfg->lossless) { 1.162 + RANGE_CHECK_HI(cfg, rc_max_quantizer, 0); 1.163 + RANGE_CHECK_HI(cfg, rc_min_quantizer, 0); 1.164 + } 1.165 + RANGE_CHECK(vp8_cfg, aq_mode, 0, AQ_MODES_COUNT - 1); 1.166 + 1.167 + RANGE_CHECK_HI(cfg, g_threads, 64); 1.168 + RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS); 1.169 + RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q); 1.170 + RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000); 1.171 + RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000); 1.172 + RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100); 1.173 + RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO); 1.174 + // RANGE_CHECK_BOOL(cfg, g_delete_firstpassfile); 1.175 + RANGE_CHECK_BOOL(cfg, rc_resize_allowed); 1.176 + RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100); 1.177 + RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100); 1.178 + RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100); 1.179 + RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS); 1.180 + 1.181 + RANGE_CHECK(cfg, ss_number_layers, 1, 1.182 + VPX_SS_MAX_LAYERS); /*Spatial layers max */ 1.183 + /* VP8 does not support a lower bound on the keyframe interval in 1.184 + * automatic keyframe placement mode. 1.185 + */ 1.186 + if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist 1.187 + && cfg->kf_min_dist > 0) 1.188 + ERROR("kf_min_dist not supported in auto mode, use 0 " 1.189 + "or kf_max_dist instead."); 1.190 + 1.191 + RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref); 1.192 + RANGE_CHECK(vp8_cfg, cpu_used, -16, 16); 1.193 + 1.194 + RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6); 1.195 + 1.196 + RANGE_CHECK(vp8_cfg, tile_columns, 0, 6); 1.197 + RANGE_CHECK(vp8_cfg, tile_rows, 0, 2); 1.198 + RANGE_CHECK_HI(vp8_cfg, Sharpness, 7); 1.199 + RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15); 1.200 + RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6); 1.201 + RANGE_CHECK(vp8_cfg, arnr_type, 1, 3); 1.202 + RANGE_CHECK(vp8_cfg, cq_level, 0, 63); 1.203 + 1.204 + if (cfg->g_pass == VPX_RC_LAST_PASS) { 1.205 + size_t packet_sz = sizeof(FIRSTPASS_STATS); 1.206 + int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz); 1.207 + FIRSTPASS_STATS *stats; 1.208 + 1.209 + if (!cfg->rc_twopass_stats_in.buf) 1.210 + ERROR("rc_twopass_stats_in.buf not set."); 1.211 + 1.212 + if (cfg->rc_twopass_stats_in.sz % packet_sz) 1.213 + ERROR("rc_twopass_stats_in.sz indicates truncated packet."); 1.214 + 1.215 + if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz) 1.216 + ERROR("rc_twopass_stats_in requires at least two packets."); 1.217 + 1.218 + stats = (void *)((char *)cfg->rc_twopass_stats_in.buf 1.219 + + (n_packets - 1) * packet_sz); 1.220 + 1.221 + if ((int)(stats->count + 0.5) != n_packets - 1) 1.222 + ERROR("rc_twopass_stats_in missing EOS stats packet"); 1.223 + } 1.224 + 1.225 + return VPX_CODEC_OK; 1.226 +} 1.227 + 1.228 + 1.229 +static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, 1.230 + const vpx_image_t *img) { 1.231 + switch (img->fmt) { 1.232 + case VPX_IMG_FMT_YV12: 1.233 + case VPX_IMG_FMT_I420: 1.234 + case VPX_IMG_FMT_I422: 1.235 + case VPX_IMG_FMT_I444: 1.236 + break; 1.237 + default: 1.238 + ERROR("Invalid image format. Only YV12, I420, I422, I444 images are " 1.239 + "supported."); 1.240 + } 1.241 + 1.242 + if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h)) 1.243 + ERROR("Image size must match encoder init configuration size"); 1.244 + 1.245 + return VPX_CODEC_OK; 1.246 +} 1.247 + 1.248 + 1.249 +static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf, 1.250 + vpx_codec_enc_cfg_t cfg, 1.251 + struct vp9_extracfg vp8_cfg) { 1.252 + oxcf->version = cfg.g_profile | (vp8_cfg.experimental ? 0x4 : 0); 1.253 + oxcf->width = cfg.g_w; 1.254 + oxcf->height = cfg.g_h; 1.255 + /* guess a frame rate if out of whack, use 30 */ 1.256 + oxcf->framerate = (double)(cfg.g_timebase.den) 1.257 + / (double)(cfg.g_timebase.num); 1.258 + 1.259 + if (oxcf->framerate > 180) { 1.260 + oxcf->framerate = 30; 1.261 + } 1.262 + 1.263 + switch (cfg.g_pass) { 1.264 + case VPX_RC_ONE_PASS: 1.265 + oxcf->Mode = MODE_GOODQUALITY; 1.266 + break; 1.267 + case VPX_RC_FIRST_PASS: 1.268 + oxcf->Mode = MODE_FIRSTPASS; 1.269 + break; 1.270 + case VPX_RC_LAST_PASS: 1.271 + oxcf->Mode = MODE_SECONDPASS_BEST; 1.272 + break; 1.273 + } 1.274 + 1.275 + if (cfg.g_pass == VPX_RC_FIRST_PASS) { 1.276 + oxcf->allow_lag = 0; 1.277 + oxcf->lag_in_frames = 0; 1.278 + } else { 1.279 + oxcf->allow_lag = (cfg.g_lag_in_frames) > 0; 1.280 + oxcf->lag_in_frames = cfg.g_lag_in_frames; 1.281 + } 1.282 + 1.283 + // VBR only supported for now. 1.284 + // CBR code has been deprectated for experimental phase. 1.285 + // CQ mode not yet tested 1.286 + oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK; 1.287 + if (cfg.rc_end_usage == VPX_CQ) 1.288 + oxcf->end_usage = USAGE_CONSTRAINED_QUALITY; 1.289 + else if (cfg.rc_end_usage == VPX_Q) 1.290 + oxcf->end_usage = USAGE_CONSTANT_QUALITY; 1.291 + else if (cfg.rc_end_usage == VPX_CBR) 1.292 + oxcf->end_usage = USAGE_STREAM_FROM_SERVER; 1.293 + 1.294 + oxcf->target_bandwidth = cfg.rc_target_bitrate; 1.295 + oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct; 1.296 + 1.297 + oxcf->best_allowed_q = cfg.rc_min_quantizer; 1.298 + oxcf->worst_allowed_q = cfg.rc_max_quantizer; 1.299 + oxcf->cq_level = vp8_cfg.cq_level; 1.300 + oxcf->fixed_q = -1; 1.301 + 1.302 + oxcf->under_shoot_pct = cfg.rc_undershoot_pct; 1.303 + oxcf->over_shoot_pct = cfg.rc_overshoot_pct; 1.304 + 1.305 + oxcf->maximum_buffer_size = cfg.rc_buf_sz; 1.306 + oxcf->starting_buffer_level = cfg.rc_buf_initial_sz; 1.307 + oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz; 1.308 + 1.309 + oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct; 1.310 + oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct; 1.311 + oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct; 1.312 + 1.313 + oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO 1.314 + && cfg.kf_min_dist != cfg.kf_max_dist; 1.315 + // oxcf->kf_min_dist = cfg.kf_min_dis; 1.316 + oxcf->key_freq = cfg.kf_max_dist; 1.317 + 1.318 + // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile; 1.319 + // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file); 1.320 + 1.321 + oxcf->cpu_used = vp8_cfg.cpu_used; 1.322 + oxcf->encode_breakout = vp8_cfg.static_thresh; 1.323 + oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref; 1.324 + oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity; 1.325 + oxcf->Sharpness = vp8_cfg.Sharpness; 1.326 + 1.327 + oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in; 1.328 + oxcf->output_pkt_list = vp8_cfg.pkt_list; 1.329 + 1.330 + oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames; 1.331 + oxcf->arnr_strength = vp8_cfg.arnr_strength; 1.332 + oxcf->arnr_type = vp8_cfg.arnr_type; 1.333 + 1.334 + oxcf->tuning = vp8_cfg.tuning; 1.335 + 1.336 + oxcf->tile_columns = vp8_cfg.tile_columns; 1.337 + oxcf->tile_rows = vp8_cfg.tile_rows; 1.338 + 1.339 + oxcf->lossless = vp8_cfg.lossless; 1.340 + 1.341 + oxcf->error_resilient_mode = cfg.g_error_resilient; 1.342 + oxcf->frame_parallel_decoding_mode = vp8_cfg.frame_parallel_decoding_mode; 1.343 + 1.344 + oxcf->aq_mode = vp8_cfg.aq_mode; 1.345 + 1.346 + oxcf->ss_number_layers = cfg.ss_number_layers; 1.347 + /* 1.348 + printf("Current VP9 Settings: \n"); 1.349 + printf("target_bandwidth: %d\n", oxcf->target_bandwidth); 1.350 + printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity); 1.351 + printf("Sharpness: %d\n", oxcf->Sharpness); 1.352 + printf("cpu_used: %d\n", oxcf->cpu_used); 1.353 + printf("Mode: %d\n", oxcf->Mode); 1.354 + // printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file); 1.355 + printf("auto_key: %d\n", oxcf->auto_key); 1.356 + printf("key_freq: %d\n", oxcf->key_freq); 1.357 + printf("end_usage: %d\n", oxcf->end_usage); 1.358 + printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct); 1.359 + printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct); 1.360 + printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level); 1.361 + printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level); 1.362 + printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size); 1.363 + printf("fixed_q: %d\n", oxcf->fixed_q); 1.364 + printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q); 1.365 + printf("best_allowed_q: %d\n", oxcf->best_allowed_q); 1.366 + printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias); 1.367 + printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section); 1.368 + printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section); 1.369 + printf("allow_lag: %d\n", oxcf->allow_lag); 1.370 + printf("lag_in_frames: %d\n", oxcf->lag_in_frames); 1.371 + printf("play_alternate: %d\n", oxcf->play_alternate); 1.372 + printf("Version: %d\n", oxcf->Version); 1.373 + printf("encode_breakout: %d\n", oxcf->encode_breakout); 1.374 + printf("error resilient: %d\n", oxcf->error_resilient_mode); 1.375 + printf("frame parallel detokenization: %d\n", 1.376 + oxcf->frame_parallel_decoding_mode); 1.377 + */ 1.378 + return VPX_CODEC_OK; 1.379 +} 1.380 + 1.381 +static vpx_codec_err_t vp9e_set_config(vpx_codec_alg_priv_t *ctx, 1.382 + const vpx_codec_enc_cfg_t *cfg) { 1.383 + vpx_codec_err_t res; 1.384 + 1.385 + if ((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h)) 1.386 + ERROR("Cannot change width or height after initialization"); 1.387 + 1.388 + /* Prevent increasing lag_in_frames. This check is stricter than it needs 1.389 + * to be -- the limit is not increasing past the first lag_in_frames 1.390 + * value, but we don't track the initial config, only the last successful 1.391 + * config. 1.392 + */ 1.393 + if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)) 1.394 + ERROR("Cannot increase lag_in_frames"); 1.395 + 1.396 + res = validate_config(ctx, cfg, &ctx->vp8_cfg); 1.397 + 1.398 + if (!res) { 1.399 + ctx->cfg = *cfg; 1.400 + set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg); 1.401 + vp9_change_config(ctx->cpi, &ctx->oxcf); 1.402 + } 1.403 + 1.404 + return res; 1.405 +} 1.406 + 1.407 + 1.408 +int vp9_reverse_trans(int q); 1.409 + 1.410 + 1.411 +static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx, 1.412 + int ctrl_id, 1.413 + va_list args) { 1.414 + void *arg = va_arg(args, void *); 1.415 + 1.416 +#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break 1.417 + 1.418 + if (!arg) 1.419 + return VPX_CODEC_INVALID_PARAM; 1.420 + 1.421 + switch (ctrl_id) { 1.422 + MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi)); 1.423 + MAP(VP8E_GET_LAST_QUANTIZER_64, 1.424 + vp9_reverse_trans(vp9_get_quantizer(ctx->cpi))); 1.425 + } 1.426 + 1.427 + return VPX_CODEC_OK; 1.428 +#undef MAP 1.429 +} 1.430 + 1.431 + 1.432 +static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx, 1.433 + int ctrl_id, 1.434 + va_list args) { 1.435 + vpx_codec_err_t res = VPX_CODEC_OK; 1.436 + struct vp9_extracfg xcfg = ctx->vp8_cfg; 1.437 + 1.438 +#define MAP(id, var) case id: var = CAST(id, args); break; 1.439 + 1.440 + switch (ctrl_id) { 1.441 + MAP(VP8E_SET_CPUUSED, xcfg.cpu_used); 1.442 + MAP(VP8E_SET_ENABLEAUTOALTREF, xcfg.enable_auto_alt_ref); 1.443 + MAP(VP8E_SET_NOISE_SENSITIVITY, xcfg.noise_sensitivity); 1.444 + MAP(VP8E_SET_SHARPNESS, xcfg.Sharpness); 1.445 + MAP(VP8E_SET_STATIC_THRESHOLD, xcfg.static_thresh); 1.446 + MAP(VP9E_SET_TILE_COLUMNS, xcfg.tile_columns); 1.447 + MAP(VP9E_SET_TILE_ROWS, xcfg.tile_rows); 1.448 + MAP(VP8E_SET_ARNR_MAXFRAMES, xcfg.arnr_max_frames); 1.449 + MAP(VP8E_SET_ARNR_STRENGTH, xcfg.arnr_strength); 1.450 + MAP(VP8E_SET_ARNR_TYPE, xcfg.arnr_type); 1.451 + MAP(VP8E_SET_TUNING, xcfg.tuning); 1.452 + MAP(VP8E_SET_CQ_LEVEL, xcfg.cq_level); 1.453 + MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct); 1.454 + MAP(VP9E_SET_LOSSLESS, xcfg.lossless); 1.455 + MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode); 1.456 + MAP(VP9E_SET_AQ_MODE, xcfg.aq_mode); 1.457 + } 1.458 + 1.459 + res = validate_config(ctx, &ctx->cfg, &xcfg); 1.460 + 1.461 + if (!res) { 1.462 + ctx->vp8_cfg = xcfg; 1.463 + set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg); 1.464 + vp9_change_config(ctx->cpi, &ctx->oxcf); 1.465 + } 1.466 + 1.467 + return res; 1.468 +#undef MAP 1.469 +} 1.470 + 1.471 + 1.472 +static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx, 1.473 + int experimental) { 1.474 + vpx_codec_err_t res = VPX_CODEC_OK; 1.475 + struct vpx_codec_alg_priv *priv; 1.476 + vpx_codec_enc_cfg_t *cfg; 1.477 + unsigned int i; 1.478 + 1.479 + VP9_PTR optr; 1.480 + 1.481 + if (!ctx->priv) { 1.482 + priv = calloc(1, sizeof(struct vpx_codec_alg_priv)); 1.483 + 1.484 + if (!priv) { 1.485 + return VPX_CODEC_MEM_ERROR; 1.486 + } 1.487 + 1.488 + ctx->priv = &priv->base; 1.489 + ctx->priv->sz = sizeof(*ctx->priv); 1.490 + ctx->priv->iface = ctx->iface; 1.491 + ctx->priv->alg_priv = priv; 1.492 + ctx->priv->init_flags = ctx->init_flags; 1.493 + ctx->priv->enc.total_encoders = 1; 1.494 + 1.495 + if (ctx->config.enc) { 1.496 + /* Update the reference to the config structure to an 1.497 + * internal copy. 1.498 + */ 1.499 + ctx->priv->alg_priv->cfg = *ctx->config.enc; 1.500 + ctx->config.enc = &ctx->priv->alg_priv->cfg; 1.501 + } 1.502 + 1.503 + cfg = &ctx->priv->alg_priv->cfg; 1.504 + 1.505 + /* Select the extra vp6 configuration table based on the current 1.506 + * usage value. If the current usage value isn't found, use the 1.507 + * values for usage case 0. 1.508 + */ 1.509 + for (i = 0; 1.510 + extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage; 1.511 + i++) {} 1.512 + 1.513 + priv->vp8_cfg = extracfg_map[i].cfg; 1.514 + priv->vp8_cfg.pkt_list = &priv->pkt_list.head; 1.515 + priv->vp8_cfg.experimental = experimental; 1.516 + 1.517 + // TODO(agrange) Check the limits set on this buffer, or the check that is 1.518 + // applied in vp9e_encode. 1.519 + priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8; 1.520 +// priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2; 1.521 + 1.522 + if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096; 1.523 + 1.524 + priv->cx_data = malloc(priv->cx_data_sz); 1.525 + 1.526 + if (!priv->cx_data) { 1.527 + return VPX_CODEC_MEM_ERROR; 1.528 + } 1.529 + 1.530 + vp9_initialize_enc(); 1.531 + 1.532 + res = validate_config(priv, &priv->cfg, &priv->vp8_cfg); 1.533 + 1.534 + if (!res) { 1.535 + set_vp9e_config(&ctx->priv->alg_priv->oxcf, 1.536 + ctx->priv->alg_priv->cfg, 1.537 + ctx->priv->alg_priv->vp8_cfg); 1.538 + optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf); 1.539 + 1.540 + if (!optr) 1.541 + res = VPX_CODEC_MEM_ERROR; 1.542 + else 1.543 + ctx->priv->alg_priv->cpi = optr; 1.544 + } 1.545 + } 1.546 + 1.547 + return res; 1.548 +} 1.549 + 1.550 + 1.551 +static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx, 1.552 + vpx_codec_priv_enc_mr_cfg_t *data) { 1.553 + return vp9e_common_init(ctx, 0); 1.554 +} 1.555 + 1.556 + 1.557 +#if CONFIG_EXPERIMENTAL 1.558 +static vpx_codec_err_t vp9e_exp_init(vpx_codec_ctx_t *ctx, 1.559 + vpx_codec_priv_enc_mr_cfg_t *data) { 1.560 + return vp9e_common_init(ctx, 1); 1.561 +} 1.562 +#endif 1.563 + 1.564 + 1.565 +static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) { 1.566 + free(ctx->cx_data); 1.567 + vp9_remove_compressor(&ctx->cpi); 1.568 + free(ctx); 1.569 + return VPX_CODEC_OK; 1.570 +} 1.571 + 1.572 +static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx, 1.573 + unsigned long duration, 1.574 + unsigned long deadline) { 1.575 + unsigned int new_qc; 1.576 + 1.577 + /* Use best quality mode if no deadline is given. */ 1.578 + if (deadline) 1.579 + new_qc = MODE_GOODQUALITY; 1.580 + else 1.581 + new_qc = MODE_BESTQUALITY; 1.582 + 1.583 + if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS) 1.584 + new_qc = MODE_FIRSTPASS; 1.585 + else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS) 1.586 + new_qc = (new_qc == MODE_BESTQUALITY) 1.587 + ? MODE_SECONDPASS_BEST 1.588 + : MODE_SECONDPASS; 1.589 + 1.590 + if (ctx->oxcf.Mode != new_qc) { 1.591 + ctx->oxcf.Mode = new_qc; 1.592 + vp9_change_config(ctx->cpi, &ctx->oxcf); 1.593 + } 1.594 +} 1.595 + 1.596 + 1.597 +static int write_superframe_index(vpx_codec_alg_priv_t *ctx) { 1.598 + uint8_t marker = 0xc0; 1.599 + unsigned int mask; 1.600 + int mag, index_sz; 1.601 + 1.602 + assert(ctx->pending_frame_count); 1.603 + assert(ctx->pending_frame_count <= 8); 1.604 + 1.605 + /* Add the number of frames to the marker byte */ 1.606 + marker |= ctx->pending_frame_count - 1; 1.607 + 1.608 + /* Choose the magnitude */ 1.609 + for (mag = 0, mask = 0xff; mag < 4; mag++) { 1.610 + if (ctx->pending_frame_magnitude < mask) 1.611 + break; 1.612 + mask <<= 8; 1.613 + mask |= 0xff; 1.614 + } 1.615 + marker |= mag << 3; 1.616 + 1.617 + /* Write the index */ 1.618 + index_sz = 2 + (mag + 1) * ctx->pending_frame_count; 1.619 + if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) { 1.620 + uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz; 1.621 + int i, j; 1.622 + 1.623 + *x++ = marker; 1.624 + for (i = 0; i < ctx->pending_frame_count; i++) { 1.625 + int this_sz = ctx->pending_frame_sizes[i]; 1.626 + 1.627 + for (j = 0; j <= mag; j++) { 1.628 + *x++ = this_sz & 0xff; 1.629 + this_sz >>= 8; 1.630 + } 1.631 + } 1.632 + *x++ = marker; 1.633 + ctx->pending_cx_data_sz += index_sz; 1.634 + } 1.635 + return index_sz; 1.636 +} 1.637 + 1.638 +static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t *ctx, 1.639 + const vpx_image_t *img, 1.640 + vpx_codec_pts_t pts, 1.641 + unsigned long duration, 1.642 + vpx_enc_frame_flags_t flags, 1.643 + unsigned long deadline) { 1.644 + vpx_codec_err_t res = VPX_CODEC_OK; 1.645 + 1.646 + if (img) 1.647 + res = validate_img(ctx, img); 1.648 + 1.649 + pick_quickcompress_mode(ctx, duration, deadline); 1.650 + vpx_codec_pkt_list_init(&ctx->pkt_list); 1.651 + 1.652 + /* Handle Flags */ 1.653 + if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) 1.654 + || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) { 1.655 + ctx->base.err_detail = "Conflicting flags."; 1.656 + return VPX_CODEC_INVALID_PARAM; 1.657 + } 1.658 + 1.659 + if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF 1.660 + | VP8_EFLAG_NO_REF_ARF)) { 1.661 + int ref = 7; 1.662 + 1.663 + if (flags & VP8_EFLAG_NO_REF_LAST) 1.664 + ref ^= VP9_LAST_FLAG; 1.665 + 1.666 + if (flags & VP8_EFLAG_NO_REF_GF) 1.667 + ref ^= VP9_GOLD_FLAG; 1.668 + 1.669 + if (flags & VP8_EFLAG_NO_REF_ARF) 1.670 + ref ^= VP9_ALT_FLAG; 1.671 + 1.672 + vp9_use_as_reference(ctx->cpi, ref); 1.673 + } 1.674 + 1.675 + if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF 1.676 + | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF 1.677 + | VP8_EFLAG_FORCE_ARF)) { 1.678 + int upd = 7; 1.679 + 1.680 + if (flags & VP8_EFLAG_NO_UPD_LAST) 1.681 + upd ^= VP9_LAST_FLAG; 1.682 + 1.683 + if (flags & VP8_EFLAG_NO_UPD_GF) 1.684 + upd ^= VP9_GOLD_FLAG; 1.685 + 1.686 + if (flags & VP8_EFLAG_NO_UPD_ARF) 1.687 + upd ^= VP9_ALT_FLAG; 1.688 + 1.689 + vp9_update_reference(ctx->cpi, upd); 1.690 + } 1.691 + 1.692 + if (flags & VP8_EFLAG_NO_UPD_ENTROPY) { 1.693 + vp9_update_entropy(ctx->cpi, 0); 1.694 + } 1.695 + 1.696 + /* Handle fixed keyframe intervals */ 1.697 + if (ctx->cfg.kf_mode == VPX_KF_AUTO 1.698 + && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) { 1.699 + if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) { 1.700 + flags |= VPX_EFLAG_FORCE_KF; 1.701 + ctx->fixed_kf_cntr = 1; 1.702 + } 1.703 + } 1.704 + 1.705 + /* Initialize the encoder instance on the first frame*/ 1.706 + if (!res && ctx->cpi) { 1.707 + unsigned int lib_flags; 1.708 + YV12_BUFFER_CONFIG sd; 1.709 + int64_t dst_time_stamp, dst_end_time_stamp; 1.710 + unsigned long size, cx_data_sz; 1.711 + unsigned char *cx_data; 1.712 + 1.713 + /* Set up internal flags */ 1.714 + if (ctx->base.init_flags & VPX_CODEC_USE_PSNR) 1.715 + ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1; 1.716 + 1.717 + // if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION) 1.718 + // ((VP9_COMP *)ctx->cpi)->output_partition = 1; 1.719 + 1.720 + /* Convert API flags to internal codec lib flags */ 1.721 + lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0; 1.722 + 1.723 + /* vp8 use 10,000,000 ticks/second as time stamp */ 1.724 + dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num 1.725 + / ctx->cfg.g_timebase.den; 1.726 + dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / 1.727 + ctx->cfg.g_timebase.den; 1.728 + 1.729 + if (img != NULL) { 1.730 + res = image2yuvconfig(img, &sd); 1.731 + 1.732 + if (vp9_receive_raw_frame(ctx->cpi, lib_flags, 1.733 + &sd, dst_time_stamp, dst_end_time_stamp)) { 1.734 + VP9_COMP *cpi = (VP9_COMP *)ctx->cpi; 1.735 + res = update_error_state(ctx, &cpi->common.error); 1.736 + } 1.737 + } 1.738 + 1.739 + cx_data = ctx->cx_data; 1.740 + cx_data_sz = ctx->cx_data_sz; 1.741 + lib_flags = 0; 1.742 + 1.743 + /* Any pending invisible frames? */ 1.744 + if (ctx->pending_cx_data) { 1.745 + memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz); 1.746 + ctx->pending_cx_data = cx_data; 1.747 + cx_data += ctx->pending_cx_data_sz; 1.748 + cx_data_sz -= ctx->pending_cx_data_sz; 1.749 + 1.750 + /* TODO: this is a minimal check, the underlying codec doesn't respect 1.751 + * the buffer size anyway. 1.752 + */ 1.753 + if (cx_data_sz < ctx->cx_data_sz / 2) { 1.754 + ctx->base.err_detail = "Compressed data buffer too small"; 1.755 + return VPX_CODEC_ERROR; 1.756 + } 1.757 + } 1.758 + 1.759 + while (cx_data_sz >= ctx->cx_data_sz / 2 && 1.760 + -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size, 1.761 + cx_data, &dst_time_stamp, 1.762 + &dst_end_time_stamp, !img)) { 1.763 + if (size) { 1.764 + vpx_codec_pts_t round, delta; 1.765 + vpx_codec_cx_pkt_t pkt; 1.766 + VP9_COMP *cpi = (VP9_COMP *)ctx->cpi; 1.767 + 1.768 + /* Pack invisible frames with the next visible frame */ 1.769 + if (!cpi->common.show_frame) { 1.770 + if (!ctx->pending_cx_data) 1.771 + ctx->pending_cx_data = cx_data; 1.772 + ctx->pending_cx_data_sz += size; 1.773 + ctx->pending_frame_sizes[ctx->pending_frame_count++] = size; 1.774 + ctx->pending_frame_magnitude |= size; 1.775 + cx_data += size; 1.776 + cx_data_sz -= size; 1.777 + continue; 1.778 + } 1.779 + 1.780 + /* Add the frame packet to the list of returned packets. */ 1.781 + round = (vpx_codec_pts_t)1000000 * ctx->cfg.g_timebase.num / 2 - 1; 1.782 + delta = (dst_end_time_stamp - dst_time_stamp); 1.783 + pkt.kind = VPX_CODEC_CX_FRAME_PKT; 1.784 + pkt.data.frame.pts = 1.785 + (dst_time_stamp * ctx->cfg.g_timebase.den + round) 1.786 + / ctx->cfg.g_timebase.num / 10000000; 1.787 + pkt.data.frame.duration = (unsigned long) 1.788 + ((delta * ctx->cfg.g_timebase.den + round) 1.789 + / ctx->cfg.g_timebase.num / 10000000); 1.790 + pkt.data.frame.flags = lib_flags << 16; 1.791 + 1.792 + if (lib_flags & FRAMEFLAGS_KEY) 1.793 + pkt.data.frame.flags |= VPX_FRAME_IS_KEY; 1.794 + 1.795 + if (!cpi->common.show_frame) { 1.796 + pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE; 1.797 + 1.798 + // This timestamp should be as close as possible to the 1.799 + // prior PTS so that if a decoder uses pts to schedule when 1.800 + // to do this, we start right after last frame was decoded. 1.801 + // Invisible frames have no duration. 1.802 + pkt.data.frame.pts = ((cpi->last_time_stamp_seen 1.803 + * ctx->cfg.g_timebase.den + round) 1.804 + / ctx->cfg.g_timebase.num / 10000000) + 1; 1.805 + pkt.data.frame.duration = 0; 1.806 + } 1.807 + 1.808 + if (cpi->droppable) 1.809 + pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE; 1.810 + 1.811 + /*if (cpi->output_partition) 1.812 + { 1.813 + int i; 1.814 + const int num_partitions = 1; 1.815 + 1.816 + pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT; 1.817 + 1.818 + for (i = 0; i < num_partitions; ++i) 1.819 + { 1.820 + pkt.data.frame.buf = cx_data; 1.821 + pkt.data.frame.sz = cpi->partition_sz[i]; 1.822 + pkt.data.frame.partition_id = i; 1.823 + // don't set the fragment bit for the last partition 1.824 + if (i == (num_partitions - 1)) 1.825 + pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT; 1.826 + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); 1.827 + cx_data += cpi->partition_sz[i]; 1.828 + cx_data_sz -= cpi->partition_sz[i]; 1.829 + } 1.830 + } 1.831 + else*/ 1.832 + { 1.833 + if (ctx->pending_cx_data) { 1.834 + ctx->pending_frame_sizes[ctx->pending_frame_count++] = size; 1.835 + ctx->pending_frame_magnitude |= size; 1.836 + ctx->pending_cx_data_sz += size; 1.837 + size += write_superframe_index(ctx); 1.838 + pkt.data.frame.buf = ctx->pending_cx_data; 1.839 + pkt.data.frame.sz = ctx->pending_cx_data_sz; 1.840 + ctx->pending_cx_data = NULL; 1.841 + ctx->pending_cx_data_sz = 0; 1.842 + ctx->pending_frame_count = 0; 1.843 + ctx->pending_frame_magnitude = 0; 1.844 + } else { 1.845 + pkt.data.frame.buf = cx_data; 1.846 + pkt.data.frame.sz = size; 1.847 + } 1.848 + pkt.data.frame.partition_id = -1; 1.849 + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); 1.850 + cx_data += size; 1.851 + cx_data_sz -= size; 1.852 + } 1.853 + } 1.854 + } 1.855 + } 1.856 + 1.857 + return res; 1.858 +} 1.859 + 1.860 + 1.861 +static const vpx_codec_cx_pkt_t *vp9e_get_cxdata(vpx_codec_alg_priv_t *ctx, 1.862 + vpx_codec_iter_t *iter) { 1.863 + return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter); 1.864 +} 1.865 + 1.866 +static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx, 1.867 + int ctr_id, 1.868 + va_list args) { 1.869 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.870 + 1.871 + if (data) { 1.872 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.873 + YV12_BUFFER_CONFIG sd; 1.874 + 1.875 + image2yuvconfig(&frame->img, &sd); 1.876 + vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type), 1.877 + &sd); 1.878 + return VPX_CODEC_OK; 1.879 + } else { 1.880 + return VPX_CODEC_INVALID_PARAM; 1.881 + } 1.882 +} 1.883 + 1.884 +static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx, 1.885 + int ctr_id, 1.886 + va_list args) { 1.887 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.888 + 1.889 + if (data) { 1.890 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.891 + YV12_BUFFER_CONFIG sd; 1.892 + 1.893 + image2yuvconfig(&frame->img, &sd); 1.894 + vp9_copy_reference_enc(ctx->cpi, 1.895 + ref_frame_to_vp9_reframe(frame->frame_type), &sd); 1.896 + return VPX_CODEC_OK; 1.897 + } else { 1.898 + return VPX_CODEC_INVALID_PARAM; 1.899 + } 1.900 +} 1.901 + 1.902 +static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx, 1.903 + int ctr_id, 1.904 + va_list args) { 1.905 + vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); 1.906 + 1.907 + if (data) { 1.908 + YV12_BUFFER_CONFIG* fb; 1.909 + 1.910 + vp9_get_reference_enc(ctx->cpi, data->idx, &fb); 1.911 + yuvconfig2image(&data->img, fb, NULL); 1.912 + return VPX_CODEC_OK; 1.913 + } else { 1.914 + return VPX_CODEC_INVALID_PARAM; 1.915 + } 1.916 +} 1.917 + 1.918 +static vpx_codec_err_t vp9e_set_previewpp(vpx_codec_alg_priv_t *ctx, 1.919 + int ctr_id, 1.920 + va_list args) { 1.921 +#if CONFIG_VP9_POSTPROC 1.922 + vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *); 1.923 + (void)ctr_id; 1.924 + 1.925 + if (data) { 1.926 + ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data); 1.927 + return VPX_CODEC_OK; 1.928 + } else { 1.929 + return VPX_CODEC_INVALID_PARAM; 1.930 + } 1.931 +#else 1.932 + (void)ctx; 1.933 + (void)ctr_id; 1.934 + (void)args; 1.935 + return VPX_CODEC_INCAPABLE; 1.936 +#endif 1.937 +} 1.938 + 1.939 + 1.940 +static vpx_image_t *vp9e_get_preview(vpx_codec_alg_priv_t *ctx) { 1.941 + YV12_BUFFER_CONFIG sd; 1.942 + vp9_ppflags_t flags = {0}; 1.943 + 1.944 + if (ctx->preview_ppcfg.post_proc_flag) { 1.945 + flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag; 1.946 + flags.deblocking_level = ctx->preview_ppcfg.deblocking_level; 1.947 + flags.noise_level = ctx->preview_ppcfg.noise_level; 1.948 + } 1.949 + 1.950 + if (0 == vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags)) { 1.951 + yuvconfig2image(&ctx->preview_img, &sd, NULL); 1.952 + return &ctx->preview_img; 1.953 + } else { 1.954 + return NULL; 1.955 + } 1.956 +} 1.957 + 1.958 +static vpx_codec_err_t vp9e_update_entropy(vpx_codec_alg_priv_t *ctx, 1.959 + int ctr_id, 1.960 + va_list args) { 1.961 + int update = va_arg(args, int); 1.962 + vp9_update_entropy(ctx->cpi, update); 1.963 + return VPX_CODEC_OK; 1.964 +} 1.965 + 1.966 +static vpx_codec_err_t vp9e_update_reference(vpx_codec_alg_priv_t *ctx, 1.967 + int ctr_id, 1.968 + va_list args) { 1.969 + int update = va_arg(args, int); 1.970 + vp9_update_reference(ctx->cpi, update); 1.971 + return VPX_CODEC_OK; 1.972 +} 1.973 + 1.974 +static vpx_codec_err_t vp9e_use_reference(vpx_codec_alg_priv_t *ctx, 1.975 + int ctr_id, 1.976 + va_list args) { 1.977 + int reference_flag = va_arg(args, int); 1.978 + vp9_use_as_reference(ctx->cpi, reference_flag); 1.979 + return VPX_CODEC_OK; 1.980 +} 1.981 + 1.982 +static vpx_codec_err_t vp9e_set_roi_map(vpx_codec_alg_priv_t *ctx, 1.983 + int ctr_id, 1.984 + va_list args) { 1.985 + // TODO(yaowu): Need to re-implement and test for VP9. 1.986 + return VPX_CODEC_INVALID_PARAM; 1.987 +} 1.988 + 1.989 + 1.990 +static vpx_codec_err_t vp9e_set_activemap(vpx_codec_alg_priv_t *ctx, 1.991 + int ctr_id, 1.992 + va_list args) { 1.993 + // TODO(yaowu): Need to re-implement and test for VP9. 1.994 + return VPX_CODEC_INVALID_PARAM; 1.995 +} 1.996 + 1.997 +static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx, 1.998 + int ctr_id, 1.999 + va_list args) { 1.1000 + vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *); 1.1001 + 1.1002 + if (data) { 1.1003 + int res; 1.1004 + vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data; 1.1005 + res = vp9_set_internal_size(ctx->cpi, 1.1006 + (VPX_SCALING)scalemode.h_scaling_mode, 1.1007 + (VPX_SCALING)scalemode.v_scaling_mode); 1.1008 + 1.1009 + if (!res) { 1.1010 + return VPX_CODEC_OK; 1.1011 + } else { 1.1012 + return VPX_CODEC_INVALID_PARAM; 1.1013 + } 1.1014 + } else { 1.1015 + return VPX_CODEC_INVALID_PARAM; 1.1016 + } 1.1017 +} 1.1018 + 1.1019 +static vpx_codec_err_t vp9e_set_svc(vpx_codec_alg_priv_t *ctx, int ctr_id, 1.1020 + va_list args) { 1.1021 + int data = va_arg(args, int); 1.1022 + vp9_set_svc(ctx->cpi, data); 1.1023 + return VPX_CODEC_OK; 1.1024 +} 1.1025 + 1.1026 +static vpx_codec_err_t vp9e_set_svc_parameters(vpx_codec_alg_priv_t *ctx, 1.1027 + int ctr_id, va_list args) { 1.1028 + vpx_svc_parameters_t *data = va_arg(args, vpx_svc_parameters_t *); 1.1029 + VP9_COMP *cpi = (VP9_COMP *)ctx->cpi; 1.1030 + vpx_svc_parameters_t params; 1.1031 + 1.1032 + if (data == NULL) { 1.1033 + return VPX_CODEC_INVALID_PARAM; 1.1034 + } 1.1035 + 1.1036 + params = *(vpx_svc_parameters_t *)data; 1.1037 + 1.1038 + cpi->current_layer = params.layer; 1.1039 + cpi->lst_fb_idx = params.lst_fb_idx; 1.1040 + cpi->gld_fb_idx = params.gld_fb_idx; 1.1041 + cpi->alt_fb_idx = params.alt_fb_idx; 1.1042 + 1.1043 + if (vp9_set_size_literal(ctx->cpi, params.width, params.height) != 0) { 1.1044 + return VPX_CODEC_INVALID_PARAM; 1.1045 + } 1.1046 + 1.1047 + ctx->cfg.rc_max_quantizer = params.max_quantizer; 1.1048 + ctx->cfg.rc_min_quantizer = params.min_quantizer; 1.1049 + 1.1050 + set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg); 1.1051 + vp9_change_config(ctx->cpi, &ctx->oxcf); 1.1052 + 1.1053 + return VPX_CODEC_OK; 1.1054 +} 1.1055 + 1.1056 +static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps[] = { 1.1057 + {VP8_SET_REFERENCE, vp9e_set_reference}, 1.1058 + {VP8_COPY_REFERENCE, vp9e_copy_reference}, 1.1059 + {VP8_SET_POSTPROC, vp9e_set_previewpp}, 1.1060 + {VP8E_UPD_ENTROPY, vp9e_update_entropy}, 1.1061 + {VP8E_UPD_REFERENCE, vp9e_update_reference}, 1.1062 + {VP8E_USE_REFERENCE, vp9e_use_reference}, 1.1063 + {VP8E_SET_ROI_MAP, vp9e_set_roi_map}, 1.1064 + {VP8E_SET_ACTIVEMAP, vp9e_set_activemap}, 1.1065 + {VP8E_SET_SCALEMODE, vp9e_set_scalemode}, 1.1066 + {VP8E_SET_CPUUSED, set_param}, 1.1067 + {VP8E_SET_NOISE_SENSITIVITY, set_param}, 1.1068 + {VP8E_SET_ENABLEAUTOALTREF, set_param}, 1.1069 + {VP8E_SET_SHARPNESS, set_param}, 1.1070 + {VP8E_SET_STATIC_THRESHOLD, set_param}, 1.1071 + {VP9E_SET_TILE_COLUMNS, set_param}, 1.1072 + {VP9E_SET_TILE_ROWS, set_param}, 1.1073 + {VP8E_GET_LAST_QUANTIZER, get_param}, 1.1074 + {VP8E_GET_LAST_QUANTIZER_64, get_param}, 1.1075 + {VP8E_SET_ARNR_MAXFRAMES, set_param}, 1.1076 + {VP8E_SET_ARNR_STRENGTH, set_param}, 1.1077 + {VP8E_SET_ARNR_TYPE, set_param}, 1.1078 + {VP8E_SET_TUNING, set_param}, 1.1079 + {VP8E_SET_CQ_LEVEL, set_param}, 1.1080 + {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param}, 1.1081 + {VP9E_SET_LOSSLESS, set_param}, 1.1082 + {VP9E_SET_FRAME_PARALLEL_DECODING, set_param}, 1.1083 + {VP9E_SET_AQ_MODE, set_param}, 1.1084 + {VP9_GET_REFERENCE, get_reference}, 1.1085 + {VP9E_SET_SVC, vp9e_set_svc}, 1.1086 + {VP9E_SET_SVC_PARAMETERS, vp9e_set_svc_parameters}, 1.1087 + { -1, NULL}, 1.1088 +}; 1.1089 + 1.1090 +static vpx_codec_enc_cfg_map_t vp9e_usage_cfg_map[] = { 1.1091 + { 1.1092 + 0, 1.1093 + { // NOLINT 1.1094 + 0, /* g_usage */ 1.1095 + 0, /* g_threads */ 1.1096 + 0, /* g_profile */ 1.1097 + 1.1098 + 320, /* g_width */ 1.1099 + 240, /* g_height */ 1.1100 + {1, 30}, /* g_timebase */ 1.1101 + 1.1102 + 0, /* g_error_resilient */ 1.1103 + 1.1104 + VPX_RC_ONE_PASS, /* g_pass */ 1.1105 + 1.1106 + 25, /* g_lag_in_frames */ 1.1107 + 1.1108 + 0, /* rc_dropframe_thresh */ 1.1109 + 0, /* rc_resize_allowed */ 1.1110 + 60, /* rc_resize_down_thresold */ 1.1111 + 30, /* rc_resize_up_thresold */ 1.1112 + 1.1113 + VPX_VBR, /* rc_end_usage */ 1.1114 +#if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION) 1.1115 + {0}, /* rc_twopass_stats_in */ 1.1116 +#endif 1.1117 + 256, /* rc_target_bandwidth */ 1.1118 + 0, /* rc_min_quantizer */ 1.1119 + 63, /* rc_max_quantizer */ 1.1120 + 100, /* rc_undershoot_pct */ 1.1121 + 100, /* rc_overshoot_pct */ 1.1122 + 1.1123 + 6000, /* rc_max_buffer_size */ 1.1124 + 4000, /* rc_buffer_initial_size; */ 1.1125 + 5000, /* rc_buffer_optimal_size; */ 1.1126 + 1.1127 + 50, /* rc_two_pass_vbrbias */ 1.1128 + 0, /* rc_two_pass_vbrmin_section */ 1.1129 + 2000, /* rc_two_pass_vbrmax_section */ 1.1130 + 1.1131 + /* keyframing settings (kf) */ 1.1132 + VPX_KF_AUTO, /* g_kfmode*/ 1.1133 + 0, /* kf_min_dist */ 1.1134 + 9999, /* kf_max_dist */ 1.1135 + 1.1136 + VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */ 1.1137 + 1.1138 +#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION) 1.1139 + 1, /* g_delete_first_pass_file */ 1.1140 + "vp8.fpf" /* first pass filename */ 1.1141 +#endif 1.1142 + } 1.1143 + }, 1.1144 + { -1, {NOT_IMPLEMENTED}} 1.1145 +}; 1.1146 + 1.1147 + 1.1148 +#ifndef VERSION_STRING 1.1149 +#define VERSION_STRING 1.1150 +#endif 1.1151 +CODEC_INTERFACE(vpx_codec_vp9_cx) = { 1.1152 + "WebM Project VP9 Encoder" VERSION_STRING, 1.1153 + VPX_CODEC_INTERNAL_ABI_VERSION, 1.1154 + VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR | 1.1155 + VPX_CODEC_CAP_OUTPUT_PARTITION, 1.1156 + /* vpx_codec_caps_t caps; */ 1.1157 + vp9e_init, /* vpx_codec_init_fn_t init; */ 1.1158 + vp9e_destroy, /* vpx_codec_destroy_fn_t destroy; */ 1.1159 + vp9e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 1.1160 + NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */ 1.1161 + NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */ 1.1162 + { // NOLINT 1.1163 + NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */ 1.1164 + NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */ 1.1165 + NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */ 1.1166 + NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */ 1.1167 + }, 1.1168 + { // NOLINT 1.1169 + vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */ 1.1170 + vp9e_encode, /* vpx_codec_encode_fn_t encode; */ 1.1171 + vp9e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */ 1.1172 + vp9e_set_config, 1.1173 + NOT_IMPLEMENTED, 1.1174 + vp9e_get_preview, 1.1175 + } /* encoder functions */ 1.1176 +}; 1.1177 + 1.1178 + 1.1179 +#if CONFIG_EXPERIMENTAL 1.1180 + 1.1181 +CODEC_INTERFACE(vpx_codec_vp9x_cx) = { 1.1182 + "VP8 Experimental Encoder" VERSION_STRING, 1.1183 + VPX_CODEC_INTERNAL_ABI_VERSION, 1.1184 + VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR, 1.1185 + /* vpx_codec_caps_t caps; */ 1.1186 + vp9e_exp_init, /* vpx_codec_init_fn_t init; */ 1.1187 + vp9e_destroy, /* vpx_codec_destroy_fn_t destroy; */ 1.1188 + vp9e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 1.1189 + NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */ 1.1190 + NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */ 1.1191 + { // NOLINT 1.1192 + NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */ 1.1193 + NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */ 1.1194 + NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */ 1.1195 + NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */ 1.1196 + }, 1.1197 + { // NOLINT 1.1198 + vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */ 1.1199 + vp9e_encode, /* vpx_codec_encode_fn_t encode; */ 1.1200 + vp9e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */ 1.1201 + vp9e_set_config, 1.1202 + NOT_IMPLEMENTED, 1.1203 + vp9e_get_preview, 1.1204 + } /* encoder functions */ 1.1205 +}; 1.1206 +#endif