diff --git a/app/oapv_app_args.h b/app/oapv_app_args.h index 55711ed..f6e85c3 100644 --- a/app/oapv_app_args.h +++ b/app/oapv_app_args.h @@ -69,6 +69,7 @@ struct args_parser { int (*get_int)(args_parser_t *args, char *keyl, int *val, int *flag); int (*set_str)(args_parser_t *args, char *keyl, char *str); int (*set_int)(args_parser_t *args, char *keyl, int val); + int (*set_int2str)(args_parser_t* args, char* keyl, int val); int (*set_flag)(args_parser_t *args, char *keyl, int flag); int (*check_mandatory)(args_parser_t *args, char **err_arg); @@ -406,6 +407,21 @@ static int args_set_int(args_parser_t *args, char *keyl, int val) } } +static int args_set_int2str(args_parser_t* args, char* keyl, int val) +{ + int idx; + + idx = args_search_long_key(args->opts, keyl); + if (idx >= 0) { + sprintf((char*)(args->opts[idx].val), "%d", val); + args->opts[idx].flag = 1; + return 0; + } + else { + return -1; + } +} + static int args_set_flag(args_parser_t *args, char *keyl, int flag) { int idx; @@ -572,6 +588,7 @@ static args_parser_t *args_create(const args_opt_t *opt_table, int num_opt) args->get_int = args_get_int; args->set_str = args_set_str; args->set_int = args_set_int; + args->set_int2str = args_set_int2str; args->set_flag = args_set_flag; args->check_mandatory = args_check_mandatory; diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 58fa94c..1341b47 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -70,18 +70,18 @@ static const args_opt_t enc_args_opts[] = { "file name of reconstructed video" }, { - 'w', "width", ARGS_VAL_TYPE_INTEGER | ARGS_VAL_TYPE_MANDATORY, 0, NULL, + 'w', "width", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, "pixel width of input video" }, { - 'h', "height", ARGS_VAL_TYPE_INTEGER | ARGS_VAL_TYPE_MANDATORY, 0, NULL, + 'h', "height", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, "pixel height of input video" }, { - 'q', "qp", ARGS_VAL_TYPE_INTEGER, 0, NULL, + 'q', "qp", ARGS_VAL_TYPE_STRING, 0, NULL, "QP value: 0 ~ (63 + (bitdepth - 10)*6) \n" " - 10bit input: 0 ~ 63\n" - " - 12bit input: 0 ~ 75\n" + " - 12bit input: 0 ~ 75" }, { 'z', "fps", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, @@ -89,7 +89,8 @@ static const args_opt_t enc_args_opts[] = { }, { 'm', "threads", ARGS_VAL_TYPE_INTEGER, 0, NULL, - "force to use a specific number of threads" + "force to use a specific number of threads\n" + " - '0' means decision of the number automatically" }, { ARGS_NO_KEY, "preset", ARGS_VAL_TYPE_STRING, 0, NULL, @@ -142,12 +143,12 @@ static const args_opt_t enc_args_opts[] = { "QP offset value for Component 3" }, { - ARGS_NO_KEY, "tile-w-mb", ARGS_VAL_TYPE_INTEGER, 0, NULL, - "width of tile in units of MBs" + ARGS_NO_KEY, "tile-w", ARGS_VAL_TYPE_STRING, 0, NULL, + "width of tile in units of pixels" }, { - ARGS_NO_KEY, "tile-h-mb", ARGS_VAL_TYPE_INTEGER, 0, NULL, - "height of tile in units of MBs" + ARGS_NO_KEY, "tile-h", ARGS_VAL_TYPE_STRING, 0, NULL, + "height of tile in units of pixels" }, { ARGS_NO_KEY, "bitrate", ARGS_VAL_TYPE_STRING, 0, NULL, @@ -155,10 +156,6 @@ static const args_opt_t enc_args_opts[] = { " bitrate in terms of kilo-bits per second: Kbps(none,K,k), Mbps(M,m)\n" " ex) 100 = 100K = 0.1M" }, - { - ARGS_NO_KEY, "use-filler", ARGS_VAL_TYPE_INTEGER, 0, NULL, - "user filler flag" - }, { ARGS_NO_KEY, "q-matrix-c0", ARGS_VAL_TYPE_STRING, 0, NULL, "custom quantization matrix for component 0 (Y) \"q1 q2 ... q63 q64\"" @@ -197,13 +194,35 @@ typedef struct args_var { int input_csp; int seek; int threads; - char profile[32]; - char level[32]; - int band; - char bitrate[64]; + + char profile[16]; + char level[16]; + char band[16]; + + char width[16]; + char height[16]; char fps[256]; - char q_matrix[OAPV_MAX_CC][512]; // raster-scan order - char preset[32]; + + char qp[16]; + char qp_offset_c1[16]; + char qp_offset_c2[16]; + char qp_offset_c3[16]; + char bitrate[32]; + + char preset[16]; + + char q_matrix_c0[512]; // raster-scan order + char q_matrix_c1[512]; // raster-scan order + char q_matrix_c2[512]; // raster-scan order + char q_matrix_c3[512]; // raster-scan order + char tile_w[16]; + char tile_h[16]; + + char color_primaries[16]; + char color_transfer[16]; + char color_matrix[16]; + char color_range[16]; + oapve_param_t *param; } args_var_t; @@ -236,33 +255,32 @@ static args_var_t *args_init_vars(args_parser_t *args, oapve_param_t *param) strcpy(vars->profile, "422-10"); args_set_variable_by_key_long(opts, "level", vars->level); strcpy(vars->level, "4.1"); - args_set_variable_by_key_long(opts, "band", &vars->band); - vars->band = 2; /* default */ - args_set_variable_by_key_long(opts, "bitrate", vars->bitrate); + args_set_variable_by_key_long(opts, "band", vars->band); + strcpy(vars->band, "2"); /* default */ + + args_set_variable_by_key_long(opts, "width", vars->width); + args_set_variable_by_key_long(opts, "height", vars->height); args_set_variable_by_key_long(opts, "fps", vars->fps); - strcpy(vars->fps, "60"); - args_set_variable_by_key_long(opts, "q-matrix-c0", vars->q_matrix[0]); - strcpy(vars->q_matrix[0], ""); - args_set_variable_by_key_long(opts, "q-matrix-c1", vars->q_matrix[1]); - strcpy(vars->q_matrix[1], ""); - args_set_variable_by_key_long(opts, "q-matrix-c2", vars->q_matrix[2]); - strcpy(vars->q_matrix[2], ""); - args_set_variable_by_key_long(opts, "q-matrix-c3", vars->q_matrix[3]); - strcpy(vars->q_matrix[3], ""); + + args_set_variable_by_key_long(opts, "qp", vars->qp); + args_set_variable_by_key_long(opts, "qp_offset_c1", vars->qp_offset_c1); + args_set_variable_by_key_long(opts, "qp_offset_c2", vars->qp_offset_c2); + args_set_variable_by_key_long(opts, "qp_offset_c3", vars->qp_offset_c3); + + + args_set_variable_by_key_long(opts, "bitrate", vars->bitrate); + args_set_variable_by_key_long(opts, "q-matrix-c0", vars->q_matrix_c0); + args_set_variable_by_key_long(opts, "q-matrix-c1", vars->q_matrix_c1); + args_set_variable_by_key_long(opts, "q-matrix-c2", vars->q_matrix_c2); + args_set_variable_by_key_long(opts, "q-matrix-c3", vars->q_matrix_c3); + args_set_variable_by_key_long(opts, "threads", &vars->threads); - vars->threads = 1; /* default */ + vars->threads = OAPVE_CDESC_THREADS_AUTO; /* default */ + + args_set_variable_by_key_long(opts, "tile-w", vars->tile_w); + args_set_variable_by_key_long(opts, "tile-h", vars->tile_h); + args_set_variable_by_key_long(opts, "preset", vars->preset); - strcpy(vars->preset, ""); - - ARGS_SET_PARAM_VAR_KEY(opts, param, w); - ARGS_SET_PARAM_VAR_KEY(opts, param, h); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, use_filler); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, tile_w_mb); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, tile_h_mb); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp_offset_c1); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp_offset_c2); - ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp_offset_c3); return vars; } @@ -353,6 +371,29 @@ static void print_commandline(int argc, const char **argv) logv3("\n\n"); } +static void add_thousands_comma_to_number(char *in, char *out) +{ + int len, left = 0; + len = strlen(in); + left = len % 3; + + while(len > 0) { + *out = *in; + + out++; in++; + + left--; + len--; + + if(left == 0 && len >= 3) { + *out = ','; + out++; + left = 3; + } + } + *out='\0'; +} + static void print_config(args_var_t *vars, oapve_param_t *param) { if(op_verbose < VERBOSE_FRAME) @@ -367,16 +408,21 @@ static void print_config(args_var_t *vars, oapve_param_t *param) logv3("Reconstructed sequence : %s \n", vars->fname_rec); } logv3(" profile = %s\n", vars->profile); + logv3(" level = %s\n", vars->level); + logv3(" band = %s\n", vars->band); logv3(" width = %d\n", param->w); logv3(" height = %d\n", param->h); - logv3(" FPS = %.2f\n", (float)param->fps_num / param->fps_den); - logv3(" QP = %d\n", param->qp); - logv3(" max number of AUs = %d\n", vars->max_au); - logv3(" rate control type = %s\n", (param->rc_type == OAPV_RC_ABR) ? "average Bitrate" : "constant QP"); - if(param->rc_type == OAPV_RC_ABR) { - logv3(" target bitrate = %dkbps\n", param->bitrate); + logv3(" fps = %.2f\n", (float)param->fps_num / param->fps_den); + logv3(" rate control type = %s\n", (param->rc_type == OAPV_RC_ABR) ? "average bitrate" : "constant qp"); + if(param->rc_type == OAPV_RC_CQP){ + logv3(" qp = %d\n", param->qp); + } + else if(param->rc_type == OAPV_RC_ABR) { + //add_thousands_comma_to_number(vars->bitrate, tstr); + logv3(" target bitrate = %s\n", vars->bitrate); } - logv3(" tile size = %d x %d\n", param->tile_w_mb * OAPV_MB_W, param->tile_h_mb * OAPV_MB_H); + logv3(" max number of AUs = %d\n", vars->max_au); + logv3(" tile size = %d x %d\n", param->tile_w, param->tile_h); } static void print_stat_au(oapve_stat_t *stat, int au_cnt, oapve_param_t *param, int max_au, double bitrate_tot, oapv_clk_t clk_au, oapv_clk_t clk_tot) @@ -462,108 +508,47 @@ static int kbps_str_to_int(char *str) return kbps; } +#define UPDATE_A_PARAM_W_KEY_VAL(param, key, val) \ + if(strlen(val) > 0) { \ + if(OAPV_FAILED(oapve_param_parse(param, key, val))) { \ + logerr("input value (%s) of %s is invalid\n", val, key); \ + return -1; \ + } \ + } + static int update_param(args_var_t *vars, oapve_param_t *param) { - int q_len[OAPV_MAX_CC]; - /* update reate controller parameters */ - if(strlen(vars->bitrate) > 0) { - param->bitrate = kbps_str_to_int(vars->bitrate); - param->rc_type = OAPV_RC_ABR; - } - - /* update q_matrix */ - for(int c = 0; c < OAPV_MAX_CC; c++) { - q_len[c] = (int)strlen(vars->q_matrix[c]); - if(q_len[c] > 0) { - param->use_q_matrix = 1; - char *qstr = vars->q_matrix[c]; - int qcnt = 0; - while(strlen(qstr) > 0 && qcnt < OAPV_BLK_D) { - int t0, read; - sscanf(qstr, "%d%n", &t0, &read); - if(t0 < 1 || t0 > 255) { - logerr("input value (%d) for q_matrix[%d][%d] is invalid\n", t0, c, qcnt); - return -1; - } - param->q_matrix[c][qcnt] = t0; - qstr += read; - qcnt++; - } - if(qcnt < OAPV_BLK_D) { - logerr("input number of q_matrix[%d] is not enough\n", c); - return -1; - } - } - } + UPDATE_A_PARAM_W_KEY_VAL(param, "profile", vars->profile); + UPDATE_A_PARAM_W_KEY_VAL(param, "level", vars->level); + UPDATE_A_PARAM_W_KEY_VAL(param, "band", vars->band); - param->csp = vars->input_csp; + UPDATE_A_PARAM_W_KEY_VAL(param, "width", vars->width); + UPDATE_A_PARAM_W_KEY_VAL(param, "height", vars->height); + UPDATE_A_PARAM_W_KEY_VAL(param, "fps", vars->fps); - /* update level idc */ - float tmp_level = 0; - sscanf(vars->level, "%f", &tmp_level); - param->level_idc = (int)((tmp_level * 30.0) + 0.5); - /* update band idc */ - param->band_idc = vars->band; + UPDATE_A_PARAM_W_KEY_VAL(param, "qp", vars->qp); + UPDATE_A_PARAM_W_KEY_VAL(param, "qp-offset-c1", vars->qp_offset_c1); + UPDATE_A_PARAM_W_KEY_VAL(param, "qp-offset-c2", vars->qp_offset_c2); + UPDATE_A_PARAM_W_KEY_VAL(param, "qp-offset-c3", vars->qp_offset_c3); + UPDATE_A_PARAM_W_KEY_VAL(param, "bitrate", vars->bitrate); - /* update fps */ - if(strpbrk(vars->fps, "/") != NULL) { - sscanf(vars->fps, "%d/%d", ¶m->fps_num, ¶m->fps_den); - } - else if(strpbrk(vars->fps, ".") != NULL) { - float tmp_fps = 0; - sscanf(vars->fps, "%f", &tmp_fps); - param->fps_num = tmp_fps * 10000; - param->fps_den = 10000; - } - else { - sscanf(vars->fps, "%d", ¶m->fps_num); - param->fps_den = 1; - } + UPDATE_A_PARAM_W_KEY_VAL(param, "preset", vars->preset); - if(strlen(vars->preset) > 0) { - if(strcmp(vars->preset, "fastest") == 0) { - param->preset = OAPV_PRESET_FASTEST; - } - else if(strcmp(vars->preset, "fast") == 0) { - param->preset = OAPV_PRESET_FAST; - } - else if(strcmp(vars->preset, "medium") == 0) { - param->preset = OAPV_PRESET_MEDIUM; - } - else if(strcmp(vars->preset, "slow") == 0) { - param->preset = OAPV_PRESET_SLOW; - } - else if(strcmp(vars->preset, "placebo") == 0) { - param->preset = OAPV_PRESET_PLACEBO; - } - else { - logerr("input value of preset is invalid\n"); - return -1; - } - } - else { - param->preset = OAPV_PRESET_DEFAULT; - } + UPDATE_A_PARAM_W_KEY_VAL(param, "q-matrix-c0", vars->q_matrix_c0); + UPDATE_A_PARAM_W_KEY_VAL(param, "q-matrix-c1", vars->q_matrix_c1); + UPDATE_A_PARAM_W_KEY_VAL(param, "q-matrix-c2", vars->q_matrix_c2); + UPDATE_A_PARAM_W_KEY_VAL(param, "q-matrix-c3", vars->q_matrix_c3); - /* update tile */ - if (param->tile_w_mb < OAPV_MIN_TILE_W_MB) { - param->tile_w_mb = OAPV_MIN_TILE_W_MB; - } - if (param->tile_h_mb < OAPV_MIN_TILE_H_MB) { - param->tile_h_mb = OAPV_MIN_TILE_H_MB; - } + UPDATE_A_PARAM_W_KEY_VAL(param, "color-primaries", vars->color_primaries); + UPDATE_A_PARAM_W_KEY_VAL(param, "color-transfer", vars->color_transfer); + UPDATE_A_PARAM_W_KEY_VAL(param, "color-matrix", vars->color_matrix); + UPDATE_A_PARAM_W_KEY_VAL(param, "color-range", vars->color_range); - int tile_w = param->tile_w_mb << OAPV_LOG2_MB_W; - int tile_h = param->tile_h_mb << OAPV_LOG2_MB_H; - int tile_cols = (param->w + tile_w - 1) / tile_w; - int tile_rows = (param->h + tile_h - 1) / tile_h; - if (tile_cols > OAPV_MAX_TILE_COLS) { - param->tile_w_mb = (((param->w + OAPV_MB_W - 1) >> OAPV_LOG2_MB_W) + OAPV_MAX_TILE_COLS - 1) / OAPV_MAX_TILE_COLS; - } - if (tile_rows > OAPV_MAX_TILE_ROWS) { - param->tile_h_mb = (((param->h + OAPV_MB_H - 1) >> OAPV_LOG2_MB_H) + OAPV_MAX_TILE_ROWS - 1) / OAPV_MAX_TILE_ROWS; - } + UPDATE_A_PARAM_W_KEY_VAL(param, "tile-w", vars->tile_w); + UPDATE_A_PARAM_W_KEY_VAL(param, "tile-w", vars->tile_h); + + param->csp = vars->input_csp; return 0; } diff --git a/app/oapv_app_y4m.h b/app/oapv_app_y4m.h index e385028..8f6fe79 100644 --- a/app/oapv_app_y4m.h +++ b/app/oapv_app_y4m.h @@ -207,8 +207,8 @@ int y4m_header_parser(FILE *ip_y4m, y4m_params_t *y4m) static void y4m_update_param(args_parser_t *args, y4m_params_t *y4m) { - args->set_int(args, "width", y4m->w); - args->set_int(args, "height", y4m->h); + args->set_int2str(args, "width", y4m->w); + args->set_int2str(args, "height", y4m->h); char tmp_fps[256]; sprintf(tmp_fps, "%d/%d", y4m->fps_num, y4m->fps_den); args->set_str(args, "fps", tmp_fps); diff --git a/inc/oapv.h b/inc/oapv.h index db4a091..d0e9432 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -60,11 +60,13 @@ extern "C" { #define OAPV_BLK_D (OAPV_BLK_W * OAPV_BLK_H) /* size of tile */ -#define OAPV_MAX_TILE_ROWS (20) -#define OAPV_MAX_TILE_COLS (20) +#define OAPV_MAX_TILE_ROWS (20) // max number of tiles in row +#define OAPV_MAX_TILE_COLS (20) // max number of tiles in column #define OAPV_MAX_TILES (OAPV_MAX_TILE_ROWS * OAPV_MAX_TILE_COLS) #define OAPV_MIN_TILE_W_MB (16) #define OAPV_MIN_TILE_H_MB (8) +#define OAPV_MIN_TILE_W (OAPV_MIN_TILE_W_MB << OAPV_LOG2_MB_W) +#define OAPV_MIN_TILE_H (OAPV_MIN_TILE_H_MB << OAPV_LOG2_MB_H) /* maximum number of thread */ #define OAPV_MAX_THREADS (32) @@ -377,16 +379,103 @@ struct oapv_au_info { oapv_frm_info_t frm_info[OAPV_MAX_NUM_FRAMES]; }; +/***************************************************************************** + * constant string values for oapve_param_parse() and command-line options + *****************************************************************************/ +typedef struct oapv_dict_str_int oapv_dict_str_int_t; // dictionary type +struct oapv_dict_str_int { + const char * key; + const int val; +}; + +static const oapv_dict_str_int_t oapv_param_opts_profile[] = { + {"422-10", OAPV_PROFILE_422_10}, + {"", 0} // termination +}; + +static const oapv_dict_str_int_t oapv_param_opts_preset[] = { + {"fastest", OAPV_PRESET_FASTEST}, + {"fast", OAPV_PRESET_FAST}, + {"medium", OAPV_PRESET_MEDIUM}, + {"slow", OAPV_PRESET_SLOW}, + {"placebo", OAPV_PRESET_PLACEBO}, + {"", 0} // termination +}; + +static const oapv_dict_str_int_t oapv_param_opts_color_range[] = { + {"limited", 0}, + {"full", 1}, + {"", 0} // termination +}; + +static const oapv_dict_str_int_t oapv_param_opts_color_primaries[] = { + {"reserved", 0}, + {"bt709", 1}, + {"unspecified", 2}, + {"reserved", 3}, + {"bt470m", 4}, + {"bt470bg", 5}, + {"smpte170m", 6}, + {"smpte240m", 7}, + {"film", 8}, + {"bt2020", 9}, + {"smpte428", 10}, + {"smpte431", 11}, + {"smpte432", 12}, + {"", 0} // termination +}; + +static const oapv_dict_str_int_t oapv_param_opts_color_transfer[] = { + {"reserved", 0}, + {"bt709", 1}, + {"unspecified", 2}, + {"reserved", 3}, + {"bt470m", 4}, + {"bt470bg", 5}, + {"smpte170m", 6}, + {"smpte240m", 7}, + {"linear", 8}, + {"log100", 9}, + {"log316", 10}, + {"iec61966-2-4", 11}, + {"bt1361e", 12}, + {"iec61966-2-1", 13}, + {"bt2020-10", 14}, + {"bt2020-12", 15}, + {"smpte2084", 16}, + {"smpte428", 17}, + {"arib-std-b67", 18}, + {"", 0} // termination +}; +static const oapv_dict_str_int_t oapv_param_opts_color_matrix[] = { + {"gbr", 0}, + {"bt709", 1}, + {"unspecified", 2}, + {"reserved", 3}, + {"fcc", 4}, + {"bt470bg", 5}, + {"smpte170m", 6}, + {"smpte240m", 7}, + {"ycgco", 8}, + {"bt2020nc", 9}, + {"bt2020c", 10}, + {"smpte2085", 11}, + {"chroma-derived-nc", 12}, + {"chroma-derived-c", 13}, + {"ictcp", 14}, + {"", 0} // termination +}; + /***************************************************************************** * coding parameters *****************************************************************************/ typedef struct oapve_param oapve_param_t; struct oapve_param { - /* profile_idc */ + /* profile_idc defined in spec. */ int profile_idc; - /* level */ + /* level_idc defined in spec. */ int level_idc; - /* band */ + /* band_idc defined in spec. */ int band_idc; /* width of input frame */ int w; @@ -417,10 +506,13 @@ struct oapve_param { unsigned char q_matrix[OAPV_MAX_CC][OAPV_BLK_D]; // raster-scan order /* color space */ int csp; - int tile_cols; - int tile_rows; - int tile_w_mb; - int tile_h_mb; + /* NOTE: tile_w and tile_h value can be changed internally, + if the values are not set properly. + the min and max values are defeind in APV specification */ + int tile_w; // width of tile MUST be N * MB width + int tile_h; // height of tile MUST be N * MB height + + /* preset for setting trade-off between complexity and coding gain */ int preset; /* color description values */ int color_description_present_flag; @@ -433,6 +525,8 @@ struct oapve_param { /***************************************************************************** * description for encoder creation *****************************************************************************/ +#define OAPVE_CDESC_THREADS_AUTO 0 + typedef struct oapve_cdesc oapve_cdesc_t; struct oapve_cdesc { int max_bs_buf_size; // max bitstream buffer size @@ -504,6 +598,7 @@ oapve_t OAPV_EXPORT oapve_create(oapve_cdesc_t *cdesc, int *err); void OAPV_EXPORT oapve_delete(oapve_t eid); int OAPV_EXPORT oapve_config(oapve_t eid, int cfg, void *buf, int *size); int OAPV_EXPORT oapve_param_default(oapve_param_t *param); +int OAPV_EXPORT oapve_param_parse(oapve_param_t* param, const char* name, const char* value); int OAPV_EXPORT oapve_encode(oapve_t eid, oapv_frms_t *ifrms, oapvm_t mid, oapv_bitb_t *bitb, oapve_stat_t *stat, oapv_frms_t *rfrms); /***************************************************************************** diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9bee1bc..ee8fec7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -105,7 +105,11 @@ elseif( UNIX OR MINGW ) set_target_properties(${LIB_NAME_BASE}_dynamic PROPERTIES FOLDER lib LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - target_compile_definitions( ${LIB_NAME_BASE} PUBLIC ANY LINUX ) + if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_compile_definitions( ${LIB_NAME_BASE} PUBLIC ANY MACOS ) + else() + target_compile_definitions( ${LIB_NAME_BASE} PUBLIC ANY LINUX ) + endif() target_link_libraries(${LIB_NAME_BASE} m) endif() diff --git a/src/neon/oapv_sad_neon.c b/src/neon/oapv_sad_neon.c index f494ae7..0c37318 100644 --- a/src/neon/oapv_sad_neon.c +++ b/src/neon/oapv_sad_neon.c @@ -182,7 +182,6 @@ static s64 ssd_16b_neon_8x8(int w, int h, void *src1, void *src2, int s_src1, in s64 ssd = 0; s16* s1 = (s16*) src1; s16* s2 = (s16*) src2; - s16 i; int16x8_t s1_vector, s2_vector; int32x4_t diff1, diff2; int32x2_t diff1_low, diff2_low; @@ -480,7 +479,6 @@ int oapv_dc_removed_had8x8_neon(pel* org, int s_org) int16x8_t pred4_8x16b, pred5_8x16b, pred6_8x16b, pred7_8x16b; int16x8_t out0_8x16b, out1_8x16b, out2_8x16b, out3_8x16b; int16x8_t out4_8x16b, out5_8x16b, out6_8x16b, out7_8x16b; - int16x8x2_t out0_8x16bx2, out1_8x16bx2, out2_8x16bx2, out3_8x16bx2; src0_8x16b = (vld1q_s16(&org[0])); org = org + s_org; diff --git a/src/oapv.c b/src/oapv.c index e970620..7a831e7 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -296,8 +296,8 @@ static void enc_minus_mid_val(s16 *coef, int w_blk, int h_blk, int bit_depth) static int enc_set_tile_info(oapve_tile_t *ti, int w_pel, int h_pel, int tile_w, int tile_h, int *num_tile_cols, int *num_tile_rows, int *num_tiles) { - (*num_tile_cols) = (w_pel + (tile_w - 1)) / tile_w; - (*num_tile_rows) = (h_pel + (tile_h - 1)) / tile_h; + (*num_tile_cols) = oapv_div_round_up(w_pel, tile_w); + (*num_tile_rows) = oapv_div_round_up(h_pel, tile_h); (*num_tiles) = (*num_tile_cols) * (*num_tile_rows); for(int i = 0; i < (*num_tiles); i++) { @@ -638,6 +638,39 @@ static double enc_block_rdo_placebo(oapve_ctx_t *ctx, oapve_core_t *core, int lo return best_cost; } +static int enc_update_param(oapve_ctx_t* ctx, oapve_param_t* param) +{ + /* set various value */ + ctx->w = oapv_div_round_up(param->w, OAPV_MB_W) * OAPV_MB_W; + ctx->h = oapv_div_round_up(param->h, OAPV_MB_H) * OAPV_MB_H; + + /* find correct tile width and height */ + int tile_w, tile_h; + + oapv_assert_rv(param->tile_w >= OAPV_MIN_TILE_W && param->tile_h >= OAPV_MIN_TILE_H, OAPV_ERR_INVALID_ARGUMENT); + oapv_assert_rv((param->tile_w & (OAPV_MB_W - 1)) == 0 && (param->tile_h & (OAPV_MB_H - 1)) == 0, OAPV_ERR_INVALID_ARGUMENT); + + if (oapv_div_round_up(ctx->w, param->tile_w) > OAPV_MAX_TILE_COLS) { + tile_w = oapv_div_round_up(ctx->w, OAPV_MAX_TILE_COLS); + tile_w = oapv_div_round_up(tile_w, OAPV_MB_W) * OAPV_MB_W; // align to MB width + } + else { + tile_w = param->tile_w; + } + param->tile_w = tile_w; + + if (oapv_div_round_up(ctx->h, param->tile_h) > OAPV_MAX_TILE_ROWS) { + tile_h = oapv_div_round_up(ctx->h, OAPV_MAX_TILE_ROWS); + tile_h = oapv_div_round_up(tile_h, OAPV_MB_H) * OAPV_MB_H; // align to MB height + } + else { + tile_h = param->tile_h; + } + param->tile_h = tile_h; + + return OAPV_OK; +} + static int enc_read_param(oapve_ctx_t *ctx, oapve_param_t *param) { /* check input parameters */ @@ -671,12 +704,10 @@ static int enc_read_param(oapve_ctx_t *ctx, oapve_param_t *param) ctx->log2_block = OAPV_LOG2_BLK; /* set various value */ - ctx->w = ((param->w + (OAPV_MB_W - 1)) >> OAPV_LOG2_MB_W) << OAPV_LOG2_MB_W; - ctx->h = ((param->h + (OAPV_MB_H - 1)) >> OAPV_LOG2_MB_H) << OAPV_LOG2_MB_H; + ctx->w = oapv_div_round_up(param->w, OAPV_MB_W) * OAPV_MB_W; + ctx->h = oapv_div_round_up(param->h, OAPV_MB_H) * OAPV_MB_H; - int tile_w = param->tile_w_mb * OAPV_MB_W; - int tile_h = param->tile_h_mb * OAPV_MB_H; - enc_set_tile_info(ctx->tile, ctx->w, ctx->h, tile_w, tile_h, &ctx->num_tile_cols, &ctx->num_tile_rows, &ctx->num_tiles); + enc_set_tile_info(ctx->tile, ctx->w, ctx->h, ctx->param->tile_w, ctx->param->tile_h, &ctx->num_tile_cols, &ctx->num_tile_rows, &ctx->num_tiles); return OAPV_OK; } @@ -684,11 +715,11 @@ static int enc_read_param(oapve_ctx_t *ctx, oapve_param_t *param) static void enc_flush(oapve_ctx_t *ctx) { // Release thread pool controller and created threads - if(ctx->cdesc.threads >= 1) { + if(ctx->threads >= 1) { if(ctx->tpool) { // thread controller instance is present // terminate the created thread - for(int i = 0; i < ctx->cdesc.threads; i++) { + for(int i = 0; i < ctx->threads; i++) { if(ctx->thread_id[i]) { // valid thread instance ctx->tpool->release(&ctx->thread_id[i]); @@ -702,7 +733,7 @@ static void enc_flush(oapve_ctx_t *ctx) } oapv_tpool_sync_obj_delete(&ctx->sync_obj); - for(int i = 0; i < ctx->cdesc.threads; i++) { + for(int i = 0; i < ctx->threads; i++) { enc_core_free(ctx->core[i]); ctx->core[i] = NULL; } @@ -716,7 +747,21 @@ static int enc_ready(oapve_ctx_t *ctx) int ret = OAPV_OK; oapv_assert(ctx->core[0] == NULL); - for(int i = 0; i < ctx->cdesc.threads; i++) { + int min_num_tiles = OAPV_MAX_TILES; + for (int i = 0; i < ctx->cdesc.max_num_frms; i++) { + enc_update_param(ctx, &ctx->cdesc.param[i]); + int num_tiles = oapv_div_round_up(ctx->w, ctx->cdesc.param[i].tile_w) * oapv_div_round_up(ctx->h, ctx->cdesc.param[i].tile_h); + min_num_tiles = oapv_min(min_num_tiles, num_tiles); + } + + if(ctx->cdesc.threads == OAPVE_CDESC_THREADS_AUTO) { + ctx->threads = oapv_min(OAPV_MAX_THREADS, oapv_min(oapv_get_num_cpu_cores(), min_num_tiles)); + } + else { + ctx->threads = ctx->cdesc.threads; + } + + for(int i = 0; i < ctx->threads; i++) { core = enc_core_alloc(); oapv_assert_gv(core != NULL, ret, OAPV_ERR_OUT_OF_MEMORY, ERR); ctx->core[i] = core; @@ -731,10 +776,10 @@ static int enc_ready(oapve_ctx_t *ctx) ctx->sync_obj = oapv_tpool_sync_obj_create(); oapv_assert_gv(ctx->sync_obj != NULL, ret, OAPV_ERR_UNKNOWN, ERR); - if(ctx->cdesc.threads >= 1) { + if(ctx->threads >= 1) { ctx->tpool = oapv_malloc(sizeof(oapv_tpool_t)); - oapv_tpool_init(ctx->tpool, ctx->cdesc.threads); - for(int i = 0; i < ctx->cdesc.threads; i++) { + oapv_tpool_init(ctx->tpool, ctx->threads); + for(int i = 0; i < ctx->threads; i++) { ctx->thread_id[i] = ctx->tpool->create(ctx->tpool, i); oapv_assert_gv(ctx->thread_id[i] != NULL, ret, OAPV_ERR_UNKNOWN, ERR); } @@ -1092,7 +1137,7 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapv_imgb_t *imgb_i, oapv_imgb_t *i ctx->tile[i].bs_buf_max = buf_size; } - for(int i = 0; i < ctx->cdesc.threads; i++) { + for(int i = 0; i < ctx->threads; i++) { ctx->core[i]->ctx = ctx; ctx->core[i]->thread_idx = i; } @@ -1146,7 +1191,7 @@ static int enc_frame(oapve_ctx_t *ctx) oapv_tpool_t *tpool = ctx->tpool; int res, tidx = 0, thread_num1 = 0; - int parallel_task = (ctx->cdesc.threads > ctx->num_tiles) ? ctx->num_tiles : ctx->cdesc.threads; + int parallel_task = (ctx->threads > ctx->num_tiles) ? ctx->num_tiles : ctx->threads; /* encode tiles ************************************/ for(tidx = 0; tidx < (parallel_task - 1); tidx++) { @@ -1307,7 +1352,7 @@ int oapve_encode(oapve_t eid, oapv_frms_t *ifrms, oapvm_t mid, oapv_bitb_t *bitb /* set default value for encoding parameter */ ctx->param = &ctx->cdesc.param[i]; ret = enc_read_param(ctx, ctx->param); - oapv_assert_rv(ret == OAPV_OK, OAPV_ERR); + oapv_assert_rv(ret == OAPV_OK, ret); oapv_assert_rv(ctx->param->profile_idc == OAPV_PROFILE_422_10, OAPV_ERR_UNSUPPORTED); @@ -1454,39 +1499,6 @@ int oapve_config(oapve_t eid, int cfg, void *buf, int *size) return OAPV_OK; } -int oapve_param_default(oapve_param_t *param) -{ - oapv_mset(param, 0, sizeof(oapve_param_t)); - param->preset = OAPV_PRESET_DEFAULT; - - param->qp_offset_c1 = 0; - param->qp_offset_c2 = 0; - param->qp_offset_c3 = 0; - - param->tile_w_mb = 16; - param->tile_h_mb = 16; - - param->profile_idc = OAPV_PROFILE_422_10; - param->level_idc = (int)((4.1 * 30.0) + 0.5); - param->band_idc = 2; - - param->use_q_matrix = 0; - - param->color_description_present_flag = 0; - param->color_primaries = 2; // unspecified color primaries - param->transfer_characteristics = 2; // unspecified transfer characteristics - param->matrix_coefficients = 2; // unspecified matrix coefficients - param->full_range_flag = 0; // limited range - - for(int c = 0; c < OAPV_MAX_CC; c++) { - for(int i = 0; i < OAPV_BLK_D; i++) { - param->q_matrix[c][i] = 16; - } - } - - return OAPV_OK; -} - /////////////////////////////////////////////////////////////////////////////// // enc of encoder code #endif // ENABLE_ENCODER @@ -2130,4 +2142,4 @@ int oapvd_info(void *au, int au_size, oapv_au_info_t *aui) /////////////////////////////////////////////////////////////////////////////// // end of decoder code #endif // ENABLE_DECODER -/////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/oapv_def.h b/src/oapv_def.h index acb4f6f..2dc0a58 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -271,6 +271,7 @@ struct oapve_ctx { oapve_param_t *param; oapv_fh_t fh; oapve_tile_t tile[OAPV_MAX_TILES]; + int num_tiles_frms[OAPV_MAX_NUM_FRAMES]; int num_tiles; int num_tile_cols; int num_tile_rows; @@ -308,6 +309,7 @@ struct oapve_ctx { int use_frm_hash; oapve_rc_param_t rc_param; + int threads; // num of thread for encoding /* platform specific data, if needed */ void *pf; }; @@ -410,6 +412,7 @@ struct oapvd_ctx { #include "oapv_tbl.h" #include "oapv_rc.h" #include "oapv_sad.h" +#include "oapv_param.h" #if X86_SSE #include "sse/oapv_sad_sse.h" diff --git a/src/oapv_param.c b/src/oapv_param.c new file mode 100644 index 0000000..a808b76 --- /dev/null +++ b/src/oapv_param.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the copyright owner, nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oapv_def.h" + +#define LEVEL_TO_LEVEL_IDC(level) (int)(((level) * 30.0) + 0.5) + +int oapve_param_default(oapve_param_t *param) +{ + oapv_mset(param, 0, sizeof(oapve_param_t)); + param->preset = OAPV_PRESET_DEFAULT; + + param->qp = 10; // default + param->qp_offset_c1 = 0; + param->qp_offset_c2 = 0; + param->qp_offset_c3 = 0; + + param->tile_w = 16 * OAPV_MB_W; // default: 256 + param->tile_h = 16 * OAPV_MB_H; // default: 256 + + param->profile_idc = OAPV_PROFILE_422_10; + param->level_idc = LEVEL_TO_LEVEL_IDC(4.1); + param->band_idc = 2; + + param->use_q_matrix = 0; + + for(int c = 0; c < OAPV_MAX_CC; c++) { + for(int i = 0; i < OAPV_BLK_D; i++) { + param->q_matrix[c][i] = 16; + } + } + + param->color_description_present_flag = 0; + param->color_primaries = 2; // unspecified color primaries + param->transfer_characteristics = 2; // unspecified transfer characteristics + param->matrix_coefficients = 2; // unspecified matrix coefficients + param->full_range_flag = 0; // limited range + + return OAPV_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// parameter parsing helper function for encoder +static int is_digit(const char* str) +{ + while(*str) { + if(*str < '0' || *str > '9') + return 0; + ++str; + } + return 1; +} + +static int get_ival_from_skey(const oapv_dict_str_int_t * dict, const char * skey, int * ival) +{ + while(strlen(dict->key) > 0) { + if(strcmp(dict->key, skey) == 0){ + *ival = dict->val; + return 0; + } + dict++; + } + return -1; +} + +static int kbps_str_to_int(const char *str) +{ + int kbps; + char *s = (char *)str; + if(strchr(s, 'K') || strchr(s, 'k')) { + char *tmp = strtok(s, "Kk "); + kbps = (int)(atof(tmp)); + } + else if(strchr(s, 'M') || strchr(s, 'm')) { + char *tmp = strtok(s, "Mm "); + kbps = (int)(atof(tmp) * 1000); + } + else { + kbps = atoi(s); + } + return kbps; +} + +static int get_q_matrix(const char *str, u8 q_matrix[OAPV_BLK_D]) +{ + int t0, qcnt = 0; + char *left; + char *qstr = (char *)str; + + while(strlen(qstr) > 0 && qcnt < OAPV_BLK_D) { + t0 = strtol(qstr, &left, 10); + oapv_assert_rv(t0 >= 1 && t0 <= 255, -1); + + q_matrix[qcnt] = (u8)t0; + qstr = left; + qcnt++; + } + oapv_assert_rv(qcnt == OAPV_BLK_D, -1); + return 0; +} + + +#define NAME_CMP(VAL) else if(strcmp(name, VAL)== 0) +#define GET_INTEGER_OR_ERR(STR, F) { \ + char * left; (F) = strtol(STR, &left, 10); \ + if(strlen(left)>0) return OAPV_ERR_INVALID_ARGUMENT; \ +} +#define GET_INTEGER_MIN_OR_ERR(STR, F, MIN) { \ + GET_INTEGER_OR_ERR(STR, F); \ + if((F) < (MIN)) return OAPV_ERR_INVALID_ARGUMENT; \ +} +#define GET_INTEGER_MIN_MAX_OR_ERR(STR, F, MIN, MAX) { \ + GET_INTEGER_OR_ERR(STR, F); \ + if((F) < (MIN) || (F) > (MAX)) return OAPV_ERR_INVALID_ARGUMENT; \ +} +#define GET_FLOAT_OR_ERR(STR, F) { \ + char * left; (F) = strtof(STR, &left); \ + if(strlen(left)>0) return OAPV_ERR_INVALID_ARGUMENT; \ +} + +int oapve_param_parse(oapve_param_t *param, const char *name, const char *value) +{ + u8 q_matrix[OAPV_BLK_D]; + char str_buf[64]; + int ti0; + float tf0; + + /* normalization of name and value ***************************************/ + // pass '-- prefix' if exists + if(name[0] == '-' && name[1] == '-') { name += 2; } + + // replace '_' with '-' + if(strlen(name) + 1 < sizeof(str_buf) && strchr(name, '_')) { + char *c; + strcpy(str_buf, name); + while((c = strchr(str_buf, '_')) != 0) { *c = '-'; } // replace + name = str_buf; // change address + } + + /* parsing ***************************************************************/ + if(0){;} + NAME_CMP("profile") { + if(get_ival_from_skey(oapv_param_opts_profile, value, &ti0)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + param->profile_idc = ti0; + } + NAME_CMP("level") { + GET_FLOAT_OR_ERR(value, tf0); + // validation check + // level == [1, 1.1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 6, 6.1, 7, 7.1] + if(tf0 == 1.0f || tf0 == 1.1f || tf0 == 2.0f || tf0 == 2.1f || \ + tf0 == 3.0f || tf0 == 3.1f || tf0 == 4.0f || tf0 == 4.1f ||\ + tf0 == 5.0f || tf0 == 5.1f || tf0 == 6.0f || tf0 == 6.1f ||\ + tf0 == 7.0f || tf0 == 7.1f) { + param->level_idc = LEVEL_TO_LEVEL_IDC(tf0); + } + else { + return OAPV_ERR_INVALID_ARGUMENT; + } + } + NAME_CMP("band") { + GET_INTEGER_MIN_MAX_OR_ERR(value, ti0, 0, 3); + param->band_idc = ti0; + } + NAME_CMP("preset") { + if(get_ival_from_skey(oapv_param_opts_preset, value, &ti0)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + param->preset = ti0; + } + NAME_CMP("width") { + GET_INTEGER_OR_ERR(value, ti0); + oapv_assert_rv(ti0 > 0, OAPV_ERR_INVALID_ARGUMENT); + param->w = ti0; + } + NAME_CMP("height") { + GET_INTEGER_OR_ERR(value, ti0); + oapv_assert_rv(ti0 > 0, OAPV_ERR_INVALID_ARGUMENT); + param->h = ti0; + } + NAME_CMP("fps") { + if(strpbrk(value, "/") != NULL) { + sscanf(value, "%d/%d", ¶m->fps_num, ¶m->fps_den); + } + else if(strpbrk(value, ".") != NULL) { + GET_FLOAT_OR_ERR(value, tf0); + param->fps_num = tf0 * 10000; + param->fps_den = 10000; + } + else { + GET_INTEGER_OR_ERR(value, ti0); + param->fps_num = ti0; + param->fps_den = 1; + } + } + NAME_CMP("qp") { + // QP value: 0 ~ (63 + (bitdepth - 10)*6) + // - 10bit input: 0 ~ 63" + // - 12bit input: 0 ~ 75" + // max value cannot be decided without bitdepth value + GET_INTEGER_MIN_MAX_OR_ERR(value, ti0, MIN_QUANT, MAX_QUANT(12)); + param->qp = ti0; + param->rc_type = OAPV_RC_CQP; + } + NAME_CMP("qp_offset_c1") { + GET_INTEGER_OR_ERR(value, ti0); + param->qp_offset_c1 = ti0; + } + NAME_CMP("qp_offset_c2") { + GET_INTEGER_OR_ERR(value, ti0); + param->qp_offset_c2 = ti0; + } + NAME_CMP("qp_offset_c3") { + GET_INTEGER_OR_ERR(value, ti0); + param->qp_offset_c3 = ti0; + } + NAME_CMP("bitrate") { + if(strlen(value) > 0) { + strcpy(str_buf, value); // to maintain original value + param->bitrate = kbps_str_to_int(str_buf); // unit: kbps + if(param->bitrate <= 0) return OAPV_ERR_INVALID_ARGUMENT; + param->rc_type = OAPV_RC_ABR; + } + else return OAPV_ERR_INVALID_ARGUMENT; + } + NAME_CMP("q-matrix-c0") { + + if(get_q_matrix(value, q_matrix)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + oapv_mcpy(param->q_matrix[Y_C], q_matrix, sizeof(u8)*OAPV_BLK_D); + param->use_q_matrix = 1; + } + NAME_CMP("q-matrix-c1") { + + if(get_q_matrix(value, q_matrix)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + oapv_mcpy(param->q_matrix[U_C], q_matrix, sizeof(u8)*OAPV_BLK_D); + param->use_q_matrix = 1; + } + NAME_CMP("q-matrix-c2") { + + if(get_q_matrix(value, q_matrix)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + oapv_mcpy(param->q_matrix[V_C], q_matrix, sizeof(u8)*OAPV_BLK_D); + param->use_q_matrix = 1; + } + NAME_CMP("q-matrix-c3") { + + if(get_q_matrix(value, q_matrix)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + oapv_mcpy(param->q_matrix[X_C], q_matrix, sizeof(u8)*OAPV_BLK_D); + param->use_q_matrix = 1; + } + NAME_CMP("tile-w") { + GET_INTEGER_MIN_OR_ERR(value, ti0, OAPV_MIN_TILE_W); + oapv_assert_rv((ti0 & (OAPV_MB_W - 1)) == 0, OAPV_ERR_INVALID_ARGUMENT); + param->tile_w = ti0; + } + NAME_CMP("tile-h") { + GET_INTEGER_MIN_OR_ERR(value, ti0, OAPV_MIN_TILE_H); + oapv_assert_rv((ti0 & (OAPV_MB_W - 1)) == 0, OAPV_ERR_INVALID_ARGUMENT); + param->tile_h = ti0; + } + NAME_CMP("color-primaries") { + if(get_ival_from_skey(oapv_param_opts_color_primaries, value, &ti0)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + param->color_primaries = ti0; + param->color_description_present_flag = 1; + } + NAME_CMP("color-transfer") { + if(get_ival_from_skey(oapv_param_opts_color_transfer, value, &ti0)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + param->transfer_characteristics = ti0; + param->color_description_present_flag = 1; + } + NAME_CMP("color-matrix") { + if(get_ival_from_skey(oapv_param_opts_color_matrix, value, &ti0)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + param->matrix_coefficients = ti0; + param->color_description_present_flag = 1; + } + NAME_CMP("color-range") { + if(get_ival_from_skey(oapv_param_opts_color_range, value, &ti0)) { + return OAPV_ERR_INVALID_ARGUMENT; + } + param->full_range_flag = ti0; + param->color_description_present_flag = 1; + } + return OAPV_OK; +} + diff --git a/src/oapv_param.h b/src/oapv_param.h new file mode 100644 index 0000000..4873894 --- /dev/null +++ b/src/oapv_param.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the copyright owner, nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OAPV_PARAM_H__32943289478329438247238643278463728473829__ +#define ifndef __OAPV_PARAM_H__32943289478329438247238643278463728473829__ + +#include "oapv.h" + +int oapve_param_default(oapve_param_t *param); +int oapve_param_parse(oapve_param_t *param, const char *name, const char *value); + +#endif /* __OAPV_PARAM_H__32943289478329438247238643278463728473829__ */ + diff --git a/src/oapv_port.c b/src/oapv_port.c index b42d144..ea1d7e2 100644 --- a/src/oapv_port.c +++ b/src/oapv_port.c @@ -29,6 +29,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#if defined(LINUX) +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // for sched_getaffinity() +#endif +#endif + #include #include "oapv_port.h" @@ -87,4 +93,39 @@ void oapv_trace_line(char *pre) } str[chars] = '\0'; printf("%s\n", str); -} \ No newline at end of file +} + +#if defined(WIN32) || defined(WIN64) +#include +#include +#elif defined(LINUX) +#include +#elif defined(MACOS) +#include +#endif + +int oapv_get_num_cpu_cores(void) +{ + int num_cores = 1; // default +#if defined(WIN32) || defined(WIN64) + { + SYSTEM_INFO si; + GetNativeSystemInfo(&si); + num_cores = si.dwNumberOfProcessors; + } +#elif defined(LINUX) + { + cpu_set_t cset; + memset(&cset, 0, sizeof(cset)); + if(!sched_getaffinity(0, sizeof(cset), &cset)) { + num_cores = CPU_COUNT(&cset); + } + } +#elif defined(MACOS) + { + num_cores = sysconf(_SC_NPROCESSORS_ONLN); + } +#endif + return num_cores; +} + diff --git a/src/oapv_port.h b/src/oapv_port.h index 0ff627e..83769c2 100644 --- a/src/oapv_port.h +++ b/src/oapv_port.h @@ -199,4 +199,9 @@ void oapv_trace_line(char *pre); #define ALIGNED_32(var) DECLARE_ALIGNED(var, 32) #define ALIGNED_128(var) DECLARE_ALIGNED(var, 128) + +/* CPU information */ +int oapv_get_num_cpu_cores(void); + #endif /* _OAPV_PORT_H_ */ + diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 91e2ae5..f6f48f3 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -101,7 +101,7 @@ int oapve_rc_get_tile_cost_thread(oapve_ctx_t* ctx, u64* sum) } oapv_tpool_t* tpool = ctx->tpool; - int parallel_task = (ctx->cdesc.threads > ctx->num_tiles) ? ctx->num_tiles : ctx->cdesc.threads; + int parallel_task = (ctx->threads > ctx->num_tiles) ? ctx->num_tiles : ctx->threads; // run new threads int tidx = 0; diff --git a/src/oapv_util.h b/src/oapv_util.h index 302452e..4c7a4cb 100644 --- a/src/oapv_util.h +++ b/src/oapv_util.h @@ -38,6 +38,10 @@ #define oapv_min(a, b) (((a) < (b)) ? (a) : (b)) #define oapv_median(x, y, z) ((((y) < (z)) ^ ((z) < (x))) ? (((x) < (y)) ^ ((z) < (x))) ? (y) : (x) : (z)) +#define oapv_div_round_up(n, d) ((int)(((n) + (d) - 1) / (d))) +#define oapv_div_round_closest(n, d) ((int)(((n) + (d)/2)/(d))) + + #define oapv_abs(a) (((a) > (0)) ? (a) : (-(a))) #define oapv_abs64(a) (((a) ^ ((a) >> 63)) - ((a) >> 63)) // only for 64bit variable #define oapv_abs32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31)) // only for 32bit variable diff --git a/src/oapv_vlc.c b/src/oapv_vlc.c index bc80e6c..c9aab77 100644 --- a/src/oapv_vlc.c +++ b/src/oapv_vlc.c @@ -279,8 +279,8 @@ void oapve_set_frame_header(oapve_ctx_t *ctx, oapv_fh_t *fh) fh->fi.frame_height = param->h; fh->fi.chroma_format_idc = ctx->cfi; fh->fi.bit_depth = ctx->bit_depth; - fh->tile_width_in_mbs = param->tile_w_mb; - fh->tile_height_in_mbs = param->tile_h_mb; + fh->tile_width_in_mbs = param->tile_w / OAPV_MB_W; + fh->tile_height_in_mbs = param->tile_h / OAPV_MB_H; fh->color_description_present_flag = param->color_description_present_flag; fh->color_primaries = param->color_primaries;