diff options
Diffstat (limited to 'libvpx/vp9/vp9_cx_iface.c')
-rw-r--r-- | libvpx/vp9/vp9_cx_iface.c | 534 |
1 files changed, 392 insertions, 142 deletions
diff --git a/libvpx/vp9/vp9_cx_iface.c b/libvpx/vp9/vp9_cx_iface.c index 45e03f2de..f415e50f7 100644 --- a/libvpx/vp9/vp9_cx_iface.c +++ b/libvpx/vp9/vp9_cx_iface.c @@ -13,6 +13,7 @@ #include "./vpx_config.h" #include "vpx/vpx_encoder.h" +#include "vpx_dsp/psnr.h" #include "vpx_ports/vpx_once.h" #include "vpx_ports/system_state.h" #include "vpx_util/vpx_timestamp.h" @@ -20,10 +21,14 @@ #include "./vpx_version.h" #include "vp9/encoder/vp9_encoder.h" #include "vpx/vp8cx.h" +#include "vp9/common/vp9_alloccommon.h" +#include "vp9/vp9_cx_iface.h" #include "vp9/encoder/vp9_firstpass.h" +#include "vp9/encoder/vp9_lookahead.h" +#include "vp9/vp9_cx_iface.h" #include "vp9/vp9_iface_common.h" -struct vp9_extracfg { +typedef struct vp9_extracfg { int cpu_used; // available cpu percentage in 1/16 unsigned int enable_auto_alt_ref; unsigned int noise_sensitivity; @@ -55,7 +60,7 @@ struct vp9_extracfg { int render_height; unsigned int row_mt; unsigned int motion_vector_unit_test; -}; +} vp9_extracfg; static struct vp9_extracfg default_extra_cfg = { 0, // cpu_used @@ -466,6 +471,15 @@ static void config_target_level(VP9EncoderConfig *oxcf) { } } +static vpx_rational64_t get_g_timebase_in_ts(vpx_rational_t g_timebase) { + vpx_rational64_t g_timebase_in_ts; + g_timebase_in_ts.den = g_timebase.den; + g_timebase_in_ts.num = g_timebase.num; + g_timebase_in_ts.num *= TICKS_PER_SEC; + reduce_ratio(&g_timebase_in_ts); + return g_timebase_in_ts; +} + static vpx_codec_err_t set_encoder_config( VP9EncoderConfig *oxcf, const vpx_codec_enc_cfg_t *cfg, const struct vp9_extracfg *extra_cfg) { @@ -477,9 +491,13 @@ static vpx_codec_err_t set_encoder_config( oxcf->height = cfg->g_h; oxcf->bit_depth = cfg->g_bit_depth; oxcf->input_bit_depth = cfg->g_input_bit_depth; + // TODO(angiebird): Figure out if we can just use g_timebase to indicate the + // inverse of framerate // guess a frame rate if out of whack, use 30 oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num; if (oxcf->init_framerate > 180) oxcf->init_framerate = 30; + oxcf->g_timebase = cfg->g_timebase; + oxcf->g_timebase_in_ts = get_g_timebase_in_ts(oxcf->g_timebase); oxcf->mode = GOOD; @@ -539,10 +557,16 @@ static vpx_codec_err_t set_encoder_config( oxcf->speed = abs(extra_cfg->cpu_used); oxcf->encode_breakout = extra_cfg->static_thresh; oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref; - oxcf->noise_sensitivity = extra_cfg->noise_sensitivity; + if (oxcf->bit_depth == VPX_BITS_8) { + oxcf->noise_sensitivity = extra_cfg->noise_sensitivity; + } else { + // Disable denoiser for high bitdepth since vp9_denoiser_filter only works + // for 8 bits. + oxcf->noise_sensitivity = 0; + } oxcf->sharpness = extra_cfg->sharpness; - oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in; + vp9_set_first_pass_stats(oxcf, &cfg->rc_twopass_stats_in); #if CONFIG_FP_MB_STATS oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in; @@ -611,40 +635,7 @@ static vpx_codec_err_t set_encoder_config( } if (get_level_index(oxcf->target_level) >= 0) config_target_level(oxcf); - /* - printf("Current VP9 Settings: \n"); - printf("target_bandwidth: %d\n", oxcf->target_bandwidth); - printf("target_level: %d\n", oxcf->target_level); - printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity); - printf("sharpness: %d\n", oxcf->sharpness); - printf("cpu_used: %d\n", oxcf->cpu_used); - printf("Mode: %d\n", oxcf->mode); - printf("auto_key: %d\n", oxcf->auto_key); - printf("key_freq: %d\n", oxcf->key_freq); - printf("end_usage: %d\n", oxcf->end_usage); - printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct); - printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct); - printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level); - printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level); - printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size); - printf("fixed_q: %d\n", oxcf->fixed_q); - printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q); - printf("best_allowed_q: %d\n", oxcf->best_allowed_q); - printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling); - printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width); - printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height); - printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias); - printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section); - printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section); - printf("vbr_corpus_complexity: %d\n", oxcf->vbr_corpus_complexity); - printf("lag_in_frames: %d\n", oxcf->lag_in_frames); - printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf); - printf("Version: %d\n", oxcf->Version); - printf("encode_breakout: %d\n", oxcf->encode_breakout); - printf("error resilient: %d\n", oxcf->error_resilient_mode); - printf("frame parallel detokenization: %d\n", - oxcf->frame_parallel_decoding_mode); - */ + // vp9_dump_encoder_config(oxcf); return VPX_CODEC_OK; } @@ -935,10 +926,9 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx, if (res == VPX_CODEC_OK) { priv->pts_offset_initialized = 0; - priv->timestamp_ratio.den = priv->cfg.g_timebase.den; - priv->timestamp_ratio.num = (int64_t)priv->cfg.g_timebase.num; - priv->timestamp_ratio.num *= TICKS_PER_SEC; - reduce_ratio(&priv->timestamp_ratio); + // TODO(angiebird): Replace priv->timestamp_ratio by + // oxcf->g_timebase_in_ts + priv->timestamp_ratio = get_g_timebase_in_ts(priv->cfg.g_timebase); set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg); #if CONFIG_VP9_HIGHBITDEPTH @@ -946,10 +936,7 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx, (ctx->init_flags & VPX_CODEC_USE_HIGHBITDEPTH) ? 1 : 0; #endif priv->cpi = vp9_create_compressor(&priv->oxcf, priv->buffer_pool); - if (priv->cpi == NULL) - res = VPX_CODEC_MEM_ERROR; - else - priv->cpi->output_pkt_list = &priv->pkt_list.head; + if (priv->cpi == NULL) res = VPX_CODEC_MEM_ERROR; } } @@ -1067,18 +1054,6 @@ static int write_superframe_index(vpx_codec_alg_priv_t *ctx) { return index_sz; } -static int64_t timebase_units_to_ticks(const vpx_rational64_t *timestamp_ratio, - int64_t n) { - return n * timestamp_ratio->num / timestamp_ratio->den; -} - -static int64_t ticks_to_timebase_units(const vpx_rational64_t *timestamp_ratio, - int64_t n) { - int64_t round = timestamp_ratio->num / 2; - if (round > 0) --round; - return (n * timestamp_ratio->den + round) / timestamp_ratio->num; -} - static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi, unsigned int lib_flags) { vpx_codec_frame_flags_t flags = lib_flags << 16; @@ -1096,6 +1071,27 @@ static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi, return flags; } +static INLINE vpx_codec_cx_pkt_t get_psnr_pkt(const PSNR_STATS *psnr) { + vpx_codec_cx_pkt_t pkt; + pkt.kind = VPX_CODEC_PSNR_PKT; + pkt.data.psnr = *psnr; + return pkt; +} + +#if !CONFIG_REALTIME_ONLY +static INLINE vpx_codec_cx_pkt_t +get_first_pass_stats_pkt(FIRSTPASS_STATS *stats) { + // WARNNING: This function assumes that stats will + // exist and not be changed until the packet is processed + // TODO(angiebird): Refactor the code to avoid using the assumption. + vpx_codec_cx_pkt_t pkt; + pkt.kind = VPX_CODEC_STATS_PKT; + pkt.data.twopass_stats.buf = stats; + pkt.data.twopass_stats.sz = sizeof(*stats); + return pkt; +} +#endif + const size_t kMinCompressedSize = 8192; static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, const vpx_image_t *img, @@ -1109,19 +1105,11 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, VP9_COMP *const cpi = ctx->cpi; const vpx_rational64_t *const timestamp_ratio = &ctx->timestamp_ratio; size_t data_sz; + vpx_codec_cx_pkt_t pkt; + memset(&pkt, 0, sizeof(pkt)); if (cpi == NULL) return VPX_CODEC_INVALID_PARAM; - if (cpi->oxcf.pass == 2 && cpi->level_constraint.level_index >= 0 && - !cpi->level_constraint.rc_config_updated) { - const VP9EncoderConfig *const oxcf = &cpi->oxcf; - TWO_PASS *const twopass = &cpi->twopass; - FIRSTPASS_STATS *stats = &twopass->total_stats; - twopass->bits_left = - (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0); - cpi->level_constraint.rc_config_updated = 1; - } - if (img != NULL) { res = validate_img(ctx, img); if (res == VPX_CODEC_OK) { @@ -1223,92 +1211,135 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, } } - while (cx_data_sz >= ctx->cx_data_sz / 2 && - -1 != vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data, - &dst_time_stamp, &dst_end_time_stamp, - !img)) { - if (size || (cpi->use_svc && cpi->svc.skip_enhancement_layer)) { - vpx_codec_cx_pkt_t pkt; - - // Pack invisible frames with the next visible frame - if (!cpi->common.show_frame || - (cpi->use_svc && - cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)) { - if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data; - ctx->pending_cx_data_sz += size; - if (size) ctx->pending_frame_sizes[ctx->pending_frame_count++] = size; - ctx->pending_frame_magnitude |= size; - cx_data += size; - cx_data_sz -= size; + if (cpi->oxcf.pass == 1 && !cpi->use_svc) { +#if !CONFIG_REALTIME_ONLY + // compute first pass stats + if (img) { + int ret; + ENCODE_FRAME_RESULT encode_frame_result; + vpx_codec_cx_pkt_t fps_pkt; + // TODO(angiebird): Call vp9_first_pass directly + ret = vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data, + &dst_time_stamp, &dst_end_time_stamp, + !img, &encode_frame_result); + assert(size == 0); // There is no compressed data in the first pass + (void)ret; + assert(ret == 0); + fps_pkt = get_first_pass_stats_pkt(&cpi->twopass.this_frame_stats); + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &fps_pkt); + } else { + if (!cpi->twopass.first_pass_done) { + vpx_codec_cx_pkt_t fps_pkt; + vp9_end_first_pass(cpi); + fps_pkt = get_first_pass_stats_pkt(&cpi->twopass.total_stats); + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &fps_pkt); + } + } +#else // !CONFIG_REALTIME_ONLY + assert(0); +#endif // !CONFIG_REALTIME_ONLY + } else { + ENCODE_FRAME_RESULT encode_frame_result; + while (cx_data_sz >= ctx->cx_data_sz / 2 && + -1 != vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data, + &dst_time_stamp, &dst_end_time_stamp, + !img, &encode_frame_result)) { + // Pack psnr pkt + if (size > 0 && !cpi->use_svc) { + // TODO(angiebird): Figure out while we don't need psnr pkt when + // use_svc is on + PSNR_STATS psnr; + if (vp9_get_psnr(cpi, &psnr)) { + vpx_codec_cx_pkt_t psnr_pkt = get_psnr_pkt(&psnr); + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &psnr_pkt); + } + } + + if (size || (cpi->use_svc && cpi->svc.skip_enhancement_layer)) { + // Pack invisible frames with the next visible frame + if (!cpi->common.show_frame || + (cpi->use_svc && cpi->svc.spatial_layer_id < + cpi->svc.number_spatial_layers - 1)) { + if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data; + ctx->pending_cx_data_sz += size; + if (size) + ctx->pending_frame_sizes[ctx->pending_frame_count++] = size; + ctx->pending_frame_magnitude |= size; + cx_data += size; + cx_data_sz -= size; + pkt.data.frame.width[cpi->svc.spatial_layer_id] = cpi->common.width; + pkt.data.frame.height[cpi->svc.spatial_layer_id] = + cpi->common.height; + pkt.data.frame.spatial_layer_encoded[cpi->svc.spatial_layer_id] = + 1 - cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id]; + + if (ctx->output_cx_pkt_cb.output_cx_pkt) { + pkt.kind = VPX_CODEC_CX_FRAME_PKT; + pkt.data.frame.pts = + ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) + + ctx->pts_offset; + pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units( + timestamp_ratio, dst_end_time_stamp - dst_time_stamp); + pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); + pkt.data.frame.buf = ctx->pending_cx_data; + pkt.data.frame.sz = size; + ctx->pending_cx_data = NULL; + ctx->pending_cx_data_sz = 0; + ctx->pending_frame_count = 0; + ctx->pending_frame_magnitude = 0; + ctx->output_cx_pkt_cb.output_cx_pkt( + &pkt, ctx->output_cx_pkt_cb.user_priv); + } + continue; + } + + // Add the frame packet to the list of returned packets. + pkt.kind = VPX_CODEC_CX_FRAME_PKT; + pkt.data.frame.pts = + ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) + + ctx->pts_offset; + pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units( + timestamp_ratio, dst_end_time_stamp - dst_time_stamp); + pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); pkt.data.frame.width[cpi->svc.spatial_layer_id] = cpi->common.width; pkt.data.frame.height[cpi->svc.spatial_layer_id] = cpi->common.height; pkt.data.frame.spatial_layer_encoded[cpi->svc.spatial_layer_id] = 1 - cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id]; - if (ctx->output_cx_pkt_cb.output_cx_pkt) { - pkt.kind = VPX_CODEC_CX_FRAME_PKT; - pkt.data.frame.pts = - ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) + - ctx->pts_offset; - pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units( - timestamp_ratio, dst_end_time_stamp - dst_time_stamp); - pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); + if (ctx->pending_cx_data) { + if (size) + ctx->pending_frame_sizes[ctx->pending_frame_count++] = size; + ctx->pending_frame_magnitude |= size; + ctx->pending_cx_data_sz += size; + // write the superframe only for the case when + if (!ctx->output_cx_pkt_cb.output_cx_pkt) + size += write_superframe_index(ctx); pkt.data.frame.buf = ctx->pending_cx_data; - pkt.data.frame.sz = size; + pkt.data.frame.sz = ctx->pending_cx_data_sz; ctx->pending_cx_data = NULL; ctx->pending_cx_data_sz = 0; ctx->pending_frame_count = 0; ctx->pending_frame_magnitude = 0; + } else { + pkt.data.frame.buf = cx_data; + pkt.data.frame.sz = size; + } + pkt.data.frame.partition_id = -1; + + if (ctx->output_cx_pkt_cb.output_cx_pkt) ctx->output_cx_pkt_cb.output_cx_pkt( &pkt, ctx->output_cx_pkt_cb.user_priv); - } - continue; - } + else + vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); - // Add the frame packet to the list of returned packets. - pkt.kind = VPX_CODEC_CX_FRAME_PKT; - pkt.data.frame.pts = - ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) + - ctx->pts_offset; - pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units( - timestamp_ratio, dst_end_time_stamp - dst_time_stamp); - pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); - pkt.data.frame.width[cpi->svc.spatial_layer_id] = cpi->common.width; - pkt.data.frame.height[cpi->svc.spatial_layer_id] = cpi->common.height; - pkt.data.frame.spatial_layer_encoded[cpi->svc.spatial_layer_id] = - 1 - cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id]; - - if (ctx->pending_cx_data) { - if (size) ctx->pending_frame_sizes[ctx->pending_frame_count++] = size; - ctx->pending_frame_magnitude |= size; - ctx->pending_cx_data_sz += size; - // write the superframe only for the case when - if (!ctx->output_cx_pkt_cb.output_cx_pkt) - size += write_superframe_index(ctx); - pkt.data.frame.buf = ctx->pending_cx_data; - pkt.data.frame.sz = ctx->pending_cx_data_sz; - ctx->pending_cx_data = NULL; - ctx->pending_cx_data_sz = 0; - ctx->pending_frame_count = 0; - ctx->pending_frame_magnitude = 0; - } else { - pkt.data.frame.buf = cx_data; - pkt.data.frame.sz = size; - } - pkt.data.frame.partition_id = -1; - - if (ctx->output_cx_pkt_cb.output_cx_pkt) - ctx->output_cx_pkt_cb.output_cx_pkt(&pkt, - ctx->output_cx_pkt_cb.user_priv); - else - vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt); - - cx_data += size; - cx_data_sz -= size; - if (is_one_pass_cbr_svc(cpi) && - (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) { - // Encoded all spatial layers; exit loop. - break; + cx_data += size; + cx_data_sz -= size; + if (is_one_pass_cbr_svc(cpi) && + (cpi->svc.spatial_layer_id == + cpi->svc.number_spatial_layers - 1)) { + // Encoded all spatial layers; exit loop. + break; + } } } } @@ -1765,7 +1796,7 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = { VPX_VBR, // rc_end_usage { NULL, 0 }, // rc_twopass_stats_in { NULL, 0 }, // rc_firstpass_mb_stats_in - 256, // rc_target_bandwidth + 256, // rc_target_bitrate 0, // rc_min_quantizer 63, // rc_max_quantizer 25, // rc_undershoot_pct @@ -1831,3 +1862,222 @@ CODEC_INTERFACE(vpx_codec_vp9_cx) = { NULL // vpx_codec_enc_mr_get_mem_loc_fn_t } }; + +static vpx_codec_enc_cfg_t get_enc_cfg(int frame_width, int frame_height, + vpx_rational_t frame_rate, + int target_bitrate, + vpx_enc_pass enc_pass) { + vpx_codec_enc_cfg_t enc_cfg = encoder_usage_cfg_map[0].cfg; + enc_cfg.g_w = frame_width; + enc_cfg.g_h = frame_height; + enc_cfg.rc_target_bitrate = target_bitrate; + enc_cfg.g_pass = enc_pass; + // g_timebase is the inverse of frame_rate + enc_cfg.g_timebase.num = frame_rate.den; + enc_cfg.g_timebase.den = frame_rate.num; + return enc_cfg; +} + +static vp9_extracfg get_extra_cfg() { + vp9_extracfg extra_cfg = default_extra_cfg; + return extra_cfg; +} + +VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, + vpx_rational_t frame_rate, + int target_bitrate, + vpx_enc_pass enc_pass) { + /* This function will generate the same VP9EncoderConfig used by the + * vpxenc command given below. + * The configs in the vpxenc command corresponds to parameters of + * vp9_get_encoder_config() as follows. + * + * WIDTH: frame_width + * HEIGHT: frame_height + * FPS: frame_rate + * BITRATE: target_bitrate + * + * INPUT, OUTPUT, LIMIT will not affect VP9EncoderConfig + * + * vpxenc command: + * INPUT=bus_cif.y4m + * OUTPUT=output.webm + * WIDTH=352 + * HEIGHT=288 + * BITRATE=600 + * FPS=30/1 + * LIMIT=150 + * ./vpxenc --limit=$LIMIT --width=$WIDTH --height=$HEIGHT --fps=$FPS + * --lag-in-frames=25 \ + * --codec=vp9 --good --cpu-used=0 --threads=0 --profile=0 \ + * --min-q=0 --max-q=63 --auto-alt-ref=1 --passes=2 --kf-max-dist=150 \ + * --kf-min-dist=0 --drop-frame=0 --static-thresh=0 --bias-pct=50 \ + * --minsection-pct=0 --maxsection-pct=150 --arnr-maxframes=7 --psnr \ + * --arnr-strength=5 --sharpness=0 --undershoot-pct=100 --overshoot-pct=100 \ + * --frame-parallel=0 --tile-columns=0 --cpu-used=0 --end-usage=vbr \ + * --target-bitrate=$BITRATE -o $OUTPUT $INPUT + */ + + VP9EncoderConfig oxcf; + vp9_extracfg extra_cfg = get_extra_cfg(); + vpx_codec_enc_cfg_t enc_cfg = get_enc_cfg( + frame_width, frame_height, frame_rate, target_bitrate, enc_pass); + set_encoder_config(&oxcf, &enc_cfg, &extra_cfg); + + // These settings are made to match the settings of the vpxenc command. + oxcf.key_freq = 150; + oxcf.under_shoot_pct = 100; + oxcf.over_shoot_pct = 100; + oxcf.max_threads = 0; + oxcf.tile_columns = 0; + oxcf.frame_parallel_decoding_mode = 0; + oxcf.two_pass_vbrmax_section = 150; + return oxcf; +} + +#define DUMP_STRUCT_VALUE(struct, value) \ + printf(#value " %" PRId64 "\n", (int64_t)(struct)->value) + +void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf) { + DUMP_STRUCT_VALUE(oxcf, profile); + DUMP_STRUCT_VALUE(oxcf, bit_depth); + DUMP_STRUCT_VALUE(oxcf, width); + DUMP_STRUCT_VALUE(oxcf, height); + DUMP_STRUCT_VALUE(oxcf, input_bit_depth); + DUMP_STRUCT_VALUE(oxcf, init_framerate); + // TODO(angiebird): dump g_timebase + // TODO(angiebird): dump g_timebase_in_ts + + DUMP_STRUCT_VALUE(oxcf, target_bandwidth); + + DUMP_STRUCT_VALUE(oxcf, noise_sensitivity); + DUMP_STRUCT_VALUE(oxcf, sharpness); + DUMP_STRUCT_VALUE(oxcf, speed); + DUMP_STRUCT_VALUE(oxcf, rc_max_intra_bitrate_pct); + DUMP_STRUCT_VALUE(oxcf, rc_max_inter_bitrate_pct); + DUMP_STRUCT_VALUE(oxcf, gf_cbr_boost_pct); + + DUMP_STRUCT_VALUE(oxcf, mode); + DUMP_STRUCT_VALUE(oxcf, pass); + + // Key Framing Operations + DUMP_STRUCT_VALUE(oxcf, auto_key); + DUMP_STRUCT_VALUE(oxcf, key_freq); + + DUMP_STRUCT_VALUE(oxcf, lag_in_frames); + + // ---------------------------------------------------------------- + // DATARATE CONTROL OPTIONS + + // vbr, cbr, constrained quality or constant quality + DUMP_STRUCT_VALUE(oxcf, rc_mode); + + // buffer targeting aggressiveness + DUMP_STRUCT_VALUE(oxcf, under_shoot_pct); + DUMP_STRUCT_VALUE(oxcf, over_shoot_pct); + + // buffering parameters + // TODO(angiebird): dump tarting_buffer_level_ms + // TODO(angiebird): dump ptimal_buffer_level_ms + // TODO(angiebird): dump maximum_buffer_size_ms + + // Frame drop threshold. + DUMP_STRUCT_VALUE(oxcf, drop_frames_water_mark); + + // controlling quality + DUMP_STRUCT_VALUE(oxcf, fixed_q); + DUMP_STRUCT_VALUE(oxcf, worst_allowed_q); + DUMP_STRUCT_VALUE(oxcf, best_allowed_q); + DUMP_STRUCT_VALUE(oxcf, cq_level); + DUMP_STRUCT_VALUE(oxcf, aq_mode); + + // Special handling of Adaptive Quantization for AltRef frames + DUMP_STRUCT_VALUE(oxcf, alt_ref_aq); + + // Internal frame size scaling. + DUMP_STRUCT_VALUE(oxcf, resize_mode); + DUMP_STRUCT_VALUE(oxcf, scaled_frame_width); + DUMP_STRUCT_VALUE(oxcf, scaled_frame_height); + + // Enable feature to reduce the frame quantization every x frames. + DUMP_STRUCT_VALUE(oxcf, frame_periodic_boost); + + // two pass datarate control + DUMP_STRUCT_VALUE(oxcf, two_pass_vbrbias); + DUMP_STRUCT_VALUE(oxcf, two_pass_vbrmin_section); + DUMP_STRUCT_VALUE(oxcf, two_pass_vbrmax_section); + DUMP_STRUCT_VALUE(oxcf, vbr_corpus_complexity); + // END DATARATE CONTROL OPTIONS + // ---------------------------------------------------------------- + + // Spatial and temporal scalability. + DUMP_STRUCT_VALUE(oxcf, ss_number_layers); + DUMP_STRUCT_VALUE(oxcf, ts_number_layers); + + // Bitrate allocation for spatial layers. + // TODO(angiebird): dump layer_target_bitrate[VPX_MAX_LAYERS] + // TODO(angiebird): dump ss_target_bitrate[VPX_SS_MAX_LAYERS] + // TODO(angiebird): dump ss_enable_auto_arf[VPX_SS_MAX_LAYERS] + // TODO(angiebird): dump ts_rate_decimator[VPX_TS_MAX_LAYERS] + + DUMP_STRUCT_VALUE(oxcf, enable_auto_arf); + DUMP_STRUCT_VALUE(oxcf, encode_breakout); + DUMP_STRUCT_VALUE(oxcf, error_resilient_mode); + DUMP_STRUCT_VALUE(oxcf, frame_parallel_decoding_mode); + + DUMP_STRUCT_VALUE(oxcf, arnr_max_frames); + DUMP_STRUCT_VALUE(oxcf, arnr_strength); + + DUMP_STRUCT_VALUE(oxcf, min_gf_interval); + DUMP_STRUCT_VALUE(oxcf, max_gf_interval); + + DUMP_STRUCT_VALUE(oxcf, tile_columns); + DUMP_STRUCT_VALUE(oxcf, tile_rows); + + DUMP_STRUCT_VALUE(oxcf, enable_tpl_model); + + DUMP_STRUCT_VALUE(oxcf, max_threads); + + DUMP_STRUCT_VALUE(oxcf, target_level); + + // TODO(angiebird): dump two_pass_stats_in + +#if CONFIG_FP_MB_STATS + // TODO(angiebird): dump firstpass_mb_stats_in +#endif + + DUMP_STRUCT_VALUE(oxcf, tuning); + DUMP_STRUCT_VALUE(oxcf, content); +#if CONFIG_VP9_HIGHBITDEPTH + DUMP_STRUCT_VALUE(oxcf, use_highbitdepth); +#endif + DUMP_STRUCT_VALUE(oxcf, color_space); + DUMP_STRUCT_VALUE(oxcf, color_range); + DUMP_STRUCT_VALUE(oxcf, render_width); + DUMP_STRUCT_VALUE(oxcf, render_height); + DUMP_STRUCT_VALUE(oxcf, temporal_layering_mode); + + DUMP_STRUCT_VALUE(oxcf, row_mt); + DUMP_STRUCT_VALUE(oxcf, motion_vector_unit_test); +} + +FRAME_INFO vp9_get_frame_info(const VP9EncoderConfig *oxcf) { + FRAME_INFO frame_info; + int dummy; + frame_info.frame_width = oxcf->width; + frame_info.frame_height = oxcf->height; + frame_info.render_frame_width = oxcf->width; + frame_info.render_frame_height = oxcf->height; + frame_info.bit_depth = oxcf->bit_depth; + vp9_set_mi_size(&frame_info.mi_rows, &frame_info.mi_cols, &dummy, + frame_info.frame_width, frame_info.frame_height); + vp9_set_mb_size(&frame_info.mb_rows, &frame_info.mb_cols, &frame_info.num_mbs, + frame_info.mi_rows, frame_info.mi_cols); + // TODO(angiebird): Figure out how to get subsampling_x/y here + return frame_info; +} + +void vp9_set_first_pass_stats(VP9EncoderConfig *oxcf, + const vpx_fixed_buf_t *stats) { + oxcf->two_pass_stats_in = *stats; +} |