/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/ #include <limits.h> #include <math.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> #include <string.h>
aom_timing_info_type_t timing_info_type; unsignedint frame_parallel_decoding_mode; int enable_dual_filter; unsignedint enable_chroma_deltaq;
AQ_MODE aq_mode;
DELTAQ_MODE deltaq_mode; int deltaq_strength; int deltalf_mode; unsignedint frame_periodic_boost;
aom_tune_content content;
aom_color_primaries_t color_primaries;
aom_transfer_characteristics_t transfer_characteristics;
aom_matrix_coefficients_t matrix_coefficients;
aom_chroma_sample_position_t chroma_sample_position; int color_range; int render_width; int render_height;
aom_superblock_size_t superblock_size; unsignedint single_tile_decoding; int error_resilient_mode; int s_frame_mode;
int film_grain_test_vector; constchar *film_grain_table_filename; unsignedint motion_vector_unit_test; #if CONFIG_FPMT_TEST unsignedint fpmt_unit_test; #endif unsignedint cdf_update_mode; int enable_rect_partitions; // enable rectangular partitions for sequence int enable_ab_partitions; // enable AB partitions for sequence int enable_1to4_partitions; // enable 1:4 and 4:1 partitions for sequence int min_partition_size; // min partition size [4,8,16,32,64,128] int max_partition_size; // max partition size [4,8,16,32,64,128] int enable_intra_edge_filter; // enable intra-edge filter for sequence int enable_order_hint; // enable order hint for sequence int enable_tx64; // enable 64-pt transform usage for sequence int enable_flip_idtx; // enable flip and identity transform types int enable_rect_tx; // enable rectangular transform usage for sequence int enable_dist_wtd_comp; // enable dist wtd compound for sequence int max_reference_frames; // maximum number of references per frame int enable_reduced_reference_set; // enable reduced set of references int enable_ref_frame_mvs; // sequence level int allow_ref_frame_mvs; // frame level int enable_masked_comp; // enable masked compound for sequence int enable_onesided_comp; // enable one sided compound for sequence int enable_interintra_comp; // enable interintra compound for sequence int enable_smooth_interintra; // enable smooth interintra mode usage int enable_diff_wtd_comp; // enable diff-wtd compound usage int enable_interinter_wedge; // enable interinter-wedge compound usage int enable_interintra_wedge; // enable interintra-wedge compound usage int enable_global_motion; // enable global motion usage for sequence int enable_warped_motion; // sequence level int allow_warped_motion; // frame level int enable_filter_intra; // enable filter intra for sequence int enable_smooth_intra; // enable smooth intra modes for sequence int enable_paeth_intra; // enable Paeth intra mode for sequence int enable_cfl_intra; // enable CFL uv intra mode for sequence int enable_directional_intra; // enable directional modes for sequence int enable_diagonal_intra; // enable D45 to D203 intra modes for sequence int enable_superres; int enable_overlay; // enable overlay for filtered arf frames int enable_palette; int enable_intrabc; int enable_angle_delta; #if CONFIG_DENOISE float noise_level; int noise_block_size; int enable_dnl_denoising; #endif
unsignedint chroma_subsampling_x; unsignedint chroma_subsampling_y; int reduced_tx_type_set; int use_intra_dct_only; int use_inter_dct_only; int use_intra_default_tx_only; int enable_tx_size_search; int quant_b_adapt; unsignedint vbr_corpus_complexity_lap;
AV1_LEVEL target_seq_level_idx[MAX_NUM_OPERATING_POINTS]; // Bit mask to specify which tier each of the 32 possible operating points // conforms to. unsignedint tier_mask; // min_cr / 100 is the target minimum compression ratio for each frame. unsignedint min_cr;
COST_UPDATE_TYPE coeff_cost_upd_freq;
COST_UPDATE_TYPE mode_cost_upd_freq;
COST_UPDATE_TYPE mv_cost_upd_freq;
COST_UPDATE_TYPE dv_cost_upd_freq; unsignedint ext_tile_debug; unsignedint sb_multipass_unit_test; // Total number of passes. If this number is -1, then we assume passes = 1 or // 2 (passes = 1 if pass == AOM_RC_ONE_PASS and passes = 2 otherwise). int passes; int fwd_kf_dist;
LOOPFILTER_CONTROL loopfilter_control; // Indicates if the application of post-processing filters should be skipped // on reconstructed frame. unsignedint skip_postproc_filtering; // the name of the second pass output file when passes > 2 constchar *two_pass_output; constchar *second_pass_log; // Automatically determine whether to disable several intra tools // when "--deltaq-mode=3" is true. // Default as 0. // When set to 1, the encoder will analyze the reconstruction quality // as compared to the source image in the preprocessing pass. // If the recontruction quality is considered high enough, we disable // the following intra coding tools, for better encoding speed: // "--enable_smooth_intra", // "--enable_paeth_intra", // "--enable_cfl_intra", // "--enable_diagonal_intra". int auto_intra_tools_off; int strict_level_conformance; int kf_max_pyr_height; int sb_qp_sweep;
};
// Called by encoder_encode() only. Must not be called by encoder_init() // because the `error` paramerer will be destroyed by aom_codec_enc_init_ver() // after encoder_init() returns an error. See the "IMPORTANT" comment in // aom_codec_enc_init_ver(). static aom_codec_err_t update_error_state(
aom_codec_alg_priv_t *ctx, conststruct aom_internal_error_info *error) { const aom_codec_err_t res = error->error_code;
// This function deep copies a string src to *dst. For default string we will // use a string literal, and otherwise we will allocate memory for the string. static aom_codec_err_t allocate_and_set_string(constchar *src, constchar *default_src, constchar **dst, char *err_detail) { if (!src) {
snprintf(err_detail, ARG_ERR_MSG_MAX_LEN, "Null pointer given to a string parameter."); return AOM_CODEC_INVALID_PARAM;
} if (*dst && strcmp(src, *dst) == 0) return AOM_CODEC_OK; // If the input is exactly the same as default, we will use the string // literal, so do not free here. if (*dst != default_src) {
aom_free((void *)*dst);
}
if (default_src && strcmp(src, default_src) == 0) { // default_src should be a string literal
*dst = default_src;
} else {
size_t len = strlen(src) + 1; char *tmp = aom_malloc(len * sizeof(*tmp)); if (!tmp) {
snprintf(err_detail, ARG_ERR_MSG_MAX_LEN, "Failed to allocate memory for copying parameters."); return AOM_CODEC_MEM_ERROR;
}
memcpy(tmp, src, len);
*dst = tmp;
} return 0;
}
#undef ERROR #define ERROR(str) \ do { \
ctx->base.err_detail = str; \ return AOM_CODEC_INVALID_PARAM; \
} while (0)
#define RANGE_CHECK(p, memb, lo, hi) \ do { \ if (!((p)->memb >= (lo) && (p)->memb <= (hi))) \
ERROR(#memb" out of range ["#lo".."#hi"]"); \
} while (0)
#define RANGE_CHECK_HI(p, memb, hi) \ do { \ if (!((p)->memb <= (hi))) ERROR(#memb" out of range [.."#hi"]"); \
} while (0)
#define RANGE_CHECK_BOOL(p, memb) \ do { \ if (!!((p)->memb) != (p)->memb) ERROR(#memb" expected boolean"); \
} while (0)
static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx, const aom_codec_enc_cfg_t *cfg, conststruct av1_extracfg *extra_cfg) {
RANGE_CHECK(cfg, g_w, 1, 65536); // 16 bits available
RANGE_CHECK(cfg, g_h, 1, 65536); // 16 bits available
RANGE_CHECK_HI(cfg, g_forced_max_frame_width, 65536); // 16 bits available
RANGE_CHECK_HI(cfg, g_forced_max_frame_height, 65536); // 16 bits available if (cfg->g_forced_max_frame_width) {
RANGE_CHECK_HI(cfg, g_w, cfg->g_forced_max_frame_width);
} if (cfg->g_forced_max_frame_height) {
RANGE_CHECK_HI(cfg, g_h, cfg->g_forced_max_frame_height);
} // To avoid integer overflows when multiplying width by height (or values // derived from width and height) using the int type, impose a maximum frame // area (width * height) of 2^30. constunsignedint max_frame_width =
cfg->g_forced_max_frame_width ? cfg->g_forced_max_frame_width : cfg->g_w; constunsignedint max_frame_height = cfg->g_forced_max_frame_height
? cfg->g_forced_max_frame_height
: cfg->g_h; const int64_t max_frame_area = (int64_t)max_frame_width * max_frame_height; if (max_frame_area > (1 << 30)) {
ERROR("max_frame_area out of range [..2^30]");
}
RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
RANGE_CHECK(cfg, g_timebase.num, 1, 1000000000);
RANGE_CHECK_HI(cfg, g_profile, MAX_PROFILES - 1);
if (cfg->g_usage != ALLINTRA &&
extra_cfg->deltaq_mode == DELTA_Q_VARIANCE_BOOST) {
ERROR("Variance Boost (deltaq_mode = 6) can only be set in all intra mode");
}
if (extra_cfg->passes != -1 && (int)cfg->g_pass > extra_cfg->passes) {
ERROR("Current pass is larger than total number of passes.");
}
if (cfg->g_profile == (unsignedint)PROFILE_1 && cfg->monochrome) {
ERROR("Monochrome is not supported in profile 1");
}
if (cfg->g_profile <= (unsignedint)PROFILE_1 &&
cfg->g_bit_depth > AOM_BITS_10) {
ERROR("Codec bit-depth 12 not supported in profile < 2");
} if (cfg->g_profile <= (unsignedint)PROFILE_1 &&
cfg->g_input_bit_depth > 10) {
ERROR("Source bit-depth 12 not supported in profile < 2");
}
if (cfg->rc_end_usage == AOM_Q) {
RANGE_CHECK_HI(cfg, use_fixed_qp_offsets, 1);
} else { if (cfg->use_fixed_qp_offsets > 0) {
ERROR("--use_fixed_qp_offsets can only be used with --end-usage=q");
}
}
RANGE_CHECK(extra_cfg, color_primaries, AOM_CICP_CP_BT_709,
AOM_CICP_CP_EBU_3213); // Need to check range more precisely to // check for reserved values?
RANGE_CHECK(extra_cfg, transfer_characteristics, AOM_CICP_TC_BT_709,
AOM_CICP_TC_HLG);
RANGE_CHECK(extra_cfg, matrix_coefficients, AOM_CICP_MC_IDENTITY,
AOM_CICP_MC_ICTCP);
RANGE_CHECK(extra_cfg, color_range, 0, 1);
/* Average corpus complexity is supported only in the case of single pass
* VBR*/ if (cfg->g_pass == AOM_RC_ONE_PASS && cfg->rc_end_usage == AOM_VBR)
RANGE_CHECK_HI(extra_cfg, vbr_corpus_complexity_lap,
MAX_VBR_CORPUS_COMPLEXITY); elseif (extra_cfg->vbr_corpus_complexity_lap != 0)
ERROR( "VBR corpus complexity is supported only in the case of single pass " "VBR mode.");
#if !CONFIG_TUNE_BUTTERAUGLI if (extra_cfg->tuning == AOM_TUNE_BUTTERAUGLI) {
ERROR( "This error may be related to the wrong configuration options: try to " "set -DCONFIG_TUNE_BUTTERAUGLI=1 at the time CMake is run.");
} #endif
#if !CONFIG_TUNE_VMAF if (extra_cfg->tuning >= AOM_TUNE_VMAF_WITH_PREPROCESSING &&
extra_cfg->tuning <= AOM_TUNE_VMAF_NEG_MAX_GAIN) {
ERROR( "This error may be related to the wrong configuration options: try to " "set -DCONFIG_TUNE_VMAF=1 at the time CMake is run.");
} #endif
if (extra_cfg->lossless) { if (extra_cfg->aq_mode != 0)
ERROR("Only --aq_mode=0 can be used with --lossless=1."); if (extra_cfg->enable_chroma_deltaq)
ERROR("Only --enable_chroma_deltaq=0 can be used with --lossless=1.");
}
for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) { constint level_idx = extra_cfg->target_seq_level_idx[i]; if (!is_valid_seq_level_idx(level_idx) &&
level_idx != SEQ_LEVEL_KEEP_STATS) {
ERROR("Target sequence level index is invalid");
}
}
RANGE_CHECK(extra_cfg, kf_max_pyr_height, -1, 5); if (extra_cfg->kf_max_pyr_height != -1 &&
extra_cfg->kf_max_pyr_height < (int)extra_cfg->gf_min_pyr_height) {
ERROR( "The value of kf-max-pyr-height should not be smaller than " "gf-min-pyr-height");
}
return AOM_CODEC_OK;
}
static aom_codec_err_t validate_img(aom_codec_alg_priv_t *ctx, const aom_image_t *img) { switch (img->fmt) { case AOM_IMG_FMT_YV12: case AOM_IMG_FMT_NV12: case AOM_IMG_FMT_I420: case AOM_IMG_FMT_YV1216: case AOM_IMG_FMT_I42016: break; case AOM_IMG_FMT_I444: case AOM_IMG_FMT_I44416: if (ctx->cfg.g_profile == (unsignedint)PROFILE_0 &&
!ctx->cfg.monochrome) {
ERROR("Invalid image format. I444 images not supported in profile.");
} break; case AOM_IMG_FMT_I422: case AOM_IMG_FMT_I42216: if (ctx->cfg.g_profile != (unsignedint)PROFILE_2) {
ERROR("Invalid image format. I422 images not supported in profile.");
} break; default:
ERROR( "Invalid image format. Only YV12, NV12, I420, I422, I444 images are " "supported."); break;
}
if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
ERROR("Image size must match encoder init configuration size");
#if CONFIG_TUNE_BUTTERAUGLI if (ctx->extra_cfg.tuning == AOM_TUNE_BUTTERAUGLI) { if (img->bit_depth > 8) {
ERROR("Only 8 bit depth images supported in tune=butteraugli mode.");
} if (img->mc != 0 && img->mc != AOM_CICP_MC_BT_709 &&
img->mc != AOM_CICP_MC_BT_601 && img->mc != AOM_CICP_MC_BT_470_B_G) {
ERROR( "Only BT.709 and BT.601 matrix coefficients supported in " "tune=butteraugli mode. Identity matrix is treated as BT.601.");
}
} #endif
return AOM_CODEC_OK;
}
staticint get_image_bps(const aom_image_t *img) { switch (img->fmt) { case AOM_IMG_FMT_YV12: case AOM_IMG_FMT_NV12: case AOM_IMG_FMT_I420: return 12; case AOM_IMG_FMT_I422: return 16; case AOM_IMG_FMT_I444: return 24; case AOM_IMG_FMT_YV1216: case AOM_IMG_FMT_I42016: return 24; case AOM_IMG_FMT_I42216: return 32; case AOM_IMG_FMT_I44416: return 48; default: assert(0 && "Invalid image format"); break;
} return 0;
}
staticvoid set_auto_tiles(TileConfig *const tile_cfg, unsignedint width, unsignedint height, unsignedint threads) { int tile_cols_log2 = 0; int tile_rows_log2 = 0; if (threads < 2) return; // Avoid small tiles because they are particularly bad for coding. // Use no more tiles than the number of threads. Aim for one tile per // thread. Using more than one thread inside one tile could be less // efficient. Using more tiles than the number of threads would result // in a compression penalty without much benefit. const uint32_t kMinTileArea = 128 * 128; const uint32_t kMaxTiles = 32;
uint32_t frame_area = width * height;
uint32_t tiles = (frame_area + kMinTileArea - 1) / kMinTileArea; if (tiles > kMaxTiles) {
tiles = kMaxTiles;
} if (tiles > threads) {
tiles = threads;
} int tiles_log2 = (int)log2(tiles); // If the frame width is equal or greater than the height, use more tile // columns than tile rows. if (width >= height) {
tile_cols_log2 = (tiles_log2 + 1) / 2;
tile_rows_log2 = tiles_log2 - tile_cols_log2;
} else {
tile_rows_log2 = (tiles_log2 + 1) / 2;
tile_cols_log2 = tiles_log2 - tile_rows_log2;
}
tile_cfg->tile_columns = tile_cols_log2;
tile_cfg->tile_rows = tile_rows_log2;
}
// Explicitly disable global motion in a few cases: // * For realtime mode, we never search global motion, and disabling // it here prevents later code from allocating buffers we don't need // * For large scale tile mode, some of the intended use cases expect // all frame headers to be identical. This breaks if global motion is // used, since global motion data is stored in the frame header. // eg, see test/lightfield_test.sh, which checks that all frame headers // are the same.
tool_cfg->enable_global_motion = extra_cfg->enable_global_motion &&
cfg->g_usage != AOM_USAGE_REALTIME &&
!cfg->large_scale_tile;
oxcf->speed = extra_cfg->cpu_used; // TODO(yunqingwang, any) In REALTIME mode, 1080p performance at speed 5 & 6 // is quite bad. Force to use speed 7 for now. Will investigate it when we // work on rd path optimization later. if (oxcf->mode == REALTIME && AOMMIN(cfg->g_w, cfg->g_h) >= 1080 &&
oxcf->speed < 7)
oxcf->speed = 7;
// Set Color related configuration.
color_cfg->color_primaries = extra_cfg->color_primaries;
color_cfg->transfer_characteristics = extra_cfg->transfer_characteristics;
color_cfg->matrix_coefficients = extra_cfg->matrix_coefficients;
color_cfg->color_range = extra_cfg->color_range;
color_cfg->chroma_sample_position = extra_cfg->chroma_sample_position;
// Set Group of frames configuration. // Force lag_in_frames to 0 for REALTIME mode
gf_cfg->lag_in_frames = (oxcf->mode == REALTIME)
? 0
: clamp(cfg->g_lag_in_frames, 0, MAX_LAG_BUFFERS);
gf_cfg->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
gf_cfg->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
gf_cfg->min_gf_interval = extra_cfg->min_gf_interval;
gf_cfg->max_gf_interval = extra_cfg->max_gf_interval;
gf_cfg->gf_min_pyr_height = extra_cfg->gf_min_pyr_height;
gf_cfg->gf_max_pyr_height = extra_cfg->gf_max_pyr_height;
#if CONFIG_AV1_TEMPORAL_DENOISING // Temporal denoiser is for nonrd pickmode so disable it for speed < 7. // Also disable it for speed 7 for now since it needs to be modified for // the check_partition_merge_mode feature. if (cfg->g_bit_depth == AOM_BITS_8 && oxcf->speed > 7) {
oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
} else {
oxcf->noise_sensitivity = 0;
} #endif // Set Tile related configuration.
tile_cfg->num_tile_groups = extra_cfg->num_tg; // In large-scale tile encoding mode, num_tile_groups is always 1. if (cfg->large_scale_tile) tile_cfg->num_tile_groups = 1;
tile_cfg->mtu = extra_cfg->mtu_size;
tile_cfg->enable_large_scale_tile = cfg->large_scale_tile;
tile_cfg->enable_single_tile_decoding =
(tile_cfg->enable_large_scale_tile) ? extra_cfg->single_tile_decoding : 0; if (extra_cfg->auto_tiles) {
set_auto_tiles(tile_cfg, cfg->g_w, cfg->g_h, cfg->g_threads);
extra_cfg->tile_columns = tile_cfg->tile_columns;
extra_cfg->tile_rows = tile_cfg->tile_rows;
} else {
tile_cfg->tile_columns = extra_cfg->tile_columns;
tile_cfg->tile_rows = extra_cfg->tile_rows;
}
tile_cfg->tile_width_count = AOMMIN(cfg->tile_width_count, MAX_TILE_COLS);
tile_cfg->tile_height_count = AOMMIN(cfg->tile_height_count, MAX_TILE_ROWS); for (int i = 0; i < tile_cfg->tile_width_count; i++) {
tile_cfg->tile_widths[i] = cfg->tile_widths[i];
} for (int i = 0; i < tile_cfg->tile_height_count; i++) {
tile_cfg->tile_heights[i] = cfg->tile_heights[i];
}
tile_cfg->enable_ext_tile_debug = extra_cfg->ext_tile_debug;
if (tile_cfg->enable_large_scale_tile) { // The superblock_size can only be AOM_SUPERBLOCK_SIZE_64X64 or // AOM_SUPERBLOCK_SIZE_128X128 while tile_cfg->enable_large_scale_tile = 1. // If superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC, hard set it to // AOM_SUPERBLOCK_SIZE_64X64(default value in large_scale_tile). if (extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_64X64 &&
extra_cfg->superblock_size != AOM_SUPERBLOCK_SIZE_128X128)
tool_cfg->superblock_size = AOM_SUPERBLOCK_SIZE_64X64;
}
// Set reference frame related configuration.
oxcf->ref_frm_cfg.max_reference_frames = extra_cfg->max_reference_frames;
oxcf->ref_frm_cfg.enable_reduced_reference_set =
extra_cfg->enable_reduced_reference_set;
oxcf->ref_frm_cfg.enable_onesided_comp = extra_cfg->enable_onesided_comp;
if (input_cfg->limit == 1) { // still picture mode, display model and timing is meaningless
dec_model_cfg->display_model_info_present_flag = 0;
dec_model_cfg->timing_info_present = 0;
}
oxcf->save_as_annexb = cfg->save_as_annexb;
// Set unit test related configuration.
oxcf->unit_test_cfg.motion_vector_unit_test =
extra_cfg->motion_vector_unit_test;
oxcf->unit_test_cfg.sb_multipass_unit_test =
extra_cfg->sb_multipass_unit_test;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.