1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp8/vp8_cx_iface.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1313 @@ 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 + 1.15 +#include "vp8_rtcd.h" 1.16 +#include "vpx/vpx_codec.h" 1.17 +#include "vpx/internal/vpx_codec_internal.h" 1.18 +#include "vpx_version.h" 1.19 +#include "vp8/encoder/onyx_int.h" 1.20 +#include "vpx/vp8cx.h" 1.21 +#include "vp8/encoder/firstpass.h" 1.22 +#include "vp8/common/onyx.h" 1.23 +#include <stdlib.h> 1.24 +#include <string.h> 1.25 + 1.26 +struct vp8_extracfg 1.27 +{ 1.28 + struct vpx_codec_pkt_list *pkt_list; 1.29 + int cpu_used; /** available cpu percentage in 1/16*/ 1.30 + unsigned int enable_auto_alt_ref; /** if encoder decides to uses alternate reference frame */ 1.31 + unsigned int noise_sensitivity; 1.32 + unsigned int Sharpness; 1.33 + unsigned int static_thresh; 1.34 + unsigned int token_partitions; 1.35 + unsigned int arnr_max_frames; /* alt_ref Noise Reduction Max Frame Count */ 1.36 + unsigned int arnr_strength; /* alt_ref Noise Reduction Strength */ 1.37 + unsigned int arnr_type; /* alt_ref filter type */ 1.38 + vp8e_tuning tuning; 1.39 + unsigned int cq_level; /* constrained quality level */ 1.40 + unsigned int rc_max_intra_bitrate_pct; 1.41 + 1.42 +}; 1.43 + 1.44 +struct extraconfig_map 1.45 +{ 1.46 + int usage; 1.47 + struct vp8_extracfg cfg; 1.48 +}; 1.49 + 1.50 +static const struct extraconfig_map extracfg_map[] = 1.51 +{ 1.52 + { 1.53 + 0, 1.54 + { 1.55 + NULL, 1.56 +#if !(CONFIG_REALTIME_ONLY) 1.57 + 0, /* cpu_used */ 1.58 +#else 1.59 + 4, /* cpu_used */ 1.60 +#endif 1.61 + 0, /* enable_auto_alt_ref */ 1.62 + 0, /* noise_sensitivity */ 1.63 + 0, /* Sharpness */ 1.64 + 0, /* static_thresh */ 1.65 +#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) 1.66 + VP8_EIGHT_TOKENPARTITION, 1.67 +#else 1.68 + VP8_ONE_TOKENPARTITION, /* token_partitions */ 1.69 +#endif 1.70 + 0, /* arnr_max_frames */ 1.71 + 3, /* arnr_strength */ 1.72 + 3, /* arnr_type*/ 1.73 + 0, /* tuning*/ 1.74 + 10, /* cq_level */ 1.75 + 0, /* rc_max_intra_bitrate_pct */ 1.76 + } 1.77 + } 1.78 +}; 1.79 + 1.80 +struct vpx_codec_alg_priv 1.81 +{ 1.82 + vpx_codec_priv_t base; 1.83 + vpx_codec_enc_cfg_t cfg; 1.84 + struct vp8_extracfg vp8_cfg; 1.85 + VP8_CONFIG oxcf; 1.86 + struct VP8_COMP *cpi; 1.87 + unsigned char *cx_data; 1.88 + unsigned int cx_data_sz; 1.89 + vpx_image_t preview_img; 1.90 + unsigned int next_frame_flag; 1.91 + vp8_postproc_cfg_t preview_ppcfg; 1.92 + /* pkt_list size depends on the maximum number of lagged frames allowed. */ 1.93 + vpx_codec_pkt_list_decl(64) pkt_list; 1.94 + unsigned int fixed_kf_cntr; 1.95 +}; 1.96 + 1.97 + 1.98 +static vpx_codec_err_t 1.99 +update_error_state(vpx_codec_alg_priv_t *ctx, 1.100 + const struct vpx_internal_error_info *error) 1.101 +{ 1.102 + vpx_codec_err_t res; 1.103 + 1.104 + if ((res = error->error_code)) 1.105 + ctx->base.err_detail = error->has_detail 1.106 + ? error->detail 1.107 + : NULL; 1.108 + 1.109 + return res; 1.110 +} 1.111 + 1.112 + 1.113 +#undef ERROR 1.114 +#define ERROR(str) do {\ 1.115 + ctx->base.err_detail = str;\ 1.116 + return VPX_CODEC_INVALID_PARAM;\ 1.117 + } while(0) 1.118 + 1.119 +#define RANGE_CHECK(p,memb,lo,hi) do {\ 1.120 + if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \ 1.121 + ERROR(#memb " out of range ["#lo".."#hi"]");\ 1.122 + } while(0) 1.123 + 1.124 +#define RANGE_CHECK_HI(p,memb,hi) do {\ 1.125 + if(!((p)->memb <= (hi))) \ 1.126 + ERROR(#memb " out of range [.."#hi"]");\ 1.127 + } while(0) 1.128 + 1.129 +#define RANGE_CHECK_LO(p,memb,lo) do {\ 1.130 + if(!((p)->memb >= (lo))) \ 1.131 + ERROR(#memb " out of range ["#lo"..]");\ 1.132 + } while(0) 1.133 + 1.134 +#define RANGE_CHECK_BOOL(p,memb) do {\ 1.135 + if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\ 1.136 + } while(0) 1.137 + 1.138 +static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, 1.139 + const vpx_codec_enc_cfg_t *cfg, 1.140 + const struct vp8_extracfg *vp8_cfg, 1.141 + int finalize) 1.142 +{ 1.143 + RANGE_CHECK(cfg, g_w, 1, 16383); /* 14 bits available */ 1.144 + RANGE_CHECK(cfg, g_h, 1, 16383); /* 14 bits available */ 1.145 + RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000); 1.146 + RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den); 1.147 + RANGE_CHECK_HI(cfg, g_profile, 3); 1.148 + RANGE_CHECK_HI(cfg, rc_max_quantizer, 63); 1.149 + RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer); 1.150 + RANGE_CHECK_HI(cfg, g_threads, 64); 1.151 +#if CONFIG_REALTIME_ONLY 1.152 + RANGE_CHECK_HI(cfg, g_lag_in_frames, 0); 1.153 +#elif CONFIG_MULTI_RES_ENCODING 1.154 + if (ctx->base.enc.total_encoders > 1) 1.155 + RANGE_CHECK_HI(cfg, g_lag_in_frames, 0); 1.156 +#else 1.157 + RANGE_CHECK_HI(cfg, g_lag_in_frames, 25); 1.158 +#endif 1.159 + RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q); 1.160 + RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000); 1.161 + RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000); 1.162 + RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100); 1.163 + RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO); 1.164 + 1.165 +/* TODO: add spatial re-sampling support and frame dropping in 1.166 + * multi-res-encoder.*/ 1.167 +#if CONFIG_MULTI_RES_ENCODING 1.168 + if (ctx->base.enc.total_encoders > 1) 1.169 + RANGE_CHECK_HI(cfg, rc_resize_allowed, 0); 1.170 +#else 1.171 + RANGE_CHECK_BOOL(cfg, rc_resize_allowed); 1.172 +#endif 1.173 + RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100); 1.174 + RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100); 1.175 + RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100); 1.176 + 1.177 +#if CONFIG_REALTIME_ONLY 1.178 + RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS); 1.179 +#elif CONFIG_MULTI_RES_ENCODING 1.180 + if (ctx->base.enc.total_encoders > 1) 1.181 + RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS); 1.182 +#else 1.183 + RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS); 1.184 +#endif 1.185 + 1.186 + /* VP8 does not support a lower bound on the keyframe interval in 1.187 + * automatic keyframe placement mode. 1.188 + */ 1.189 + if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist 1.190 + && cfg->kf_min_dist > 0) 1.191 + ERROR("kf_min_dist not supported in auto mode, use 0 " 1.192 + "or kf_max_dist instead."); 1.193 + 1.194 + RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref); 1.195 + RANGE_CHECK(vp8_cfg, cpu_used, -16, 16); 1.196 + 1.197 +#if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING 1.198 + RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0); 1.199 +#else 1.200 + RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6); 1.201 +#endif 1.202 + 1.203 + RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION, 1.204 + VP8_EIGHT_TOKENPARTITION); 1.205 + RANGE_CHECK_HI(vp8_cfg, Sharpness, 7); 1.206 + RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15); 1.207 + RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6); 1.208 + RANGE_CHECK(vp8_cfg, arnr_type, 1, 3); 1.209 + RANGE_CHECK(vp8_cfg, cq_level, 0, 63); 1.210 + if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q)) 1.211 + RANGE_CHECK(vp8_cfg, cq_level, 1.212 + cfg->rc_min_quantizer, cfg->rc_max_quantizer); 1.213 + 1.214 +#if !(CONFIG_REALTIME_ONLY) 1.215 + if (cfg->g_pass == VPX_RC_LAST_PASS) 1.216 + { 1.217 + size_t packet_sz = sizeof(FIRSTPASS_STATS); 1.218 + int n_packets = (int)(cfg->rc_twopass_stats_in.sz / 1.219 + packet_sz); 1.220 + FIRSTPASS_STATS *stats; 1.221 + 1.222 + if (!cfg->rc_twopass_stats_in.buf) 1.223 + ERROR("rc_twopass_stats_in.buf not set."); 1.224 + 1.225 + if (cfg->rc_twopass_stats_in.sz % packet_sz) 1.226 + ERROR("rc_twopass_stats_in.sz indicates truncated packet."); 1.227 + 1.228 + if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz) 1.229 + ERROR("rc_twopass_stats_in requires at least two packets."); 1.230 + 1.231 + stats = (void*)((char *)cfg->rc_twopass_stats_in.buf 1.232 + + (n_packets - 1) * packet_sz); 1.233 + 1.234 + if ((int)(stats->count + 0.5) != n_packets - 1) 1.235 + ERROR("rc_twopass_stats_in missing EOS stats packet"); 1.236 + } 1.237 +#endif 1.238 + 1.239 + RANGE_CHECK(cfg, ts_number_layers, 1, 5); 1.240 + 1.241 + if (cfg->ts_number_layers > 1) 1.242 + { 1.243 + unsigned int i; 1.244 + RANGE_CHECK_HI(cfg, ts_periodicity, 16); 1.245 + 1.246 + for (i=1; i<cfg->ts_number_layers; i++) 1.247 + if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1]) 1.248 + ERROR("ts_target_bitrate entries are not strictly increasing"); 1.249 + 1.250 + RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1); 1.251 + for (i=cfg->ts_number_layers-2; i>0; i--) 1.252 + if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i]) 1.253 + ERROR("ts_rate_decimator factors are not powers of 2"); 1.254 + 1.255 + RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers-1); 1.256 + } 1.257 + 1.258 +#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) 1.259 + if(cfg->g_threads > (1 << vp8_cfg->token_partitions)) 1.260 + ERROR("g_threads cannot be bigger than number of token partitions"); 1.261 +#endif 1.262 + 1.263 + return VPX_CODEC_OK; 1.264 +} 1.265 + 1.266 + 1.267 +static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, 1.268 + const vpx_image_t *img) 1.269 +{ 1.270 + switch (img->fmt) 1.271 + { 1.272 + case VPX_IMG_FMT_YV12: 1.273 + case VPX_IMG_FMT_I420: 1.274 + case VPX_IMG_FMT_VPXI420: 1.275 + case VPX_IMG_FMT_VPXYV12: 1.276 + break; 1.277 + default: 1.278 + ERROR("Invalid image format. Only YV12 and I420 images are supported"); 1.279 + } 1.280 + 1.281 + if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h)) 1.282 + ERROR("Image size must match encoder init configuration size"); 1.283 + 1.284 + return VPX_CODEC_OK; 1.285 +} 1.286 + 1.287 + 1.288 +static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf, 1.289 + vpx_codec_enc_cfg_t cfg, 1.290 + struct vp8_extracfg vp8_cfg, 1.291 + vpx_codec_priv_enc_mr_cfg_t *mr_cfg) 1.292 +{ 1.293 + oxcf->multi_threaded = cfg.g_threads; 1.294 + oxcf->Version = cfg.g_profile; 1.295 + 1.296 + oxcf->Width = cfg.g_w; 1.297 + oxcf->Height = cfg.g_h; 1.298 + oxcf->timebase = cfg.g_timebase; 1.299 + 1.300 + oxcf->error_resilient_mode = cfg.g_error_resilient; 1.301 + 1.302 + switch (cfg.g_pass) 1.303 + { 1.304 + case VPX_RC_ONE_PASS: 1.305 + oxcf->Mode = MODE_BESTQUALITY; 1.306 + break; 1.307 + case VPX_RC_FIRST_PASS: 1.308 + oxcf->Mode = MODE_FIRSTPASS; 1.309 + break; 1.310 + case VPX_RC_LAST_PASS: 1.311 + oxcf->Mode = MODE_SECONDPASS_BEST; 1.312 + break; 1.313 + } 1.314 + 1.315 + if (cfg.g_pass == VPX_RC_FIRST_PASS || cfg.g_pass == VPX_RC_ONE_PASS) 1.316 + { 1.317 + oxcf->allow_lag = 0; 1.318 + oxcf->lag_in_frames = 0; 1.319 + } 1.320 + else 1.321 + { 1.322 + oxcf->allow_lag = (cfg.g_lag_in_frames) > 0; 1.323 + oxcf->lag_in_frames = cfg.g_lag_in_frames; 1.324 + } 1.325 + 1.326 + oxcf->allow_df = (cfg.rc_dropframe_thresh > 0); 1.327 + oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh; 1.328 + 1.329 + oxcf->allow_spatial_resampling = cfg.rc_resize_allowed; 1.330 + oxcf->resample_up_water_mark = cfg.rc_resize_up_thresh; 1.331 + oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh; 1.332 + 1.333 + if (cfg.rc_end_usage == VPX_VBR) { 1.334 + oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK; 1.335 + } else if (cfg.rc_end_usage == VPX_CBR) { 1.336 + oxcf->end_usage = USAGE_STREAM_FROM_SERVER; 1.337 + } else if (cfg.rc_end_usage == VPX_CQ) { 1.338 + oxcf->end_usage = USAGE_CONSTRAINED_QUALITY; 1.339 + } else if (cfg.rc_end_usage == VPX_Q) { 1.340 + oxcf->end_usage = USAGE_CONSTANT_QUALITY; 1.341 + } 1.342 + 1.343 + oxcf->target_bandwidth = cfg.rc_target_bitrate; 1.344 + oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct; 1.345 + 1.346 + oxcf->best_allowed_q = cfg.rc_min_quantizer; 1.347 + oxcf->worst_allowed_q = cfg.rc_max_quantizer; 1.348 + oxcf->cq_level = vp8_cfg.cq_level; 1.349 + oxcf->fixed_q = -1; 1.350 + 1.351 + oxcf->under_shoot_pct = cfg.rc_undershoot_pct; 1.352 + oxcf->over_shoot_pct = cfg.rc_overshoot_pct; 1.353 + 1.354 + oxcf->maximum_buffer_size_in_ms = cfg.rc_buf_sz; 1.355 + oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz; 1.356 + oxcf->optimal_buffer_level_in_ms = cfg.rc_buf_optimal_sz; 1.357 + 1.358 + oxcf->maximum_buffer_size = cfg.rc_buf_sz; 1.359 + oxcf->starting_buffer_level = cfg.rc_buf_initial_sz; 1.360 + oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz; 1.361 + 1.362 + oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct; 1.363 + oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct; 1.364 + oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct; 1.365 + 1.366 + oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO 1.367 + && cfg.kf_min_dist != cfg.kf_max_dist; 1.368 + oxcf->key_freq = cfg.kf_max_dist; 1.369 + 1.370 + oxcf->number_of_layers = cfg.ts_number_layers; 1.371 + oxcf->periodicity = cfg.ts_periodicity; 1.372 + 1.373 + if (oxcf->number_of_layers > 1) 1.374 + { 1.375 + memcpy (oxcf->target_bitrate, cfg.ts_target_bitrate, 1.376 + sizeof(cfg.ts_target_bitrate)); 1.377 + memcpy (oxcf->rate_decimator, cfg.ts_rate_decimator, 1.378 + sizeof(cfg.ts_rate_decimator)); 1.379 + memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id)); 1.380 + } 1.381 + 1.382 +#if CONFIG_MULTI_RES_ENCODING 1.383 + /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id 1.384 + * are both memset to 0, which ensures the correct logic under this 1.385 + * situation. 1.386 + */ 1.387 + if(mr_cfg) 1.388 + { 1.389 + oxcf->mr_total_resolutions = mr_cfg->mr_total_resolutions; 1.390 + oxcf->mr_encoder_id = mr_cfg->mr_encoder_id; 1.391 + oxcf->mr_down_sampling_factor.num = mr_cfg->mr_down_sampling_factor.num; 1.392 + oxcf->mr_down_sampling_factor.den = mr_cfg->mr_down_sampling_factor.den; 1.393 + oxcf->mr_low_res_mode_info = mr_cfg->mr_low_res_mode_info; 1.394 + } 1.395 +#endif 1.396 + 1.397 + oxcf->cpu_used = vp8_cfg.cpu_used; 1.398 + oxcf->encode_breakout = vp8_cfg.static_thresh; 1.399 + oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref; 1.400 + oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity; 1.401 + oxcf->Sharpness = vp8_cfg.Sharpness; 1.402 + oxcf->token_partitions = vp8_cfg.token_partitions; 1.403 + 1.404 + oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in; 1.405 + oxcf->output_pkt_list = vp8_cfg.pkt_list; 1.406 + 1.407 + oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames; 1.408 + oxcf->arnr_strength = vp8_cfg.arnr_strength; 1.409 + oxcf->arnr_type = vp8_cfg.arnr_type; 1.410 + 1.411 + oxcf->tuning = vp8_cfg.tuning; 1.412 + 1.413 + /* 1.414 + printf("Current VP8 Settings: \n"); 1.415 + printf("target_bandwidth: %d\n", oxcf->target_bandwidth); 1.416 + printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity); 1.417 + printf("Sharpness: %d\n", oxcf->Sharpness); 1.418 + printf("cpu_used: %d\n", oxcf->cpu_used); 1.419 + printf("Mode: %d\n", oxcf->Mode); 1.420 + printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file); 1.421 + printf("auto_key: %d\n", oxcf->auto_key); 1.422 + printf("key_freq: %d\n", oxcf->key_freq); 1.423 + printf("end_usage: %d\n", oxcf->end_usage); 1.424 + printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct); 1.425 + printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct); 1.426 + printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level); 1.427 + printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level); 1.428 + printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size); 1.429 + printf("fixed_q: %d\n", oxcf->fixed_q); 1.430 + printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q); 1.431 + printf("best_allowed_q: %d\n", oxcf->best_allowed_q); 1.432 + printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling); 1.433 + printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark); 1.434 + printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark); 1.435 + printf("allow_df: %d\n", oxcf->allow_df); 1.436 + printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark); 1.437 + printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias); 1.438 + printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section); 1.439 + printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section); 1.440 + printf("allow_lag: %d\n", oxcf->allow_lag); 1.441 + printf("lag_in_frames: %d\n", oxcf->lag_in_frames); 1.442 + printf("play_alternate: %d\n", oxcf->play_alternate); 1.443 + printf("Version: %d\n", oxcf->Version); 1.444 + printf("multi_threaded: %d\n", oxcf->multi_threaded); 1.445 + printf("encode_breakout: %d\n", oxcf->encode_breakout); 1.446 + */ 1.447 + return VPX_CODEC_OK; 1.448 +} 1.449 + 1.450 +static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t *ctx, 1.451 + const vpx_codec_enc_cfg_t *cfg) 1.452 +{ 1.453 + vpx_codec_err_t res; 1.454 + 1.455 + if (((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h)) 1.456 + && (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)) 1.457 + ERROR("Cannot change width or height after initialization"); 1.458 + 1.459 + /* Prevent increasing lag_in_frames. This check is stricter than it needs 1.460 + * to be -- the limit is not increasing past the first lag_in_frames 1.461 + * value, but we don't track the initial config, only the last successful 1.462 + * config. 1.463 + */ 1.464 + if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)) 1.465 + ERROR("Cannot increase lag_in_frames"); 1.466 + 1.467 + res = validate_config(ctx, cfg, &ctx->vp8_cfg, 0); 1.468 + 1.469 + if (!res) 1.470 + { 1.471 + ctx->cfg = *cfg; 1.472 + set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL); 1.473 + vp8_change_config(ctx->cpi, &ctx->oxcf); 1.474 + } 1.475 + 1.476 + return res; 1.477 +} 1.478 + 1.479 + 1.480 +int vp8_reverse_trans(int); 1.481 + 1.482 + 1.483 +static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx, 1.484 + int ctrl_id, 1.485 + va_list args) 1.486 +{ 1.487 + void *arg = va_arg(args, void *); 1.488 + 1.489 +#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break 1.490 + 1.491 + if (!arg) 1.492 + return VPX_CODEC_INVALID_PARAM; 1.493 + 1.494 + switch (ctrl_id) 1.495 + { 1.496 + MAP(VP8E_GET_LAST_QUANTIZER, vp8_get_quantizer(ctx->cpi)); 1.497 + MAP(VP8E_GET_LAST_QUANTIZER_64, vp8_reverse_trans(vp8_get_quantizer(ctx->cpi))); 1.498 + } 1.499 + 1.500 + return VPX_CODEC_OK; 1.501 +#undef MAP 1.502 +} 1.503 + 1.504 + 1.505 +static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx, 1.506 + int ctrl_id, 1.507 + va_list args) 1.508 +{ 1.509 + vpx_codec_err_t res = VPX_CODEC_OK; 1.510 + struct vp8_extracfg xcfg = ctx->vp8_cfg; 1.511 + 1.512 +#define MAP(id, var) case id: var = CAST(id, args); break; 1.513 + 1.514 + switch (ctrl_id) 1.515 + { 1.516 + MAP(VP8E_SET_CPUUSED, xcfg.cpu_used); 1.517 + MAP(VP8E_SET_ENABLEAUTOALTREF, xcfg.enable_auto_alt_ref); 1.518 + MAP(VP8E_SET_NOISE_SENSITIVITY, xcfg.noise_sensitivity); 1.519 + MAP(VP8E_SET_SHARPNESS, xcfg.Sharpness); 1.520 + MAP(VP8E_SET_STATIC_THRESHOLD, xcfg.static_thresh); 1.521 + MAP(VP8E_SET_TOKEN_PARTITIONS, xcfg.token_partitions); 1.522 + 1.523 + MAP(VP8E_SET_ARNR_MAXFRAMES, xcfg.arnr_max_frames); 1.524 + MAP(VP8E_SET_ARNR_STRENGTH , xcfg.arnr_strength); 1.525 + MAP(VP8E_SET_ARNR_TYPE , xcfg.arnr_type); 1.526 + MAP(VP8E_SET_TUNING, xcfg.tuning); 1.527 + MAP(VP8E_SET_CQ_LEVEL, xcfg.cq_level); 1.528 + MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct); 1.529 + 1.530 + } 1.531 + 1.532 + res = validate_config(ctx, &ctx->cfg, &xcfg, 0); 1.533 + 1.534 + if (!res) 1.535 + { 1.536 + ctx->vp8_cfg = xcfg; 1.537 + set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL); 1.538 + vp8_change_config(ctx->cpi, &ctx->oxcf); 1.539 + } 1.540 + 1.541 + return res; 1.542 +#undef MAP 1.543 +} 1.544 + 1.545 +static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg, 1.546 + void **mem_loc) 1.547 +{ 1.548 + vpx_codec_err_t res = 0; 1.549 + 1.550 +#if CONFIG_MULTI_RES_ENCODING 1.551 + LOWER_RES_FRAME_INFO *shared_mem_loc; 1.552 + int mb_rows = ((cfg->g_w + 15) >>4); 1.553 + int mb_cols = ((cfg->g_h + 15) >>4); 1.554 + 1.555 + shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO)); 1.556 + if(!shared_mem_loc) 1.557 + { 1.558 + res = VPX_CODEC_MEM_ERROR; 1.559 + } 1.560 + 1.561 + shared_mem_loc->mb_info = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_MB_INFO)); 1.562 + if(!(shared_mem_loc->mb_info)) 1.563 + { 1.564 + res = VPX_CODEC_MEM_ERROR; 1.565 + } 1.566 + else 1.567 + { 1.568 + *mem_loc = (void *)shared_mem_loc; 1.569 + res = VPX_CODEC_OK; 1.570 + } 1.571 +#endif 1.572 + return res; 1.573 +} 1.574 + 1.575 +static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx, 1.576 + vpx_codec_priv_enc_mr_cfg_t *mr_cfg) 1.577 +{ 1.578 + vpx_codec_err_t res = VPX_CODEC_OK; 1.579 + struct vpx_codec_alg_priv *priv; 1.580 + vpx_codec_enc_cfg_t *cfg; 1.581 + unsigned int i; 1.582 + 1.583 + struct VP8_COMP *optr; 1.584 + 1.585 + vp8_rtcd(); 1.586 + 1.587 + if (!ctx->priv) 1.588 + { 1.589 + priv = calloc(1, sizeof(struct vpx_codec_alg_priv)); 1.590 + 1.591 + if (!priv) 1.592 + { 1.593 + return VPX_CODEC_MEM_ERROR; 1.594 + } 1.595 + 1.596 + ctx->priv = &priv->base; 1.597 + ctx->priv->sz = sizeof(*ctx->priv); 1.598 + ctx->priv->iface = ctx->iface; 1.599 + ctx->priv->alg_priv = priv; 1.600 + ctx->priv->init_flags = ctx->init_flags; 1.601 + 1.602 + if (ctx->config.enc) 1.603 + { 1.604 + /* Update the reference to the config structure to an 1.605 + * internal copy. 1.606 + */ 1.607 + ctx->priv->alg_priv->cfg = *ctx->config.enc; 1.608 + ctx->config.enc = &ctx->priv->alg_priv->cfg; 1.609 + } 1.610 + 1.611 + cfg = &ctx->priv->alg_priv->cfg; 1.612 + 1.613 + /* Select the extra vp8 configuration table based on the current 1.614 + * usage value. If the current usage value isn't found, use the 1.615 + * values for usage case 0. 1.616 + */ 1.617 + for (i = 0; 1.618 + extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage; 1.619 + i++); 1.620 + 1.621 + priv->vp8_cfg = extracfg_map[i].cfg; 1.622 + priv->vp8_cfg.pkt_list = &priv->pkt_list.head; 1.623 + 1.624 + priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2; 1.625 + 1.626 + if (priv->cx_data_sz < 32768) priv->cx_data_sz = 32768; 1.627 + 1.628 + priv->cx_data = malloc(priv->cx_data_sz); 1.629 + 1.630 + if (!priv->cx_data) 1.631 + { 1.632 + return VPX_CODEC_MEM_ERROR; 1.633 + } 1.634 + 1.635 + if(mr_cfg) 1.636 + ctx->priv->enc.total_encoders = mr_cfg->mr_total_resolutions; 1.637 + else 1.638 + ctx->priv->enc.total_encoders = 1; 1.639 + 1.640 + res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0); 1.641 + 1.642 + if (!res) 1.643 + { 1.644 + set_vp8e_config(&ctx->priv->alg_priv->oxcf, 1.645 + ctx->priv->alg_priv->cfg, 1.646 + ctx->priv->alg_priv->vp8_cfg, 1.647 + mr_cfg); 1.648 + 1.649 + optr = vp8_create_compressor(&ctx->priv->alg_priv->oxcf); 1.650 + 1.651 + if (!optr) 1.652 + res = VPX_CODEC_MEM_ERROR; 1.653 + else 1.654 + ctx->priv->alg_priv->cpi = optr; 1.655 + } 1.656 + } 1.657 + 1.658 + return res; 1.659 +} 1.660 + 1.661 +static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx) 1.662 +{ 1.663 +#if CONFIG_MULTI_RES_ENCODING 1.664 + /* Free multi-encoder shared memory */ 1.665 + if (ctx->oxcf.mr_total_resolutions > 0 && (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions-1)) 1.666 + { 1.667 + LOWER_RES_FRAME_INFO *shared_mem_loc = (LOWER_RES_FRAME_INFO *)ctx->oxcf.mr_low_res_mode_info; 1.668 + free(shared_mem_loc->mb_info); 1.669 + free(ctx->oxcf.mr_low_res_mode_info); 1.670 + } 1.671 +#endif 1.672 + 1.673 + free(ctx->cx_data); 1.674 + vp8_remove_compressor(&ctx->cpi); 1.675 + free(ctx); 1.676 + return VPX_CODEC_OK; 1.677 +} 1.678 + 1.679 +static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, 1.680 + YV12_BUFFER_CONFIG *yv12) 1.681 +{ 1.682 + vpx_codec_err_t res = VPX_CODEC_OK; 1.683 + yv12->y_buffer = img->planes[VPX_PLANE_Y]; 1.684 + yv12->u_buffer = img->planes[VPX_PLANE_U]; 1.685 + yv12->v_buffer = img->planes[VPX_PLANE_V]; 1.686 + 1.687 + yv12->y_crop_width = img->d_w; 1.688 + yv12->y_crop_height = img->d_h; 1.689 + yv12->y_width = img->d_w; 1.690 + yv12->y_height = img->d_h; 1.691 + yv12->uv_width = (1 + yv12->y_width) / 2; 1.692 + yv12->uv_height = (1 + yv12->y_height) / 2; 1.693 + 1.694 + yv12->y_stride = img->stride[VPX_PLANE_Y]; 1.695 + yv12->uv_stride = img->stride[VPX_PLANE_U]; 1.696 + 1.697 + yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2; 1.698 + return res; 1.699 +} 1.700 + 1.701 +static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx, 1.702 + unsigned long duration, 1.703 + unsigned long deadline) 1.704 +{ 1.705 + unsigned int new_qc; 1.706 + 1.707 +#if !(CONFIG_REALTIME_ONLY) 1.708 + /* Use best quality mode if no deadline is given. */ 1.709 + new_qc = MODE_BESTQUALITY; 1.710 + 1.711 + if (deadline) 1.712 + { 1.713 + uint64_t duration_us; 1.714 + 1.715 + /* Convert duration parameter from stream timebase to microseconds */ 1.716 + duration_us = (uint64_t)duration * 1000000 1.717 + * (uint64_t)ctx->cfg.g_timebase.num 1.718 + / (uint64_t)ctx->cfg.g_timebase.den; 1.719 + 1.720 + /* If the deadline is more that the duration this frame is to be shown, 1.721 + * use good quality mode. Otherwise use realtime mode. 1.722 + */ 1.723 + new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME; 1.724 + } 1.725 + 1.726 +#else 1.727 + new_qc = MODE_REALTIME; 1.728 +#endif 1.729 + 1.730 + if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS) 1.731 + new_qc = MODE_FIRSTPASS; 1.732 + else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS) 1.733 + new_qc = (new_qc == MODE_BESTQUALITY) 1.734 + ? MODE_SECONDPASS_BEST 1.735 + : MODE_SECONDPASS; 1.736 + 1.737 + if (ctx->oxcf.Mode != new_qc) 1.738 + { 1.739 + ctx->oxcf.Mode = new_qc; 1.740 + vp8_change_config(ctx->cpi, &ctx->oxcf); 1.741 + } 1.742 +} 1.743 + 1.744 + 1.745 +static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, 1.746 + const vpx_image_t *img, 1.747 + vpx_codec_pts_t pts, 1.748 + unsigned long duration, 1.749 + vpx_enc_frame_flags_t flags, 1.750 + unsigned long deadline) 1.751 +{ 1.752 + vpx_codec_err_t res = VPX_CODEC_OK; 1.753 + 1.754 + if (!ctx->cfg.rc_target_bitrate) 1.755 + return res; 1.756 + 1.757 + if (!ctx->cfg.rc_target_bitrate) 1.758 + return res; 1.759 + 1.760 + if (img) 1.761 + res = validate_img(ctx, img); 1.762 + 1.763 + if (!res) 1.764 + res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1); 1.765 + 1.766 + pick_quickcompress_mode(ctx, duration, deadline); 1.767 + vpx_codec_pkt_list_init(&ctx->pkt_list); 1.768 + 1.769 + /* Handle Flags */ 1.770 + if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) 1.771 + || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) 1.772 + { 1.773 + ctx->base.err_detail = "Conflicting flags."; 1.774 + return VPX_CODEC_INVALID_PARAM; 1.775 + } 1.776 + 1.777 + if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF 1.778 + | VP8_EFLAG_NO_REF_ARF)) 1.779 + { 1.780 + int ref = 7; 1.781 + 1.782 + if (flags & VP8_EFLAG_NO_REF_LAST) 1.783 + ref ^= VP8_LAST_FRAME; 1.784 + 1.785 + if (flags & VP8_EFLAG_NO_REF_GF) 1.786 + ref ^= VP8_GOLD_FRAME; 1.787 + 1.788 + if (flags & VP8_EFLAG_NO_REF_ARF) 1.789 + ref ^= VP8_ALTR_FRAME; 1.790 + 1.791 + vp8_use_as_reference(ctx->cpi, ref); 1.792 + } 1.793 + 1.794 + if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF 1.795 + | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF 1.796 + | VP8_EFLAG_FORCE_ARF)) 1.797 + { 1.798 + int upd = 7; 1.799 + 1.800 + if (flags & VP8_EFLAG_NO_UPD_LAST) 1.801 + upd ^= VP8_LAST_FRAME; 1.802 + 1.803 + if (flags & VP8_EFLAG_NO_UPD_GF) 1.804 + upd ^= VP8_GOLD_FRAME; 1.805 + 1.806 + if (flags & VP8_EFLAG_NO_UPD_ARF) 1.807 + upd ^= VP8_ALTR_FRAME; 1.808 + 1.809 + vp8_update_reference(ctx->cpi, upd); 1.810 + } 1.811 + 1.812 + if (flags & VP8_EFLAG_NO_UPD_ENTROPY) 1.813 + { 1.814 + vp8_update_entropy(ctx->cpi, 0); 1.815 + } 1.816 + 1.817 + /* Handle fixed keyframe intervals */ 1.818 + if (ctx->cfg.kf_mode == VPX_KF_AUTO 1.819 + && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) 1.820 + { 1.821 + if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) 1.822 + { 1.823 + flags |= VPX_EFLAG_FORCE_KF; 1.824 + ctx->fixed_kf_cntr = 1; 1.825 + } 1.826 + } 1.827 + 1.828 + /* Initialize the encoder instance on the first frame*/ 1.829 + if (!res && ctx->cpi) 1.830 + { 1.831 + unsigned int lib_flags; 1.832 + YV12_BUFFER_CONFIG sd; 1.833 + int64_t dst_time_stamp, dst_end_time_stamp; 1.834 + unsigned long size, cx_data_sz; 1.835 + unsigned char *cx_data; 1.836 + unsigned char *cx_data_end; 1.837 + int comp_data_state = 0; 1.838 + 1.839 + /* Set up internal flags */ 1.840 + if (ctx->base.init_flags & VPX_CODEC_USE_PSNR) 1.841 + ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1; 1.842 + 1.843 + if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION) 1.844 + ((VP8_COMP *)ctx->cpi)->output_partition = 1; 1.845 + 1.846 + /* Convert API flags to internal codec lib flags */ 1.847 + lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0; 1.848 + 1.849 + /* vp8 use 10,000,000 ticks/second as time stamp */ 1.850 + dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den; 1.851 + dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den; 1.852 + 1.853 + if (img != NULL) 1.854 + { 1.855 + res = image2yuvconfig(img, &sd); 1.856 + 1.857 + if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, 1.858 + &sd, dst_time_stamp, dst_end_time_stamp)) 1.859 + { 1.860 + VP8_COMP *cpi = (VP8_COMP *)ctx->cpi; 1.861 + res = update_error_state(ctx, &cpi->common.error); 1.862 + } 1.863 + 1.864 + /* reset for next frame */ 1.865 + ctx->next_frame_flag = 0; 1.866 + } 1.867 + 1.868 + cx_data = ctx->cx_data; 1.869 + cx_data_sz = ctx->cx_data_sz; 1.870 + cx_data_end = ctx->cx_data + cx_data_sz; 1.871 + lib_flags = 0; 1.872 + 1.873 + while (cx_data_sz >= ctx->cx_data_sz / 2) 1.874 + { 1.875 + comp_data_state = vp8_get_compressed_data(ctx->cpi, 1.876 + &lib_flags, 1.877 + &size, 1.878 + cx_data, 1.879 + cx_data_end, 1.880 + &dst_time_stamp, 1.881 + &dst_end_time_stamp, 1.882 + !img); 1.883 + 1.884 + if(comp_data_state == VPX_CODEC_CORRUPT_FRAME) 1.885 + return VPX_CODEC_CORRUPT_FRAME; 1.886 + else if(comp_data_state == -1) 1.887 + break; 1.888 + 1.889 + if (size) 1.890 + { 1.891 + vpx_codec_pts_t round, delta; 1.892 + vpx_codec_cx_pkt_t pkt; 1.893 + VP8_COMP *cpi = (VP8_COMP *)ctx->cpi; 1.894 + 1.895 + /* Add the frame packet to the list of returned packets. */ 1.896 + round = (vpx_codec_pts_t)1000000 1.897 + * ctx->cfg.g_timebase.num / 2 - 1; 1.898 + delta = (dst_end_time_stamp - dst_time_stamp); 1.899 + pkt.kind = VPX_CODEC_CX_FRAME_PKT; 1.900 + pkt.data.frame.pts = 1.901 + (dst_time_stamp * ctx->cfg.g_timebase.den + round) 1.902 + / ctx->cfg.g_timebase.num / 10000000; 1.903 + pkt.data.frame.duration = (unsigned long) 1.904 + ((delta * ctx->cfg.g_timebase.den + round) 1.905 + / ctx->cfg.g_timebase.num / 10000000); 1.906 + pkt.data.frame.flags = lib_flags << 16; 1.907 + 1.908 + if (lib_flags & FRAMEFLAGS_KEY) 1.909 + pkt.data.frame.flags |= VPX_FRAME_IS_KEY; 1.910 + 1.911 + if (!cpi->common.show_frame) 1.912 + { 1.913 + pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE; 1.914 + 1.915 + /* This timestamp should be as close as possible to the 1.916 + * prior PTS so that if a decoder uses pts to schedule when 1.917 + * to do this, we start right after last frame was decoded. 1.918 + * Invisible frames have no duration. 1.919 + */ 1.920 + pkt.data.frame.pts = ((cpi->last_time_stamp_seen 1.921 + * ctx->cfg.g_timebase.den + round) 1.922 + / ctx->cfg.g_timebase.num / 10000000) + 1; 1.923 + pkt.data.frame.duration = 0; 1.924 + } 1.925 + 1.926 + if (cpi->droppable) 1.927 + pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE; 1.928 + 1.929 + if (cpi->output_partition) 1.930 + { 1.931 + int i; 1.932 + const int num_partitions = 1.933 + (1 << cpi->common.multi_token_partition) + 1; 1.934 + 1.935 + pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT; 1.936 + 1.937 + for (i = 0; i < num_partitions; ++i) 1.938 + { 1.939 +#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING 1.940 + pkt.data.frame.buf = cpi->partition_d[i]; 1.941 +#else 1.942 + pkt.data.frame.buf = cx_data; 1.943 + cx_data += cpi->partition_sz[i]; 1.944 + cx_data_sz -= cpi->partition_sz[i]; 1.945 +#endif 1.946 + pkt.data.frame.sz = cpi->partition_sz[i]; 1.947 + pkt.data.frame.partition_id = i; 1.948 + /* don't set the fragment bit for the last partition */ 1.949 + if (i == (num_partitions - 1)) 1.950 + pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT; 1.951 + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); 1.952 + } 1.953 +#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING 1.954 + /* In lagged mode the encoder can buffer multiple frames. 1.955 + * We don't want this in partitioned output because 1.956 + * partitions are spread all over the output buffer. 1.957 + * So, force an exit! 1.958 + */ 1.959 + cx_data_sz -= ctx->cx_data_sz / 2; 1.960 +#endif 1.961 + } 1.962 + else 1.963 + { 1.964 + pkt.data.frame.buf = cx_data; 1.965 + pkt.data.frame.sz = size; 1.966 + pkt.data.frame.partition_id = -1; 1.967 + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); 1.968 + cx_data += size; 1.969 + cx_data_sz -= size; 1.970 + } 1.971 + } 1.972 + } 1.973 + } 1.974 + 1.975 + return res; 1.976 +} 1.977 + 1.978 + 1.979 +static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx, 1.980 + vpx_codec_iter_t *iter) 1.981 +{ 1.982 + return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter); 1.983 +} 1.984 + 1.985 +static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx, 1.986 + int ctr_id, 1.987 + va_list args) 1.988 +{ 1.989 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.990 + 1.991 + if (data) 1.992 + { 1.993 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.994 + YV12_BUFFER_CONFIG sd; 1.995 + 1.996 + image2yuvconfig(&frame->img, &sd); 1.997 + vp8_set_reference(ctx->cpi, frame->frame_type, &sd); 1.998 + return VPX_CODEC_OK; 1.999 + } 1.1000 + else 1.1001 + return VPX_CODEC_INVALID_PARAM; 1.1002 + 1.1003 +} 1.1004 + 1.1005 +static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx, 1.1006 + int ctr_id, 1.1007 + va_list args) 1.1008 +{ 1.1009 + 1.1010 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.1011 + 1.1012 + if (data) 1.1013 + { 1.1014 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.1015 + YV12_BUFFER_CONFIG sd; 1.1016 + 1.1017 + image2yuvconfig(&frame->img, &sd); 1.1018 + vp8_get_reference(ctx->cpi, frame->frame_type, &sd); 1.1019 + return VPX_CODEC_OK; 1.1020 + } 1.1021 + else 1.1022 + return VPX_CODEC_INVALID_PARAM; 1.1023 +} 1.1024 + 1.1025 +static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx, 1.1026 + int ctr_id, 1.1027 + va_list args) 1.1028 +{ 1.1029 +#if CONFIG_POSTPROC 1.1030 + vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *); 1.1031 + (void)ctr_id; 1.1032 + 1.1033 + if (data) 1.1034 + { 1.1035 + ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data); 1.1036 + return VPX_CODEC_OK; 1.1037 + } 1.1038 + else 1.1039 + return VPX_CODEC_INVALID_PARAM; 1.1040 +#else 1.1041 + (void)ctx; 1.1042 + (void)ctr_id; 1.1043 + (void)args; 1.1044 + return VPX_CODEC_INCAPABLE; 1.1045 +#endif 1.1046 +} 1.1047 + 1.1048 + 1.1049 +static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx) 1.1050 +{ 1.1051 + 1.1052 + YV12_BUFFER_CONFIG sd; 1.1053 + vp8_ppflags_t flags = {0}; 1.1054 + 1.1055 + if (ctx->preview_ppcfg.post_proc_flag) 1.1056 + { 1.1057 + flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag; 1.1058 + flags.deblocking_level = ctx->preview_ppcfg.deblocking_level; 1.1059 + flags.noise_level = ctx->preview_ppcfg.noise_level; 1.1060 + } 1.1061 + 1.1062 + if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, &flags)) 1.1063 + { 1.1064 + 1.1065 + /* 1.1066 + vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12, 1.1067 + sd.y_width + 2*VP8BORDERINPIXELS, 1.1068 + sd.y_height + 2*VP8BORDERINPIXELS, 1.1069 + 1, 1.1070 + sd.buffer_alloc); 1.1071 + vpx_img_set_rect(&ctx->preview_img, 1.1072 + VP8BORDERINPIXELS, VP8BORDERINPIXELS, 1.1073 + sd.y_width, sd.y_height); 1.1074 + */ 1.1075 + 1.1076 + ctx->preview_img.bps = 12; 1.1077 + ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer; 1.1078 + ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer; 1.1079 + ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer; 1.1080 + 1.1081 + ctx->preview_img.fmt = VPX_IMG_FMT_I420; 1.1082 + ctx->preview_img.x_chroma_shift = 1; 1.1083 + ctx->preview_img.y_chroma_shift = 1; 1.1084 + 1.1085 + ctx->preview_img.d_w = sd.y_width; 1.1086 + ctx->preview_img.d_h = sd.y_height; 1.1087 + ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride; 1.1088 + ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride; 1.1089 + ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride; 1.1090 + ctx->preview_img.w = sd.y_width; 1.1091 + ctx->preview_img.h = sd.y_height; 1.1092 + 1.1093 + return &ctx->preview_img; 1.1094 + } 1.1095 + else 1.1096 + return NULL; 1.1097 +} 1.1098 + 1.1099 +static vpx_codec_err_t vp8e_update_entropy(vpx_codec_alg_priv_t *ctx, 1.1100 + int ctr_id, 1.1101 + va_list args) 1.1102 +{ 1.1103 + int update = va_arg(args, int); 1.1104 + vp8_update_entropy(ctx->cpi, update); 1.1105 + return VPX_CODEC_OK; 1.1106 + 1.1107 +} 1.1108 + 1.1109 +static vpx_codec_err_t vp8e_update_reference(vpx_codec_alg_priv_t *ctx, 1.1110 + int ctr_id, 1.1111 + va_list args) 1.1112 +{ 1.1113 + int update = va_arg(args, int); 1.1114 + vp8_update_reference(ctx->cpi, update); 1.1115 + return VPX_CODEC_OK; 1.1116 +} 1.1117 + 1.1118 +static vpx_codec_err_t vp8e_use_reference(vpx_codec_alg_priv_t *ctx, 1.1119 + int ctr_id, 1.1120 + va_list args) 1.1121 +{ 1.1122 + int reference_flag = va_arg(args, int); 1.1123 + vp8_use_as_reference(ctx->cpi, reference_flag); 1.1124 + return VPX_CODEC_OK; 1.1125 +} 1.1126 + 1.1127 +static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx, 1.1128 + int ctr_id, 1.1129 + va_list args) 1.1130 +{ 1.1131 + vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *); 1.1132 + 1.1133 + if (data) 1.1134 + { 1.1135 + vpx_roi_map_t *roi = (vpx_roi_map_t *)data; 1.1136 + 1.1137 + if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols, roi->delta_q, roi->delta_lf, roi->static_threshold)) 1.1138 + return VPX_CODEC_OK; 1.1139 + else 1.1140 + return VPX_CODEC_INVALID_PARAM; 1.1141 + } 1.1142 + else 1.1143 + return VPX_CODEC_INVALID_PARAM; 1.1144 +} 1.1145 + 1.1146 + 1.1147 +static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx, 1.1148 + int ctr_id, 1.1149 + va_list args) 1.1150 +{ 1.1151 + vpx_active_map_t *data = va_arg(args, vpx_active_map_t *); 1.1152 + 1.1153 + if (data) 1.1154 + { 1.1155 + 1.1156 + vpx_active_map_t *map = (vpx_active_map_t *)data; 1.1157 + 1.1158 + if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols)) 1.1159 + return VPX_CODEC_OK; 1.1160 + else 1.1161 + return VPX_CODEC_INVALID_PARAM; 1.1162 + } 1.1163 + else 1.1164 + return VPX_CODEC_INVALID_PARAM; 1.1165 +} 1.1166 + 1.1167 +static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx, 1.1168 + int ctr_id, 1.1169 + va_list args) 1.1170 +{ 1.1171 + 1.1172 + vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *); 1.1173 + 1.1174 + if (data) 1.1175 + { 1.1176 + int res; 1.1177 + vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data ; 1.1178 + res = vp8_set_internal_size(ctx->cpi, 1.1179 + (VPX_SCALING)scalemode.h_scaling_mode, 1.1180 + (VPX_SCALING)scalemode.v_scaling_mode); 1.1181 + 1.1182 + if (!res) 1.1183 + { 1.1184 + /*force next frame a key frame to effect scaling mode */ 1.1185 + ctx->next_frame_flag |= FRAMEFLAGS_KEY; 1.1186 + return VPX_CODEC_OK; 1.1187 + } 1.1188 + else 1.1189 + return VPX_CODEC_INVALID_PARAM; 1.1190 + } 1.1191 + else 1.1192 + return VPX_CODEC_INVALID_PARAM; 1.1193 +} 1.1194 + 1.1195 + 1.1196 +static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] = 1.1197 +{ 1.1198 + {VP8_SET_REFERENCE, vp8e_set_reference}, 1.1199 + {VP8_COPY_REFERENCE, vp8e_get_reference}, 1.1200 + {VP8_SET_POSTPROC, vp8e_set_previewpp}, 1.1201 + {VP8E_UPD_ENTROPY, vp8e_update_entropy}, 1.1202 + {VP8E_UPD_REFERENCE, vp8e_update_reference}, 1.1203 + {VP8E_USE_REFERENCE, vp8e_use_reference}, 1.1204 + {VP8E_SET_ROI_MAP, vp8e_set_roi_map}, 1.1205 + {VP8E_SET_ACTIVEMAP, vp8e_set_activemap}, 1.1206 + {VP8E_SET_SCALEMODE, vp8e_set_scalemode}, 1.1207 + {VP8E_SET_CPUUSED, set_param}, 1.1208 + {VP8E_SET_NOISE_SENSITIVITY, set_param}, 1.1209 + {VP8E_SET_ENABLEAUTOALTREF, set_param}, 1.1210 + {VP8E_SET_SHARPNESS, set_param}, 1.1211 + {VP8E_SET_STATIC_THRESHOLD, set_param}, 1.1212 + {VP8E_SET_TOKEN_PARTITIONS, set_param}, 1.1213 + {VP8E_GET_LAST_QUANTIZER, get_param}, 1.1214 + {VP8E_GET_LAST_QUANTIZER_64, get_param}, 1.1215 + {VP8E_SET_ARNR_MAXFRAMES, set_param}, 1.1216 + {VP8E_SET_ARNR_STRENGTH , set_param}, 1.1217 + {VP8E_SET_ARNR_TYPE , set_param}, 1.1218 + {VP8E_SET_TUNING, set_param}, 1.1219 + {VP8E_SET_CQ_LEVEL, set_param}, 1.1220 + {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param}, 1.1221 + { -1, NULL}, 1.1222 +}; 1.1223 + 1.1224 +static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] = 1.1225 +{ 1.1226 + { 1.1227 + 0, 1.1228 + { 1.1229 + 0, /* g_usage */ 1.1230 + 0, /* g_threads */ 1.1231 + 0, /* g_profile */ 1.1232 + 1.1233 + 320, /* g_width */ 1.1234 + 240, /* g_height */ 1.1235 + {1, 30}, /* g_timebase */ 1.1236 + 1.1237 + 0, /* g_error_resilient */ 1.1238 + 1.1239 + VPX_RC_ONE_PASS, /* g_pass */ 1.1240 + 1.1241 + 0, /* g_lag_in_frames */ 1.1242 + 1.1243 + 0, /* rc_dropframe_thresh */ 1.1244 + 0, /* rc_resize_allowed */ 1.1245 + 60, /* rc_resize_down_thresold */ 1.1246 + 30, /* rc_resize_up_thresold */ 1.1247 + 1.1248 + VPX_VBR, /* rc_end_usage */ 1.1249 +#if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION) 1.1250 + {0}, /* rc_twopass_stats_in */ 1.1251 +#endif 1.1252 + 256, /* rc_target_bandwidth */ 1.1253 + 4, /* rc_min_quantizer */ 1.1254 + 63, /* rc_max_quantizer */ 1.1255 + 100, /* rc_undershoot_pct */ 1.1256 + 100, /* rc_overshoot_pct */ 1.1257 + 1.1258 + 6000, /* rc_max_buffer_size */ 1.1259 + 4000, /* rc_buffer_initial_size; */ 1.1260 + 5000, /* rc_buffer_optimal_size; */ 1.1261 + 1.1262 + 50, /* rc_two_pass_vbrbias */ 1.1263 + 0, /* rc_two_pass_vbrmin_section */ 1.1264 + 400, /* rc_two_pass_vbrmax_section */ 1.1265 + 1.1266 + /* keyframing settings (kf) */ 1.1267 + VPX_KF_AUTO, /* g_kfmode*/ 1.1268 + 0, /* kf_min_dist */ 1.1269 + 128, /* kf_max_dist */ 1.1270 + 1.1271 +#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION) 1.1272 + 1, /* g_delete_first_pass_file */ 1.1273 + "vp8.fpf" /* first pass filename */ 1.1274 +#endif 1.1275 + VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */ 1.1276 + 1, /* ts_number_layers */ 1.1277 + {0}, /* ts_target_bitrate */ 1.1278 + {0}, /* ts_rate_decimator */ 1.1279 + 0, /* ts_periodicity */ 1.1280 + {0}, /* ts_layer_id */ 1.1281 + }}, 1.1282 + { -1, {NOT_IMPLEMENTED}} 1.1283 +}; 1.1284 + 1.1285 + 1.1286 +#ifndef VERSION_STRING 1.1287 +#define VERSION_STRING 1.1288 +#endif 1.1289 +CODEC_INTERFACE(vpx_codec_vp8_cx) = 1.1290 +{ 1.1291 + "WebM Project VP8 Encoder" VERSION_STRING, 1.1292 + VPX_CODEC_INTERNAL_ABI_VERSION, 1.1293 + VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR | 1.1294 + VPX_CODEC_CAP_OUTPUT_PARTITION, 1.1295 + /* vpx_codec_caps_t caps; */ 1.1296 + vp8e_init, /* vpx_codec_init_fn_t init; */ 1.1297 + vp8e_destroy, /* vpx_codec_destroy_fn_t destroy; */ 1.1298 + vp8e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 1.1299 + NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */ 1.1300 + NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */ 1.1301 + { 1.1302 + NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */ 1.1303 + NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */ 1.1304 + NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */ 1.1305 + NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */ 1.1306 + }, 1.1307 + { 1.1308 + vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */ 1.1309 + vp8e_encode, /* vpx_codec_encode_fn_t encode; */ 1.1310 + vp8e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */ 1.1311 + vp8e_set_config, 1.1312 + NOT_IMPLEMENTED, 1.1313 + vp8e_get_preview, 1.1314 + vp8e_mr_alloc_mem, 1.1315 + } /* encoder functions */ 1.1316 +};