From 2a3291db22a7cf23bee3b201f0854557f9a6fe51 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Tue, 3 Mar 2026 17:27:04 +0900 Subject: [PATCH 01/31] initial code Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 1 + app/oapv_app_enc.c | 3 ++- app/oapv_app_util.h | 12 ++++++------ inc/oapv.h | 3 +++ src/oapv.c | 1 + 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 3607f0f4..7887792c 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -322,6 +322,7 @@ static void print_stat_frm(oapvd_stat_t *stat, oapv_frms_t *frms, oapvm_t mid, a : finfo[i].cs == OAPV_CS_YCBCR444_12LE ? "4:4:4-12" : finfo[i].cs == OAPV_CS_YCBCR4444_10LE ? "4:4:4:4-10" : finfo[i].cs == OAPV_CS_YCBCR4444_12LE ? "4:4:4:4-12" + : finfo[i].cs == OAPV_CS_YCBCR4444_16LE ? "4:4:4:4-12c16" : "unknown-cs"; // clang-format on diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 09b48c5e..4300f7aa 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -1100,7 +1100,8 @@ int main(int argc, const char **argv) param->profile_idc == OAPV_PROFILE_4444_10) ? 10 : ( param->profile_idc == OAPV_PROFILE_422_12 || param->profile_idc == OAPV_PROFILE_444_12 || - param->profile_idc == OAPV_PROFILE_4444_12) ? 12 : 0; + param->profile_idc == OAPV_PROFILE_4444_12) ? 12 : ( + param->profile_idc == OAPV_PROFILE_4444_12C16) ? 16 : 0; if (codec_depth == 0) { logerr("ERR: invalid profile\n"); diff --git a/app/oapv_app_util.h b/app/oapv_app_util.h index 407bdd00..77398ae3 100644 --- a/app/oapv_app_util.h +++ b/app/oapv_app_util.h @@ -407,10 +407,10 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y } /* reading YUV format */ - int chroma_format = OAPV_CS_GET_FORMAT(img->cs); + int color_format = OAPV_CS_GET_FORMAT(img->cs); int bit_depth = OAPV_CS_GET_BIT_DEPTH(img->cs); - int w_shift = (chroma_format == OAPV_CF_YCBCR420) || ((chroma_format == OAPV_CF_YCBCR422) || (chroma_format == OAPV_CF_PLANAR2)) ? 1 : 0; - int h_shift = chroma_format == OAPV_CF_YCBCR420 ? 1 : 0; + int w_shift = (color_format == OAPV_CF_YCBCR420) || ((color_format == OAPV_CF_YCBCR422) || (color_format == OAPV_CF_PLANAR2)) ? 1 : 0; + int h_shift = color_format == OAPV_CF_YCBCR420 ? 1 : 0; if(bit_depth == 8) { f_w = width; @@ -433,7 +433,7 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y p8 += img->s[0]; } - if(chroma_format == OAPV_CF_PLANAR2) { + if(color_format == OAPV_CF_PLANAR2) { p8 = (unsigned char *)img->a[1]; for(int j = 0; j < f_h; j++) { if(fread(p8, 1, f_w, fp) != (unsigned)f_w) { @@ -442,7 +442,7 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y p8 += img->s[1]; } } - else if(chroma_format != OAPV_CF_YCBCR400) { + else if(color_format != OAPV_CF_YCBCR400) { f_w = f_w >> w_shift; f_h = f_h >> h_shift; @@ -463,7 +463,7 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y } } - if(chroma_format == OAPV_CF_YCBCR4444) { + if(color_format == OAPV_CF_YCBCR4444) { f_w = f_w >> w_shift; f_h = f_h >> h_shift; diff --git a/inc/oapv.h b/inc/oapv.h index ac6862fa..1f88a0ae 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -164,6 +164,7 @@ extern "C" { #define OAPV_CS_YCBCR422_12LE OAPV_CS_SET(OAPV_CF_YCBCR422, 12, 0) #define OAPV_CS_YCBCR444_12LE OAPV_CS_SET(OAPV_CF_YCBCR444, 12, 0) #define OAPV_CS_YCBCR4444_12LE OAPV_CS_SET(OAPV_CF_YCBCR4444, 12, 0) +#define OAPV_CS_YCBCR4444_16LE OAPV_CS_SET(OAPV_CF_YCBCR4444, 16, 0) #define OAPV_CS_P210 OAPV_CS_SET(OAPV_CF_PLANAR2, 10, 0) /* max number of color channel: ex) YCbCr4444 -> 4 channels */ @@ -239,6 +240,7 @@ extern "C" { #define OAPV_PROFILE_444_12 (66) #define OAPV_PROFILE_4444_10 (77) #define OAPV_PROFILE_4444_12 (88) +#define OAPV_PROFILE_4444_12C16 (90) #define OAPV_PROFILE_400_10 (99) /***************************************************************************** @@ -450,6 +452,7 @@ static const oapv_dict_str_int_t oapv_param_opts_profile[] = { {"444-12", OAPV_PROFILE_444_12}, {"4444-10", OAPV_PROFILE_4444_10}, {"4444-12", OAPV_PROFILE_4444_12}, + {"4444-12c16", OAPV_PROFILE_4444_12C16}, {"400-10", OAPV_PROFILE_400_10}, {"", 0} // termination }; diff --git a/src/oapv.c b/src/oapv.c index 6d29453f..4a10e5a9 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -967,6 +967,7 @@ static int enc_profile_spec[][5] = { {OAPV_PROFILE_444_12, 2, 3, 10, 12}, {OAPV_PROFILE_4444_10, 2, 4, 10, 10}, {OAPV_PROFILE_4444_12, 2, 4, 10, 12}, + {OAPV_PROFILE_4444_12C16, 3, 4, 12, 12}, {OAPV_PROFILE_400_10, 0, 0, 10, 10}, {0, 0, 0, 0, 0} // termination }; From 0d785d1c365b6d43e144eee546ddc516d3eb2d79 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Wed, 4 Mar 2026 16:54:05 +0900 Subject: [PATCH 02/31] need to add companding functionality Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_enc.c | 15 ++++++++------- app/oapv_app_util.h | 8 ++++---- inc/oapv.h | 2 +- src/oapv.c | 16 +++++++++++++--- src/oapv_def.h | 5 ++++- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 8b58d71b..23299cf2 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -81,7 +81,7 @@ static const args_opt_t enc_args_opts[] = { '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 and 12C16bit: 0 ~ 75\n" " - 'auto' means that the value is internally determined" }, { @@ -99,7 +99,7 @@ static const args_opt_t enc_args_opts[] = { }, { 'd', "input-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL, - "input bit depth (8, 10-12)\n" + "input bit depth (8, 10-12, 16)\n" " - Note: 8bit input will be converted to 10bit" }, { @@ -127,10 +127,11 @@ static const args_opt_t enc_args_opts[] = { "profile string\n" " - 422-10: YCbCr422 10bit (default)\n" " - 422-12; YCbCr422 12bit\n" - " - 444-10: YCbCr444 10bit\n" - " - 444-12; YCbCr444 12bit\n" - " - 4444-10: YCbCr4444 10bit\n" - " - 4444-12; YCbCr4444 12bit\n" + " - 444-10: YCbCr(RGB)444 10bit\n" + " - 444-12; YCbCr(RGB)444 12bit\n" + " - 4444-10: YCbCrX(RGBA)4444 10bit\n" + " - 4444-12: YCbCrX(RGBA)4444 12bit\n" + " - 4444-12C16: YCbCrX(RGBA)4444 12bit companded from 16bit\n" " - 400-10: YCbCr400 (monochrome) 10bit\n" " Note: Color space and bit depth of input video will be converted\n" " automatically to support the given profile, if needs\n" @@ -1032,7 +1033,7 @@ int main(int argc, const char **argv) if(strlen(args_var->fname_rec) > 0) { ret = check_file_name_type(args_var->fname_rec); - if(ret > 0) { + if(ret > 0 && args_var->input_csp != 16) { is_rec_y4m = 1; } else if(ret == 0) { diff --git a/app/oapv_app_util.h b/app/oapv_app_util.h index 77398ae3..c25e9e88 100644 --- a/app/oapv_app_util.h +++ b/app/oapv_app_util.h @@ -416,7 +416,7 @@ static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y f_w = width; f_h = height; } - else if(bit_depth >= 10 && bit_depth <= 14) { + else if(bit_depth >= 10 && bit_depth <= 16) { f_w = width * sizeof(short); f_h = height; } @@ -497,7 +497,7 @@ static int imgb_write(char *fname, oapv_imgb_t *imgb) chroma_format == OAPV_CF_YCBCR444 || chroma_format == OAPV_CF_YCBCR4444)) { bd = 1; } - else if(bit_depth >= 10 && bit_depth <= 14 && (chroma_format == OAPV_CF_YCBCR400 || chroma_format == OAPV_CF_YCBCR420 || chroma_format == OAPV_CF_YCBCR422 || chroma_format == OAPV_CF_YCBCR444 || chroma_format == OAPV_CF_YCBCR4444)) { + else if(bit_depth >= 10 && bit_depth <= 16 && (chroma_format == OAPV_CF_YCBCR400 || chroma_format == OAPV_CF_YCBCR420 || chroma_format == OAPV_CF_YCBCR422 || chroma_format == OAPV_CF_YCBCR444 || chroma_format == OAPV_CF_YCBCR4444)) { bd = 2; } else if(bit_depth >= 10 && chroma_format == OAPV_CF_PLANAR2) { @@ -697,7 +697,7 @@ static void measure_psnr(oapv_imgb_t *org, oapv_imgb_t *rec, double psnr[4], int r += rec->s[i]; } mse[i] = sum[i] / (org->w[i] * org->h[i]); - psnr[i] = (mse[i] == 0.0) ? 100. : fabs(10 * log10(((255 * 255) / mse[i]))); + psnr[i] = (mse[i] == 0.0) ? 100. : fabs(10 * log10(((255.f * 255.f) / mse[i]))); } } else { @@ -723,7 +723,7 @@ static void measure_psnr(oapv_imgb_t *org, oapv_imgb_t *rec, double psnr[4], int r = (unsigned short *)((unsigned char *)r + rec->s[i]); } mse[i] = sum[i] / (org->w[i] * org->h[i]); - psnr[i] = (mse[i] == 0.0) ? 100. : fabs(10 * log10(((255 * 255 * factor) / mse[i]))); + psnr[i] = (mse[i] == 0.0) ? 100. : fabs(10 * log10(((255.f * 255.f * factor) / mse[i]))); } } } diff --git a/inc/oapv.h b/inc/oapv.h index 1f88a0ae..117eff43 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -452,7 +452,7 @@ static const oapv_dict_str_int_t oapv_param_opts_profile[] = { {"444-12", OAPV_PROFILE_444_12}, {"4444-10", OAPV_PROFILE_4444_10}, {"4444-12", OAPV_PROFILE_4444_12}, - {"4444-12c16", OAPV_PROFILE_4444_12C16}, + {"4444-12C16", OAPV_PROFILE_4444_12C16}, {"400-10", OAPV_PROFILE_400_10}, {"", 0} // termination }; diff --git a/src/oapv.c b/src/oapv.c index 4a10e5a9..61f79b75 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -967,7 +967,7 @@ static int enc_profile_spec[][5] = { {OAPV_PROFILE_444_12, 2, 3, 10, 12}, {OAPV_PROFILE_4444_10, 2, 4, 10, 10}, {OAPV_PROFILE_4444_12, 2, 4, 10, 12}, - {OAPV_PROFILE_4444_12C16, 3, 4, 12, 12}, + {OAPV_PROFILE_4444_12C16, 3, 4, 16, 16}, {OAPV_PROFILE_400_10, 0, 0, 10, 10}, {0, 0, 0, 0, 0} // termination }; @@ -1030,13 +1030,23 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } // color information ctx->cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb_i->cs)); - ctx->bit_depth = OAPV_CS_GET_BIT_DEPTH(imgb_i->cs); + ctx->bit_depth_inp = OAPV_CS_GET_BIT_DEPTH(imgb_i->cs); ctx->num_comp = get_num_comp(ctx->cfi); // check whether input frame type is suitable to profile definition - ret = enc_check_profile(param->profile_idc, ctx->cfi, ctx->bit_depth); + ret = enc_check_profile(param->profile_idc, ctx->cfi, ctx->bit_depth_inp); oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); + // check internal bit-depth and companding option + if(param->profile_idc == OAPV_PROFILE_4444_12C16 && ctx->bit_depth == 16) { + ctx->bit_depth = 12; // use 12bit internal bit-depth + ctx->use_companding = 1; + } + else { + ctx->bit_depth = ctx->bit_depth_inp; + ctx->use_companding = 0; + } + // shift parameter for each color component ctx->comp_sft[Y_C][0] = 0; ctx->comp_sft[Y_C][1] = 0; diff --git a/src/oapv_def.h b/src/oapv_def.h index 3b42b852..e132186f 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -288,7 +288,8 @@ struct oapve_ctx { int h; int cfi; int num_comp; - int bit_depth; + int bit_depth; // bit-depth of internal part + int bit_depth_inp; // bit-depth of input video int comp_sft[N_C][2]; oapv_tpool_t *tpool; oapv_thread_t thread_id[OAPV_MAX_THREADS]; @@ -316,6 +317,7 @@ struct oapve_ctx { int threads; // num of thread for encoding int au_bs_fmt; // access unit bitstream format + int use_companding; /* platform specific data, if needed */ void *pf; }; @@ -399,6 +401,7 @@ struct oapvd_ctx { int num_comp; // number of components int comp_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height int use_frm_hash; + int use_companding; /* platform specific data, if needed */ void *pf; From c4028b39e8a1d9e595ccffb2d8f6b8b1f6e360a5 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Thu, 5 Mar 2026 10:20:50 +0900 Subject: [PATCH 03/31] refactoring Signed-off-by: kp5.choi@samsung.com --- src/oapv.c | 102 ++++++++++++++++++++++++------------------------- src/oapv_def.h | 63 +++++++++++++++--------------- src/oapv_rc.c | 16 ++++---- src/oapv_vlc.c | 12 +++--- 4 files changed, 96 insertions(+), 97 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index 61f79b75..d3773ceb 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -123,7 +123,7 @@ static void imgb_pad_p210(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2 } } -static void imgb_to_blk(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd) +static void imgb_to_blk(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp) { u8 *src, *dst; int i, sft_hor, sft_ver; @@ -149,7 +149,7 @@ static void imgb_to_blk(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int } } -static void imgb_to_blk_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd) +static void imgb_to_blk_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); s16 *s = (s16 *)src; @@ -164,7 +164,7 @@ static void imgb_to_blk_16(void *src, int blk_w, int blk_h, int s_src, int offse } } -static void imgb_to_blk_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd) +static void imgb_to_blk_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)src; @@ -180,7 +180,7 @@ static void imgb_to_blk_p21x_y(void *src, int blk_w, int blk_h, int s_src, int o } } -static void imgb_to_blk_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd) +static void imgb_to_blk_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)src + offset_src; @@ -196,7 +196,7 @@ static void imgb_to_blk_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int } } -static void imgb_to_blk_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd) +static void imgb_to_blk_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp) { u16 *src, *dst; int sft_hor, sft_ver, s_src; @@ -228,7 +228,7 @@ static void imgb_to_blk_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l } } -static void blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd) +static void blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); @@ -244,7 +244,7 @@ static void blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offse } } -static void blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd) +static void blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); @@ -261,7 +261,7 @@ static void blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int o } } -static void blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd) +static void blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); @@ -779,20 +779,20 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa u8 *bs_cur = oapv_bsw_sink(bs); oapv_assert_rv(bsw_is_align8(bs), OAPV_ERR_MALFORMED_BITSTREAM); - mb_w = OAPV_MB_W >> ctx->comp_sft[c][0]; - mb_h = OAPV_MB_H >> ctx->comp_sft[c][1]; + mb_w = OAPV_MB_W >> ctx->c_sft[c][0]; + mb_h = OAPV_MB_H >> ctx->c_sft[c][1]; - int tile_le = tile->x >> ctx->comp_sft[c][0]; - int tile_ri = (tile->w >> ctx->comp_sft[c][0]) + tile_le; - int tile_to = tile->y >> ctx->comp_sft[c][1]; - int tile_bo = (tile->h >> ctx->comp_sft[c][1]) + tile_to; + int tile_le = tile->x >> ctx->c_sft[c][0]; + int tile_ri = (tile->w >> ctx->c_sft[c][0]) + tile_le; + int tile_to = tile->y >> ctx->c_sft[c][1]; + int tile_bo = (tile->h >> ctx->c_sft[c][1]) + tile_to; for(mb_y = tile_to; mb_y < tile_bo; mb_y += mb_h) { for(mb_x = tile_le; mb_x < tile_ri; mb_x += mb_w) { for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) { for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) { o16 = (s16 *)((u8 *)org + blk_y * s_org) + blk_x; - ctx->fn_imgb_to_blk[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth); + ctx->fn_imgb_to_blk[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_compand); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); @@ -801,7 +801,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa if(rec != NULL) { r16 = (s16 *)((u8 *)rec + blk_y * s_rec) + blk_x; - ctx->fn_blk_to_imgb[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth); + ctx->fn_blk_to_imgb[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth, ctx->use_compand); } } } @@ -839,7 +839,7 @@ static int enc_tile(oapve_ctx_t *ctx, oapve_core_t *core, oapve_tile_t *tile) oapve_set_tile_header(ctx, &tile->th, core->tile_idx, qp); oapve_vlc_tile_header(ctx, &bs, &tile->th); - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { int cnt = 0; core->qp[c] = tile->th.tile_qp[c]; int qscale = oapv_quant_scale[core->qp[c] % 6]; @@ -867,7 +867,7 @@ static int enc_tile(oapve_ctx_t *ctx, oapve_core_t *core, oapve_tile_t *tile) } } - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { core->kparam_dc[c] = OAPV_KPARAM_DC_MAX; core->kparam_ac[c] = OAPV_KPARAM_AC_MIN; core->prev_dc[c] = 0; @@ -1031,7 +1031,7 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * // color information ctx->cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb_i->cs)); ctx->bit_depth_inp = OAPV_CS_GET_BIT_DEPTH(imgb_i->cs); - ctx->num_comp = get_num_comp(ctx->cfi); + ctx->num_c = get_num_comp(ctx->cfi); // check whether input frame type is suitable to profile definition ret = enc_check_profile(param->profile_idc, ctx->cfi, ctx->bit_depth_inp); @@ -1040,19 +1040,19 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * // check internal bit-depth and companding option if(param->profile_idc == OAPV_PROFILE_4444_12C16 && ctx->bit_depth == 16) { ctx->bit_depth = 12; // use 12bit internal bit-depth - ctx->use_companding = 1; + ctx->use_compand = 1; } else { ctx->bit_depth = ctx->bit_depth_inp; - ctx->use_companding = 0; + ctx->use_compand = 0; } // shift parameter for each color component - ctx->comp_sft[Y_C][0] = 0; - ctx->comp_sft[Y_C][1] = 0; - for(i = 1; i < ctx->num_comp; i++) { - ctx->comp_sft[i][0] = get_chroma_sft_w(ctx->cfi); - ctx->comp_sft[i][1] = get_chroma_sft_h(ctx->cfi); + ctx->c_sft[Y_C][0] = 0; + ctx->c_sft[Y_C][1] = 0; + for(i = 1; i < ctx->num_c; i++) { + ctx->c_sft[i][0] = get_chroma_sft_w(ctx->cfi); + ctx->c_sft[i][1] = get_chroma_sft_h(ctx->cfi); } if(OAPV_CS_GET_FORMAT(imgb_i->cs) == OAPV_CF_PLANAR2) { @@ -1069,14 +1069,14 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } else { ctx->fn_imgb_to_blk_rc = imgb_to_blk; - for(int i = 0; i < ctx->num_comp; i++) { + for(int i = 0; i < ctx->num_c; i++) { ctx->fn_imgb_to_blk[i] = imgb_to_blk_16; ctx->fn_blk_to_imgb[i] = blk_to_imgb_16; } ctx->fn_imgb_pad = imgb_pad; } // padding input picture, if needs - ctx->fn_imgb_pad(imgb_i, ctx->w, ctx->h, ctx->comp_sft); + ctx->fn_imgb_pad(imgb_i, ctx->w, ctx->h, ctx->c_sft); // calculate tile info ret = enc_set_tile_info(ctx->tile, ctx->w, ctx->h, param->tile_w, param->tile_h, &ctx->num_tile_cols, &ctx->num_tile_rows, &ctx->num_tiles); @@ -1096,7 +1096,7 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } // recontruction picture if(imgb_r != NULL) { - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { imgb_r->w[c] = imgb_i->w[c]; imgb_r->h[c] = imgb_i->h[c]; imgb_r->x[c] = imgb_i->x[c]; @@ -1157,7 +1157,7 @@ static int enc_frame(oapve_ctx_t *ctx, oapv_bs_t *bs) ctx->rc_param.qp = ctx->param->qp; } - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { ctx->qp[c] = oapv_clip3(MIN_QUANT, MAX_QUANT(10), ctx->rc_param.qp + ctx->qp_offset[c]); } } @@ -1568,26 +1568,26 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) ctx->bit_depth = ctx->fh.fi.bit_depth; ctx->cfi = ctx->fh.fi.chroma_format_idc; - ctx->num_comp = get_num_comp(ctx->cfi); - ctx->comp_sft[Y_C][0] = 0; - ctx->comp_sft[Y_C][1] = 0; + ctx->num_c = get_num_comp(ctx->cfi); + ctx->c_sft[Y_C][0] = 0; + ctx->c_sft[Y_C][1] = 0; - for(int c = 1; c < ctx->num_comp; c++) { - ctx->comp_sft[c][0] = get_chroma_sft_w(color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs))); - ctx->comp_sft[c][1] = get_chroma_sft_h(color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs))); + for(int c = 1; c < ctx->num_c; c++) { + ctx->c_sft[c][0] = get_chroma_sft_w(color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs))); + ctx->c_sft[c][1] = get_chroma_sft_h(color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs))); } ctx->w = oapv_align_value(ctx->fh.fi.frame_width, OAPV_MB_W); ctx->h = oapv_align_value(ctx->fh.fi.frame_height, OAPV_MB_H); if(OAPV_CS_GET_FORMAT(imgb->cs) == OAPV_CF_PLANAR2) { - ctx->fn_block_to_imgb[Y_C] = blk_to_imgb_p21x_y; - ctx->fn_block_to_imgb[U_C] = blk_to_imgb_p21x_uv; - ctx->fn_block_to_imgb[V_C] = blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[Y_C] = blk_to_imgb_p21x_y; + ctx->fn_blk_to_imgb[U_C] = blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[V_C] = blk_to_imgb_p21x_uv; } else { - for(int c = 0; c < ctx->num_comp; c++) { - ctx->fn_block_to_imgb[c] = blk_to_imgb_16; + for(int c = 0; c < ctx->num_c; c++) { + ctx->fn_blk_to_imgb[c] = blk_to_imgb_16; } } @@ -1628,13 +1628,13 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor int ret; s16 *d16; - mb_h = OAPV_MB_H >> ctx->comp_sft[c][1]; - mb_w = OAPV_MB_W >> ctx->comp_sft[c][0]; + mb_h = OAPV_MB_H >> ctx->c_sft[c][1]; + mb_w = OAPV_MB_W >> ctx->c_sft[c][0]; - le = tile->x >> ctx->comp_sft[c][0]; // left position of tile - ri = (tile->w >> ctx->comp_sft[c][0]) + le; // right pixel position of tile - to = tile->y >> ctx->comp_sft[c][1]; // top pixel position of tile - bo = (tile->h >> ctx->comp_sft[c][1]) + to; // bottom pixel position of tile + le = tile->x >> ctx->c_sft[c][0]; // left position of tile + ri = (tile->w >> ctx->c_sft[c][0]) + le; // right pixel position of tile + to = tile->y >> ctx->c_sft[c][1]; // top pixel position of tile + bo = (tile->h >> ctx->c_sft[c][1]) + to; // bottom pixel position of tile for(mb_y = to; mb_y < bo; mb_y += mb_h) { for(mb_x = le; mb_x < ri; mb_x += mb_w) { @@ -1658,7 +1658,7 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor // copy decoded block to image buffer d16 = (s16 *)((u8 *)dst + blk_y * s_dst) + blk_x; - ctx->fn_block_to_imgb[c](core->coef, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_dst, d16, ctx->bit_depth); + ctx->fn_blk_to_imgb[c](core->coef, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_dst, d16, ctx->bit_depth, ctx->use_compand); } } } @@ -1679,10 +1679,10 @@ static int dec_tile(oapvd_core_t *core, oapvd_tile_t *tile) oapv_bs_t bs; // bs for 'tile()' syntax oapv_bsr_init(&bs, tile->bs_beg + OAPV_TILE_SIZE_LEN, tile->tile_size, NULL); - ret = oapvd_vlc_tile_header(&bs, ctx->num_comp, &tile->th, tile->tile_size); + ret = oapvd_vlc_tile_header(&bs, ctx->num_c, &tile->th, tile->tile_size); oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); - for(c = 0; c < ctx->num_comp; c++) { + for(c = 0; c < ctx->num_c; c++) { core->qp[c] = tile->th.tile_qp[c]; u8 dq_scale = oapv_tbl_dq_scale[core->qp[c] % 6]; core->dq_shift[c] = ctx->bit_depth - 2 - (core->qp[c] / 6); @@ -1699,7 +1699,7 @@ static int dec_tile(oapvd_core_t *core, oapvd_tile_t *tile) } } - for(c = 0; c < ctx->num_comp; c++) { + for(c = 0; c < ctx->num_c; c++) { int tc, s_dst; s16 *dst; oapv_bs_t bsc; // bs for 'tile_data()' syntax diff --git a/src/oapv_def.h b/src/oapv_def.h index e132186f..ce1f862e 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -186,9 +186,9 @@ typedef s64 (*oapv_fn_ssd_t)(int w, int h, void *src1, void *src2, int s_src1, i typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, int s_src2, int s_diff, s16 *diff); typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); -typedef void (*oapv_fn_imgb_to_blk_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bit_depth); -typedef void (*oapv_fn_imgb_to_blk_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bit_depth); -typedef void (*oapv_fn_blk_to_imgb_t)(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bit_depth); +typedef void (*oapv_fn_imgb_to_blk_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); +typedef void (*oapv_fn_imgb_to_blk_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +typedef void (*oapv_fn_blk_to_imgb_t)(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); @@ -272,12 +272,18 @@ struct oapve_ctx { u32 magic; // magic code oapve_t id; // identifier oapve_cdesc_t cdesc; + oapve_core_t *core[OAPV_MAX_THREADS]; oapv_imgb_t *imgb_i; oapv_imgb_t *imgb_r; - oapve_param_t *param; oapv_fh_t fh; oapve_tile_t tile[OAPV_MAX_TILES]; + oapve_rc_param_t rc_param; + oapv_tpool_t *tpool; + oapv_thread_t thread_id[OAPV_MAX_THREADS]; + oapv_sync_obj_t sync_obj; + int threads; // num of thread for encoding + int au_bs_fmt; // access unit bitstream format int num_tiles_frms[OAPV_MAX_NUM_FRAMES]; int num_tiles; int num_tile_cols; @@ -287,14 +293,12 @@ struct oapve_ctx { int w; int h; int cfi; - int num_comp; - int bit_depth; // bit-depth of internal part + int num_c; // number of components + int bit_depth; // bit-depth of internal part int bit_depth_inp; // bit-depth of input video - int comp_sft[N_C][2]; - oapv_tpool_t *tpool; - oapv_thread_t thread_id[OAPV_MAX_THREADS]; - oapv_sync_obj_t sync_obj; - oapve_core_t *core[OAPV_MAX_THREADS]; + int c_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height + int use_frm_hash; + int use_compand; const oapv_fn_itx_part_t *fn_itx_part; const oapv_fn_itx_t *fn_itx; @@ -305,6 +309,7 @@ struct oapve_ctx { const oapv_fn_sad_t *fn_sad; const oapv_fn_ssd_t *fn_ssd; const oapv_fn_diff_t *fn_diff; + oapv_fn_imgb_to_blk_rc_t fn_imgb_to_blk_rc; oapv_fn_imgb_to_blk_t fn_imgb_to_blk[N_C]; oapv_fn_blk_to_imgb_t fn_blk_to_imgb[N_C]; @@ -312,12 +317,6 @@ struct oapve_ctx { oapv_fn_enc_blk_cost_t fn_enc_blk; oapv_fn_had8x8_t fn_had8x8; - int use_frm_hash; - oapve_rc_param_t rc_param; - - int threads; // num of thread for encoding - int au_bs_fmt; // access unit bitstream format - int use_companding; /* platform specific data, if needed */ void *pf; }; @@ -374,18 +373,15 @@ struct oapvd_core { struct oapvd_ctx { u32 magic; // magic code oapvd_t id; // identifier - oapvd_cdesc_t cdesc; oapvd_core_t *core[OAPV_MAX_THREADS]; - oapv_imgb_t *imgb; - const oapv_fn_itx_t *fn_itx; - const oapv_fn_dquant_t *fn_dquant; - oapv_fn_blk_to_imgb_t fn_block_to_imgb[N_C]; oapv_bs_t bs; - + oapv_imgb_t *imgb; oapv_fh_t fh; oapvd_tile_t tile[OAPV_MAX_TILES]; - + oapv_tpool_t *tpool; + oapv_thread_t thread_id[OAPV_MAX_THREADS]; + oapv_sync_obj_t sync_obj; u8 *tile_end; int num_tiles; int num_tile_cols; @@ -393,15 +389,17 @@ struct oapvd_ctx { int w; int h; int threads; - oapv_tpool_t *tpool; - oapv_thread_t thread_id[OAPV_MAX_THREADS]; - oapv_sync_obj_t sync_obj; - int cfi; // chroma format indicator - int bit_depth; // bit depth of decoding picture - int num_comp; // number of components - int comp_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height + int cfi; // chroma format indicator + int bit_depth; // bit depth of decoding picture + int num_c; // number of components + int c_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height int use_frm_hash; - int use_companding; + int use_compand; // flag of companding + + const oapv_fn_itx_t *fn_itx; + const oapv_fn_dquant_t *fn_dquant; + + oapv_fn_blk_to_imgb_t fn_blk_to_imgb[N_C]; /* platform specific data, if needed */ void *pf; @@ -422,6 +420,7 @@ struct oapvd_ctx { #include "oapv_rc.h" #include "oapv_sad.h" #include "oapv_param.h" +#include "oapv_comp.h" #if X86_SSE #include "sse/oapv_sad_sse.h" diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 5f798dbd..540ab6ad 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -35,15 +35,15 @@ int oapve_rc_get_tile_cost(oapve_ctx_t* ctx, oapve_core_t* core, oapve_tile_t* t { int sum = 0; tile->rc.number_pixel = 0; - for (int c = Y_C; c < ctx->num_comp; c++) { - int step_w = 8 << ctx->comp_sft[c][0]; - int step_h = 8 << ctx->comp_sft[c][1]; + for (int c = Y_C; c < ctx->num_c; c++) { + int step_w = 8 << ctx->c_sft[c][0]; + int step_h = 8 << ctx->c_sft[c][1]; for (int y = 0; y < tile->h; y += step_h) { for (int x = 0; x < tile->w; x += step_w) { int tx = tile->x + x; int ty = tile->y + y; - ctx->fn_imgb_to_blk_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth); + ctx->fn_imgb_to_blk_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth, ctx->use_compand); sum += ctx->fn_had8x8(core->coef, 8); tile->rc.number_pixel += 64; } @@ -130,8 +130,8 @@ static double rc_calculate_lambda(double alpha, double beta, double cost_pixel, double oapve_rc_estimate_pic_lambda(oapve_ctx_t* ctx, double cost) { int num_pixel = ctx->w * ctx->h; - for (int c = 1; c < ctx->num_comp; c++) { - num_pixel += (ctx->w * ctx->h) >> (ctx->comp_sft[c][0] + ctx->comp_sft[c][1]); + for (int c = 1; c < ctx->num_c; c++) { + num_pixel += (ctx->w * ctx->h) >> (ctx->c_sft[c][0] + ctx->c_sft[c][1]); } double alpha = ctx->rc_param.alpha; @@ -184,8 +184,8 @@ void oapve_rc_update_after_pic(oapve_ctx_t* ctx, double cost) { if (cost > 0) { int num_pixel = ctx->w * ctx->h; - for (int c = 1; c < ctx->num_comp; c++) { - num_pixel += (ctx->w * ctx->h) >> (ctx->comp_sft[c][0] + ctx->comp_sft[c][1]); + for (int c = 1; c < ctx->num_c; c++) { + num_pixel += (ctx->w * ctx->h) >> (ctx->c_sft[c][0] + ctx->c_sft[c][1]); } int total_bits = 0; diff --git a/src/oapv_vlc.c b/src/oapv_vlc.c index d0ed8ae6..d25bdc08 100644 --- a/src/oapv_vlc.c +++ b/src/oapv_vlc.c @@ -168,7 +168,7 @@ static u64 enc_vlc_write_to_code(oapv_bs_t *bs, int val, int k, int *nbits) static int enc_vlc_quantization_matrix(oapv_bs_t *bs, oapve_ctx_t *ctx, oapv_fh_t *fh) { - for(int cidx = 0; cidx < ctx->num_comp; cidx++) { + for(int cidx = 0; cidx < ctx->num_c; cidx++) { for(int y = 0; y < 8; y++) { for(int x = 0; x < 8; x++) { oapv_bsw_write(bs, fh->q_matrix[cidx][y][x], 8); @@ -295,7 +295,7 @@ void oapve_set_frame_header(oapve_ctx_t *ctx, oapv_fh_t *fh) fh->use_q_matrix = param->use_q_matrix; if(fh->use_q_matrix == 0) { - for(int cidx = 0; cidx < ctx->num_comp; cidx++) { + for(int cidx = 0; cidx < ctx->num_c; cidx++) { for(int y = 0; y < OAPV_BLK_H; y++) { for(int x = 0; x < OAPV_BLK_W; x++) { fh->q_matrix[cidx][y][x] = 16; @@ -318,7 +318,7 @@ void oapve_set_tile_header(oapve_ctx_t *ctx, oapv_th_t *th, int tile_idx, int qp { oapv_mset(th, 0, sizeof(oapv_th_t)); - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { th->tile_qp[c] = oapv_clip3(MIN_QUANT, MAX_QUANT(10), qp + ctx->qp_offset[c]); } th->tile_index = tile_idx; @@ -397,17 +397,17 @@ int oapve_vlc_tile_header(oapve_ctx_t *ctx, oapv_bs_t *bs, oapv_th_t *th) { oapv_assert_rv(bsw_is_align8(bs), OAPV_ERR_MALFORMED_BITSTREAM); th->tile_header_size = 5; // tile_header_size + tile_index + reserved_zero_8bits - th->tile_header_size += (ctx->num_comp * 5); // tile_data_size + tile_qp + th->tile_header_size += (ctx->num_c * 5); // tile_data_size + tile_qp oapv_bsw_write(bs, th->tile_header_size, 16); DUMP_HLS(th->tile_header_size, th->tile_header_size); oapv_bsw_write(bs, th->tile_index, 16); DUMP_HLS(th->tile_index, th->tile_index); - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { oapv_bsw_write(bs, th->tile_data_size[c], 32); DUMP_HLS(th->tile_data_size, th->tile_data_size[c]); } - for(int c = 0; c < ctx->num_comp; c++) { + for(int c = 0; c < ctx->num_c; c++) { oapv_bsw_write(bs, th->tile_qp[c], 8); DUMP_HLS(th->tile_qp, th->tile_qp[c]); } From 013d0d669eddb27b21f5cf687ae73f1dd260e6a6 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Thu, 5 Mar 2026 11:21:55 +0900 Subject: [PATCH 04/31] maybe working code Signed-off-by: kp5.choi@samsung.com --- src/oapv.c | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index 092097a3..62642c2f 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -152,15 +152,29 @@ static void imgb_to_blk(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int static void imgb_to_blk_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; + u16 *s = (u16 *)src; s16 *d = (s16 *)dst; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = s[w] - mid_val; + if(comp) { + u16 p12; + + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + p12 = OAPV_COMP_16C12(s[w]); + d[w] = p12 - mid_val; + } + s = (u16 *)(((u8 *)s) + s_src); + d = (s16 *)(((u8 *)d) + s_dst); + } + } + else { + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = s[w] - mid_val; + } + s = (u16 *)(((u8 *)s) + s_src); + d = (s16 *)(((u8 *)d) + s_dst); } - s = (s16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); } } @@ -235,12 +249,25 @@ static void blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offse s16 *s = (s16 *)src; u16 *d = (u16 *)dst; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = oapv_clip3(0, max_val, s[w] + mid_val); + if(comp) { + u16 p12; + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + p12 = oapv_clip3(0, max_val, s[w] + mid_val); + d[w] = OAPV_COMP_12E16(p12); + } + s = (s16 *)(((u8 *)s) + s_src); + d = (u16 *)(((u8 *)d) + s_dst); + } + } + else { + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = oapv_clip3(0, max_val, s[w] + mid_val); + } + s = (s16 *)(((u8 *)s) + s_src); + d = (u16 *)(((u8 *)d) + s_dst); } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); } } @@ -1038,7 +1065,7 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); // check internal bit-depth and companding option - if(param->profile_idc == OAPV_PROFILE_4444_12C16 && ctx->bit_depth == 16) { + if(param->profile_idc == OAPV_PROFILE_4444_12C16 && ctx->bit_depth_inp == 16) { ctx->bit_depth = 12; // use 12bit internal bit-depth ctx->use_compand = 1; } From ef0809fdcc844964878ea3927f18b8f2e339205a Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Thu, 5 Mar 2026 19:04:45 +0900 Subject: [PATCH 05/31] added new c file Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_enc.c | 2 +- src/oapv.c | 224 +++---------------------------------- src/oapv_blk.c | 269 +++++++++++++++++++++++++++++++++++++++++++++ src/oapv_blk.h | 46 ++++++++ src/oapv_def.h | 100 ++++++++--------- src/oapv_rc.c | 2 +- 6 files changed, 382 insertions(+), 261 deletions(-) create mode 100644 src/oapv_blk.c create mode 100644 src/oapv_blk.h diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 23299cf2..9e4d60ed 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -1283,7 +1283,7 @@ int main(int argc, const char **argv) bitrate_tot, psnr_avg[FRM_IDX][0]); } else if(cfmt == OAPV_CF_YCBCR4444) { // 4-channel - logv3(" -----------------: bitrate(kbps)\tPSNR-Y\tPSNR-U\tPSNR-V\tPSNR-T\n"); + logv3(" -----------------: bitrate(kbps)\tPSNR-Y\tPSNR-U\tPSNR-V\tPSNR-X\n"); logv3(" Summary : %-4.4f\t%-5.4f\t%-5.4f\t%-5.4f\t%-5.4f\n", bitrate_tot, psnr_avg[FRM_IDX][0], psnr_avg[FRM_IDX][1], psnr_avg[FRM_IDX][2], psnr_avg[FRM_IDX][3]); } diff --git a/src/oapv.c b/src/oapv.c index 62642c2f..8fda9651 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -123,200 +123,6 @@ static void imgb_pad_p210(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2 } } -static void imgb_to_blk(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp) -{ - u8 *src, *dst; - int i, sft_hor, sft_ver; - int byte_depth = (bd + 7) >> 3; - - if(c == 0) { - sft_hor = sft_ver = 0; - } - else { - u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); - sft_hor = get_chroma_sft_w(cfi); - sft_ver = get_chroma_sft_h(cfi); - } - - src = ((u8 *)imgb->a[c]) + ((y_l >> sft_ver) * imgb->s[c]) + ((x_l * byte_depth) >> sft_hor); - dst = (u8 *)blk; - - for(i = 0; i < (h_l); i++) { - oapv_mcpy(dst, src, (w_l) * byte_depth); - - src += imgb->s[c]; - dst += (w_l) * byte_depth; - } -} - -static void imgb_to_blk_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) -{ - const int mid_val = (1 << (bd - 1)); - u16 *s = (u16 *)src; - s16 *d = (s16 *)dst; - - if(comp) { - u16 p12; - - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - p12 = OAPV_COMP_16C12(s[w]); - d[w] = p12 - mid_val; - } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); - } - } - else { - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = s[w] - mid_val; - } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); - } - } -} - -static void imgb_to_blk_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) -{ - const int mid_val = (1 << (bd - 1)); - u16 *s = (u16 *)src; - s16 *d = (s16 *)dst; - int shift_pic_bits = 16 - bd; - - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = (s16)(s[w] >> shift_pic_bits) - mid_val; - } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); - } -} - -static void imgb_to_blk_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) -{ - const int mid_val = (1 << (bd - 1)); - u16 *s = (u16 *)src + offset_src; - s16 *d = (s16 *)dst; - int shift_pic_bits = 16 - bd; - - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = (s16)(s[w * 2] >> shift_pic_bits) - mid_val; - } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); - } -} - -static void imgb_to_blk_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp) -{ - u16 *src, *dst; - int sft_hor, sft_ver, s_src; - int size_scale = 1; - int tc = c; - int shift_pic_bits = 16 - bd; - - if(c == 0) { - sft_hor = sft_ver = 0; - } - else { - u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); - sft_hor = get_chroma_sft_w(cfi); - sft_ver = get_chroma_sft_h(cfi); - size_scale = 2; - tc = 1; - } - - s_src = imgb->s[tc] >> (bd > 1 ? 1 : 0); - src = ((u16 *)imgb->a[tc]) + ((y_l >> sft_ver) * s_src) + ((x_l * size_scale) >> sft_hor); - dst = (u16 *)block; - - for(int i = 0; i < (h_l); i++) { - for(int j = 0; j < (w_l); j++) { - dst[j] = (src[j * size_scale + (c >> 1)] >> shift_pic_bits); - } - src += s_src; - dst += w_l; - } -} - -static void blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) -{ - const int max_val = (1 << bd) - 1; - const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; - u16 *d = (u16 *)dst; - - if(comp) { - u16 p12; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - p12 = oapv_clip3(0, max_val, s[w] + mid_val); - d[w] = OAPV_COMP_12E16(p12); - } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); - } - } - else { - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = oapv_clip3(0, max_val, s[w] + mid_val); - } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); - } - } -} - -static void blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) -{ - const int max_val = (1 << bd) - 1; - const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; - u16 *d = (u16 *)dst; - int shift_pic_bits = 16 - bd; - - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = oapv_clip3(0, max_val, s[w] + mid_val) << shift_pic_bits; - } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); - } -} - -static void blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp) -{ - const int max_val = (1 << bd) - 1; - const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; - int shift_pic_bits = 16 - bd; - - // x_pel is x-offset value from left boundary of picture in unit of pixel. - // the 'dst' address has calculated by - // dst = (s16*)((u8*)origin + y_pel*s_dst) + x_pel; - // in case of P210 color format, - // since 's_dst' is byte size of stride including all U and V pixel values, - // y-offset calculation is correct. - // however, the adding only x_pel is not enough to address the correct pixel - // position of U or V because U & V use the same buffer plane - // in interleaved way, - // so, the 'dst' address should be increased by 'x_pel' to address pixel - // position correctly. - u16 *d = (u16 *)dst + x_pel; // p210 pixel value needs 0~65535 range - - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w * 2] = ((u16)oapv_clip3(0, max_val, s[w] + mid_val)) << shift_pic_bits; - } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); - } -} - static void fi_to_finfo(oapv_fi_t *fi, int pbu_type, int group_id, oapv_frm_info_t *finfo) { finfo->w = (int)fi->frame_width; // casting to 'int' would be fine here @@ -819,7 +625,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) { for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) { o16 = (s16 *)((u8 *)org + blk_y * s_org) + blk_x; - ctx->fn_imgb_to_blk[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_compand); + ctx->fn_blk_from_imgb[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_compand); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); @@ -1083,22 +889,22 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } if(OAPV_CS_GET_FORMAT(imgb_i->cs) == OAPV_CF_PLANAR2) { - ctx->fn_imgb_to_blk_rc = imgb_to_blk_p21x; + ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb_p21x; - ctx->fn_imgb_to_blk[Y_C] = imgb_to_blk_p21x_y; - ctx->fn_imgb_to_blk[U_C] = imgb_to_blk_p21x_uv; - ctx->fn_imgb_to_blk[V_C] = imgb_to_blk_p21x_uv; + ctx->fn_blk_from_imgb[Y_C] = oapv_blk_from_imgb_p21x_y; + ctx->fn_blk_from_imgb[U_C] = oapv_blk_from_imgb_p21x_uv; + ctx->fn_blk_from_imgb[V_C] = oapv_blk_from_imgb_p21x_uv; - ctx->fn_blk_to_imgb[Y_C] = blk_to_imgb_p21x_y; - ctx->fn_blk_to_imgb[U_C] = blk_to_imgb_p21x_uv; - ctx->fn_blk_to_imgb[V_C] = blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[Y_C] = oapv_blk_to_imgb_p21x_y; + ctx->fn_blk_to_imgb[U_C] = oapv_blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[V_C] = oapv_blk_to_imgb_p21x_uv; ctx->fn_imgb_pad = imgb_pad_p210; } else { - ctx->fn_imgb_to_blk_rc = imgb_to_blk; + ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb; for(int i = 0; i < ctx->num_c; i++) { - ctx->fn_imgb_to_blk[i] = imgb_to_blk_16; - ctx->fn_blk_to_imgb[i] = blk_to_imgb_16; + ctx->fn_blk_from_imgb[i] = oapv_blk_from_imgb_16; + ctx->fn_blk_to_imgb[i] = oapv_blk_to_imgb_16; } ctx->fn_imgb_pad = imgb_pad; } @@ -1608,13 +1414,13 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) ctx->h = oapv_align_value(ctx->fh.fi.frame_height, OAPV_MB_H); if(OAPV_CS_GET_FORMAT(imgb->cs) == OAPV_CF_PLANAR2) { - ctx->fn_blk_to_imgb[Y_C] = blk_to_imgb_p21x_y; - ctx->fn_blk_to_imgb[U_C] = blk_to_imgb_p21x_uv; - ctx->fn_blk_to_imgb[V_C] = blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[Y_C] = oapv_blk_to_imgb_p21x_y; + ctx->fn_blk_to_imgb[U_C] = oapv_blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[V_C] = oapv_blk_to_imgb_p21x_uv; } else { for(int c = 0; c < ctx->num_c; c++) { - ctx->fn_blk_to_imgb[c] = blk_to_imgb_16; + ctx->fn_blk_to_imgb[c] = oapv_blk_to_imgb_16; } } diff --git a/src/oapv_blk.c b/src/oapv_blk.c new file mode 100644 index 00000000..9b7e17eb --- /dev/null +++ b/src/oapv_blk.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2026 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" + +/*****************************************************************************/ +/* macro for companding (compressing and expanding) */ +/*****************************************************************************/ +/* Compressing 16-bit pixel values to 12-bit by the companding method: + if 'count_leading_zero()' can be supported, the following pseudo code could be efficient. + + if(p16 < 1024) p12 = p16; + else { + int k = (16 - count_leading_zero(p16)) - 9; + p12 = (p16 >> k) + (512 * k); + } +*/ +// input (p16): 16bit unsigned, return: 12bit unsigned +#define OAPV_COMP_16C12(p16) \ + (((p16) < 1024)? (p16) : \ + ((p16) < 2048)? 1024 + (((p16) - 1024) >> 1) : \ + ((p16) < 4096)? 1536 + (((p16) - 2048) >> 2) : \ + ((p16) < 8192)? 2048 + (((p16) - 4096) >> 3) : \ + ((p16) < 16384)? 2560 + (((p16) - 8192) >> 4) : \ + ((p16) < 32768)? 3072 + (((p16) - 16384) >> 5) : \ + /*((p16) < 65537)?*/ 3584 + (((p16) - 32768) >> 6)) + + +/* Expanding 12-bit pixel values to 16-bit by the companding method: + the following pseudo code is an equation form' + + if(p12 < 1024) p16 = p12; + else { + int m = (int)(p12 / 512); + p16 = (p12 - m * 512) << m; + } +*/ +// input (p12): 12bit unsigned, return: 16bit unsigned +#define OAPV_COMP_12E16(p12) \ + (((p12) < 1024)? (p12) : \ + ((p12) < 1536)? 1024 + (((p12) - 1024) << 1) : \ + ((p12) < 2048)? 2048 + (((p12) - 1536) << 2) : \ + ((p12) < 2560)? 4096 + (((p12) - 2048) << 3) : \ + ((p12) < 3072)? 8192 + (((p12) - 2560) << 4) : \ + ((p12) < 3584)? 16384 + (((p12) - 3072) << 5) : \ + /*((p12) < 4096)?*/ 32768 + (((p12) - 3584) << 6)) + + +void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp) +{ + u8 *src, *dst; + int i, sft_hor, sft_ver; + int byte_depth = (bd + 7) >> 3; + + if(c == 0) { + sft_hor = sft_ver = 0; + } + else { + u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); + sft_hor = get_chroma_sft_w(cfi); + sft_ver = get_chroma_sft_h(cfi); + } + + src = ((u8 *)imgb->a[c]) + ((y_l >> sft_ver) * imgb->s[c]) + ((x_l * byte_depth) >> sft_hor); + dst = (u8 *)blk; + + for(i = 0; i < (h_l); i++) { + oapv_mcpy(dst, src, (w_l) * byte_depth); + + src += imgb->s[c]; + dst += (w_l) * byte_depth; + } +} + +void oapv_blk_from_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +{ + const int mid_val = (1 << (bd - 1)); + u16 *s = (u16 *)src; + s16 *d = (s16 *)dst; + + if(comp) { + u16 p12; + + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + p12 = OAPV_COMP_16C12(s[w]); + d[w] = p12 - mid_val; + } + s = (u16 *)(((u8 *)s) + s_src); + d = (s16 *)(((u8 *)d) + s_dst); + } + } + else { + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = s[w] - mid_val; + } + s = (u16 *)(((u8 *)s) + s_src); + d = (s16 *)(((u8 *)d) + s_dst); + } + } +} + +void oapv_blk_from_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +{ + const int mid_val = (1 << (bd - 1)); + u16 *s = (u16 *)src; + s16 *d = (s16 *)dst; + int shift_pic_bits = 16 - bd; + + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = (s16)(s[w] >> shift_pic_bits) - mid_val; + } + s = (u16 *)(((u8 *)s) + s_src); + d = (s16 *)(((u8 *)d) + s_dst); + } +} + +void oapv_blk_from_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +{ + const int mid_val = (1 << (bd - 1)); + u16 *s = (u16 *)src + offset_src; + s16 *d = (s16 *)dst; + int shift_pic_bits = 16 - bd; + + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = (s16)(s[w * 2] >> shift_pic_bits) - mid_val; + } + s = (u16 *)(((u8 *)s) + s_src); + d = (s16 *)(((u8 *)d) + s_dst); + } +} + +void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp) +{ + u16 *src, *dst; + int sft_hor, sft_ver, s_src; + int size_scale = 1; + int tc = c; + int shift_pic_bits = 16 - bd; + + if(c == 0) { + sft_hor = sft_ver = 0; + } + else { + u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); + sft_hor = get_chroma_sft_w(cfi); + sft_ver = get_chroma_sft_h(cfi); + size_scale = 2; + tc = 1; + } + + s_src = imgb->s[tc] >> (bd > 1 ? 1 : 0); + src = ((u16 *)imgb->a[tc]) + ((y_l >> sft_ver) * s_src) + ((x_l * size_scale) >> sft_hor); + dst = (u16 *)block; + + for(int i = 0; i < (h_l); i++) { + for(int j = 0; j < (w_l); j++) { + dst[j] = (src[j * size_scale + (c >> 1)] >> shift_pic_bits); + } + src += s_src; + dst += w_l; + } +} + +void oapv_blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) +{ + const int max_val = (1 << bd) - 1; + const int mid_val = (1 << (bd - 1)); + s16 *s = (s16 *)src; + u16 *d = (u16 *)dst; + + if(comp) { + u16 p12; + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + p12 = oapv_clip3(0, max_val, s[w] + mid_val); + d[w] = OAPV_COMP_12E16(p12); + } + s = (s16 *)(((u8 *)s) + s_src); + d = (u16 *)(((u8 *)d) + s_dst); + } + } + else { + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = oapv_clip3(0, max_val, s[w] + mid_val); + } + s = (s16 *)(((u8 *)s) + s_src); + d = (u16 *)(((u8 *)d) + s_dst); + } + } +} + +void oapv_blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) +{ + const int max_val = (1 << bd) - 1; + const int mid_val = (1 << (bd - 1)); + s16 *s = (s16 *)src; + u16 *d = (u16 *)dst; + int shift_pic_bits = 16 - bd; + + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w] = oapv_clip3(0, max_val, s[w] + mid_val) << shift_pic_bits; + } + s = (s16 *)(((u8 *)s) + s_src); + d = (u16 *)(((u8 *)d) + s_dst); + } +} + +void oapv_blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp) +{ + const int max_val = (1 << bd) - 1; + const int mid_val = (1 << (bd - 1)); + s16 *s = (s16 *)src; + int shift_pic_bits = 16 - bd; + + // x_pel is x-offset value from left boundary of picture in unit of pixel. + // the 'dst' address has calculated by + // dst = (s16*)((u8*)origin + y_pel*s_dst) + x_pel; + // in case of P210 color format, + // since 's_dst' is byte size of stride including all U and V pixel values, + // y-offset calculation is correct. + // however, the adding only x_pel is not enough to address the correct pixel + // position of U or V because U & V use the same buffer plane + // in interleaved way, + // so, the 'dst' address should be increased by 'x_pel' to address pixel + // position correctly. + u16 *d = (u16 *)dst + x_pel; // p210 pixel value needs 0~65535 range + + for(int h = 0; h < blk_h; h++) { + for(int w = 0; w < blk_w; w++) { + d[w * 2] = ((u16)oapv_clip3(0, max_val, s[w] + mid_val)) << shift_pic_bits; + } + s = (s16 *)(((u8 *)s) + s_src); + d = (u16 *)(((u8 *)d) + s_dst); + } +} diff --git a/src/oapv_blk.h b/src/oapv_blk.h new file mode 100644 index 00000000..d04d02ed --- /dev/null +++ b/src/oapv_blk.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 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_BLK_H_3243243920473824893204832876483924637286__ +#define __OAPV_BLK_H_3243243920473824893204832876483924637286__ + +#include "oapv_port.h" + +void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); +void oapv_blk_from_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp); +void oapv_blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); +void oapv_blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); +void oapv_blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp); + +#endif /* __OAPV_BLK_H_3243243920473824893204832876483924637286__ */ diff --git a/src/oapv_def.h b/src/oapv_def.h index ce1f862e..101eb113 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -186,8 +186,8 @@ typedef s64 (*oapv_fn_ssd_t)(int w, int h, void *src1, void *src2, int s_src1, i typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, int s_src2, int s_diff, s16 *diff); typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); -typedef void (*oapv_fn_imgb_to_blk_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -typedef void (*oapv_fn_imgb_to_blk_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +typedef void (*oapv_fn_blk_from_imgb_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); +typedef void (*oapv_fn_blk_from_imgb_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); typedef void (*oapv_fn_blk_to_imgb_t)(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); @@ -269,53 +269,53 @@ struct oapve_tile { * All have to be stored are in this structure. *****************************************************************************/ struct oapve_ctx { - u32 magic; // magic code - oapve_t id; // identifier - oapve_cdesc_t cdesc; - oapve_core_t *core[OAPV_MAX_THREADS]; - oapv_imgb_t *imgb_i; - oapv_imgb_t *imgb_r; - oapve_param_t *param; - oapv_fh_t fh; - oapve_tile_t tile[OAPV_MAX_TILES]; - oapve_rc_param_t rc_param; - oapv_tpool_t *tpool; - oapv_thread_t thread_id[OAPV_MAX_THREADS]; - oapv_sync_obj_t sync_obj; - int threads; // num of thread for encoding - int au_bs_fmt; // access unit bitstream format - int num_tiles_frms[OAPV_MAX_NUM_FRAMES]; - int num_tiles; - int num_tile_cols; - int num_tile_rows; - int qp[N_C]; - s8 qp_offset[N_C]; - int w; - int h; - int cfi; - int num_c; // number of components - int bit_depth; // bit-depth of internal part - int bit_depth_inp; // bit-depth of input video - int c_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height - int use_frm_hash; - int use_compand; - - const oapv_fn_itx_part_t *fn_itx_part; - const oapv_fn_itx_t *fn_itx; - const oapv_fn_itx_adj_t *fn_itx_adj; - const oapv_fn_tx_t *fn_txb; - const oapv_fn_quant_t *fn_quant; - const oapv_fn_dquant_t *fn_dquant; - const oapv_fn_sad_t *fn_sad; - const oapv_fn_ssd_t *fn_ssd; - const oapv_fn_diff_t *fn_diff; - - oapv_fn_imgb_to_blk_rc_t fn_imgb_to_blk_rc; - oapv_fn_imgb_to_blk_t fn_imgb_to_blk[N_C]; - oapv_fn_blk_to_imgb_t fn_blk_to_imgb[N_C]; - oapv_fn_imgb_pad_t fn_imgb_pad; - oapv_fn_enc_blk_cost_t fn_enc_blk; - oapv_fn_had8x8_t fn_had8x8; + u32 magic; // magic code + oapve_t id; // identifier + oapve_cdesc_t cdesc; + oapve_core_t *core[OAPV_MAX_THREADS]; + oapv_imgb_t *imgb_i; + oapv_imgb_t *imgb_r; + oapve_param_t *param; + oapv_fh_t fh; + oapve_tile_t tile[OAPV_MAX_TILES]; + oapve_rc_param_t rc_param; + oapv_tpool_t *tpool; + oapv_thread_t thread_id[OAPV_MAX_THREADS]; + oapv_sync_obj_t sync_obj; + int threads; // num of thread for encoding + int au_bs_fmt; // access unit bitstream format + int num_tiles_frms[OAPV_MAX_NUM_FRAMES]; + int num_tiles; + int num_tile_cols; + int num_tile_rows; + int qp[N_C]; + s8 qp_offset[N_C]; + int w; + int h; + int cfi; + int num_c; // number of components + int bit_depth; // bit-depth of internal part + int bit_depth_inp; // bit-depth of input video + int c_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height + int use_frm_hash; + int use_compand; + + const oapv_fn_itx_part_t *fn_itx_part; + const oapv_fn_itx_t *fn_itx; + const oapv_fn_itx_adj_t *fn_itx_adj; + const oapv_fn_tx_t *fn_txb; + const oapv_fn_quant_t *fn_quant; + const oapv_fn_dquant_t *fn_dquant; + const oapv_fn_sad_t *fn_sad; + const oapv_fn_ssd_t *fn_ssd; + const oapv_fn_diff_t *fn_diff; + + oapv_fn_blk_from_imgb_rc_t fn_blk_from_imgb_rc; + oapv_fn_blk_from_imgb_t fn_blk_from_imgb[N_C]; + oapv_fn_blk_to_imgb_t fn_blk_to_imgb[N_C]; + oapv_fn_imgb_pad_t fn_imgb_pad; + oapv_fn_enc_blk_cost_t fn_enc_blk; + oapv_fn_had8x8_t fn_had8x8; /* platform specific data, if needed */ void *pf; @@ -420,7 +420,7 @@ struct oapvd_ctx { #include "oapv_rc.h" #include "oapv_sad.h" #include "oapv_param.h" -#include "oapv_comp.h" +#include "oapv_blk.h" #if X86_SSE #include "sse/oapv_sad_sse.h" diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 540ab6ad..3eac87bd 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -43,7 +43,7 @@ int oapve_rc_get_tile_cost(oapve_ctx_t* ctx, oapve_core_t* core, oapve_tile_t* t int tx = tile->x + x; int ty = tile->y + y; - ctx->fn_imgb_to_blk_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth, ctx->use_compand); + ctx->fn_blk_from_imgb_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth, ctx->use_compand); sum += ctx->fn_had8x8(core->coef, 8); tile->rc.number_pixel += 64; } From b8dc9a4a813283132ce4b97aafac61d6cb4be47e Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Thu, 5 Mar 2026 19:22:44 +0900 Subject: [PATCH 06/31] changed profile name Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_enc.c | 4 ++-- inc/oapv.h | 4 ++-- src/oapv.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 9e4d60ed..e598c78d 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -131,7 +131,7 @@ static const args_opt_t enc_args_opts[] = { " - 444-12; YCbCr(RGB)444 12bit\n" " - 4444-10: YCbCrX(RGBA)4444 10bit\n" " - 4444-12: YCbCrX(RGBA)4444 12bit\n" - " - 4444-12C16: YCbCrX(RGBA)4444 12bit companded from 16bit\n" + " - 4444-16C12: YCbCrX(RGBA)4444 16bit companded to 12bit\n" " - 400-10: YCbCr400 (monochrome) 10bit\n" " Note: Color space and bit depth of input video will be converted\n" " automatically to support the given profile, if needs\n" @@ -1102,7 +1102,7 @@ int main(int argc, const char **argv) param->profile_idc == OAPV_PROFILE_422_12 || param->profile_idc == OAPV_PROFILE_444_12 || param->profile_idc == OAPV_PROFILE_4444_12) ? 12 : ( - param->profile_idc == OAPV_PROFILE_4444_12C16) ? 16 : 0; + param->profile_idc == OAPV_PROFILE_4444_16C12) ? 16 : 0; if (codec_depth == 0) { logerr("ERR: invalid profile\n"); diff --git a/inc/oapv.h b/inc/oapv.h index 117eff43..6184e67a 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -240,7 +240,7 @@ extern "C" { #define OAPV_PROFILE_444_12 (66) #define OAPV_PROFILE_4444_10 (77) #define OAPV_PROFILE_4444_12 (88) -#define OAPV_PROFILE_4444_12C16 (90) +#define OAPV_PROFILE_4444_16C12 (90) #define OAPV_PROFILE_400_10 (99) /***************************************************************************** @@ -452,7 +452,7 @@ static const oapv_dict_str_int_t oapv_param_opts_profile[] = { {"444-12", OAPV_PROFILE_444_12}, {"4444-10", OAPV_PROFILE_4444_10}, {"4444-12", OAPV_PROFILE_4444_12}, - {"4444-12C16", OAPV_PROFILE_4444_12C16}, + {"4444-16C12", OAPV_PROFILE_4444_16C12}, {"400-10", OAPV_PROFILE_400_10}, {"", 0} // termination }; diff --git a/src/oapv.c b/src/oapv.c index 8fda9651..187d794f 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -800,7 +800,7 @@ static int enc_profile_spec[][5] = { {OAPV_PROFILE_444_12, 2, 3, 10, 12}, {OAPV_PROFILE_4444_10, 2, 4, 10, 10}, {OAPV_PROFILE_4444_12, 2, 4, 10, 12}, - {OAPV_PROFILE_4444_12C16, 3, 4, 16, 16}, + {OAPV_PROFILE_4444_16C12, 3, 4, 16, 16}, {OAPV_PROFILE_400_10, 0, 0, 10, 10}, {0, 0, 0, 0, 0} // termination }; @@ -871,7 +871,7 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); // check internal bit-depth and companding option - if(param->profile_idc == OAPV_PROFILE_4444_12C16 && ctx->bit_depth_inp == 16) { + if(param->profile_idc == OAPV_PROFILE_4444_16C12 && ctx->bit_depth_inp == 16) { ctx->bit_depth = 12; // use 12bit internal bit-depth ctx->use_compand = 1; } From 39f34d68f259fd3f045901f563cda73fe07b425d Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Fri, 6 Mar 2026 12:42:25 +0900 Subject: [PATCH 07/31] changed profile idc and added use_companding syntax Signed-off-by: kp5.choi@samsung.com --- inc/oapv.h | 4 +++- src/oapv.c | 9 +++++---- src/oapv_def.h | 5 +++-- src/oapv_rc.c | 2 +- src/oapv_vlc.c | 15 ++++++++++++--- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/inc/oapv.h b/inc/oapv.h index 6184e67a..3b2c2604 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -240,8 +240,9 @@ extern "C" { #define OAPV_PROFILE_444_12 (66) #define OAPV_PROFILE_4444_10 (77) #define OAPV_PROFILE_4444_12 (88) -#define OAPV_PROFILE_4444_16C12 (90) #define OAPV_PROFILE_400_10 (99) +#define OAPV_PROFILE_4444_16C12 (170) + /***************************************************************************** * family @@ -416,6 +417,7 @@ struct oapv_frm_info { int chroma_format_idc; int bit_depth; int capture_time_distance; + int use_companding; // flag for custom quantization matrix int use_q_matrix; // q_matrix is meaningful if use_q_matrix is true diff --git a/src/oapv.c b/src/oapv.c index 187d794f..01088ad1 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -136,6 +136,7 @@ static void fi_to_finfo(oapv_fi_t *fi, int pbu_type, int group_id, oapv_frm_info finfo->chroma_format_idc = fi->chroma_format_idc; finfo->bit_depth = fi->bit_depth; finfo->capture_time_distance = fi->capture_time_distance; + finfo->use_companding = fi->use_companding; } static void fh_to_finfo(oapv_fh_t *fh, int pbu_type, int group_id, oapv_frm_info_t *finfo) @@ -625,7 +626,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) { for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) { o16 = (s16 *)((u8 *)org + blk_y * s_org) + blk_x; - ctx->fn_blk_from_imgb[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_compand); + ctx->fn_blk_from_imgb[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_companding); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); @@ -634,7 +635,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa if(rec != NULL) { r16 = (s16 *)((u8 *)rec + blk_y * s_rec) + blk_x; - ctx->fn_blk_to_imgb[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth, ctx->use_compand); + ctx->fn_blk_to_imgb[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth, ctx->use_companding); } } } @@ -873,11 +874,11 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * // check internal bit-depth and companding option if(param->profile_idc == OAPV_PROFILE_4444_16C12 && ctx->bit_depth_inp == 16) { ctx->bit_depth = 12; // use 12bit internal bit-depth - ctx->use_compand = 1; + ctx->use_companding = 1; } else { ctx->bit_depth = ctx->bit_depth_inp; - ctx->use_compand = 0; + ctx->use_companding = 0; } // shift parameter for each color component diff --git a/src/oapv_def.h b/src/oapv_def.h index 101eb113..8ce1bed7 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -108,7 +108,8 @@ struct oapv_fi { // 112byte int chroma_format_idc; /* u( 4) */ int bit_depth; /* u( 4) */ int capture_time_distance; /* u( 8) */ - // int reserved_zero_8bits; /* u( 8) */ + int use_companding; /* u( 1) */ + // int reserved_zero_7bits; /* u( 7) */ }; /***************************************************************************** @@ -298,7 +299,7 @@ struct oapve_ctx { int bit_depth_inp; // bit-depth of input video int c_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height int use_frm_hash; - int use_compand; + int use_companding; const oapv_fn_itx_part_t *fn_itx_part; const oapv_fn_itx_t *fn_itx; diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 3eac87bd..6ce944a7 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -43,7 +43,7 @@ int oapve_rc_get_tile_cost(oapve_ctx_t* ctx, oapve_core_t* core, oapve_tile_t* t int tx = tile->x + x; int ty = tile->y + y; - ctx->fn_blk_from_imgb_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth, ctx->use_compand); + ctx->fn_blk_from_imgb_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth, ctx->use_companding); sum += ctx->fn_had8x8(core->coef, 8); tile->rc.number_pixel += 64; } diff --git a/src/oapv_vlc.c b/src/oapv_vlc.c index fa6bb7cf..7c50cc07 100644 --- a/src/oapv_vlc.c +++ b/src/oapv_vlc.c @@ -284,9 +284,10 @@ 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->fi.use_companding = ctx->use_companding; + 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; fh->transfer_characteristics = param->transfer_characteristics; @@ -349,7 +350,9 @@ int oapve_vlc_frame_info(oapv_bs_t *bs, oapv_fi_t *fi) DUMP_HLS(fi->bit_depth, fi->bit_depth - 8); oapv_bsw_write(bs, fi->capture_time_distance, 8); DUMP_HLS(fi->capture_time_distance, fi->capture_time_distance); - oapv_bsw_write(bs, 0, 8); // reserved_zero_8bits + oapv_bsw_write1(bs, fi->use_companding); + DUMP_HLS(fi->use_companding, fi->use_companding); + oapv_bsw_write(bs, 0, 7); // reserved_zero_7bits DUMP_HLS(reserved_zero, 0); return OAPV_OK; } @@ -986,7 +989,13 @@ int oapvd_vlc_frame_info(oapv_bs_t *bs, oapv_fi_t *fi) fi->capture_time_distance = oapv_bsr_read(bs, 8); DUMP_HLS(fi->capture_time_distance, fi->capture_time_distance); - reserved_zero = oapv_bsr_read(bs, 8); + fi->use_companding = oapv_bsr_read1(bs); + DUMP_HLS(fi->use_companding, fi->use_companding); + if(fi->profile_idc != OAPV_PROFILE_4444_16C12) { + oapv_assert_rv(fi->use_companding == 0, OAPV_ERR_MALFORMED_BITSTREAM); + } + + reserved_zero = oapv_bsr_read(bs, 7); DUMP_HLS(reserved_zero, reserved_zero); oapv_assert_rv(reserved_zero == 0, OAPV_ERR_MALFORMED_BITSTREAM); From a03d2038c4c56dde98ec2a068428c7be354e9038 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 9 Mar 2026 15:03:10 +0900 Subject: [PATCH 08/31] initial commit for decoder Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 26 +++++++++++++++++++++++--- inc/oapv.h | 3 ++- src/oapv.c | 10 +++++++--- src/oapv_def.h | 2 +- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 7887792c..a943d4bc 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -75,7 +75,8 @@ static const args_opt_t dec_args_opts[] = { }, { 'd', "output-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL, - "output bit depth (8, 10, 12) " + "output bit depth (8, 10, 12)\n" + " Note: This is option does not support 444/4444-16C12 profile." }, { ARGS_NO_KEY, "hash", ARGS_VAL_TYPE_NONE, 0, NULL, @@ -87,6 +88,11 @@ static const args_opt_t dec_args_opts[] = { " - 0: coded CSP\n" " - 1: convert to P210 in case of YCbCr422\n" }, + { + ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, + "forcely disable companding process\n" + " Note: this option forces to output 12 bits picture in case of 444/4444-16C12 profile" + }, {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */ }; @@ -102,6 +108,7 @@ typedef struct args_var { char threads[16]; int output_depth; int output_csp; + int disable_companding; } args_var_t; static args_var_t *args_init_vars(args_parser_t *args) @@ -118,6 +125,7 @@ static args_var_t *args_init_vars(args_parser_t *args) args_set_variable_by_key_long(opts, "output", vars->fname_out); args_set_variable_by_key_long(opts, "max-au", &vars->max_au); args_set_variable_by_key_long(opts, "hash", &vars->hash); + args_set_variable_by_key_long(opts, "disable-companding", &vars->disable_companding); args_set_variable_by_key_long(opts, "verbose", &op_verbose); op_verbose = VERBOSE_SIMPLE; /* default */ args_set_variable_by_key_long(opts, "threads", vars->threads); @@ -216,7 +224,7 @@ static int set_extra_config(oapvd_t id, args_var_t *args_vars) int ret, size, value; if(args_vars->hash) { // enable frame hash calculation - value = 1; + value = 1; // true size = 4; ret = oapvd_config(id, OAPV_CFG_SET_USE_FRM_HASH, &value, &size); if(OAPV_FAILED(ret)) { @@ -224,6 +232,15 @@ static int set_extra_config(oapvd_t id, args_var_t *args_vars) return -1; } } + if(args_vars->disable_companding) { + value = 1; // true + size = 4; + ret = oapvd_config(id, OAPV_CFG_SET_DISABLE_COMPANDING, &value, &size); + if(OAPV_FAILED(ret)) { + logerr("failed to set config for disabling companding process\n"); + return -1; + } + } return 0; } @@ -525,6 +542,9 @@ int main(int argc, const char **argv) } } + if(args_var->disable_companding && finfo->use_companding == 1) { + args_var->output_depth = 12; + } if(args_var->output_depth == 0) { args_var->output_depth = OAPV_CS_GET_BIT_DEPTH(finfo->cs); } @@ -584,7 +604,7 @@ int main(int argc, const char **argv) for(i = 0; i < ofrms.num_frms; i++) { frm = &ofrms.frm[i]; if(ofrms.num_frms > 0) { - if(OAPV_CS_GET_BIT_DEPTH(frm->imgb->cs) != args_var->output_depth && args_var->output_csp != 1) { + if(OAPV_CS_GET_BIT_DEPTH(frm->imgb->cs) != args_var->output_depth && args_var->output_csp != OUTPUT_CSP_P210) { if(imgb_w == NULL) { imgb_w = imgb_create(frm->imgb->w[0], frm->imgb->h[0], OAPV_CS_SET(OAPV_CS_GET_FORMAT(frm->imgb->cs), args_var->output_depth, 0)); diff --git a/inc/oapv.h b/inc/oapv.h index 3b2c2604..2e684133 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -181,6 +181,7 @@ extern "C" { #define OAPV_CFG_SET_QP_MAX (209) #define OAPV_CFG_SET_USE_FRM_HASH (301) #define OAPV_CFG_SET_AU_BS_FMT (302) +#define OAPV_CFG_SET_DISABLE_COMPANDING (400) #define OAPV_CFG_GET_QP_MIN (600) #define OAPV_CFG_GET_QP_MAX (601) #define OAPV_CFG_GET_QP (602) @@ -454,8 +455,8 @@ static const oapv_dict_str_int_t oapv_param_opts_profile[] = { {"444-12", OAPV_PROFILE_444_12}, {"4444-10", OAPV_PROFILE_4444_10}, {"4444-12", OAPV_PROFILE_4444_12}, - {"4444-16C12", OAPV_PROFILE_4444_16C12}, {"400-10", OAPV_PROFILE_400_10}, + {"4444-16C12", OAPV_PROFILE_4444_16C12}, {"", 0} // termination }; diff --git a/src/oapv.c b/src/oapv.c index 01088ad1..9ed7ffcf 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -801,8 +801,8 @@ static int enc_profile_spec[][5] = { {OAPV_PROFILE_444_12, 2, 3, 10, 12}, {OAPV_PROFILE_4444_10, 2, 4, 10, 10}, {OAPV_PROFILE_4444_12, 2, 4, 10, 12}, - {OAPV_PROFILE_4444_16C12, 3, 4, 16, 16}, {OAPV_PROFILE_400_10, 0, 0, 10, 10}, + {OAPV_PROFILE_4444_16C12, 3, 4, 16, 16}, {0, 0, 0, 0, 0} // termination }; @@ -1459,7 +1459,7 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor { int mb_h, mb_w, mb_y, mb_x, blk_y, blk_x; int le, ri, to, bo; - int ret; + int ret, comp; s16 *d16; mb_h = OAPV_MB_H >> ctx->c_sft[c][1]; @@ -1491,8 +1491,9 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); // copy decoded block to image buffer + comp = (ctx->disable_companding)? 0: ctx->fh.fi.use_companding; d16 = (s16 *)((u8 *)dst + blk_y * s_dst) + blk_x; - ctx->fn_blk_to_imgb[c](core->coef, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_dst, d16, ctx->bit_depth, ctx->use_compand); + ctx->fn_blk_to_imgb[c](core->coef, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_dst, d16, ctx->bit_depth, comp); } } } @@ -1914,6 +1915,9 @@ int oapvd_config(oapvd_t did, int cfg, void *buf, int *size) ctx->use_frm_hash = (*((int *)buf)) ? 1 : 0; break; + case OAPV_CFG_SET_DISABLE_COMPANDING: + ctx->disable_companding = (*((int *)buf)) ? 1 : 0; + break; default: oapv_assert_rv(0, OAPV_ERR_UNSUPPORTED); } diff --git a/src/oapv_def.h b/src/oapv_def.h index 8ce1bed7..b4eaacaa 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -395,7 +395,7 @@ struct oapvd_ctx { int num_c; // number of components int c_sft[N_C][2]; // width or height shift value of each compoents, 0: width, 1: height int use_frm_hash; - int use_compand; // flag of companding + int disable_companding; // flag of companding const oapv_fn_itx_t *fn_itx; const oapv_fn_dquant_t *fn_dquant; From 906c56bffe07cee53df2a95dcc82c357affa7c74 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 9 Mar 2026 15:33:20 +0900 Subject: [PATCH 09/31] fixed bug in colorspace setting Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 16 ++++++++-------- inc/oapv.h | 5 ++++- src/oapv.c | 37 +++++++++++++++++++++---------------- src/oapv_blk.c | 14 +++++++------- src/oapv_blk.h | 14 +++++++------- src/oapv_def.h | 10 +++++----- 6 files changed, 52 insertions(+), 44 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index a943d4bc..007e3d4c 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -332,14 +332,14 @@ static void print_stat_frm(oapvd_stat_t *stat, oapv_frms_t *frms, oapvm_t mid, a : finfo[i].pbu_type == OAPV_PBU_TYPE_ALPHA_FRAME ? "ALPHA" : "UNKNOWN"; - const char * str_csp = finfo[i].cs == OAPV_CS_YCBCR400_10LE ? "4:0:0-10" - : finfo[i].cs == OAPV_CS_YCBCR422_10LE ? "4:2:2-10" - : finfo[i].cs == OAPV_CS_YCBCR422_12LE ? "4:2:2-12" - : finfo[i].cs == OAPV_CS_YCBCR444_10LE ? "4:4:4-10" - : finfo[i].cs == OAPV_CS_YCBCR444_12LE ? "4:4:4-12" - : finfo[i].cs == OAPV_CS_YCBCR4444_10LE ? "4:4:4:4-10" - : finfo[i].cs == OAPV_CS_YCBCR4444_12LE ? "4:4:4:4-12" - : finfo[i].cs == OAPV_CS_YCBCR4444_16LE ? "4:4:4:4-12c16" + const char * str_csp = finfo[i].cs == OAPV_CS_YCBCR400_10LE ? "400-10" + : finfo[i].cs == OAPV_CS_YCBCR422_10LE ? "422-10" + : finfo[i].cs == OAPV_CS_YCBCR422_12LE ? "422-12" + : finfo[i].cs == OAPV_CS_YCBCR444_10LE ? "444-10" + : finfo[i].cs == OAPV_CS_YCBCR444_12LE ? "444-12" + : finfo[i].cs == OAPV_CS_YCBCR4444_10LE ? "4444-10" + : finfo[i].cs == OAPV_CS_YCBCR4444_12LE ? "4444-12" + : finfo[i].cs == OAPV_CS_YCBCR4444_16LE ? "4444-16" : "unknown-cs"; // clang-format on diff --git a/inc/oapv.h b/inc/oapv.h index 2e684133..a3fa6476 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -242,7 +242,8 @@ extern "C" { #define OAPV_PROFILE_4444_10 (77) #define OAPV_PROFILE_4444_12 (88) #define OAPV_PROFILE_400_10 (99) -#define OAPV_PROFILE_4444_16C12 (170) +#define OAPV_PROFILE_444_16C12 (140) +#define OAPV_PROFILE_4444_16C12 (144) /***************************************************************************** @@ -409,6 +410,8 @@ typedef struct oapv_frm_info oapv_frm_info_t; struct oapv_frm_info { int w; int h; + // output frame's color space + // 16bit color space will be set if the profile is 444/4444-16C12 int cs; int pbu_type; int group_id; diff --git a/src/oapv.c b/src/oapv.c index 9ed7ffcf..36ce0295 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -127,7 +127,12 @@ static void fi_to_finfo(oapv_fi_t *fi, int pbu_type, int group_id, oapv_frm_info { finfo->w = (int)fi->frame_width; // casting to 'int' would be fine here finfo->h = (int)fi->frame_height; // casting to 'int' would be fine here - finfo->cs = OAPV_CS_SET(chroma_format_idc_to_color_format(fi->chroma_format_idc), fi->bit_depth, 0); + if(fi->profile_idc == OAPV_PROFILE_444_16C12 || fi->profile_idc == OAPV_PROFILE_4444_16C12) { + finfo->cs = OAPV_CS_SET(chroma_format_idc_to_color_format(fi->chroma_format_idc), 16, 0); + } + else { + finfo->cs = OAPV_CS_SET(chroma_format_idc_to_color_format(fi->chroma_format_idc), fi->bit_depth, 0); + } finfo->pbu_type = pbu_type; finfo->group_id = group_id; finfo->profile_idc = fi->profile_idc; @@ -626,7 +631,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) { for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) { o16 = (s16 *)((u8 *)org + blk_y * s_org) + blk_x; - ctx->fn_blk_from_imgb[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_companding); + ctx->fn_blk_from_pic[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_companding); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); @@ -635,7 +640,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa if(rec != NULL) { r16 = (s16 *)((u8 *)rec + blk_y * s_rec) + blk_x; - ctx->fn_blk_to_imgb[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth, ctx->use_companding); + ctx->fn_blk_to_pic[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth, ctx->use_companding); } } } @@ -890,22 +895,22 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } if(OAPV_CS_GET_FORMAT(imgb_i->cs) == OAPV_CF_PLANAR2) { - ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb_p21x; + ctx->fn_blk_from_imgb_rc = oapv_blk_from_pic_p21x; - ctx->fn_blk_from_imgb[Y_C] = oapv_blk_from_imgb_p21x_y; - ctx->fn_blk_from_imgb[U_C] = oapv_blk_from_imgb_p21x_uv; - ctx->fn_blk_from_imgb[V_C] = oapv_blk_from_imgb_p21x_uv; + ctx->fn_blk_from_pic[Y_C] = oapv_blk_from_pic_p21x_y; + ctx->fn_blk_from_pic[U_C] = oapv_blk_from_pic_p21x_uv; + ctx->fn_blk_from_pic[V_C] = oapv_blk_from_pic_p21x_uv; - ctx->fn_blk_to_imgb[Y_C] = oapv_blk_to_imgb_p21x_y; - ctx->fn_blk_to_imgb[U_C] = oapv_blk_to_imgb_p21x_uv; - ctx->fn_blk_to_imgb[V_C] = oapv_blk_to_imgb_p21x_uv; + ctx->fn_blk_to_pic[Y_C] = oapv_blk_to_pic_p21x_y; + ctx->fn_blk_to_pic[U_C] = oapv_blk_to_pic_p21x_uv; + ctx->fn_blk_to_pic[V_C] = oapv_blk_to_pic_p21x_uv; ctx->fn_imgb_pad = imgb_pad_p210; } else { ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb; for(int i = 0; i < ctx->num_c; i++) { - ctx->fn_blk_from_imgb[i] = oapv_blk_from_imgb_16; - ctx->fn_blk_to_imgb[i] = oapv_blk_to_imgb_16; + ctx->fn_blk_from_pic[i] = oapv_blk_from_pic_16; + ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_16; } ctx->fn_imgb_pad = imgb_pad; } @@ -1415,13 +1420,13 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) ctx->h = oapv_align_value(ctx->fh.fi.frame_height, OAPV_MB_H); if(OAPV_CS_GET_FORMAT(imgb->cs) == OAPV_CF_PLANAR2) { - ctx->fn_blk_to_imgb[Y_C] = oapv_blk_to_imgb_p21x_y; - ctx->fn_blk_to_imgb[U_C] = oapv_blk_to_imgb_p21x_uv; - ctx->fn_blk_to_imgb[V_C] = oapv_blk_to_imgb_p21x_uv; + ctx->fn_blk_to_imgb[Y_C] = oapv_blk_to_pic_p21x_y; + ctx->fn_blk_to_imgb[U_C] = oapv_blk_to_pic_p21x_uv; + ctx->fn_blk_to_imgb[V_C] = oapv_blk_to_pic_p21x_uv; } else { for(int c = 0; c < ctx->num_c; c++) { - ctx->fn_blk_to_imgb[c] = oapv_blk_to_imgb_16; + ctx->fn_blk_to_imgb[c] = oapv_blk_to_pic_16; } } diff --git a/src/oapv_blk.c b/src/oapv_blk.c index 9b7e17eb..cdd973e7 100644 --- a/src/oapv_blk.c +++ b/src/oapv_blk.c @@ -100,7 +100,7 @@ void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int } } -void oapv_blk_from_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +void oapv_blk_from_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)src; @@ -129,7 +129,7 @@ void oapv_blk_from_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offse } } -void oapv_blk_from_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +void oapv_blk_from_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)src; @@ -145,7 +145,7 @@ void oapv_blk_from_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int o } } -void oapv_blk_from_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +void oapv_blk_from_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)src + offset_src; @@ -161,7 +161,7 @@ void oapv_blk_from_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int } } -void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp) +void oapv_blk_from_pic_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp) { u16 *src, *dst; int sft_hor, sft_ver, s_src; @@ -193,7 +193,7 @@ void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l } } -void oapv_blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) +void oapv_blk_to_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); @@ -222,7 +222,7 @@ void oapv_blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_ } } -void oapv_blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) +void oapv_blk_to_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); @@ -239,7 +239,7 @@ void oapv_blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int off } } -void oapv_blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp) +void oapv_blk_to_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); diff --git a/src/oapv_blk.h b/src/oapv_blk.h index d04d02ed..5aac33eb 100644 --- a/src/oapv_blk.h +++ b/src/oapv_blk.h @@ -35,12 +35,12 @@ #include "oapv_port.h" void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -void oapv_blk_from_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -void oapv_blk_from_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -void oapv_blk_from_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp); -void oapv_blk_to_imgb_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); -void oapv_blk_to_imgb_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); -void oapv_blk_to_imgb_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_pic_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp); +void oapv_blk_to_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); +void oapv_blk_to_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); +void oapv_blk_to_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp); #endif /* __OAPV_BLK_H_3243243920473824893204832876483924637286__ */ diff --git a/src/oapv_def.h b/src/oapv_def.h index b4eaacaa..e6c6116b 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -188,8 +188,8 @@ typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); typedef void (*oapv_fn_blk_from_imgb_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -typedef void (*oapv_fn_blk_from_imgb_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -typedef void (*oapv_fn_blk_to_imgb_t)(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); +typedef void (*oapv_fn_blk_from_pic_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); +typedef void (*oapv_fn_blk_to_pic_t)(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); @@ -312,8 +312,8 @@ struct oapve_ctx { const oapv_fn_diff_t *fn_diff; oapv_fn_blk_from_imgb_rc_t fn_blk_from_imgb_rc; - oapv_fn_blk_from_imgb_t fn_blk_from_imgb[N_C]; - oapv_fn_blk_to_imgb_t fn_blk_to_imgb[N_C]; + oapv_fn_blk_from_pic_t fn_blk_from_pic[N_C]; + oapv_fn_blk_to_pic_t fn_blk_to_pic[N_C]; oapv_fn_imgb_pad_t fn_imgb_pad; oapv_fn_enc_blk_cost_t fn_enc_blk; oapv_fn_had8x8_t fn_had8x8; @@ -400,7 +400,7 @@ struct oapvd_ctx { const oapv_fn_itx_t *fn_itx; const oapv_fn_dquant_t *fn_dquant; - oapv_fn_blk_to_imgb_t fn_blk_to_imgb[N_C]; + oapv_fn_blk_to_pic_t fn_blk_to_imgb[N_C]; /* platform specific data, if needed */ void *pf; From 2d89a129ed0cb013bf7933e8348a16b37eec901f Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 9 Mar 2026 18:57:19 +0900 Subject: [PATCH 10/31] refactoring blk code Signed-off-by: kp5.choi@samsung.com --- src/oapv.c | 94 ++++++++++++------------ src/oapv_blk.c | 196 ++++++++++++++++++++++++------------------------- src/oapv_blk.h | 15 ++-- src/oapv_def.h | 6 +- 4 files changed, 156 insertions(+), 155 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index 36ce0295..5d747bb6 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -610,10 +610,10 @@ static int enc_ready(oapve_ctx_t *ctx) return ret; } -static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oapve_core_t *core, int c, int s_org, void *org, int s_rec, void *rec) +static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oapve_core_t *core, int c, int org_s, void *org, int rec_s, void *rec) { - int mb_h, mb_w, mb_y, mb_x, blk_x, blk_y; - s16 *o16 = NULL, *r16 = NULL; + int mb_h, mb_w, y, x, i, j; + s16 *pic = NULL, *rec_t = NULL; u8 *bs_cur = oapv_bsw_sink(bs); oapv_assert_rv(bsw_is_align8(bs), OAPV_ERR_MALFORMED_BITSTREAM); @@ -621,26 +621,26 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa mb_w = OAPV_MB_W >> ctx->c_sft[c][0]; mb_h = OAPV_MB_H >> ctx->c_sft[c][1]; - int tile_le = tile->x >> ctx->c_sft[c][0]; - int tile_ri = (tile->w >> ctx->c_sft[c][0]) + tile_le; - int tile_to = tile->y >> ctx->c_sft[c][1]; - int tile_bo = (tile->h >> ctx->c_sft[c][1]) + tile_to; + int le = tile->x >> ctx->c_sft[c][0]; + int ri = (tile->w >> ctx->c_sft[c][0]) + le; + int to = tile->y >> ctx->c_sft[c][1]; + int bo = (tile->h >> ctx->c_sft[c][1]) + to; - for(mb_y = tile_to; mb_y < tile_bo; mb_y += mb_h) { - for(mb_x = tile_le; mb_x < tile_ri; mb_x += mb_w) { - for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) { - for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) { - o16 = (s16 *)((u8 *)org + blk_y * s_org) + blk_x; - ctx->fn_blk_from_pic[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef, ctx->bit_depth, ctx->use_companding); + for(y = to; y < bo; y += mb_h) { + for(x = le; x < ri; x += mb_w) { + for(j = y; j < (y + mb_h); j += OAPV_BLK_H) { + for(i = x; i < (x + mb_w); i += OAPV_BLK_W) { + pic = (s16 *)((u8 *)org + j * org_s) + i; + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, org_s, i, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, ctx->use_companding); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); oapve_vlc_ac_coef(bs, core->coef, &core->kparam_ac[c]); - DUMP_COEF(core->dc_diff, core->coef + 1, OAPV_BLK_D - 1, blk_x, blk_y, c); + DUMP_COEF(core->dc_diff, core->coef + 1, OAPV_BLK_D - 1, i, j, c); if(rec != NULL) { - r16 = (s16 *)((u8 *)rec + blk_y * s_rec) + blk_x; - ctx->fn_blk_to_pic[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16, ctx->bit_depth, ctx->use_companding); + rec_t = (s16 *)((u8 *)rec + j * rec_s) + i; + ctx->fn_blk_to_pic[c](OAPV_BLK_W, OAPV_BLK_H, core->coef_rec, (OAPV_BLK_W << 1), rec_t, i, rec_s, ctx->bit_depth, ctx->use_companding); } } } @@ -711,39 +711,39 @@ static int enc_tile(oapve_ctx_t *ctx, oapve_core_t *core, oapve_tile_t *tile) core->kparam_ac[c] = OAPV_KPARAM_AC_MIN; core->prev_dc[c] = 0; - int tc, s_org, s_rec; + int tc, org_s, rec_s; s16 *org, *rec; if(OAPV_CS_GET_FORMAT(ctx->imgb_i->cs) == OAPV_CF_PLANAR2) { tc = c > 0 ? 1 : 0; org = ctx->imgb_i->a[tc]; org += (c > 1) ? 1 : 0; - s_org = ctx->imgb_i->s[tc]; + org_s = ctx->imgb_i->s[tc]; if(ctx->imgb_r) { rec = ctx->imgb_r->a[tc]; rec += (c > 1) ? 1 : 0; - s_rec = ctx->imgb_i->s[tc]; + rec_s = ctx->imgb_i->s[tc]; } else { rec = NULL; - s_rec = 0; + rec_s = 0; } } else { org = ctx->imgb_i->a[c]; - s_org = ctx->imgb_i->s[c]; + org_s = ctx->imgb_i->s[c]; if(ctx->imgb_r) { rec = ctx->imgb_r->a[c]; - s_rec = ctx->imgb_i->s[c]; + rec_s = ctx->imgb_i->s[c]; } else { rec = NULL; - s_rec = 0; + rec_s = 0; } } - tile->th.tile_data_size[c] = enc_tile_comp(&bs, tile, ctx, core, c, s_org, org, s_rec, rec); + tile->th.tile_data_size[c] = enc_tile_comp(&bs, tile, ctx, core, c, org_s, org, rec_s, rec); } u32 remained_bs_size = (int)((u8*)oapv_bsw_sink(&bs) - bs.beg); @@ -895,7 +895,7 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } if(OAPV_CS_GET_FORMAT(imgb_i->cs) == OAPV_CF_PLANAR2) { - ctx->fn_blk_from_imgb_rc = oapv_blk_from_pic_p21x; + ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb_p21x; ctx->fn_blk_from_pic[Y_C] = oapv_blk_from_pic_p21x_y; ctx->fn_blk_from_pic[U_C] = oapv_blk_from_pic_p21x_uv; @@ -1420,13 +1420,13 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) ctx->h = oapv_align_value(ctx->fh.fi.frame_height, OAPV_MB_H); if(OAPV_CS_GET_FORMAT(imgb->cs) == OAPV_CF_PLANAR2) { - ctx->fn_blk_to_imgb[Y_C] = oapv_blk_to_pic_p21x_y; - ctx->fn_blk_to_imgb[U_C] = oapv_blk_to_pic_p21x_uv; - ctx->fn_blk_to_imgb[V_C] = oapv_blk_to_pic_p21x_uv; + ctx->fn_blk_to_pic[Y_C] = oapv_blk_to_pic_p21x_y; + ctx->fn_blk_to_pic[U_C] = oapv_blk_to_pic_p21x_uv; + ctx->fn_blk_to_pic[V_C] = oapv_blk_to_pic_p21x_uv; } else { for(int c = 0; c < ctx->num_c; c++) { - ctx->fn_blk_to_imgb[c] = oapv_blk_to_pic_16; + ctx->fn_blk_to_pic[c] = oapv_blk_to_pic_16; } } @@ -1460,12 +1460,12 @@ static int dec_frm_finish(oapvd_ctx_t *ctx) return OAPV_OK; } -static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *core, oapv_bs_t *bs, int c, int s_dst, void *dst) +static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *core, oapv_bs_t *bs, int c, int pic_s, void *pic) { - int mb_h, mb_w, mb_y, mb_x, blk_y, blk_x; + int mb_h, mb_w, y, x, j, i; int le, ri, to, bo; int ret, comp; - s16 *d16; + s16 *pic_t; mb_h = OAPV_MB_H >> ctx->c_sft[c][1]; mb_w = OAPV_MB_W >> ctx->c_sft[c][0]; @@ -1475,10 +1475,10 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor to = tile->y >> ctx->c_sft[c][1]; // top pixel position of tile bo = (tile->h >> ctx->c_sft[c][1]) + to; // bottom pixel position of tile - for(mb_y = to; mb_y < bo; mb_y += mb_h) { - for(mb_x = le; mb_x < ri; mb_x += mb_w) { - for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) { - for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) { + for(y = to; y < bo; y += mb_h) { + for(x = le; x < ri; x += mb_w) { + for(j = y; j < (y + mb_h); j += OAPV_BLK_H) { + for(i = x; i < (x + mb_w); i += OAPV_BLK_W) { // clear coefficient buffers in a macroblock oapv_mset_x128(core->coef, 0, sizeof(s16)*OAPV_MB_D); @@ -1489,7 +1489,7 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor // parse AC coefficient ret = oapvd_vlc_ac_coef(bs, core->coef, &core->kparam_ac[c]); oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); - DUMP_COEF(core->dc_diff, core->coef + 1, OAPV_BLK_D - 1, blk_x, blk_y, c); + DUMP_COEF(core->dc_diff, core->coef + 1, OAPV_BLK_D - 1, i, j, c); // decode a block ret = dec_block(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); @@ -1497,8 +1497,8 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor // copy decoded block to image buffer comp = (ctx->disable_companding)? 0: ctx->fh.fi.use_companding; - d16 = (s16 *)((u8 *)dst + blk_y * s_dst) + blk_x; - ctx->fn_blk_to_imgb[c](core->coef, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_dst, d16, ctx->bit_depth, comp); + pic_t = (s16 *)((u8 *)pic + j * pic_s) + i; + ctx->fn_blk_to_pic[c](OAPV_BLK_W, OAPV_BLK_H, core->coef, (OAPV_BLK_W << 1), pic_t, i, pic_s, ctx->bit_depth, comp); } } } @@ -1540,24 +1540,24 @@ static int dec_tile(oapvd_core_t *core, oapvd_tile_t *tile) } for(c = 0; c < ctx->num_c; c++) { - int tc, s_dst; - s16 *dst; + int tc, pic_s; + s16 *pic; oapv_bs_t bsc; // bs for 'tile_data()' syntax oapv_bsr_init(&bsc, BSR_GET_CUR(&bs), tile->th.tile_data_size[c], NULL); if(OAPV_CS_GET_FORMAT(ctx->imgb->cs) == OAPV_CF_PLANAR2) { tc = c > 0 ? 1 : 0; - dst = ctx->imgb->a[tc]; - dst += (c > 1) ? 1 : 0; - s_dst = ctx->imgb->s[tc]; + pic = ctx->imgb->a[tc]; + pic += (c > 1) ? 1 : 0; + pic_s = ctx->imgb->s[tc]; } else { - dst = ctx->imgb->a[c]; - s_dst = ctx->imgb->s[c]; + pic = ctx->imgb->a[c]; + pic_s = ctx->imgb->s[c]; } - ret = dec_tile_comp(tile, ctx, core, &bsc, c, s_dst, dst); + ret = dec_tile_comp(tile, ctx, core, &bsc, c, pic_s, pic); oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); // move bs buffer to next 'tile_data()' component diff --git a/src/oapv_blk.c b/src/oapv_blk.c index cdd973e7..9d6df0e0 100644 --- a/src/oapv_blk.c +++ b/src/oapv_blk.c @@ -100,170 +100,170 @@ void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int } } -void oapv_blk_from_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp) +{ + u16 *src, *dst; + int sft_hor, sft_ver, s_src; + int size_scale = 1; + int tc = c; + int shift_pic_bits = 16 - bd; + + if(c == 0) { + sft_hor = sft_ver = 0; + } + else { + u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); + sft_hor = get_chroma_sft_w(cfi); + sft_ver = get_chroma_sft_h(cfi); + size_scale = 2; + tc = 1; + } + + s_src = imgb->s[tc] >> (bd > 1 ? 1 : 0); + src = ((u16 *)imgb->a[tc]) + ((y_l >> sft_ver) * s_src) + ((x_l * size_scale) >> sft_hor); + dst = (u16 *)blk; + + for(int i = 0; i < (h_l); i++) { + for(int j = 0; j < (w_l); j++) { + dst[j] = (src[j * size_scale + (c >> 1)] >> shift_pic_bits); + } + src += s_src; + dst += w_l; + } +} + +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp) { const int mid_val = (1 << (bd - 1)); - u16 *s = (u16 *)src; - s16 *d = (s16 *)dst; + u16 *s = (u16 *)pic; + s16 *d = (s16 *)blk; if(comp) { u16 p12; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - p12 = OAPV_COMP_16C12(s[w]); - d[w] = p12 - mid_val; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + p12 = OAPV_COMP_16C12(s[i]); + d[i] = p12 - mid_val; } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); + s = (u16 *)(((u8 *)s) + pic_s); + d = (s16 *)(((u8 *)d) + blk_s); } } else { - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = s[w] - mid_val; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i] = s[i] - mid_val; } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); + s = (u16 *)(((u8 *)s) + pic_s); + d = (s16 *)(((u8 *)d) + blk_s); } } } -void oapv_blk_from_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp) { const int mid_val = (1 << (bd - 1)); - u16 *s = (u16 *)src; - s16 *d = (s16 *)dst; + u16 *s = (u16 *)pic; + s16 *d = (s16 *)blk; int shift_pic_bits = 16 - bd; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = (s16)(s[w] >> shift_pic_bits) - mid_val; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i] = (s16)(s[i] >> shift_pic_bits) - mid_val; } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); + s = (u16 *)(((u8 *)s) + pic_s); + d = (s16 *)(((u8 *)d) + blk_s); } } -void oapv_blk_from_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp) +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp) { const int mid_val = (1 << (bd - 1)); - u16 *s = (u16 *)src + offset_src; - s16 *d = (s16 *)dst; + u16 *s = (u16 *)pic + pic_x; + s16 *d = (s16 *)blk; int shift_pic_bits = 16 - bd; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = (s16)(s[w * 2] >> shift_pic_bits) - mid_val; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i] = (s16)(s[i * 2] >> shift_pic_bits) - mid_val; } - s = (u16 *)(((u8 *)s) + s_src); - d = (s16 *)(((u8 *)d) + s_dst); - } -} - -void oapv_blk_from_pic_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp) -{ - u16 *src, *dst; - int sft_hor, sft_ver, s_src; - int size_scale = 1; - int tc = c; - int shift_pic_bits = 16 - bd; - - if(c == 0) { - sft_hor = sft_ver = 0; - } - else { - u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); - sft_hor = get_chroma_sft_w(cfi); - sft_ver = get_chroma_sft_h(cfi); - size_scale = 2; - tc = 1; - } - - s_src = imgb->s[tc] >> (bd > 1 ? 1 : 0); - src = ((u16 *)imgb->a[tc]) + ((y_l >> sft_ver) * s_src) + ((x_l * size_scale) >> sft_hor); - dst = (u16 *)block; - - for(int i = 0; i < (h_l); i++) { - for(int j = 0; j < (w_l); j++) { - dst[j] = (src[j * size_scale + (c >> 1)] >> shift_pic_bits); - } - src += s_src; - dst += w_l; + s = (u16 *)(((u8 *)s) + pic_s); + d = (s16 *)(((u8 *)d) + blk_s); } } -void oapv_blk_to_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) +void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; - u16 *d = (u16 *)dst; + s16 *s = (s16 *)blk; + u16 *d = (u16 *)pic; if(comp) { u16 p12; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - p12 = oapv_clip3(0, max_val, s[w] + mid_val); - d[w] = OAPV_COMP_12E16(p12); + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + p12 = oapv_clip3(0, max_val, s[i] + mid_val); + d[i] = OAPV_COMP_12E16(p12); } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); + s = (s16 *)(((u8 *)s) + blk_s); + d = (u16 *)(((u8 *)d) + pic_s); } } else { - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = oapv_clip3(0, max_val, s[w] + mid_val); + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i] = oapv_clip3(0, max_val, s[i] + mid_val); } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); + s = (s16 *)(((u8 *)s) + blk_s); + d = (u16 *)(((u8 *)d) + pic_s); } } } -void oapv_blk_to_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp) +void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; - u16 *d = (u16 *)dst; + s16 *s = (s16 *)blk; + u16 *d = (u16 *)pic; int shift_pic_bits = 16 - bd; - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w] = oapv_clip3(0, max_val, s[w] + mid_val) << shift_pic_bits; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i] = oapv_clip3(0, max_val, s[i] + mid_val) << shift_pic_bits; } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); + s = (s16 *)(((u8 *)s) + blk_s); + d = (u16 *)(((u8 *)d) + pic_s); } } -void oapv_blk_to_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp) +void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); - s16 *s = (s16 *)src; + s16 *s = (s16 *)blk; int shift_pic_bits = 16 - bd; - // x_pel is x-offset value from left boundary of picture in unit of pixel. - // the 'dst' address has calculated by - // dst = (s16*)((u8*)origin + y_pel*s_dst) + x_pel; + // pic_x is x-offset value from left boundary of picture in unit of pixel. + // the 'pic' address has calculated by + // pic = (s16*)((u8*)origin + y_pel*pic_s) + pic_x; // in case of P210 color format, - // since 's_dst' is byte size of stride including all U and V pixel values, + // since 'pic_s' is byte size of stride including all U and V pixel values, // y-offset calculation is correct. - // however, the adding only x_pel is not enough to address the correct pixel + // however, the adding only pic_x is not enough to address the correct pixel // position of U or V because U & V use the same buffer plane // in interleaved way, - // so, the 'dst' address should be increased by 'x_pel' to address pixel + // so, the 'pic' address should be increased by 'pic_x' to address pixel // position correctly. - u16 *d = (u16 *)dst + x_pel; // p210 pixel value needs 0~65535 range + u16 *d = (u16 *)pic + pic_x; // p210 pixel value needs 0~65535 range - for(int h = 0; h < blk_h; h++) { - for(int w = 0; w < blk_w; w++) { - d[w * 2] = ((u16)oapv_clip3(0, max_val, s[w] + mid_val)) << shift_pic_bits; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i * 2] = ((u16)oapv_clip3(0, max_val, s[i] + mid_val)) << shift_pic_bits; } - s = (s16 *)(((u8 *)s) + s_src); - d = (u16 *)(((u8 *)d) + s_dst); + s = (s16 *)(((u8 *)s) + blk_s); + d = (u16 *)(((u8 *)d) + pic_s); } } diff --git a/src/oapv_blk.h b/src/oapv_blk.h index 5aac33eb..01c640ec 100644 --- a/src/oapv_blk.h +++ b/src/oapv_blk.h @@ -35,12 +35,13 @@ #include "oapv_port.h" void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -void oapv_blk_from_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -void oapv_blk_from_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -void oapv_blk_from_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -void oapv_blk_from_pic_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block, int bd, int comp); -void oapv_blk_to_pic_16(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); -void oapv_blk_to_pic_p21x_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); -void oapv_blk_to_pic_p21x_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst, int bd, int comp); +void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); + +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); +void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); +void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); +void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); #endif /* __OAPV_BLK_H_3243243920473824893204832876483924637286__ */ diff --git a/src/oapv_def.h b/src/oapv_def.h index e6c6116b..9897ff74 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -188,8 +188,8 @@ typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); typedef void (*oapv_fn_blk_from_imgb_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -typedef void (*oapv_fn_blk_from_pic_t)(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst, int bd, int comp); -typedef void (*oapv_fn_blk_to_pic_t)(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst, int bd, int comp); +typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); +typedef void (*oapv_fn_blk_to_pic_t)(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); @@ -400,7 +400,7 @@ struct oapvd_ctx { const oapv_fn_itx_t *fn_itx; const oapv_fn_dquant_t *fn_dquant; - oapv_fn_blk_to_pic_t fn_blk_to_imgb[N_C]; + oapv_fn_blk_to_pic_t fn_blk_to_pic[N_C]; /* platform specific data, if needed */ void *pf; From bf59009b795a0de6358468f322f75b41f85855db Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 9 Mar 2026 19:28:28 +0900 Subject: [PATCH 11/31] fixed for P210 format Signed-off-by: kp5.choi@samsung.com --- src/oapv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oapv.c b/src/oapv.c index 5d747bb6..a4edf39f 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -631,7 +631,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(j = y; j < (y + mb_h); j += OAPV_BLK_H) { for(i = x; i < (x + mb_w); i += OAPV_BLK_W) { pic = (s16 *)((u8 *)org + j * org_s) + i; - ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, org_s, i, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, ctx->use_companding); + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, ctx->use_companding); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); From 5bc6c75766c2ee14ff7358a4172ef9a91dbb8965 Mon Sep 17 00:00:00 2001 From: Minsoo Park Date: Mon, 9 Mar 2026 20:10:35 +0900 Subject: [PATCH 12/31] clean up blk_from_pic Signed-off-by: Minsoo Park --- src/oapv.c | 5 +-- src/oapv_blk.c | 116 +++++++++++++++++++------------------------------ src/oapv_blk.h | 6 +-- src/oapv_def.h | 3 +- src/oapv_rc.c | 20 ++++++++- 5 files changed, 68 insertions(+), 82 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index a4edf39f..6eb4749f 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -631,7 +631,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(j = y; j < (y + mb_h); j += OAPV_BLK_H) { for(i = x; i < (x + mb_w); i += OAPV_BLK_W) { pic = (s16 *)((u8 *)org + j * org_s) + i; - ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, ctx->use_companding); + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, 1, ctx->use_companding); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); @@ -895,8 +895,6 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * } if(OAPV_CS_GET_FORMAT(imgb_i->cs) == OAPV_CF_PLANAR2) { - ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb_p21x; - ctx->fn_blk_from_pic[Y_C] = oapv_blk_from_pic_p21x_y; ctx->fn_blk_from_pic[U_C] = oapv_blk_from_pic_p21x_uv; ctx->fn_blk_from_pic[V_C] = oapv_blk_from_pic_p21x_uv; @@ -907,7 +905,6 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * ctx->fn_imgb_pad = imgb_pad_p210; } else { - ctx->fn_blk_from_imgb_rc = oapv_blk_from_imgb; for(int i = 0; i < ctx->num_c; i++) { ctx->fn_blk_from_pic[i] = oapv_blk_from_pic_16; ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_16; diff --git a/src/oapv_blk.c b/src/oapv_blk.c index 9d6df0e0..5d4c31d0 100644 --- a/src/oapv_blk.c +++ b/src/oapv_blk.c @@ -73,66 +73,7 @@ ((p12) < 3584)? 16384 + (((p12) - 3072) << 5) : \ /*((p12) < 4096)?*/ 32768 + (((p12) - 3584) << 6)) - -void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp) -{ - u8 *src, *dst; - int i, sft_hor, sft_ver; - int byte_depth = (bd + 7) >> 3; - - if(c == 0) { - sft_hor = sft_ver = 0; - } - else { - u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); - sft_hor = get_chroma_sft_w(cfi); - sft_ver = get_chroma_sft_h(cfi); - } - - src = ((u8 *)imgb->a[c]) + ((y_l >> sft_ver) * imgb->s[c]) + ((x_l * byte_depth) >> sft_hor); - dst = (u8 *)blk; - - for(i = 0; i < (h_l); i++) { - oapv_mcpy(dst, src, (w_l) * byte_depth); - - src += imgb->s[c]; - dst += (w_l) * byte_depth; - } -} - -void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp) -{ - u16 *src, *dst; - int sft_hor, sft_ver, s_src; - int size_scale = 1; - int tc = c; - int shift_pic_bits = 16 - bd; - - if(c == 0) { - sft_hor = sft_ver = 0; - } - else { - u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)); - sft_hor = get_chroma_sft_w(cfi); - sft_ver = get_chroma_sft_h(cfi); - size_scale = 2; - tc = 1; - } - - s_src = imgb->s[tc] >> (bd > 1 ? 1 : 0); - src = ((u16 *)imgb->a[tc]) + ((y_l >> sft_ver) * s_src) + ((x_l * size_scale) >> sft_hor); - dst = (u16 *)blk; - - for(int i = 0; i < (h_l); i++) { - for(int j = 0; j < (w_l); j++) { - dst[j] = (src[j * size_scale + (c >> 1)] >> shift_pic_bits); - } - src += s_src; - dst += w_l; - } -} - -void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp) +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)pic; @@ -142,9 +83,18 @@ void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *b u16 p12; for(int j = 0; j < h; j++) { - for(int i = 0; i < w; i++) { - p12 = OAPV_COMP_16C12(s[i]); - d[i] = p12 - mid_val; + if (sub_mid) { + for (int i = 0; i < w; i++) { + p12 = OAPV_COMP_16C12(s[i]); + d[i] = p12 - mid_val; + } + } + else + { + for (int i = 0; i < w; i++) { + p12 = OAPV_COMP_16C12(s[i]); + d[i] = p12; + } } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); @@ -152,8 +102,16 @@ void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *b } else { for(int j = 0; j < h; j++) { - for(int i = 0; i < w; i++) { - d[i] = s[i] - mid_val; + if (sub_mid) { + for (int i = 0; i < w; i++) { + d[i] = s[i] - mid_val; + } + } + else + { + for (int i = 0; i < w; i++) { + d[i] = s[i]; + } } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); @@ -161,7 +119,7 @@ void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *b } } -void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp) +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)pic; @@ -169,15 +127,23 @@ void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, voi int shift_pic_bits = 16 - bd; for(int j = 0; j < h; j++) { - for(int i = 0; i < w; i++) { - d[i] = (s16)(s[i] >> shift_pic_bits) - mid_val; + if (sub_mid) { + for (int i = 0; i < w; i++) { + d[i] = (s16)(s[i] >> shift_pic_bits) - mid_val; + } + } + else + { + for (int i = 0; i < w; i++) { + d[i] = (s16)(s[i] >> shift_pic_bits); + } } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); } } -void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp) +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp) { const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)pic + pic_x; @@ -185,8 +151,16 @@ void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, vo int shift_pic_bits = 16 - bd; for(int j = 0; j < h; j++) { - for(int i = 0; i < w; i++) { - d[i] = (s16)(s[i * 2] >> shift_pic_bits) - mid_val; + if (sub_mid) { + for (int i = 0; i < w; i++) { + d[i] = (s16)(s[i * 2] >> shift_pic_bits) - mid_val; + } + } + else + { + for (int i = 0; i < w; i++) { + d[i] = (s16)(s[i * 2] >> shift_pic_bits); + } } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); diff --git a/src/oapv_blk.h b/src/oapv_blk.h index 01c640ec..44d50c7f 100644 --- a/src/oapv_blk.h +++ b/src/oapv_blk.h @@ -37,9 +37,9 @@ void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); -void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); -void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); diff --git a/src/oapv_def.h b/src/oapv_def.h index 9897ff74..38094b25 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -188,7 +188,7 @@ typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); typedef void (*oapv_fn_blk_from_imgb_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int comp); +typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); typedef void (*oapv_fn_blk_to_pic_t)(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); @@ -311,7 +311,6 @@ struct oapve_ctx { const oapv_fn_ssd_t *fn_ssd; const oapv_fn_diff_t *fn_diff; - oapv_fn_blk_from_imgb_rc_t fn_blk_from_imgb_rc; oapv_fn_blk_from_pic_t fn_blk_from_pic[N_C]; oapv_fn_blk_to_pic_t fn_blk_to_pic[N_C]; oapv_fn_imgb_pad_t fn_imgb_pad; diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 6ce944a7..94cfd1cf 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -34,16 +34,32 @@ int oapve_rc_get_tile_cost(oapve_ctx_t* ctx, oapve_core_t* core, oapve_tile_t* tile) { int sum = 0; + s16* org = NULL; + s16* pic = NULL; + int org_s; + tile->rc.number_pixel = 0; for (int c = Y_C; c < ctx->num_c; c++) { int step_w = 8 << ctx->c_sft[c][0]; int step_h = 8 << ctx->c_sft[c][1]; + + if (OAPV_CS_GET_FORMAT(ctx->imgb_i->cs) == OAPV_CF_PLANAR2) { + int tc = c > 0 ? 1 : 0; + org = ctx->imgb_i->a[tc]; + org += (c > 1) ? 1 : 0; + org_s = ctx->imgb_i->s[tc]; + } + else { + org = ctx->imgb_i->a[c]; + org_s = ctx->imgb_i->s[c]; + } + for (int y = 0; y < tile->h; y += step_h) { for (int x = 0; x < tile->w; x += step_w) { int tx = tile->x + x; int ty = tile->y + y; - - ctx->fn_blk_from_imgb_rc(ctx->imgb_i, c, tx, ty, 8, 8, core->coef, ctx->bit_depth, ctx->use_companding); + pic = (s16*)((u8*)org + ty * org_s) + tx; + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, 0, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, 0, ctx->use_companding); sum += ctx->fn_had8x8(core->coef, 8); tile->rc.number_pixel += 64; } From 12a5e549017bf703c59d9cc07308f02a03c5ec58 Mon Sep 17 00:00:00 2001 From: Minsoo Park Date: Thu, 12 Mar 2026 09:12:02 +0900 Subject: [PATCH 13/31] modification of blk_from_pic Signed-off-by: Minsoo Park --- src/oapv.c | 2 +- src/oapv_blk.c | 57 ++++++++++---------------------------------------- src/oapv_blk.h | 6 +++--- src/oapv_def.h | 3 +-- 4 files changed, 16 insertions(+), 52 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index 6eb4749f..02823253 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -631,7 +631,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(j = y; j < (y + mb_h); j += OAPV_BLK_H) { for(i = x; i < (x + mb_w); i += OAPV_BLK_W) { pic = (s16 *)((u8 *)org + j * org_s) + i; - ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, 1, ctx->use_companding); + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, (1 << (ctx->bit_depth - 1)) , ctx->use_companding); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); diff --git a/src/oapv_blk.c b/src/oapv_blk.c index 5d4c31d0..aeb80924 100644 --- a/src/oapv_blk.c +++ b/src/oapv_blk.c @@ -73,9 +73,8 @@ ((p12) < 3584)? 16384 + (((p12) - 3072) << 5) : \ /*((p12) < 4096)?*/ 32768 + (((p12) - 3584) << 6)) -void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp) +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp) { - const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)pic; s16 *d = (s16 *)blk; @@ -83,18 +82,9 @@ void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *b u16 p12; for(int j = 0; j < h; j++) { - if (sub_mid) { - for (int i = 0; i < w; i++) { - p12 = OAPV_COMP_16C12(s[i]); - d[i] = p12 - mid_val; - } - } - else - { - for (int i = 0; i < w; i++) { - p12 = OAPV_COMP_16C12(s[i]); - d[i] = p12; - } + for (int i = 0; i < w; i++) { + p12 = OAPV_COMP_16C12(s[i]); + d[i] = p12 - mid_val; } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); @@ -102,65 +92,40 @@ void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *b } else { for(int j = 0; j < h; j++) { - if (sub_mid) { for (int i = 0; i < w; i++) { d[i] = s[i] - mid_val; } - } - else - { - for (int i = 0; i < w; i++) { - d[i] = s[i]; - } - } + s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); } } } -void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp) +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp) { - const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)pic; s16 *d = (s16 *)blk; int shift_pic_bits = 16 - bd; for(int j = 0; j < h; j++) { - if (sub_mid) { - for (int i = 0; i < w; i++) { - d[i] = (s16)(s[i] >> shift_pic_bits) - mid_val; - } - } - else - { - for (int i = 0; i < w; i++) { - d[i] = (s16)(s[i] >> shift_pic_bits); - } + for (int i = 0; i < w; i++) { + d[i] = (s16)(s[i] >> shift_pic_bits) - mid_val; } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); } } -void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp) +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp) { - const int mid_val = (1 << (bd - 1)); u16 *s = (u16 *)pic + pic_x; s16 *d = (s16 *)blk; int shift_pic_bits = 16 - bd; for(int j = 0; j < h; j++) { - if (sub_mid) { - for (int i = 0; i < w; i++) { - d[i] = (s16)(s[i * 2] >> shift_pic_bits) - mid_val; - } - } - else - { - for (int i = 0; i < w; i++) { - d[i] = (s16)(s[i * 2] >> shift_pic_bits); - } + for (int i = 0; i < w; i++) { + d[i] = (s16)(s[i * 2] >> shift_pic_bits) - mid_val; } s = (u16 *)(((u8 *)s) + pic_s); d = (s16 *)(((u8 *)d) + blk_s); diff --git a/src/oapv_blk.h b/src/oapv_blk.h index 44d50c7f..64191ece 100644 --- a/src/oapv_blk.h +++ b/src/oapv_blk.h @@ -37,9 +37,9 @@ void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); -void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); -void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); diff --git a/src/oapv_def.h b/src/oapv_def.h index 38094b25..3707a8d3 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -187,8 +187,7 @@ typedef s64 (*oapv_fn_ssd_t)(int w, int h, void *src1, void *src2, int s_src1, i typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, int s_src2, int s_diff, s16 *diff); typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); -typedef void (*oapv_fn_blk_from_imgb_rc_t)(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int sub_mid, int comp); +typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); typedef void (*oapv_fn_blk_to_pic_t)(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); From d88480effd89215248fc3ed99eb2e47ef0dd1a2f Mon Sep 17 00:00:00 2001 From: Subhrajit Mishra <84323996+subhrajitm20@users.noreply.github.com> Date: Sat, 14 Mar 2026 06:12:04 +0530 Subject: [PATCH 14/31] separate functions for companding and no-companding (#198) Signed-off-by: subhrajitm20 <2003subhrajit@gmail.com> --- src/oapv.c | 34 ++++++++++++++------ src/oapv_blk.c | 85 +++++++++++++++++++++++++++----------------------- src/oapv_blk.h | 14 +++++---- src/oapv_def.h | 4 +-- src/oapv_rc.c | 2 +- 5 files changed, 81 insertions(+), 58 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index 02823253..d8795bd9 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -631,7 +631,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa for(j = y; j < (y + mb_h); j += OAPV_BLK_H) { for(i = x; i < (x + mb_w); i += OAPV_BLK_W) { pic = (s16 *)((u8 *)org + j * org_s) + i; - ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, (1 << (ctx->bit_depth - 1)) , ctx->use_companding); + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, i, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, (1 << (ctx->bit_depth - 1))); ctx->fn_enc_blk(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c); oapve_vlc_dc_coef(bs, core->dc_diff, &core->kparam_dc[c]); @@ -640,7 +640,7 @@ static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oa if(rec != NULL) { rec_t = (s16 *)((u8 *)rec + j * rec_s) + i; - ctx->fn_blk_to_pic[c](OAPV_BLK_W, OAPV_BLK_H, core->coef_rec, (OAPV_BLK_W << 1), rec_t, i, rec_s, ctx->bit_depth, ctx->use_companding); + ctx->fn_blk_to_pic[c](OAPV_BLK_W, OAPV_BLK_H, core->coef_rec, (OAPV_BLK_W << 1), rec_t, i, rec_s, ctx->bit_depth); } } } @@ -905,9 +905,17 @@ static int enc_frm_prepare(oapve_ctx_t *ctx, oapve_param_t *param, oapv_imgb_t * ctx->fn_imgb_pad = imgb_pad_p210; } else { - for(int i = 0; i < ctx->num_c; i++) { - ctx->fn_blk_from_pic[i] = oapv_blk_from_pic_16; - ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_16; + if(ctx->use_companding){ + for(int i = 0; i < ctx->num_c; i++) { + ctx->fn_blk_from_pic[i] = oapv_blk_from_pic_16C12; + ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_12E16; + } + } + else{ + for(int i = 0; i < ctx->num_c; i++) { + ctx->fn_blk_from_pic[i] = oapv_blk_from_pic_16; + ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_16; + } } ctx->fn_imgb_pad = imgb_pad; } @@ -1422,8 +1430,15 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) ctx->fn_blk_to_pic[V_C] = oapv_blk_to_pic_p21x_uv; } else { - for(int c = 0; c < ctx->num_c; c++) { - ctx->fn_blk_to_pic[c] = oapv_blk_to_pic_16; + if(ctx->disable_companding){ + for(int i = 0; i < ctx->num_c; i++) { + ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_16; + } + } + else{ + for(int i = 0; i < ctx->num_c; i++) { + ctx->fn_blk_to_pic[i] = oapv_blk_to_pic_12E16; + } } } @@ -1461,7 +1476,7 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor { int mb_h, mb_w, y, x, j, i; int le, ri, to, bo; - int ret, comp; + int ret; s16 *pic_t; mb_h = OAPV_MB_H >> ctx->c_sft[c][1]; @@ -1493,9 +1508,8 @@ static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *cor oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); // copy decoded block to image buffer - comp = (ctx->disable_companding)? 0: ctx->fh.fi.use_companding; pic_t = (s16 *)((u8 *)pic + j * pic_s) + i; - ctx->fn_blk_to_pic[c](OAPV_BLK_W, OAPV_BLK_H, core->coef, (OAPV_BLK_W << 1), pic_t, i, pic_s, ctx->bit_depth, comp); + ctx->fn_blk_to_pic[c](OAPV_BLK_W, OAPV_BLK_H, core->coef, (OAPV_BLK_W << 1), pic_t, i, pic_s, ctx->bit_depth); } } } diff --git a/src/oapv_blk.c b/src/oapv_blk.c index aeb80924..f544e837 100644 --- a/src/oapv_blk.c +++ b/src/oapv_blk.c @@ -73,36 +73,39 @@ ((p12) < 3584)? 16384 + (((p12) - 3072) << 5) : \ /*((p12) < 4096)?*/ 32768 + (((p12) - 3584) << 6)) -void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp) +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val) { u16 *s = (u16 *)pic; s16 *d = (s16 *)blk; - if(comp) { - u16 p12; - - for(int j = 0; j < h; j++) { + for(int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { - p12 = OAPV_COMP_16C12(s[i]); - d[i] = p12 - mid_val; + d[i] = s[i] - mid_val; } - s = (u16 *)(((u8 *)s) + pic_s); - d = (s16 *)(((u8 *)d) + blk_s); - } + + s = (u16 *)(((u8 *)s) + pic_s); + d = (s16 *)(((u8 *)d) + blk_s); } - else { - for(int j = 0; j < h; j++) { - for (int i = 0; i < w; i++) { - d[i] = s[i] - mid_val; - } - - s = (u16 *)(((u8 *)s) + pic_s); - d = (s16 *)(((u8 *)d) + blk_s); +} + +void oapv_blk_from_pic_16C12(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val) +{ + u16 *s = (u16 *)pic; + s16 *d = (s16 *)blk; + + u16 p12; + + for(int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + p12 = OAPV_COMP_16C12(s[i]); + d[i] = p12 - mid_val; } + s = (u16 *)(((u8 *)s) + pic_s); + d = (s16 *)(((u8 *)d) + blk_s); } } -void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp) +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val) { u16 *s = (u16 *)pic; s16 *d = (s16 *)blk; @@ -117,7 +120,7 @@ void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, voi } } -void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp) +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val) { u16 *s = (u16 *)pic + pic_x; s16 *d = (s16 *)blk; @@ -132,36 +135,40 @@ void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, vo } } -void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp) +void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); s16 *s = (s16 *)blk; u16 *d = (u16 *)pic; - if(comp) { - u16 p12; - for(int j = 0; j < h; j++) { - for(int i = 0; i < w; i++) { - p12 = oapv_clip3(0, max_val, s[i] + mid_val); - d[i] = OAPV_COMP_12E16(p12); - } - s = (s16 *)(((u8 *)s) + blk_s); - d = (u16 *)(((u8 *)d) + pic_s); + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + d[i] = oapv_clip3(0, max_val, s[i] + mid_val); } + s = (s16 *)(((u8 *)s) + blk_s); + d = (u16 *)(((u8 *)d) + pic_s); } - else { - for(int j = 0; j < h; j++) { - for(int i = 0; i < w; i++) { - d[i] = oapv_clip3(0, max_val, s[i] + mid_val); - } - s = (s16 *)(((u8 *)s) + blk_s); - d = (u16 *)(((u8 *)d) + pic_s); +} +void oapv_blk_to_pic_12E16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd) +{ + const int max_val = (1 << bd) - 1; + const int mid_val = (1 << (bd - 1)); + s16 *s = (s16 *)blk; + u16 *d = (u16 *)pic; + + u16 p12; + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + p12 = oapv_clip3(0, max_val, s[i] + mid_val); + d[i] = OAPV_COMP_12E16(p12); } + s = (s16 *)(((u8 *)s) + blk_s); + d = (u16 *)(((u8 *)d) + pic_s); } } -void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp) +void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); @@ -178,7 +185,7 @@ void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int p } } -void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp) +void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd) { const int max_val = (1 << bd) - 1; const int mid_val = (1 << (bd - 1)); diff --git a/src/oapv_blk.h b/src/oapv_blk.h index 64191ece..386a4b54 100644 --- a/src/oapv_blk.h +++ b/src/oapv_blk.h @@ -37,11 +37,13 @@ void oapv_blk_from_imgb(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); void oapv_blk_from_imgb_p21x(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *blk, int bd, int comp); -void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); -void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); -void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); -void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); -void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); -void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); +void oapv_blk_from_pic_16(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val); +void oapv_blk_from_pic_16C12(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val); +void oapv_blk_from_pic_p21x_y(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val); +void oapv_blk_from_pic_p21x_uv(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val); +void oapv_blk_to_pic_16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd); +void oapv_blk_to_pic_12E16(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd); +void oapv_blk_to_pic_p21x_y(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd); +void oapv_blk_to_pic_p21x_uv(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd); #endif /* __OAPV_BLK_H_3243243920473824893204832876483924637286__ */ diff --git a/src/oapv_def.h b/src/oapv_def.h index 3707a8d3..70896004 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -187,8 +187,8 @@ typedef s64 (*oapv_fn_ssd_t)(int w, int h, void *src1, void *src2, int s_src1, i typedef void (*oapv_fn_diff_t)(int w, int h, void *src1, void *src2, int s_src1, int s_src2, int s_diff, s16 *diff); typedef double (*oapv_fn_enc_blk_cost_t)(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c); -typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val, int comp); -typedef void (*oapv_fn_blk_to_pic_t)(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd, int comp); +typedef void (*oapv_fn_blk_from_pic_t)(int w, int h, void *pic, int pic_x, int pic_s, void *blk, int blk_s, int bd, int mid_val); +typedef void (*oapv_fn_blk_to_pic_t)(int w, int h, void *blk, int blk_s, void *pic, int pic_x, int pic_s, int bd); typedef void (*oapv_fn_imgb_pad_t)(oapv_imgb_t *imgb, int aw, int ah, int comp_sft[N_C][2]); typedef int (*oapv_fn_had8x8_t)(pel *org, int s_org); diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 94cfd1cf..7d99763d 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -59,7 +59,7 @@ int oapve_rc_get_tile_cost(oapve_ctx_t* ctx, oapve_core_t* core, oapve_tile_t* t int tx = tile->x + x; int ty = tile->y + y; pic = (s16*)((u8*)org + ty * org_s) + tx; - ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, 0, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, 0, ctx->use_companding); + ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, 0, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, 0); sum += ctx->fn_had8x8(core->coef, 8); tile->rc.number_pixel += 64; } From 76580b8e8759e21d6b1c8fc74fec1df05745fcad Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 16 Mar 2026 15:54:12 +0900 Subject: [PATCH 15/31] initial code Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 373 ++++++++++++++++++++++++++++++++++++++------- inc/oapv.h | 23 +++ 2 files changed, 340 insertions(+), 56 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 007e3d4c..99ecd97b 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -368,97 +368,272 @@ static void print_stat_frm(oapvd_stat_t *stat, oapv_frms_t *frms, oapvm_t mid, a } } -int main(int argc, const char **argv) +int main_oapv1(args_var_t *args_var, FILE *fp_bs, int is_y4m) { - args_parser_t *args; - args_var_t *args_var = NULL; - unsigned char *bs_buf = NULL; oapvd_t did = NULL; oapvm_t mid = NULL; oapvd_cdesc_t cdesc; + oapv_au_info_t aui; + oapvd_stat_t stat; + unsigned char *bs_buf = NULL; + oapv_frm_info_t *finfo = NULL; oapv_bitb_t bitb; oapv_frms_t ofrms; oapv_imgb_t *imgb_w = NULL; oapv_imgb_t *imgb_o = NULL; oapv_frm_t *frm = NULL; - oapv_au_info_t aui; - oapvd_stat_t stat; int i, ret = 0; oapv_clk_t clk_beg, clk_end, clk_tot; int au_cnt, frm_cnt[OAPV_MAX_NUM_FRAMES]; int read_size, bs_buf_size = 0; - FILE *fp_bs = NULL; - int is_y4m = 0; - char *errstr = NULL; - oapv_frm_info_t *finfo = NULL; memset(frm_cnt, 0, sizeof(int) * OAPV_MAX_NUM_FRAMES); memset(&aui, 0, sizeof(oapv_au_info_t)); memset(&ofrms, 0, sizeof(oapv_frms_t)); - // print logo - logv2(" ____ ___ ___ _ __\n"); - logv2(" / __ \\___ ___ ___ / _ | / _ \\ | / / Decoder (v%s)\n", oapv_version(NULL)); - logv2("/ /_/ / _ \\/ -_) _ \\/ __ |/ ___/ |/ / \n"); - logv2("\\____/ .__/\\__/_//_/_/ |_/_/ |___/ \n"); - logv2(" /_/ \n"); - logv2("\n"); - - /* help message */ - if(argc < 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) { - print_usage(argv); - return 0; - } - /* parse command line */ - args = args_create(dec_args_opts, NUM_ARGS_OPT); - if(args == NULL) { - logerr("ERR: cannot create argument parser\n"); + // create bitstream buffer + bs_buf = malloc(MAX_BS_BUF); + if(bs_buf == NULL) { + logerr("ERR: cannot allocate bitstream buffer, size=%d\n", MAX_BS_BUF); ret = -1; goto ERR; } - args_var = args_init_vars(args); - if(args_var == NULL) { - logerr("ERR: cannot initialize argument parser\n"); + + // create decoder + if(!strcmp(args_var->threads, "auto")){ + cdesc.threads = OAPV_CDESC_THREADS_AUTO; + } + else { + cdesc.threads = atoi(args_var->threads); + } + did = oapvd_create(&cdesc, &ret); + if(did == NULL) { + logerr("ERR: cannot create OAPV decoder (err=%d)\n", ret); ret = -1; goto ERR; } - if(args->parse(args, argc, argv, &errstr)) { - logerr("ERR: command parsing error (%s)\n", errstr); + if(set_extra_config(did, args_var)) { + logerr("ERR: cannot set extra configurations\n"); ret = -1; goto ERR; } - // print command line string for information - print_commandline(argc, argv); - if(args->check_mandatory(args, &errstr)) { - logerr("ERR: '--%s' argument is mandatory\n", errstr); + clk_tot = 0; + au_cnt = 0; + + /* create metadata container */ + mid = oapvm_create(&ret); + if(OAPV_FAILED(ret)) { + logerr("ERR: cannot create OAPV metadata container (err=%d)\n", ret); ret = -1; goto ERR; } - /* open input file */ - fp_bs = fopen(args_var->fname_inp, "rb"); - if(fp_bs == NULL) { - logerr("ERR: cannot open bitstream file = %s\n", args_var->fname_inp); - print_usage(argv); - ret = -1; goto ERR; - } - /* open output file */ - if(strlen(args_var->fname_out) > 0) { - ret = check_file_name_type(args_var->fname_out); - if(ret > 0) { - is_y4m = 1; + /* decoding loop */ + while(args_var->max_au == 0 || (au_cnt < args_var->max_au)) { + read_size = read_bitstream(fp_bs, bs_buf, &bs_buf_size); + if (read_size == 0) { + logv3("--> end of bitstream\n") + break; } - else if(ret == 0) { - is_y4m = 0; + if (read_size < 0) { + logv3("--> bitstream reading error\n") + ret = -1; + goto ERR; } - else { // invalid or unknown file name type - logerr("ERR: unknown file type name for decoded video\n"); - ret = -1; goto ERR; + + if(OAPV_FAILED(oapvd_info(bs_buf, bs_buf_size, &aui))) { + logerr("ERR: cannot get information from bitstream\n"); + ret = -1; + goto ERR; } - clear_data(args_var->fname_out); /* remove decoded file contents if exists */ + + /* create decoding frame buffers */ + ofrms.num_frms = aui.num_frms; + for(i = 0; i < ofrms.num_frms; i++) { + finfo = &aui.frm_info[i]; + frm = &ofrms.frm[i]; + + if(frm->imgb != NULL && (frm->imgb->w[0] != finfo->w || frm->imgb->h[0] != finfo->h)) { + frm->imgb->release(frm->imgb); + frm->imgb = NULL; + } + + if(frm->imgb == NULL) { + if(args_var->output_csp == 1) { + frm->imgb = imgb_create(finfo->w, finfo->h, OAPV_CS_SET(OAPV_CF_PLANAR2, 10, 0)); + } + else { + frm->imgb = imgb_create(finfo->w, finfo->h, finfo->cs); + } + if(frm->imgb == NULL) { + logerr("ERR: cannot allocate image buffer (w:%d, h:%d, cs:%d)\n", + finfo->w, finfo->h, finfo->cs); + ret = -1; + goto ERR; + } + } + } + + if(args_var->disable_companding && finfo->use_companding == 1) { + args_var->output_depth = 12; + } + if(args_var->output_depth == 0) { + args_var->output_depth = OAPV_CS_GET_BIT_DEPTH(finfo->cs); + } + + /* main decoding block */ + bitb.addr = bs_buf; + bitb.ssize = bs_buf_size; + memset(&stat, 0, sizeof(oapvd_stat_t)); + + clk_beg = oapv_clk_get(); + + ret = oapvd_decode(did, &bitb, &ofrms, mid, &stat); + + clk_end = oapv_clk_from(clk_beg); + clk_tot += clk_end; + + if(OAPV_FAILED(ret)) { + logerr("ERR: failed to decode bitstream\n"); + ret = -1; + goto END; + } + if(stat.read != bs_buf_size) { + logerr("\t=> different reading of bitstream (in:%d, read:%d)\n", + bs_buf_size, stat.read); + continue; + } + + /* testing of metadata reading */ + if(mid) { + oapvm_payload_t *pld = NULL; // metadata payload + int num_plds = 0; // number of metadata payload + + ret = oapvm_get_all(mid, NULL, &num_plds); + + if(OAPV_FAILED(ret)) { + logerr("ERR: failed to read metadata\n"); + goto END; + } + if(num_plds > 0) { + pld = malloc(sizeof(oapvm_payload_t) * num_plds); + ret = oapvm_get_all(mid, pld, &num_plds); + if(OAPV_FAILED(ret)) { + logerr("ERR: failed to read metadata\n"); + free(pld); + goto END; + } + } + if(pld != NULL) + free(pld); + } + + /* print decoding results */ + print_stat_au(&stat, au_cnt, args_var, clk_end, clk_tot); + print_stat_frm(&stat, &ofrms, mid, args_var); + + /* write decoded frames into files */ + for(i = 0; i < ofrms.num_frms; i++) { + frm = &ofrms.frm[i]; + if(ofrms.num_frms > 0) { + if(OAPV_CS_GET_BIT_DEPTH(frm->imgb->cs) != args_var->output_depth && args_var->output_csp != OUTPUT_CSP_P210) { + if(imgb_w == NULL) { + imgb_w = imgb_create(frm->imgb->w[0], frm->imgb->h[0], + OAPV_CS_SET(OAPV_CS_GET_FORMAT(frm->imgb->cs), args_var->output_depth, 0)); + if(imgb_w == NULL) { + logerr("ERR: cannot allocate image buffer (w:%d, h:%d, cs:%d)\n", + frm->imgb->w[0], frm->imgb->h[0], frm->imgb->cs); + ret = -1; + goto ERR; + } + } + imgb_cpy(imgb_w, frm->imgb); + imgb_o = imgb_w; + } + else { + imgb_o = frm->imgb; + } + + if(strlen(args_var->fname_out)) { + if(frm_cnt[i] == 0 && is_y4m) { + if(write_y4m_header(args_var->fname_out, imgb_o)) { + logerr("ERR: cannot write Y4M header\n"); + ret = -1; + goto ERR; + } + } + if(write_dec_img(args_var->fname_out, imgb_o, is_y4m)) { + logerr("ERR: cannot write decoded video\n"); + ret = -1; + goto ERR; + } + } + frm_cnt[i]++; + } + } + au_cnt++; + oapvm_rem_all(mid); // remove all metadata for next au decoding + fflush(stdout); + fflush(stderr); } +END: + logv2_line("Summary"); + logv2("Processed access units = %d\n", au_cnt); + int total_frame_count = 0; + for(i = 0; i < OAPV_MAX_NUM_FRAMES; i++) + total_frame_count += frm_cnt[i]; + logv2("Decoded frame count = %d\n", total_frame_count); + if(total_frame_count > 0) { + logv2("Total decoding time = %d msec,", (int)oapv_clk_msec(clk_tot)); + logv2(" %.3f sec\n", (float)(oapv_clk_msec(clk_tot) / 1000.0)); + logv2("Average decoding time for a frame = %d msec\n", (int)oapv_clk_msec(clk_tot) / total_frame_count); + logv2("Average decoding speed = %.3f frames/sec\n", ((float)total_frame_count * 1000) / ((float)oapv_clk_msec(clk_tot))); + } + logv2_line(NULL); + +ERR: + if(did) + oapvd_delete(did); + + if(mid) + oapvm_delete(mid); + + for(int i = 0; i < ofrms.num_frms; i++) { + if(ofrms.frm[i].imgb != NULL) { + ofrms.frm[i].imgb->release(ofrms.frm[i].imgb); + } + } + if(imgb_w != NULL) + imgb_w->release(imgb_w); + + return 0; +} + +int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) +{ + oapvd_t did = NULL; + oapvm_t mid = NULL; + oapvd_cdesc_t cdesc; + oapv_au_info_t aui; + oapvd_stat_t stat; + unsigned char *bs_buf = NULL; + oapv_frm_info_t *finfo = NULL; + oapv_bitb_t bitb; + oapv_frms_t ofrms; + oapv_imgb_t *imgb_w = NULL; + oapv_imgb_t *imgb_o = NULL; + oapv_frm_t *frm = NULL; + int i, ret = 0; + oapv_clk_t clk_beg, clk_end, clk_tot; + int au_cnt, frm_cnt[OAPV_MAX_NUM_FRAMES]; + int read_size, bs_buf_size = 0; + + memset(frm_cnt, 0, sizeof(int) * OAPV_MAX_NUM_FRAMES); + memset(&aui, 0, sizeof(oapv_au_info_t)); + memset(&ofrms, 0, sizeof(oapv_frms_t)); + // create bitstream buffer bs_buf = malloc(MAX_BS_BUF); if(bs_buf == NULL) { @@ -466,6 +641,7 @@ int main(int argc, const char **argv) ret = -1; goto ERR; } + // create decoder if(!strcmp(args_var->threads, "auto")){ cdesc.threads = OAPV_CDESC_THREADS_AUTO; @@ -674,10 +850,95 @@ int main(int argc, const char **argv) } if(imgb_w != NULL) imgb_w->release(imgb_w); + + return 0; +} + +int main(int argc, const char **argv) +{ + args_parser_t *args; + args_var_t *args_var = NULL; + int ret = 0; + int is_y4m = 0; + char *errstr = NULL; + FILE *fp_bs = NULL; + + + // print logo + logv2(" ____ ___ ___ _ __\n"); + logv2(" / __ \\___ ___ ___ / _ | / _ \\ | / / Decoder (v%s)\n", oapv_version(NULL)); + logv2("/ /_/ / _ \\/ -_) _ \\/ __ |/ ___/ |/ / \n"); + logv2("\\____/ .__/\\__/_//_/_/ |_/_/ |___/ \n"); + logv2(" /_/ \n"); + logv2("\n"); + + /* help message */ + if(argc < 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) { + print_usage(argv); + return 0; + } + /* parse command line */ + args = args_create(dec_args_opts, NUM_ARGS_OPT); + if(args == NULL) { + logerr("ERR: cannot create argument parser\n"); + ret = -1; + goto ERR; + } + args_var = args_init_vars(args); + if(args_var == NULL) { + logerr("ERR: cannot initialize argument parser\n"); + ret = -1; + goto ERR; + } + if(args->parse(args, argc, argv, &errstr)) { + logerr("ERR: command parsing error (%s)\n", errstr); + ret = -1; + goto ERR; + } + // print command line string for information + print_commandline(argc, argv); + + if(args->check_mandatory(args, &errstr)) { + logerr("ERR: '--%s' argument is mandatory\n", errstr); + ret = -1; + goto ERR; + } + + /* open input file */ + fp_bs = fopen(args_var->fname_inp, "rb"); + if(fp_bs == NULL) { + logerr("ERR: cannot open bitstream file = %s\n", args_var->fname_inp); + print_usage(argv); + ret = -1; goto ERR; + } + /* open output file */ + if(strlen(args_var->fname_out) > 0) { + ret = check_file_name_type(args_var->fname_out); + if(ret > 0) { + is_y4m = 1; + } + else if(ret == 0) { + is_y4m = 0; + } + else { // invalid or unknown file name type + logerr("ERR: unknown file type name for decoded video\n"); + ret = -1; goto ERR; + } + clear_data(args_var->fname_out); /* remove decoded file contents if exists */ + } + + if(0) { + ret = main_oapv1(args_var, fp_bs, is_y4m); + } + else { + ret = main_oapv2(args_var, fp_bs, is_y4m); + } + if(ret < 0) goto ERR; + + +ERR: if(fp_bs) fclose(fp_bs); - if(bs_buf) - free(bs_buf); if(args) args->release(args); if(args_var) diff --git a/inc/oapv.h b/inc/oapv.h index a3fa6476..bb8663d6 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -752,6 +752,29 @@ OAPV_EXPORT int oapvd_info(void *au, int au_size, oapv_au_info_t *aui); *****************************************************************************/ OAPV_EXPORT const char *oapv_version(unsigned int *ver_num); +/***************************************************************************** + * OpenAPV version 2 APIs + ****************************************************************************/ +#if 0 +/* description for decoder creation */ +typedef struct oapv2d_cdesc oapvd_cdesc_t; +struct oapv2d_cdesc { + /* max number of threads (or OAPV_CDESC_THREADS_AUTO for auto-assignment) */ + int threads; +}; + +/* instance identifier for OAPV2 decoder */ +typedef void *oapv2d_t; + +/* main APIs *****************************************************************/ +OAPV_EXPORT oapv2d_t oapv2d_create(oapv2d_cdesc_t *cdesc, int *err); +OAPV_EXPORT void oapv2d_delete(oapvd_t did); +OAPV_EXPORT int oapv2d_config(oapvd_t did, int cfg, void *buf, int *size); +#endif + +OAPV_EXPORT int oapv2d_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid, oapvd_stat_t *stat); + + #ifdef __cplusplus } /* extern "C" */ #endif From d1dfdabe53b385c55f93ff63e056614dc87d3a81 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 16 Mar 2026 16:54:19 +0900 Subject: [PATCH 16/31] adding PDU level decoding Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 82 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 99ecd97b..4f9df9f4 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -173,7 +173,7 @@ static int read_au_size(FILE *fp) { unsigned char buf[4]; - for(int i = 0; i < 4; i++) { + for(int i = 0; i < 4; i++) { if(1 != fread(&buf[i], 1, 1, fp)) return -1; } @@ -611,6 +611,27 @@ int main_oapv1(args_var_t *args_var, FILE *fp_bs, int is_y4m) return 0; } +static int read_u32(FILE *fp, unsigned int * val) +{ + unsigned char buf[4]; + + for(int i = 0; i < 4; i++) { + if(1 != fread(&buf[i], 1, 1, fp)) + return -1; + } + *val = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3])); + return 0; +} + +static int read_pdu(FILE *fp, unsigned char *pdu, unsigned int pdu_size) +{ + if(pdu_size != fread(pdu, 1, pdu_size, fp)) { + logerr("Cannot read PDU!\n"); + return -1; + } + return 0; +} + int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) { oapvd_t did = NULL; @@ -628,7 +649,7 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) int i, ret = 0; oapv_clk_t clk_beg, clk_end, clk_tot; int au_cnt, frm_cnt[OAPV_MAX_NUM_FRAMES]; - int read_size, bs_buf_size = 0; + int read_size, bs_buf_size; memset(frm_cnt, 0, sizeof(int) * OAPV_MAX_NUM_FRAMES); memset(&aui, 0, sizeof(oapv_au_info_t)); @@ -672,19 +693,57 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) goto ERR; } - /* decoding loop */ + /* AU loop ***************************************************************/ while(args_var->max_au == 0 || (au_cnt < args_var->max_au)) { - read_size = read_bitstream(fp_bs, bs_buf, &bs_buf_size); - if (read_size == 0) { - logv3("--> end of bitstream\n") - break; + /* read access unit size */ + unsigned int au_size; + if(read_u32(fp_bs, &au_size) < 0) { + if(feof(fp_bs)) { + logv2_line(""); + logv2("End of file\n"); + ret = 0; goto END; + } + else { + logerr("ERR: cannot read au_size\n"); + ret = -1; goto ERR; + } } - if (read_size < 0) { - logv3("--> bitstream reading error\n") - ret = -1; - goto ERR; + logv3("AU size = %d\n", au_size); + /* check signature ('aPv1') */ + unsigned int signature = 0; + if(read_u32(fp_bs, &signature) < 0) { + logerr("ERR: cannot read signature\n"); + ret = -1; goto ERR; + } + if(signature != 0x61507631) { + logerr("ERR: signature mismatch") + ret = -1; goto ERR; + } + au_size -= 4; /* byte size of signature syntax */ + + /* PDU loop **********************************************************/ + int rsize = 0; + while(rsize < au_size) { + /* read a PDU size */ + unsigned int pdu_size; + if(read_u32(fp_bs, &pdu_size) < 0) { + logerr("ERR: cannot read PDU size\n"); + ret = -1; goto ERR; + } + logv3(" PDU size = %d\n", pdu_size); + rsize += 4; /* byte size of pdu_size syntax */ + + /* read a PDU */ + if(read_pdu(fp_bs, bs_buf, pdu_size) < 0) { + ret = -1; goto ERR; + } + /* get PDU type */ + + + rsize += pdu_size; } +#if 0 if(OAPV_FAILED(oapvd_info(bs_buf, bs_buf_size, &aui))) { logerr("ERR: cannot get information from bitstream\n"); ret = -1; @@ -819,6 +878,7 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) oapvm_rem_all(mid); // remove all metadata for next au decoding fflush(stdout); fflush(stderr); +#endif } END: From 1cbcd9254108c588a7cb5439a91a5e2c4d621b59 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 16 Mar 2026 17:06:12 +0900 Subject: [PATCH 17/31] fixed typo Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 18 +++++++++--------- inc/oapv.h | 9 +++++++++ src/oapv.c | 5 +++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 4f9df9f4..4b16162a 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -623,9 +623,9 @@ static int read_u32(FILE *fp, unsigned int * val) return 0; } -static int read_pdu(FILE *fp, unsigned char *pdu, unsigned int pdu_size) +static int read_pbu(FILE *fp, unsigned char *pbu, unsigned int pbu_size) { - if(pdu_size != fread(pdu, 1, pdu_size, fp)) { + if(pbu_size != fread(pbu, 1, pbu_size, fp)) { logerr("Cannot read PDU!\n"); return -1; } @@ -725,22 +725,22 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) int rsize = 0; while(rsize < au_size) { /* read a PDU size */ - unsigned int pdu_size; - if(read_u32(fp_bs, &pdu_size) < 0) { + unsigned int pbu_size; + if(read_u32(fp_bs, &pbu_size) < 0) { logerr("ERR: cannot read PDU size\n"); ret = -1; goto ERR; } - logv3(" PDU size = %d\n", pdu_size); - rsize += 4; /* byte size of pdu_size syntax */ + logv3(" PDU size = %d\n", pbu_size); + rsize += 4; /* byte size of pbu_size syntax */ /* read a PDU */ - if(read_pdu(fp_bs, bs_buf, pdu_size) < 0) { + if(read_pbu(fp_bs, bs_buf, pbu_size) < 0) { ret = -1; goto ERR; } - /* get PDU type */ + /* get PDU information */ - rsize += pdu_size; + rsize += pbu_size; } #if 0 diff --git a/inc/oapv.h b/inc/oapv.h index bb8663d6..43f3ad4b 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -772,8 +772,17 @@ OAPV_EXPORT void oapv2d_delete(oapvd_t did); OAPV_EXPORT int oapv2d_config(oapvd_t did, int cfg, void *buf, int *size); #endif +/* PDU information */ +typedef struct oapv_pbu_info oapv_pbu_info_t; +struct oapv_pbu_info { + unsigned char pbu_type; + unsigned short group_id; +}; + OAPV_EXPORT int oapv2d_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid, oapvd_stat_t *stat); +OAPV_EXPORT int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbui); + #ifdef __cplusplus } /* extern "C" */ diff --git a/src/oapv.c b/src/oapv.c index dbf075bc..736190e6 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -2009,6 +2009,11 @@ int oapvd_info(void *au, int au_size, oapv_au_info_t *aui) return OAPV_OK; } +int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbui) +{ + return OAPV_OK; +} + /////////////////////////////////////////////////////////////////////////////// // end of decoder code #endif // ENABLE_DECODER From a9fa6cedc2a2029909b663ed3061dd2f8e57cd55 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Fri, 27 Mar 2026 10:21:24 +0900 Subject: [PATCH 18/31] frame level decoding is working now Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 278 +++++++++++++++++++++------------------------ inc/oapv.h | 61 +++++----- src/oapv.c | 153 +++++++++++++++++++++++-- src/oapv_def.h | 4 +- 4 files changed, 311 insertions(+), 185 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 4b16162a..7eb159e1 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -368,7 +368,7 @@ static void print_stat_frm(oapvd_stat_t *stat, oapv_frms_t *frms, oapvm_t mid, a } } -int main_oapv1(args_var_t *args_var, FILE *fp_bs, int is_y4m) +int dec_oapv1(args_var_t *args_var, FILE *fp_bs, int is_y4m) { oapvd_t did = NULL; oapvm_t mid = NULL; @@ -475,7 +475,7 @@ int main_oapv1(args_var_t *args_var, FILE *fp_bs, int is_y4m) } } - if(args_var->disable_companding && finfo->use_companding == 1) { + if(args_var->disable_companding && finfo->use_companding) { args_var->output_depth = 12; } if(args_var->output_depth == 0) { @@ -632,32 +632,39 @@ static int read_pbu(FILE *fp, unsigned char *pbu, unsigned int pbu_size) return 0; } -int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) +static const char * get_key_from_val(const oapv_dict_str_int_t * dict, int val) +{ + while(strlen(dict->key) > 0) { + if(dict->val == val){ + return dict->key; + } + dict++; + } + return NULL; +} + +int dec_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) { oapvd_t did = NULL; oapvm_t mid = NULL; oapvd_cdesc_t cdesc; oapv_au_info_t aui; oapvd_stat_t stat; - unsigned char *bs_buf = NULL; - oapv_frm_info_t *finfo = NULL; + unsigned char *pbu = NULL; oapv_bitb_t bitb; - oapv_frms_t ofrms; - oapv_imgb_t *imgb_w = NULL; - oapv_imgb_t *imgb_o = NULL; - oapv_frm_t *frm = NULL; - int i, ret = 0; - oapv_clk_t clk_beg, clk_end, clk_tot; - int au_cnt, frm_cnt[OAPV_MAX_NUM_FRAMES]; - int read_size, bs_buf_size; + oapv_imgb_t *imgb_dec = NULL; + oapv_imgb_t *imgb_out = NULL; + oapv_imgb_t *imgb_tmp = NULL; - memset(frm_cnt, 0, sizeof(int) * OAPV_MAX_NUM_FRAMES); - memset(&aui, 0, sizeof(oapv_au_info_t)); - memset(&ofrms, 0, sizeof(oapv_frms_t)); + int ret = 0; + oapv_clk_t clk_beg, clk_end, clk_tot; + int au_cnt = 0; // number of decoded access unit; + int primary_frm_cnt = 0; // number of decoded primary frame + int primary_frm_gid = -1; // group id of primary frame // create bitstream buffer - bs_buf = malloc(MAX_BS_BUF); - if(bs_buf == NULL) { + pbu = malloc(MAX_BS_BUF); + if(pbu == NULL) { logerr("ERR: cannot allocate bitstream buffer, size=%d\n", MAX_BS_BUF); ret = -1; goto ERR; @@ -708,7 +715,6 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) ret = -1; goto ERR; } } - logv3("AU size = %d\n", au_size); /* check signature ('aPv1') */ unsigned int signature = 0; if(read_u32(fp_bs, &signature) < 0) { @@ -721,178 +727,158 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) } au_size -= 4; /* byte size of signature syntax */ + logv3("AU(size=%d)\n", au_size); + /* PDU loop **********************************************************/ int rsize = 0; + oapv_pbu_info_t pbu_info; + while(rsize < au_size) { - /* read a PDU size */ + /* read a PBU size */ unsigned int pbu_size; if(read_u32(fp_bs, &pbu_size) < 0) { - logerr("ERR: cannot read PDU size\n"); + logerr("ERR: cannot read PBU size\n"); ret = -1; goto ERR; } - logv3(" PDU size = %d\n", pbu_size); rsize += 4; /* byte size of pbu_size syntax */ - /* read a PDU */ - if(read_pbu(fp_bs, bs_buf, pbu_size) < 0) { + /* read a PBU */ + if(read_pbu(fp_bs, pbu, pbu_size) < 0) { ret = -1; goto ERR; } - /* get PDU information */ - - - rsize += pbu_size; - } - -#if 0 - if(OAPV_FAILED(oapvd_info(bs_buf, bs_buf_size, &aui))) { - logerr("ERR: cannot get information from bitstream\n"); - ret = -1; - goto ERR; - } - - /* create decoding frame buffers */ - ofrms.num_frms = aui.num_frms; - for(i = 0; i < ofrms.num_frms; i++) { - finfo = &aui.frm_info[i]; - frm = &ofrms.frm[i]; - - if(frm->imgb != NULL && (frm->imgb->w[0] != finfo->w || frm->imgb->h[0] != finfo->h)) { - frm->imgb->release(frm->imgb); - frm->imgb = NULL; + /* get PBU information */ + if(OAPV_FAILED(oapvd_info_pbu(pbu, pbu_size, &pbu_info))) { + logerr("ERR: cannot get PBU information\n"); + ret = -1; goto ERR; } - if(frm->imgb == NULL) { - if(args_var->output_csp == 1) { - frm->imgb = imgb_create(finfo->w, finfo->h, OAPV_CS_SET(OAPV_CF_PLANAR2, 10, 0)); - } - else { - frm->imgb = imgb_create(finfo->w, finfo->h, finfo->cs); - } - if(frm->imgb == NULL) { - logerr("ERR: cannot allocate image buffer (w:%d, h:%d, cs:%d)\n", - finfo->w, finfo->h, finfo->cs); - ret = -1; - goto ERR; - } + const char * pbu_type_str = get_key_from_val(oapv_dict_pbu_type, pbu_info.pbu_type); + if(pbu_type_str == NULL) { + logerr("ERR: unknown PBU type (%d)\n", pbu_info.pbu_type); + ret = -1; goto ERR; } - } + logv3(" PBU(%s gid=%d size=%d)\n", pbu_type_str, pbu_info.group_id, pbu_size); - if(args_var->disable_companding && finfo->use_companding == 1) { - args_var->output_depth = 12; - } - if(args_var->output_depth == 0) { - args_var->output_depth = OAPV_CS_GET_BIT_DEPTH(finfo->cs); - } + if(pbu_info.pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) { + // actual decoding is only supported for primary frames in this code + oapv_frm_info_t finfo; - /* main decoding block */ - bitb.addr = bs_buf; - bitb.ssize = bs_buf_size; - memset(&stat, 0, sizeof(oapvd_stat_t)); + // check group id + if(primary_frm_gid < 0) primary_frm_gid = pbu_info.group_id; + else if(primary_frm_gid != pbu_info.group_id) { + logv2(" WARNING: group_id of primary frame is changed\n"); + primary_frm_gid = pbu_info.group_id; + } - clk_beg = oapv_clk_get(); + // get frame information + ret = oapvd_info_frame(pbu, pbu_size, &finfo); - ret = oapvd_decode(did, &bitb, &ofrms, mid, &stat); + // create decoding frame buffers if needs + if(imgb_dec != NULL && (imgb_dec->w[0] != finfo.w || imgb_dec->h[0] != finfo.h)) { + imgb_dec->release(imgb_dec); + imgb_dec = NULL; + } + if(imgb_dec == NULL) { + if(args_var->output_csp == 1) { + imgb_dec = imgb_create(finfo.w, finfo.h, OAPV_CS_SET(OAPV_CF_PLANAR2, 10, 0)); + } + else { + imgb_dec = imgb_create(finfo.w, finfo.h, finfo.cs); + } + if(imgb_dec == NULL) { + logerr("ERR: cannot allocate image buffer (w:%d, h:%d, cs:%d)\n", + finfo.w, finfo.h, finfo.cs); + ret = -1; goto ERR; + } + } - clk_end = oapv_clk_from(clk_beg); - clk_tot += clk_end; + if(args_var->disable_companding && finfo.use_companding) { + args_var->output_depth = 12; + } + if(args_var->output_depth == 0) { + args_var->output_depth = OAPV_CS_GET_BIT_DEPTH(finfo.cs); + } + // start to decode a frame + bitb.addr = pbu; + bitb.ssize = pbu_size; - if(OAPV_FAILED(ret)) { - logerr("ERR: failed to decode bitstream\n"); - ret = -1; - goto END; - } - if(stat.read != bs_buf_size) { - logerr("\t=> different reading of bitstream (in:%d, read:%d)\n", - bs_buf_size, stat.read); - continue; - } + clk_beg = oapv_clk_get(); - /* testing of metadata reading */ - if(mid) { - oapvm_payload_t *pld = NULL; // metadata payload - int num_plds = 0; // number of metadata payload + ret = oapvd_decode_frame(did, &bitb, imgb_dec, &stat); - ret = oapvm_get_all(mid, NULL, &num_plds); + clk_end = oapv_clk_from(clk_beg); + clk_tot += clk_end; - if(OAPV_FAILED(ret)) { - logerr("ERR: failed to read metadata\n"); - goto END; - } - if(num_plds > 0) { - pld = malloc(sizeof(oapvm_payload_t) * num_plds); - ret = oapvm_get_all(mid, pld, &num_plds); if(OAPV_FAILED(ret)) { - logerr("ERR: failed to read metadata\n"); - free(pld); - goto END; + logerr("ERR: failed to decode a frame (ret = %d)\n", ret); + ret = -1; goto ERR; + } + if(stat.read != pbu_size) { + logerr("\t=> different reading of bitstream (in:%d, read:%d)\n", + pbu_size, stat.read); } - } - if(pld != NULL) - free(pld); - } - - /* print decoding results */ - print_stat_au(&stat, au_cnt, args_var, clk_end, clk_tot); - print_stat_frm(&stat, &ofrms, mid, args_var); - /* write decoded frames into files */ - for(i = 0; i < ofrms.num_frms; i++) { - frm = &ofrms.frm[i]; - if(ofrms.num_frms > 0) { - if(OAPV_CS_GET_BIT_DEPTH(frm->imgb->cs) != args_var->output_depth && args_var->output_csp != OUTPUT_CSP_P210) { - if(imgb_w == NULL) { - imgb_w = imgb_create(frm->imgb->w[0], frm->imgb->h[0], - OAPV_CS_SET(OAPV_CS_GET_FORMAT(frm->imgb->cs), args_var->output_depth, 0)); - if(imgb_w == NULL) { + /* write decoded frames into files */ + if(OAPV_CS_GET_BIT_DEPTH(imgb_dec->cs) != args_var->output_depth && args_var->output_csp != OUTPUT_CSP_P210) { + if(imgb_tmp == NULL) { + imgb_tmp = imgb_create(imgb_dec->w[0], imgb_dec->h[0], + OAPV_CS_SET(OAPV_CS_GET_FORMAT(imgb_dec->cs), args_var->output_depth, 0)); + if(imgb_tmp == NULL) { logerr("ERR: cannot allocate image buffer (w:%d, h:%d, cs:%d)\n", - frm->imgb->w[0], frm->imgb->h[0], frm->imgb->cs); - ret = -1; - goto ERR; + imgb_dec->w[0], imgb_dec->h[0], imgb_dec->cs); + ret = -1; goto ERR; } } - imgb_cpy(imgb_w, frm->imgb); - imgb_o = imgb_w; + imgb_cpy(imgb_tmp, imgb_dec); + imgb_out = imgb_tmp; } else { - imgb_o = frm->imgb; + imgb_out = imgb_dec; } if(strlen(args_var->fname_out)) { - if(frm_cnt[i] == 0 && is_y4m) { - if(write_y4m_header(args_var->fname_out, imgb_o)) { + if(primary_frm_cnt == 0 && is_y4m) { + if(write_y4m_header(args_var->fname_out, imgb_out)) { logerr("ERR: cannot write Y4M header\n"); ret = -1; goto ERR; } } - if(write_dec_img(args_var->fname_out, imgb_o, is_y4m)) { + if(write_dec_img(args_var->fname_out, imgb_out, is_y4m)) { logerr("ERR: cannot write decoded video\n"); ret = -1; goto ERR; } } - frm_cnt[i]++; + primary_frm_cnt++; + fflush(stdout); + fflush(stderr); + } + else if (OAPV_PBU_TYPE_IS_FRAME(pbu_info.pbu_type)) { + // other types of frame PBU } + else if (pbu_info.pbu_type == OAPV_PBU_TYPE_AU_INFO) { + ret = oapvd_decode_auinfo(did, &bitb, &aui); + if(OAPV_FAILED(ret)) { + logerr("ERR: cannot get PBU information\n"); + ret = -1; goto ERR; + } + } + else if (pbu_info.pbu_type == OAPV_PBU_TYPE_METADATA) { + } + rsize += pbu_size; } - au_cnt++; - oapvm_rem_all(mid); // remove all metadata for next au decoding - fflush(stdout); - fflush(stderr); -#endif } END: logv2_line("Summary"); logv2("Processed access units = %d\n", au_cnt); - int total_frame_count = 0; - for(i = 0; i < OAPV_MAX_NUM_FRAMES; i++) - total_frame_count += frm_cnt[i]; - logv2("Decoded frame count = %d\n", total_frame_count); - if(total_frame_count > 0) { + logv2("Decoded frame count = %d\n", primary_frm_cnt); + if(primary_frm_cnt > 0) { logv2("Total decoding time = %d msec,", (int)oapv_clk_msec(clk_tot)); logv2(" %.3f sec\n", (float)(oapv_clk_msec(clk_tot) / 1000.0)); - logv2("Average decoding time for a frame = %d msec\n", (int)oapv_clk_msec(clk_tot) / total_frame_count); - logv2("Average decoding speed = %.3f frames/sec\n", ((float)total_frame_count * 1000) / ((float)oapv_clk_msec(clk_tot))); + logv2("Average decoding time for a frame = %d msec\n", (int)oapv_clk_msec(clk_tot) / primary_frm_cnt); + logv2("Average decoding speed = %.3f frames/sec\n", ((float)primary_frm_cnt * 1000) / ((float)oapv_clk_msec(clk_tot))); } logv2_line(NULL); @@ -903,13 +889,11 @@ int main_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) if(mid) oapvm_delete(mid); - for(int i = 0; i < ofrms.num_frms; i++) { - if(ofrms.frm[i].imgb != NULL) { - ofrms.frm[i].imgb->release(ofrms.frm[i].imgb); - } - } - if(imgb_w != NULL) - imgb_w->release(imgb_w); + if(imgb_dec != NULL) + imgb_dec->release(imgb_dec); + + if(imgb_tmp != NULL) + imgb_tmp->release(imgb_tmp); return 0; } @@ -988,10 +972,10 @@ int main(int argc, const char **argv) } if(0) { - ret = main_oapv1(args_var, fp_bs, is_y4m); + ret = dec_oapv1(args_var, fp_bs, is_y4m); } else { - ret = main_oapv2(args_var, fp_bs, is_y4m); + ret = dec_oapv2(args_var, fp_bs, is_y4m); } if(ret < 0) goto ERR; diff --git a/inc/oapv.h b/inc/oapv.h index 43f3ad4b..7f315c25 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -222,6 +222,9 @@ extern "C" { #define OAPV_PBU_NUMS (10) #define OAPV_PBU_FRAME_TYPE_NUM (5) +#define OAPV_PBU_TYPE_IS_FRAME(pbu_type) \ + ((pbu_type)==1 || (pbu_type)==2 || ((pbu_type)>=25 && (pbu_type)<=27)) + /***************************************************************************** * metadata types @@ -443,7 +446,7 @@ struct oapv_au_info { }; /***************************************************************************** - * constant string values for oapve_param_parse() and command-line options + * constant string and value pairs *****************************************************************************/ typedef struct oapv_dict_str_int oapv_dict_str_int_t; // dictionary type struct oapv_dict_str_int { @@ -451,15 +454,27 @@ struct oapv_dict_str_int { const int val; }; +static const oapv_dict_str_int_t oapv_dict_pbu_type[] = { + {"primary frame", OAPV_PBU_TYPE_PRIMARY_FRAME}, + {"non-primary frame", OAPV_PBU_TYPE_NON_PRIMARY_FRAME}, + {"preview frame", OAPV_PBU_TYPE_PREVIEW_FRAME}, + {"depth frame", OAPV_PBU_TYPE_DEPTH_FRAME}, + {"alpha frame", OAPV_PBU_TYPE_ALPHA_FRAME}, + {"access unit information", OAPV_PBU_TYPE_AU_INFO}, + {"metadata", OAPV_PBU_TYPE_METADATA}, + {"filler", OAPV_PBU_TYPE_FILLER}, + {"", 0} // termination +}; + static const oapv_dict_str_int_t oapv_param_opts_profile[] = { - {"422-10", OAPV_PROFILE_422_10}, - {"422-12", OAPV_PROFILE_422_12}, - {"444-10", OAPV_PROFILE_444_10}, - {"444-12", OAPV_PROFILE_444_12}, - {"4444-10", OAPV_PROFILE_4444_10}, - {"4444-12", OAPV_PROFILE_4444_12}, - {"400-10", OAPV_PROFILE_400_10}, - {"4444-16C12", OAPV_PROFILE_4444_16C12}, + {"422-10", OAPV_PROFILE_422_10}, + {"422-12", OAPV_PROFILE_422_12}, + {"444-10", OAPV_PROFILE_444_10}, + {"444-12", OAPV_PROFILE_444_12}, + {"4444-10", OAPV_PROFILE_4444_10}, + {"4444-12", OAPV_PROFILE_4444_12}, + {"400-10", OAPV_PROFILE_400_10}, + {"4444-16C12", OAPV_PROFILE_4444_16C12}, {"", 0} // termination }; @@ -755,33 +770,21 @@ OAPV_EXPORT const char *oapv_version(unsigned int *ver_num); /***************************************************************************** * OpenAPV version 2 APIs ****************************************************************************/ -#if 0 -/* description for decoder creation */ -typedef struct oapv2d_cdesc oapvd_cdesc_t; -struct oapv2d_cdesc { - /* max number of threads (or OAPV_CDESC_THREADS_AUTO for auto-assignment) */ - int threads; -}; - -/* instance identifier for OAPV2 decoder */ -typedef void *oapv2d_t; - -/* main APIs *****************************************************************/ -OAPV_EXPORT oapv2d_t oapv2d_create(oapv2d_cdesc_t *cdesc, int *err); -OAPV_EXPORT void oapv2d_delete(oapvd_t did); -OAPV_EXPORT int oapv2d_config(oapvd_t did, int cfg, void *buf, int *size); -#endif - /* PDU information */ typedef struct oapv_pbu_info oapv_pbu_info_t; struct oapv_pbu_info { - unsigned char pbu_type; - unsigned short group_id; + int pbu_type; + int group_id; }; OAPV_EXPORT int oapv2d_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid, oapvd_stat_t *stat); -OAPV_EXPORT int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbui); +OAPV_EXPORT int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbu_info); +OAPV_EXPORT int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info); + +OAPV_EXPORT int oapvd_decode_auinfo(oapvd_t did, oapv_bitb_t *bitb, oapv_au_info_t *aui); +OAPV_EXPORT int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_stat_t *stat); + #ifdef __cplusplus diff --git a/src/oapv.c b/src/oapv.c index 736190e6..69d523a0 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -1897,7 +1897,7 @@ int oapvd_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid ofrms->frm[nfrms].pbu_type = pbuh.pbu_type; ofrms->frm[nfrms].group_id = pbuh.group_id; - stat->frm_size[nfrms] = pbu_size + 4 /* byte size of 'pbu_size' syntax */; + stat->frm_size[nfrms] = pbu_size + 4; /* byte size of 'pbu_size' syntax */ nfrms++; // go to the end of frame data for next PDU @@ -1987,11 +1987,7 @@ int oapvd_info(void *au, int au_size, oapv_au_info_t *aui) } return OAPV_OK; // founded access_unit_info, no need to read more PBUs } - if(pbuh.pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME || - pbuh.pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME || - pbuh.pbu_type == OAPV_PBU_TYPE_PREVIEW_FRAME || - pbuh.pbu_type == OAPV_PBU_TYPE_DEPTH_FRAME || - pbuh.pbu_type == OAPV_PBU_TYPE_ALPHA_FRAME) { + if(OAPV_PBU_TYPE_IS_FRAME(pbuh.pbu_type)) { // parse frame_info in PBU oapv_fi_t fi; @@ -2009,7 +2005,150 @@ int oapvd_info(void *au, int au_size, oapv_au_info_t *aui) return OAPV_OK; } -int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbui) +int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbu_info) +{ + oapv_bs_t bs; + oapv_assert_rv(pbu_size >= 4, OAPV_ERR_INVALID_ARGUMENT); + + oapv_bsr_init(&bs, pbu, pbu_size, NULL); + + /* parse pbu_header() */ + pbu_info->pbu_type = oapv_bsr_read(&bs, 8); + pbu_info->group_id = oapv_bsr_read(&bs, 16); + + return OAPV_OK; +} + +int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info) +{ + oapv_bs_t bs; + oapv_pbuh_t pbuh; + oapv_fh_t fh; + int ret = OAPV_OK; + + oapv_assert_rv(pbu_size >= (OAPV_PBU_HEADER_BYTE + OAPV_FRAME_INFO_BYTE), OAPV_ERR_INVALID_ARGUMENT); + oapv_bsr_init(&bs, pbu, pbu_size, NULL); + + DUMP_SET(0); + // decode PBU header + ret = oapvd_vlc_pbu_header(&bs, &pbuh); + oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); + + // check frame type PBU + oapv_assert_gv(OAPV_PBU_TYPE_IS_FRAME(pbuh.pbu_type), ret, OAPV_ERR_INVALID_ARGUMENT, ERR); + + // decode frame header + ret = oapvd_vlc_frame_header(&bs, &fh); + oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); + + fh_to_finfo(&fh, pbuh.pbu_type, pbuh.group_id, frm_info); + +ERR: + DUMP_SET(1); + return ret; +} + +int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_stat_t *stat) +{ + oapvd_ctx_t *ctx; + oapv_pbuh_t pbuh; + int ret = OAPV_OK; + + ctx = dec_id_to_ctx(did); + oapv_assert_rv(ctx, OAPV_ERR_INVALID_ARGUMENT); + oapv_mset(stat, 0, sizeof(oapvd_stat_t)); + + oapv_bs_t *bs; + oapv_assert_gv((bitb->ssize >= 8), ret, OAPV_ERR_MALFORMED_BITSTREAM, ERR); + oapv_bsr_init(&ctx->bs, (u8 *)bitb->addr, bitb->ssize, NULL); + bs = &ctx->bs; + + // parse PBU header + ret = oapvd_vlc_pbu_header(bs, &pbuh); + oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); + // check frame type PBU + oapv_assert_gv(OAPV_PBU_TYPE_IS_FRAME(pbuh.pbu_type), ret, OAPV_ERR_INVALID_ARGUMENT, ERR); + + // decode frame + ret = oapvd_vlc_frame_header(bs, &ctx->fh); + oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); + + ret = dec_frm_prepare(ctx, imgb); + oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); + + int thread_ret; + oapv_tpool_t *tpool = ctx->tpool; + int parallel_task = 1; + int tidx = 0; + + parallel_task = (ctx->threads > ctx->num_tiles) ? ctx->num_tiles : ctx->threads; + + /* decode tiles ************************************/ + for(tidx = 0; tidx < (parallel_task - 1); tidx++) { + tpool->run(ctx->thread_id[tidx], dec_thread_tile, + (void *)ctx->core[tidx]); + } + ret = dec_thread_tile((void *)ctx->core[tidx]); + for(tidx = 0; tidx < parallel_task - 1; tidx++) { + tpool->join(ctx->thread_id[tidx], &thread_ret); + if(OAPV_FAILED(thread_ret)) { + ret = thread_ret; + } + } + /****************************************************/ + + /* READ FILLER HERE !!! */ + if(OAPV_SUCCEEDED(ret) && ctx->use_frm_hash) { + oapv_imgb_set_md5(imgb); + } + else { + oapv_imgb_clr_md5(imgb); + } + // following function should be called even error cases, + // because input imgb's ref count needs to decreased. + // after this function, ctx->imgb cannot be accessed. + dec_frm_finish(ctx); + + // check thread's return value + oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); + + // go to the end of frame data + oapv_bsr_move(bs, ctx->tile_end); + // set stat + fh_to_finfo(&ctx->fh, pbuh.pbu_type, pbuh.group_id, &stat->aui.frm_info[0]); + stat->read = stat->frm_size[0] = BSR_GET_READ_BYTE(bs); + stat->aui.num_frms = 1; + return ret; + +ERR: + return ret; + + return OAPV_OK; +} + +int oapvd_decode_auinfo(oapvd_t did, oapv_bitb_t *bitb, oapv_au_info_t *aui) +{ + int ret; + oapv_bs_t bs; + oapv_aui_t ai; + + oapv_bsr_init(&bs, bitb->addr, bitb->ssize, NULL); + + DUMP_SET(0); + ret = oapvd_vlc_au_info(&bs, &ai); + oapv_assert_rv(OAPV_SUCCEEDED(ret), ret); + + oapv_mset(aui, 0, sizeof(oapv_au_info_t)); // clear + + aui->num_frms = ai.num_frames; + for(int i = 0; i < ai.num_frames; i++) { + fi_to_finfo(&ai.frame_info[i], ai.pbu_type[i], ai.group_id[i], &aui->frm_info[i]); + } + DUMP_SET(1); + return OAPV_OK; +} + +int oapvd_decode_metadata(oapvd_t did, oapv_bitb_t *bitb, oapvm_payload_t *pld) { return OAPV_OK; } diff --git a/src/oapv_def.h b/src/oapv_def.h index 70896004..81c7f79f 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -408,8 +408,8 @@ struct oapvd_ctx { #endif // ENABLE_DECODER /////////////////////////////////////////////////////////////////////////////// -#define OAPV_FRAME_INFO_BYTE (112) -#define OAPV_PBU_HEADER_BYTE (32) +#define OAPV_PBU_HEADER_BYTE (4) +#define OAPV_FRAME_INFO_BYTE (12) #include "oapv_metadata.h" #include "oapv_vlc.h" From e58f6813944d48576f75061ffccef9c27d868d69 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 30 Mar 2026 16:28:29 +0900 Subject: [PATCH 19/31] added partial decoding API Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 4 +-- inc/oapv.h | 19 +++++++++-- src/oapv.c | 78 ++++++++++++++++++++++++++++++++++++++++------ src/oapv_def.h | 9 +++--- 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 7eb159e1..76e56428 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -771,7 +771,7 @@ int dec_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) } // get frame information - ret = oapvd_info_frame(pbu, pbu_size, &finfo); + ret = oapvd_info_frame(pbu, pbu_size, &finfo, NULL); // create decoding frame buffers if needs if(imgb_dec != NULL && (imgb_dec->w[0] != finfo.w || imgb_dec->h[0] != finfo.h)) { @@ -804,7 +804,7 @@ int dec_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) clk_beg = oapv_clk_get(); - ret = oapvd_decode_frame(did, &bitb, imgb_dec, &stat); + ret = oapvd_decode_frame(did, &bitb, NULL, imgb_dec, &stat); clk_end = oapv_clk_from(clk_beg); clk_tot += clk_end; diff --git a/inc/oapv.h b/inc/oapv.h index 7f315c25..f982ae39 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -445,6 +445,21 @@ struct oapv_au_info { oapv_frm_info_t frm_info[OAPV_MAX_NUM_FRAMES]; }; +typedef struct oapv_tile_pos oapv_tile_pos_t; +struct oapv_tile_pos { + int idx; /* tile index in raster scan order */ + int x_mb; /* x-position in MB unit */ + int y_mb; /* y-position in MB unit */ + int w_mb; /* width in MB unit */ + int h_mb; /* height in MB unit */ +}; + +typedef struct oapv_tile_info oapv_tile_info_t; +struct oapv_tile_info { + int num_tiles; + oapv_tile_pos_t pos_tiles[OAPV_MAX_TILES]; +}; + /***************************************************************************** * constant string and value pairs *****************************************************************************/ @@ -780,10 +795,10 @@ struct oapv_pbu_info { OAPV_EXPORT int oapv2d_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid, oapvd_stat_t *stat); OAPV_EXPORT int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbu_info); -OAPV_EXPORT int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info); +OAPV_EXPORT int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info, oapv_tile_info_t *tile_info); OAPV_EXPORT int oapvd_decode_auinfo(oapvd_t did, oapv_bitb_t *bitb, oapv_au_info_t *aui); -OAPV_EXPORT int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_stat_t *stat); +OAPV_EXPORT int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_tile_info_t * part, oapv_imgb_t *imgb, oapvd_stat_t *stat); diff --git a/src/oapv.c b/src/oapv.c index 69d523a0..381b166b 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -1405,8 +1405,9 @@ static int dec_set_tile_info(oapvd_tile_t* tile, int w_pel, int h_pel, int tile_ return OAPV_OK; } -static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) +static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_tile_info_t * part, oapv_imgb_t *imgb) { + int i; ctx->imgb = imgb; imgb_addref(ctx->imgb); // increase reference count @@ -1457,8 +1458,18 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb) } ctx->tile[0].bs_beg = oapv_bsr_sink(&ctx->bs); - for(int i = 0; i < ctx->num_tiles; i++) { - ctx->tile[i].stat = DEC_TILE_STAT_NOT_DECODED; + if(part != NULL) { + for(i = 0; i < ctx->num_tiles; i++) { + ctx->tile[i].stat = DEC_TILE_STAT_SKIP_DECODING; /* bypass decoding */ + } + for(i = 0; i < part->num_tiles; i++) { + ctx->tile[part->pos_tiles[i].idx].stat = DEC_TILE_STAT_NOT_DECODED; + } + } + else { + for(i = 0; i < ctx->num_tiles; i++) { + ctx->tile[i].stat = DEC_TILE_STAT_NOT_DECODED; + } } return OAPV_OK; @@ -1853,7 +1864,7 @@ int oapvd_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid ret = oapvd_vlc_frame_header(bs, &ctx->fh); oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); - ret = dec_frm_prepare(ctx, ofrms->frm[nfrms].imgb); + ret = dec_frm_prepare(ctx, NULL, ofrms->frm[nfrms].imgb); oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); int thread_ret; @@ -2019,12 +2030,12 @@ int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbu_info) return OAPV_OK; } -int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info) +int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info, oapv_tile_info_t *tile_info) { oapv_bs_t bs; oapv_pbuh_t pbuh; oapv_fh_t fh; - int ret = OAPV_OK; + int i, j, ret = OAPV_OK; oapv_assert_rv(pbu_size >= (OAPV_PBU_HEADER_BYTE + OAPV_FRAME_INFO_BYTE), OAPV_ERR_INVALID_ARGUMENT); oapv_bsr_init(&bs, pbu, pbu_size, NULL); @@ -2043,12 +2054,52 @@ int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info) fh_to_finfo(&fh, pbuh.pbu_type, pbuh.group_id, frm_info); + if(tile_info != NULL) { + int pic_w, pic_h, tile_w, tile_h, tile_cols, tile_rows; + + oapv_mset(tile_info, 0, sizeof(oapv_tile_info_t)); // clear + + tile_w = fh.tile_width_in_mbs * OAPV_MB_W; + tile_h = fh.tile_height_in_mbs * OAPV_MB_H; + + pic_w = ((fh.fi.frame_width + (OAPV_MB_W - 1)) >> OAPV_LOG2_MB_W) << OAPV_LOG2_MB_W; + pic_h = ((fh.fi.frame_height + (OAPV_MB_H - 1)) >> OAPV_LOG2_MB_H) << OAPV_LOG2_MB_H; + + tile_cols = (pic_w + (tile_w - 1)) / tile_w; + tile_rows = (pic_h + (tile_h - 1)) / tile_h; + + oapv_tile_pos_t * tpos = tile_info->pos_tiles; + + for(i = 0; i < tile_rows; i++) { + for(j = 0; j < tile_cols; j++) { + tpos->x_mb = fh.tile_width_in_mbs * j; + tpos->y_mb = fh.tile_height_in_mbs * i; + + if(tpos->x_mb + fh.tile_width_in_mbs > (pic_w >> OAPV_LOG2_MB_W)) { + tpos->w_mb = (pic_w >> OAPV_LOG2_MB_W) - tpos->x_mb; + } + else { + tpos->w_mb = fh.tile_width_in_mbs; + } + if(tpos->h_mb + fh.tile_height_in_mbs > (pic_h >> OAPV_LOG2_MB_H)) { + tpos->h_mb = (pic_h >> OAPV_LOG2_MB_H) - tpos->y_mb; + } + else { + tpos->h_mb = fh.tile_height_in_mbs; + } + tpos->idx = i * tile_cols + j; + tpos++; + } + } + tile_info->num_tiles = tile_cols * tile_rows; + } + ERR: DUMP_SET(1); return ret; } -int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_stat_t *stat) +int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_tile_info_t * part, oapv_imgb_t *imgb, oapvd_stat_t *stat) { oapvd_ctx_t *ctx; oapv_pbuh_t pbuh; @@ -2069,11 +2120,12 @@ int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_ // check frame type PBU oapv_assert_gv(OAPV_PBU_TYPE_IS_FRAME(pbuh.pbu_type), ret, OAPV_ERR_INVALID_ARGUMENT, ERR); - // decode frame + // parse frame header ret = oapvd_vlc_frame_header(bs, &ctx->fh); oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); - ret = dec_frm_prepare(ctx, imgb); + // be ready to decode start + ret = dec_frm_prepare(ctx, part, imgb); oapv_assert_g(OAPV_SUCCEEDED(ret), ERR); int thread_ret; @@ -2081,7 +2133,13 @@ int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_ int parallel_task = 1; int tidx = 0; - parallel_task = (ctx->threads > ctx->num_tiles) ? ctx->num_tiles : ctx->threads; + if(part != NULL) { + oapv_assert_gv(part->num_tiles <= ctx->num_tiles, ret, OAPV_ERR_INVALID_ARGUMENT, ERR); + parallel_task = (ctx->threads > part->num_tiles) ? part->num_tiles : ctx->threads; + } + else { + parallel_task = (ctx->threads > ctx->num_tiles) ? ctx->num_tiles : ctx->threads; + } /* decode tiles ************************************/ for(tidx = 0; tidx < (parallel_task - 1); tidx++) { diff --git a/src/oapv_def.h b/src/oapv_def.h index 81c7f79f..2a7741b4 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -328,10 +328,11 @@ struct oapve_ctx { // start of decoder code #if ENABLE_DECODER /////////////////////////////////////////////////////////////////////////////// -#define DEC_TILE_STAT_NOT_DECODED 0 -#define DEC_TILE_STAT_ON_DECODING 1 -#define DEC_TILE_STAT_DECODED 2 -#define DEC_TILE_STAT_SIZE_ERROR -1 +#define DEC_TILE_STAT_NOT_DECODED (0) +#define DEC_TILE_STAT_ON_DECODING (1) +#define DEC_TILE_STAT_DECODED (2) +#define DEC_TILE_STAT_SKIP_DECODING (3) +#define DEC_TILE_STAT_SIZE_ERROR (-1) typedef struct oapvd_tile oapvd_tile_t; struct oapvd_tile { From 961195042ea4cf47b537bf2c98d9032ef82476b4 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Tue, 31 Mar 2026 08:42:12 +0900 Subject: [PATCH 20/31] refactoring Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 76e56428..f4c03170 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -86,13 +86,18 @@ static const args_opt_t dec_args_opts[] = { ARGS_NO_KEY, "output-csp", ARGS_VAL_TYPE_INTEGER, 0, NULL, "output color space (chroma format)\n" " - 0: coded CSP\n" - " - 1: convert to P210 in case of YCbCr422\n" + " - 1: convert to P210 in case of YCbCr422" }, { ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, "forcely disable companding process\n" " Note: this option forces to output 12 bits picture in case of 444/4444-16C12 profile" }, + { + ARGS_NO_KEY, "api-set", ARGS_VAL_TYPE_INTEGER, 0, NULL, + "testing with specific API set (0 or 1)\n" + " Note: API set 1 only supports 1.x or higher library version" + }, {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */ }; @@ -109,6 +114,7 @@ typedef struct args_var { int output_depth; int output_csp; int disable_companding; + int api_set; } args_var_t; static args_var_t *args_init_vars(args_parser_t *args) @@ -126,6 +132,7 @@ static args_var_t *args_init_vars(args_parser_t *args) args_set_variable_by_key_long(opts, "max-au", &vars->max_au); args_set_variable_by_key_long(opts, "hash", &vars->hash); args_set_variable_by_key_long(opts, "disable-companding", &vars->disable_companding); + args_set_variable_by_key_long(opts, "api-set", &vars->api_set); args_set_variable_by_key_long(opts, "verbose", &op_verbose); op_verbose = VERBOSE_SIMPLE; /* default */ args_set_variable_by_key_long(opts, "threads", vars->threads); @@ -368,7 +375,7 @@ static void print_stat_frm(oapvd_stat_t *stat, oapv_frms_t *frms, oapvm_t mid, a } } -int dec_oapv1(args_var_t *args_var, FILE *fp_bs, int is_y4m) +int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) { oapvd_t did = NULL; oapvm_t mid = NULL; @@ -643,7 +650,7 @@ static const char * get_key_from_val(const oapv_dict_str_int_t * dict, int val) return NULL; } -int dec_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) +int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) { oapvd_t did = NULL; oapvm_t mid = NULL; @@ -727,7 +734,7 @@ int dec_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) } au_size -= 4; /* byte size of signature syntax */ - logv3("AU(size=%d)\n", au_size); + logv3("AU(%d byte)\n", au_size); /* PDU loop **********************************************************/ int rsize = 0; @@ -757,7 +764,7 @@ int dec_oapv2(args_var_t *args_var, FILE *fp_bs, int is_y4m) logerr("ERR: unknown PBU type (%d)\n", pbu_info.pbu_type); ret = -1; goto ERR; } - logv3(" PBU(%s gid=%d size=%d)\n", pbu_type_str, pbu_info.group_id, pbu_size); + logv3(" PBU(%s, gid=%d, %d byte)\n", pbu_type_str, pbu_info.group_id, pbu_size); if(pbu_info.pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) { // actual decoding is only supported for primary frames in this code @@ -971,11 +978,14 @@ int main(int argc, const char **argv) clear_data(args_var->fname_out); /* remove decoded file contents if exists */ } - if(0) { - ret = dec_oapv1(args_var, fp_bs, is_y4m); + if(args_var->api_set == 0) { + ret = dec_api_set_0(args_var, fp_bs, is_y4m); + } + else if(args_var->api_set == 1){ + ret = dec_api_set_1(args_var, fp_bs, is_y4m); } else { - ret = dec_oapv2(args_var, fp_bs, is_y4m); + logerr("ERR: unknown API set number (%d)\n", args_var->api_set); } if(ret < 0) goto ERR; From 9368cf36354d6dd7966776a3535cac632b2b50d0 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Tue, 31 Mar 2026 08:50:28 +0900 Subject: [PATCH 21/31] refactoring Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 2 +- inc/oapv.h | 2 +- src/oapv.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index f4c03170..4b809516 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -811,7 +811,7 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) clk_beg = oapv_clk_get(); - ret = oapvd_decode_frame(did, &bitb, NULL, imgb_dec, &stat); + ret = oapvd_decode_frame(did, &bitb, imgb_dec, &stat, NULL); clk_end = oapv_clk_from(clk_beg); clk_tot += clk_end; diff --git a/inc/oapv.h b/inc/oapv.h index f982ae39..6afed65a 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -798,7 +798,7 @@ OAPV_EXPORT int oapvd_info_pbu(void *pbu, int pbu_size, oapv_pbu_info_t *pbu_inf OAPV_EXPORT int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info, oapv_tile_info_t *tile_info); OAPV_EXPORT int oapvd_decode_auinfo(oapvd_t did, oapv_bitb_t *bitb, oapv_au_info_t *aui); -OAPV_EXPORT int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_tile_info_t * part, oapv_imgb_t *imgb, oapvd_stat_t *stat); +OAPV_EXPORT int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_stat_t *stat, oapv_tile_info_t * part); diff --git a/src/oapv.c b/src/oapv.c index 381b166b..81caf1f8 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -2099,7 +2099,7 @@ int oapvd_info_frame(void *pbu, int pbu_size, oapv_frm_info_t *frm_info, oapv_ti return ret; } -int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_tile_info_t * part, oapv_imgb_t *imgb, oapvd_stat_t *stat) +int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_stat_t *stat, oapv_tile_info_t * part) { oapvd_ctx_t *ctx; oapv_pbuh_t pbuh; From e23de74a933bbef6ab0b06233d4c3f3e7fbb9e25 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Tue, 31 Mar 2026 18:46:06 +0900 Subject: [PATCH 22/31] fixed for decoding tiles Signed-off-by: kp5.choi@samsung.com --- src/oapv.c | 23 ++++++++++++----------- src/oapv_def.h | 26 +++++++++++++++++++++----- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/oapv.c b/src/oapv.c index 81caf1f8..947902be 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -1460,15 +1460,15 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_tile_info_t * part, oapv_imgb_ if(part != NULL) { for(i = 0; i < ctx->num_tiles; i++) { - ctx->tile[i].stat = DEC_TILE_STAT_SKIP_DECODING; /* bypass decoding */ + ctx->tile[i].stat = DEC_TILE_STAT_DO(DEC_TILE_STAT_SKIP); /* bypass decoding */ } for(i = 0; i < part->num_tiles; i++) { - ctx->tile[part->pos_tiles[i].idx].stat = DEC_TILE_STAT_NOT_DECODED; + ctx->tile[part->pos_tiles[i].idx].stat = DEC_TILE_STAT_DO(DEC_TILE_STAT_DECODE); } } else { for(i = 0; i < ctx->num_tiles; i++) { - ctx->tile[i].stat = DEC_TILE_STAT_NOT_DECODED; + ctx->tile[i].stat = DEC_TILE_STAT_DO(DEC_TILE_STAT_DECODE); } } @@ -1601,15 +1601,15 @@ static int dec_thread_tile(void *arg) // find not decoded tile oapv_tpool_enter_cs(ctx->sync_obj); for(i = 0; i < ctx->num_tiles; i++) { - if(tile[i].stat == DEC_TILE_STAT_NOT_DECODED) { - tile[i].stat = DEC_TILE_STAT_ON_DECODING; + if(DEC_TILE_STAT_IS_DO(tile[i].stat)) { + tile[i].stat = DEC_TILE_STAT_ON(tile[i].stat); tidx = i; break; } } oapv_tpool_leave_cs(ctx->sync_obj); if(i == ctx->num_tiles) { - break; + break; // end of worker thread } // wait until to know bistream start position @@ -1638,24 +1638,25 @@ static int dec_thread_tile(void *arg) } oapv_tpool_leave_cs(ctx->sync_obj); - ret = dec_tile(core, &tile[tidx]); + if(DEC_TILE_STAT_IS_DECODE(tile[i].stat)) { + ret = dec_tile(core, &tile[tidx]); + } oapv_tpool_enter_cs(ctx->sync_obj); if (OAPV_SUCCEEDED(ret)) { - tile[tidx].stat = DEC_TILE_STAT_DECODED; + tile[tidx].stat = DEC_TILE_STAT_DONE(tile[tidx].stat); } else { - tile[tidx].stat = ret; + tile[tidx].stat = DEC_TILE_STAT_ERR(tile[tidx].stat); thread_ret = ret; } - tile[tidx].stat = OAPV_SUCCEEDED(ret) ? DEC_TILE_STAT_DECODED : ret; oapv_tpool_leave_cs(ctx->sync_obj); } return thread_ret; ERR: oapv_tpool_enter_cs(ctx->sync_obj); - tile[tidx].stat = DEC_TILE_STAT_SIZE_ERROR; + tile[tidx].stat = DEC_TILE_STAT_ERR(tile[tidx].stat); if (tidx + 1 < ctx->num_tiles) { tile[tidx + 1].bs_beg = tile[tidx].bs_beg; diff --git a/src/oapv_def.h b/src/oapv_def.h index 2a7741b4..4f37170e 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -328,11 +328,27 @@ struct oapve_ctx { // start of decoder code #if ENABLE_DECODER /////////////////////////////////////////////////////////////////////////////// -#define DEC_TILE_STAT_NOT_DECODED (0) -#define DEC_TILE_STAT_ON_DECODING (1) -#define DEC_TILE_STAT_DECODED (2) -#define DEC_TILE_STAT_SKIP_DECODING (3) -#define DEC_TILE_STAT_SIZE_ERROR (-1) + +#define DEC_TILE_STAT_DECODE (1 << 0) +#define DEC_TILE_STAT_SKIP (1 << 1) + +#define DEC_TILE_STAT_IS_DECODE(stat) ((stat) & DEC_TILE_STAT_DECODE) +#define DEC_TILE_STAT_IS_SKIP(stat) ((stat) & DEC_TILE_STAT_SKIP) + +#define DEC_TILE_STAT_FLAG_DO (1 << 4) +#define DEC_TILE_STAT_FLAG_ON (1 << 5) +#define DEC_TILE_STAT_FLAG_DONE (1 << 6) +#define DEC_TILE_STAT_FLAG_ERR (1 << 7) + +#define DEC_TILE_STAT_DO(stat) (((stat) & 0x0F) | DEC_TILE_STAT_FLAG_DO) +#define DEC_TILE_STAT_ON(stat) (((stat) & 0x0F) | DEC_TILE_STAT_FLAG_ON) +#define DEC_TILE_STAT_DONE(stat) (((stat) & 0x0F) | DEC_TILE_STAT_FLAG_DONE) +#define DEC_TILE_STAT_ERR(stat) (((stat) & 0x0F) | DEC_TILE_STAT_FLAG_ERR) + +#define DEC_TILE_STAT_IS_DO(stat) ((stat) & DEC_TILE_STAT_FLAG_DO) +#define DEC_TILE_STAT_IS_ON(stat) ((stat) & DEC_TILE_STAT_FLAG_ON) +#define DEC_TILE_STAT_IS_DONE(stat) ((stat) & DEC_TILE_STAT_FLAG_DONE) + typedef struct oapvd_tile oapvd_tile_t; struct oapvd_tile { From 30154fc8356e9467b8debc1b06dba4a24c2b8fe0 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Wed, 1 Apr 2026 11:20:08 +0900 Subject: [PATCH 23/31] added command line option for testing tile-based decoding Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 91 +++++++++++++++++++++++++++++---------------- app/oapv_app_util.h | 8 ++++ src/oapv.c | 2 +- src/oapv_def.h | 6 +-- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 4b809516..2df343b7 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -91,13 +91,20 @@ static const args_opt_t dec_args_opts[] = { { ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, "forcely disable companding process\n" - " Note: this option forces to output 12 bits picture in case of 444/4444-16C12 profile" + " Note: this option forces to output 12 bits picture in case of 444-16C12\n" + " and 4444-16C12 profile" }, { ARGS_NO_KEY, "api-set", ARGS_VAL_TYPE_INTEGER, 0, NULL, "testing with specific API set (0 or 1)\n" " Note: API set 1 only supports 1.x or higher library version" }, + { + ARGS_NO_KEY, "cyclic-tile-decoding", ARGS_VAL_TYPE_NONE, 0, NULL, + "testing using tile-based decoding in cyclic way\n" + " Note: this option is just for testing tile-based decoding method and\n" + " API set 1 option is required to support this" + }, {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */ }; @@ -115,6 +122,7 @@ typedef struct args_var { int output_csp; int disable_companding; int api_set; + int cyclic_tile_decoding; } args_var_t; static args_var_t *args_init_vars(args_parser_t *args) @@ -133,6 +141,7 @@ static args_var_t *args_init_vars(args_parser_t *args) args_set_variable_by_key_long(opts, "hash", &vars->hash); args_set_variable_by_key_long(opts, "disable-companding", &vars->disable_companding); args_set_variable_by_key_long(opts, "api-set", &vars->api_set); + args_set_variable_by_key_long(opts, "cyclic-tile-decoding", &vars->cyclic_tile_decoding); args_set_variable_by_key_long(opts, "verbose", &op_verbose); op_verbose = VERBOSE_SIMPLE; /* default */ args_set_variable_by_key_long(opts, "threads", vars->threads); @@ -652,29 +661,45 @@ static const char * get_key_from_val(const oapv_dict_str_int_t * dict, int val) int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) { - oapvd_t did = NULL; - oapvm_t mid = NULL; - oapvd_cdesc_t cdesc; - oapv_au_info_t aui; - oapvd_stat_t stat; - unsigned char *pbu = NULL; - oapv_bitb_t bitb; - oapv_imgb_t *imgb_dec = NULL; - oapv_imgb_t *imgb_out = NULL; - oapv_imgb_t *imgb_tmp = NULL; - - int ret = 0; - oapv_clk_t clk_beg, clk_end, clk_tot; - int au_cnt = 0; // number of decoded access unit; - int primary_frm_cnt = 0; // number of decoded primary frame - int primary_frm_gid = -1; // group id of primary frame + oapvd_t did = NULL; + oapvd_cdesc_t cdesc; + oapv_au_info_t aui; + oapvd_stat_t stat; + oapv_bitb_t bitb; + oapv_tile_info_t tinfo_in_frm; + oapv_tile_info_t *ptinfo_in_frm = NULL; + oapv_tile_info_t tinfo_dec; + oapv_tile_info_t *ptinfo_dec = NULL; + + oapv_imgb_t *imgb_dec = NULL; + oapv_imgb_t *imgb_out = NULL; + oapv_imgb_t *imgb_tmp = NULL; + + int ret = 0; + oapv_clk_t clk_beg, clk_end, clk_tot; + int au_cnt = 0; // number of decoded access unit; + int primary_frm_cnt = 0; // number of decoded primary frame + int primary_frm_gid = -1; // group id of primary frame + unsigned char *pbu = NULL; // create bitstream buffer pbu = malloc(MAX_BS_BUF); if(pbu == NULL) { logerr("ERR: cannot allocate bitstream buffer, size=%d\n", MAX_BS_BUF); - ret = -1; - goto ERR; + ret = -1; goto ERR; + } + + if(args_var->cyclic_tile_decoding) { + if(args_var->api_set == 0) { + logerr("ERR: cyclic tile-based decoding cannot be supported in API set 0\n"); + ret = -1; goto ERR; + } + ptinfo_in_frm = &tinfo_in_frm; + ptinfo_dec = &tinfo_dec; + } + else { + ptinfo_in_frm = NULL; + ptinfo_dec = NULL; } // create decoder @@ -699,14 +724,6 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) clk_tot = 0; au_cnt = 0; - /* create metadata container */ - mid = oapvm_create(&ret); - if(OAPV_FAILED(ret)) { - logerr("ERR: cannot create OAPV metadata container (err=%d)\n", ret); - ret = -1; - goto ERR; - } - /* AU loop ***************************************************************/ while(args_var->max_au == 0 || (au_cnt < args_var->max_au)) { /* read access unit size */ @@ -778,7 +795,11 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) } // get frame information - ret = oapvd_info_frame(pbu, pbu_size, &finfo, NULL); + ret = oapvd_info_frame(pbu, pbu_size, &finfo, ptinfo_in_frm); + if(OAPV_FAILED(ret)) { + logerr("ERR: failed to get frame information (ret = %d)\n", ret); + ret = -1; goto ERR; + } // create decoding frame buffers if needs if(imgb_dec != NULL && (imgb_dec->w[0] != finfo.w || imgb_dec->h[0] != finfo.h)) { @@ -805,13 +826,22 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) if(args_var->output_depth == 0) { args_var->output_depth = OAPV_CS_GET_BIT_DEPTH(finfo.cs); } + + if(args_var->cyclic_tile_decoding) { + ptinfo_dec->num_tiles = 1; // only one tile decoding in cyclic-way + ptinfo_dec->pos_tiles[0].idx = primary_frm_cnt % ptinfo_in_frm->num_tiles; + + // clear image buffer to remove previous frame's decoded tile image + imgb_clear(imgb_dec); + } + // start to decode a frame bitb.addr = pbu; bitb.ssize = pbu_size; clk_beg = oapv_clk_get(); - ret = oapvd_decode_frame(did, &bitb, imgb_dec, &stat, NULL); + ret = oapvd_decode_frame(did, &bitb, imgb_dec, &stat, ptinfo_dec); clk_end = oapv_clk_from(clk_beg); clk_tot += clk_end; @@ -893,9 +923,6 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) if(did) oapvd_delete(did); - if(mid) - oapvm_delete(mid); - if(imgb_dec != NULL) imgb_dec->release(imgb_dec); diff --git a/app/oapv_app_util.h b/app/oapv_app_util.h index c25e9e88..ad77c398 100644 --- a/app/oapv_app_util.h +++ b/app/oapv_app_util.h @@ -675,6 +675,14 @@ static void imgb_cpy(oapv_imgb_t *dst, oapv_imgb_t *src) } } +void imgb_clear(oapv_imgb_t *imgb) +{ + int i; + for(i = 0; i < imgb->np; i++) { + memset(imgb->a[i], 0, imgb->bsize[i]); + } +} + static void measure_psnr(oapv_imgb_t *org, oapv_imgb_t *rec, double psnr[4], int bit_depth) { double sum[4], mse[4]; diff --git a/src/oapv.c b/src/oapv.c index 947902be..977d716f 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -2135,7 +2135,7 @@ int oapvd_decode_frame(oapvd_t did, oapv_bitb_t *bitb, oapv_imgb_t *imgb, oapvd_ int tidx = 0; if(part != NULL) { - oapv_assert_gv(part->num_tiles <= ctx->num_tiles, ret, OAPV_ERR_INVALID_ARGUMENT, ERR); + oapv_assert_gv(part->num_tiles > 0 && part->num_tiles <= ctx->num_tiles, ret, OAPV_ERR_INVALID_ARGUMENT, ERR); parallel_task = (ctx->threads > part->num_tiles) ? part->num_tiles : ctx->threads; } else { diff --git a/src/oapv_def.h b/src/oapv_def.h index 4f37170e..b834526e 100644 --- a/src/oapv_def.h +++ b/src/oapv_def.h @@ -360,9 +360,9 @@ struct oapvd_tile { int h; /* tile height in unit of pixel */ u32 tile_size; /* tile data size (byte size of tile(tileIdx) syntax) */ - u8 *bs_beg; /* start position of tile in input bistream */ - u8 *bs_end; /* end position of tile() in input bistream */ - volatile s32 stat; // decoding status + u8 *bs_beg; /* start position of tile in input bistream */ + u8 *bs_end; /* end position of tile() in input bistream */ + volatile s32 stat; /* decoding status */ }; typedef struct oapvd_core oapvd_core_t; From 6496eaa485502d86b1813f7c3343d46af2de84c6 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Wed, 1 Apr 2026 15:17:02 +0900 Subject: [PATCH 24/31] fixed memory leak Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 5 ++++- src/oapv_rc.c | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 2df343b7..3a01ee1a 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -753,7 +753,7 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) logv3("AU(%d byte)\n", au_size); - /* PDU loop **********************************************************/ + /* PBU loop **********************************************************/ int rsize = 0; oapv_pbu_info_t pbu_info; @@ -929,6 +929,9 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) if(imgb_tmp != NULL) imgb_tmp->release(imgb_tmp); + if(pbu != NULL) + free(pbu); + return 0; } diff --git a/src/oapv_rc.c b/src/oapv_rc.c index 7d99763d..fed8b046 100644 --- a/src/oapv_rc.c +++ b/src/oapv_rc.c @@ -56,8 +56,9 @@ int oapve_rc_get_tile_cost(oapve_ctx_t* ctx, oapve_core_t* core, oapve_tile_t* t for (int y = 0; y < tile->h; y += step_h) { for (int x = 0; x < tile->w; x += step_w) { - int tx = tile->x + x; - int ty = tile->y + y; + int tx = (tile->x + x) >> ctx->c_sft[c][0]; + int ty = (tile->y + y) >> ctx->c_sft[c][1]; + pic = (s16*)((u8*)org + ty * org_s) + tx; ctx->fn_blk_from_pic[c](OAPV_BLK_W, OAPV_BLK_H, pic, 0, org_s, core->coef, (OAPV_BLK_W << 1), ctx->bit_depth, 0); sum += ctx->fn_had8x8(core->coef, 8); From 840807fe44dde43087537582e32eb0b385b791a2 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Sat, 4 Apr 2026 10:06:09 +0900 Subject: [PATCH 25/31] inrease version to 1.0.0.0 Signed-off-by: kp5.choi@samsung.com --- inc/oapv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inc/oapv.h b/inc/oapv.h index 6afed65a..988aca70 100644 --- a/inc/oapv.h +++ b/inc/oapv.h @@ -55,10 +55,10 @@ extern "C" { #define OAPV_VER_GET_PATCH(v) (((v) >> 0) & 0xFF) /* version numbers (should be changed in case of new release) */ -#define OAPV_VER_APISET (0) -#define OAPV_VER_MAJOR (2) -#define OAPV_VER_MINOR (1) -#define OAPV_VER_PATCH (1) +#define OAPV_VER_APISET (1) +#define OAPV_VER_MAJOR (0) +#define OAPV_VER_MINOR (0) +#define OAPV_VER_PATCH (0) /* 4-bytes version number */ #define OAPV_VER_NUM \ From ece1f65b1d6b28de594268635f7baa67ea67ebd9 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Tue, 30 Jun 2026 15:50:41 +0900 Subject: [PATCH 26/31] refactoring and fuzzing defense code Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 140 ++++++++++++++++++++++++++++++++++++--------- src/oapv.c | 11 +++- 2 files changed, 122 insertions(+), 29 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 8960d0c1..b79bde09 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -191,25 +191,61 @@ static void print_usage(const char **argv) free(args_var); } -static int read_au_size(FILE *fp) +/* read 4-byte access unit size. + * return values: + * 1 : success, *au_size holds the parsed size + * 0 : clean end of file (no byte was read before EOF) + * -1 : read error or partial read (1~3 bytes read then EOF/error) + */ +static int read_au_size(FILE *fp, unsigned int *au_size) { unsigned char buf[4]; + size_t n; - for(int i = 0; i < 4; i++) { - if(1 != fread(&buf[i], 1, 1, fp)) + for(int i = 0; i < 4; i++) { + n = fread(&buf[i], 1, 1, fp); + if(n != 1) { + if(i == 0 && feof(fp)) { + return 0; /* clean EOF at an access unit boundary */ + } + /* partial read (truncated size field) or read error */ + if(ferror(fp)) { + logerr("ERR: file read error at byte %d of au_size field\n", i); + } else { + logerr("ERR: truncated au_size field (read %d/4 bytes before EOF)\n", i); + } return -1; + } } - return ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3])); + *au_size = ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) | + ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]); + return 1; } static int read_bitstream(FILE *fp, unsigned char *bs_buf, int *bs_buf_size) { - int au_size, read_size = 0; + unsigned int au_size; + int read_size = 0; unsigned char b = 0; + int ret; if(!fseek(fp, 0, SEEK_CUR)) { /* read size first */ - au_size = read_au_size(fp); + ret = read_au_size(fp, &au_size); + if(ret == 0) { + logv2_line(""); + logv2("End of file\n"); + return 0; + } + else if(ret < 0) { + logerr("Cannot read bitstream size!\n"); + return -1; + } if(au_size > 0) { + /* check if bitstream size exceeds MAX_BS_BUF */ + if(au_size > MAX_BS_BUF) { + logerr("ERR: bitstream size (%u bytes) exceeds maximum buffer size (%d bytes)\n", au_size, MAX_BS_BUF); + return -1; + } while(au_size > 0) { /* read byte */ if(1 != fread(&b, 1, 1, fp)) { @@ -223,15 +259,9 @@ static int read_bitstream(FILE *fp, unsigned char *bs_buf, int *bs_buf_size) *bs_buf_size = read_size; } else { - if(feof(fp)) { - logv2_line(""); - logv2("End of file\n"); - return 0; - } - else { - logerr("Cannot read bitstream size!\n") - return -1; - }; + /* size field present but zero: malformed bitstream */ + logerr("Cannot read bitstream size!\n"); + return -1; } } else { @@ -407,6 +437,7 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) oapv_clk_t clk_beg, clk_end, clk_tot; int au_cnt, frm_cnt[OAPV_MAX_NUM_FRAMES]; int read_size, bs_buf_size = 0; + int prev_frm_w = -1, prev_frm_h = -1; memset(frm_cnt, 0, sizeof(int) * OAPV_MAX_NUM_FRAMES); memset(&aui, 0, sizeof(oapv_au_info_t)); @@ -469,6 +500,15 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) goto ERR; } + /* check frame resolution change */ + if(au_cnt > 0 && aui.num_frms > 0) { + finfo = &aui.frm_info[0]; + if((prev_frm_w != -1 && prev_frm_w != finfo->w) || (prev_frm_h != -1 && prev_frm_h != finfo->h)) { + logv2("WARNING: frame resolution changed from (%dx%d) to (%dx%d) at AU %d\n", + prev_frm_w, prev_frm_h, finfo->w, finfo->h, au_cnt); + } + } + /* create decoding frame buffers */ ofrms.num_frms = aui.num_frms; for(i = 0; i < ofrms.num_frms; i++) { @@ -494,6 +534,11 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) goto ERR; } } + /* update previous frame resolution */ + if(IS_NON_AUX_FRM(finfo)) { + prev_frm_w = finfo->w; + prev_frm_h = finfo->h; + } } if(args_var->disable_companding && finfo->use_companding) { @@ -559,6 +604,11 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) frm = &ofrms.frm[i]; if(ofrms.num_frms > 0) { if(OAPV_CS_GET_BIT_DEPTH(frm->imgb->cs) != args_var->output_depth && args_var->output_csp != OUTPUT_CSP_P210) { + /* check if imgb_w needs to be reallocated due to resolution change */ + if(imgb_w != NULL && (imgb_w->w[0] != frm->imgb->w[0] || imgb_w->h[0] != frm->imgb->h[0])) { + imgb_w->release(imgb_w); + imgb_w = NULL; + } if(imgb_w == NULL) { imgb_w = imgb_create(frm->imgb->w[0], frm->imgb->h[0], OAPV_CS_SET(OAPV_CS_GET_FORMAT(frm->imgb->cs), args_var->output_depth, 0)); @@ -632,15 +682,31 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) return 0; } +/* read a 4-byte big-endian unsigned integer. + * return values: + * 0 : success, *val holds the parsed value + * -1 : EOF or read error or partial read + */ static int read_u32(FILE *fp, unsigned int * val) { unsigned char buf[4]; + size_t n; for(int i = 0; i < 4; i++) { - if(1 != fread(&buf[i], 1, 1, fp)) + n = fread(&buf[i], 1, 1, fp); + if(n != 1) { + if(i == 0 && feof(fp)) { + /* clean EOF at 4-byte boundary - normal termination */ + } else if(ferror(fp)) { + logerr("ERR: file read error at byte %d of u32 field\n", i); + } else { + logerr("ERR: truncated u32 field (read %d/4 bytes before EOF)\n", i); + } return -1; + } } - *val = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3])); + *val = ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) | + ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]); return 0; } @@ -686,6 +752,7 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) int primary_frm_cnt = 0; // number of decoded primary frame int primary_frm_gid = -1; // group id of primary frame unsigned char *pbu = NULL; + int prev_frm_w = -1, prev_frm_h = -1; // create bitstream buffer pbu = malloc(MAX_BS_BUF); @@ -734,15 +801,9 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) /* read access unit size */ unsigned int au_size; if(read_u32(fp_bs, &au_size) < 0) { - if(feof(fp_bs)) { - logv2_line(""); - logv2("End of file\n"); - ret = 0; goto END; - } - else { - logerr("ERR: cannot read au_size\n"); - ret = -1; goto ERR; - } + logv2_line(""); + logv2("End of file\n"); + ret = 0; goto END; } /* check signature ('aPv1') */ unsigned int signature = 0; @@ -751,12 +812,12 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) ret = -1; goto ERR; } if(signature != 0x61507631) { - logerr("ERR: signature mismatch") + logerr("ERR: signature mismatch (0x%08X)\n", signature); ret = -1; goto ERR; } au_size -= 4; /* byte size of signature syntax */ - logv3("AU(%d byte)\n", au_size); + logv3("AU[%03d] (%d byte)\n", au_cnt, au_size); /* PBU loop **********************************************************/ int rsize = 0; @@ -771,6 +832,12 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) } rsize += 4; /* byte size of pbu_size syntax */ + /* check if PBU size exceeds MAX_BS_BUF */ + if(pbu_size > MAX_BS_BUF) { + logerr("ERR: PBU size (%u bytes) exceeds maximum buffer size (%d bytes)\n", pbu_size, MAX_BS_BUF); + ret = -1; goto ERR; + } + /* read a PBU */ if(read_pbu(fp_bs, pbu, pbu_size) < 0) { ret = -1; goto ERR; @@ -806,6 +873,14 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) ret = -1; goto ERR; } + /* check frame resolution change */ + if(primary_frm_cnt > 0) { + if((prev_frm_w != -1 && prev_frm_w != finfo.w) || (prev_frm_h != -1 && prev_frm_h != finfo.h)) { + logv2("WARNING: frame resolution changed from (%dx%d) to (%dx%d) at frame %d\n", + prev_frm_w, prev_frm_h, finfo.w, finfo.h, primary_frm_cnt); + } + } + // create decoding frame buffers if needs if(imgb_dec != NULL && (imgb_dec->w[0] != finfo.w || imgb_dec->h[0] != finfo.h)) { imgb_dec->release(imgb_dec); @@ -862,6 +937,11 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) /* write decoded frames into files */ if(OAPV_CS_GET_BIT_DEPTH(imgb_dec->cs) != args_var->output_depth && args_var->output_csp != OUTPUT_CSP_P210) { + /* check if imgb_tmp needs to be reallocated due to resolution change */ + if(imgb_tmp != NULL && (imgb_tmp->w[0] != imgb_dec->w[0] || imgb_tmp->h[0] != imgb_dec->h[0])) { + imgb_tmp->release(imgb_tmp); + imgb_tmp = NULL; + } if(imgb_tmp == NULL) { imgb_tmp = imgb_create(imgb_dec->w[0], imgb_dec->h[0], OAPV_CS_SET(OAPV_CS_GET_FORMAT(imgb_dec->cs), args_var->output_depth, 0)); @@ -892,6 +972,9 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) goto ERR; } } + /* update previous frame resolution */ + prev_frm_w = finfo.w; + prev_frm_h = finfo.h; primary_frm_cnt++; fflush(stdout); fflush(stderr); @@ -910,6 +993,7 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) } rsize += pbu_size; } + au_cnt++; } END: diff --git a/src/oapv.c b/src/oapv.c index 83e7cbe6..18158313 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -1409,7 +1409,16 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_tile_info_t * part, oapv_imgb_ { int i; - if (imgb->w[0] < ctx->fh.fi.frame_width || imgb->h[0] < ctx->fh.fi.frame_height) { + // the input image buffer must match the frame format signaled in the + // bitstream; a mismatch (e.g. caused by a resolution change without + // reallocation) is rejected as an invalid argument + if (imgb->w[0] != ctx->fh.fi.frame_width || imgb->h[0] != ctx->fh.fi.frame_height) { + return OAPV_ERR_INVALID_ARGUMENT; + } + // the color space of the input buffer must correspond to the bitstream's + // chroma format (note: OAPV_CF_PLANAR2 maps to chroma_format_idc 2 so the + // YCbCr422 -> P210 output path is accepted) + if (color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)) != ctx->fh.fi.chroma_format_idc) { return OAPV_ERR_INVALID_ARGUMENT; } From 73d8566e8afe75dbc3fb71733631d542bb0f01b3 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Tue, 30 Jun 2026 17:39:15 +0900 Subject: [PATCH 27/31] add fuzzing defense code Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_args.h | 41 ++++++++++-- app/oapv_app_dec.c | 87 +++++++++++++++++-------- app/oapv_app_enc.c | 153 +++++++++++++++++++++++--------------------- src/oapv.c | 17 +++++ src/oapv_param.c | 36 +++++++++-- src/oapv_port.h | 1 + 6 files changed, 226 insertions(+), 109 deletions(-) diff --git a/app/oapv_app_args.h b/app/oapv_app_args.h index e7a1fff2..6ed72582 100644 --- a/app/oapv_app_args.h +++ b/app/oapv_app_args.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "oapv.h" #define ARGS_VAL_TYPE_MANDATORY (1 << 0) /* mandatory or not */ @@ -57,6 +59,7 @@ typedef struct args_opt { int val_type; /* value type */ int flag; /* flag to setting or not */ void *val; /* actual value */ + int val_size; /* size of value buffer for STRING type (0 for non-STRING) */ char desc[1024]; /* description of option */ } args_opt_t; @@ -120,11 +123,25 @@ static int args_read_value(args_opt_t *ops, const char *argv) switch(ARGS_GET_CMD_OPT_VAL_TYPE(ops->val_type)) { case ARGS_VAL_TYPE_INTEGER: - *((int *)ops->val) = atoi(argv); + { + char *endptr; + long val; + errno = 0; + val = strtol(argv, &endptr, 10); + if(endptr == argv || *endptr != '\0' || errno == ERANGE || val < INT_MIN || val > INT_MAX) { + return -1; + } + *((int *)ops->val) = (int)val; + } break; case ARGS_VAL_TYPE_STRING: - strcpy((char *)ops->val, argv); + if(ops->val_size > 0) { + strncpy((char *)ops->val, argv, ops->val_size - 1); + ((char *)ops->val)[ops->val_size - 1] = '\0'; + } else { + strcpy((char *)ops->val, argv); + } break; default: @@ -175,6 +192,8 @@ static int args_parse_int_x_int(char *str, int *num0, int *num1) char str0_t[64]; int i, cnt0 = 0, cnt1; char *str0, *str1 = NULL; + char *endptr; + long tmp_val; str0 = str; cnt1 = (int)strlen(str); @@ -205,8 +224,19 @@ static int args_parse_int_x_int(char *str, int *num0, int *num1) strncpy(str0_t, str0, cnt0); str0_t[cnt0] = '\0'; - *num0 = atoi(str0_t); - *num1 = atoi(str1); + /* parse first number using strtol with overflow check */ + tmp_val = strtol(str0_t, &endptr, 10); + if(endptr == str0_t || tmp_val < INT_MIN || tmp_val > INT_MAX) { + return -1; /* conversion failed or overflow */ + } + *num0 = (int)tmp_val; + + /* parse second number using strtol with overflow check */ + tmp_val = strtol(str1, &endptr, 10); + if(endptr == str1 || tmp_val < INT_MIN || tmp_val > INT_MAX) { + return -1; /* conversion failed or overflow */ + } + *num1 = (int)tmp_val; return 0; } @@ -314,7 +344,7 @@ static int args_parse_cmd(int argc, const char *argv[], args_opt_t *ops, return -1; } -static int args_set_variable_by_key_long(args_opt_t *opts, char *key_long, void *var) +static int args_set_variable_by_key_long(args_opt_t *opts, char *key_long, void *var, size_t size) { int idx; char buf[ARGS_MAX_KEY_LONG]; @@ -337,6 +367,7 @@ static int args_set_variable_by_key_long(args_opt_t *opts, char *key_long, void if(idx < 0) return -1; opts[idx].val = var; + opts[idx].val_size = (int)size; return 0; } diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index b79bde09..33711ead 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -49,7 +49,7 @@ /* define various command line options as a table */ static const args_opt_t dec_args_opts[] = { { - 'v', "verbose", ARGS_VAL_TYPE_INTEGER, 0, NULL, + 'v', "verbose", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "verbose (log) level\n" " - 0: no message\n" " - 1: only error message\n" @@ -57,60 +57,60 @@ static const args_opt_t dec_args_opts[] = { " - 3: frame-level messages" }, { - 'i', "input", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, + 'i', "input", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, 0, "file name of input bitstream" }, { - 'o', "output", ARGS_VAL_TYPE_STRING, 0, NULL, + 'o', "output", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "file name of decoded output" }, { - ARGS_NO_KEY, "max-au", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "max-au", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "maximum number of access units to be decoded" }, { - 'm', "threads", ARGS_VAL_TYPE_STRING, 0, NULL, + 'm', "threads", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "force use of a specific number of threads\n" " - 'auto' means that the value is internally determined" }, { - 'd', "output-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL, + 'd', "output-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "output bit depth (8, 10, 12)\n" " Note: This is option does not support 444/4444-16C12 profile." }, { - ARGS_NO_KEY, "hash", ARGS_VAL_TYPE_NONE, 0, NULL, + ARGS_NO_KEY, "hash", ARGS_VAL_TYPE_NONE, 0, NULL, 0, "parse frame hash value for conformance checking in decoding" }, { - ARGS_NO_KEY, "output-csp", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "output-csp", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "output color space (chroma format)\n" " - 0: coded CSP\n" " - 1: convert to P210 in case of YCbCr422" }, { - ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, + ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, 0, "forcely disable companding process\n" " Note: this option forces to output 12 bits picture in case of 444-16C12\n" " and 4444-16C12 profile" }, { - ARGS_NO_KEY, "api-set", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "api-set", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "testing with specific API set (0 or 1)\n" " Note: API set 1 only supports 1.x or higher library version" }, { - ARGS_NO_KEY, "cyclic-tile-decoding", ARGS_VAL_TYPE_NONE, 0, NULL, + ARGS_NO_KEY, "cyclic-tile-decoding", ARGS_VAL_TYPE_NONE, 0, NULL, 0, "testing using tile-based decoding in cyclic way\n" " Note: this option is just for testing tile-based decoding method and\n" " API set 1 option is required to support this" }, { - ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, + ARGS_NO_KEY, "disable-companding", ARGS_VAL_TYPE_NONE, 0, NULL, 0, "forcely disable companding process\n" " Note: this option forces to output 12 bits picture in case of 444/4444-16C12 profile" }, - {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */ + {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, 0, ""} /* termination */ }; // clang-format on @@ -139,21 +139,21 @@ static args_var_t *args_init_vars(args_parser_t *args) assert_rv(vars != NULL, NULL); memset(vars, 0, sizeof(args_var_t)); - /*args_set_variable_by_key_long(opts, "config", args->fname_cfg);*/ - args_set_variable_by_key_long(opts, "input", vars->fname_inp); - args_set_variable_by_key_long(opts, "output", vars->fname_out); - args_set_variable_by_key_long(opts, "max-au", &vars->max_au); - args_set_variable_by_key_long(opts, "hash", &vars->hash); - args_set_variable_by_key_long(opts, "disable-companding", &vars->disable_companding); + /*args_set_variable_by_key_long(opts, "config", args->fname_cfg, 0);*/ + args_set_variable_by_key_long(opts, "input", vars->fname_inp, sizeof(vars->fname_inp)); + args_set_variable_by_key_long(opts, "output", vars->fname_out, sizeof(vars->fname_out)); + args_set_variable_by_key_long(opts, "max-au", &vars->max_au, 0); + args_set_variable_by_key_long(opts, "hash", &vars->hash, 0); + args_set_variable_by_key_long(opts, "disable-companding", &vars->disable_companding, 0); vars->disable_companding = 0; /* default */ - args_set_variable_by_key_long(opts, "api-set", &vars->api_set); - args_set_variable_by_key_long(opts, "cyclic-tile-decoding", &vars->cyclic_tile_decoding); - args_set_variable_by_key_long(opts, "verbose", &op_verbose); + args_set_variable_by_key_long(opts, "api-set", &vars->api_set, 0); + args_set_variable_by_key_long(opts, "cyclic-tile-decoding", &vars->cyclic_tile_decoding, 0); + args_set_variable_by_key_long(opts, "verbose", &op_verbose, 0); op_verbose = VERBOSE_SIMPLE; /* default */ - args_set_variable_by_key_long(opts, "threads", vars->threads); + args_set_variable_by_key_long(opts, "threads", vars->threads, sizeof(vars->threads)); strcpy(vars->threads, "auto"); - args_set_variable_by_key_long(opts, "output-depth", &vars->output_depth); - args_set_variable_by_key_long(opts, "output-csp", &vars->output_csp); + args_set_variable_by_key_long(opts, "output-depth", &vars->output_depth, 0); + args_set_variable_by_key_long(opts, "output-csp", &vars->output_csp, 0); vars->output_csp = 0; /* default: coded CSP */ return vars; @@ -456,7 +456,14 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) cdesc.threads = OAPV_CDESC_THREADS_AUTO; } else { - cdesc.threads = atoi(args_var->threads); + char *endptr; + long threads_val = strtol(args_var->threads, &endptr, 10); + if(endptr == args_var->threads || threads_val <= 0 || threads_val > INT_MAX) { + logerr("ERR: invalid threads value: %s\n", args_var->threads); + ret = -1; + goto ERR; + } + cdesc.threads = (int)threads_val; } did = oapvd_create(&cdesc, &ret); if(did == NULL) { @@ -500,6 +507,13 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) goto ERR; } + /* validate num_frms from bitstream */ + if(aui.num_frms <= 0 || aui.num_frms > OAPV_MAX_NUM_FRAMES) { + logerr("ERR: invalid number of frames (%d), valid range is 1-%d\n", aui.num_frms, OAPV_MAX_NUM_FRAMES); + ret = -1; + goto ERR; + } + /* check frame resolution change */ if(au_cnt > 0 && aui.num_frms > 0) { finfo = &aui.frm_info[0]; @@ -582,8 +596,20 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) logerr("ERR: failed to read metadata\n"); goto END; } + + /* validate number of metadata payloads */ + if(num_plds < 0 || num_plds > 128) { + logerr("ERR: invalid number of metadata payloads (%d), valid range is 0-128\n", num_plds); + goto END; + } + if(num_plds > 0) { pld = malloc(sizeof(oapvm_payload_t) * num_plds); + if(pld == NULL) { + logerr("ERR: failed to allocate memory for metadata payloads (requested: %zu bytes)\n", + sizeof(oapvm_payload_t) * num_plds); + goto END; + } ret = oapvm_get_all(mid, pld, &num_plds); if(OAPV_FAILED(ret)) { logerr("ERR: failed to read metadata\n"); @@ -779,7 +805,14 @@ int dec_api_set_1(args_var_t *args_var, FILE *fp_bs, int is_y4m) cdesc.threads = OAPV_CDESC_THREADS_AUTO; } else { - cdesc.threads = atoi(args_var->threads); + char *endptr; + long threads_val = strtol(args_var->threads, &endptr, 10); + if(endptr == args_var->threads || threads_val <= 0 || threads_val > INT_MAX) { + logerr("ERR: invalid threads value: %s\n", args_var->threads); + ret = -1; + goto ERR; + } + cdesc.threads = (int)threads_val; } did = oapvd_create(&cdesc, &ret); if(did == NULL) { diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 38857e13..7f3cf397 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -50,7 +50,7 @@ typedef enum _STATES { /* define various command line options as a table */ static const args_opt_t enc_args_opts[] = { { - 'v', "verbose", ARGS_VAL_TYPE_INTEGER, 0, NULL, + 'v', "verbose", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "verbose (log) level\n" " - 0: no message\n" " - 1: only error message\n" @@ -58,52 +58,52 @@ static const args_opt_t enc_args_opts[] = { " - 3: frame-level messages" }, { - 'i', "input", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, + 'i', "input", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL, 0, "file name of input video" }, { - 'o', "output", ARGS_VAL_TYPE_STRING, 0, NULL, + 'o', "output", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "file name of output bitstream" }, { - 'r', "recon", ARGS_VAL_TYPE_STRING, 0, NULL, + 'r', "recon", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "file name of reconstructed video" }, { - 'w', "width", ARGS_VAL_TYPE_STRING, 0, NULL, + 'w', "width", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "pixel width of input video" }, { - 'h', "height", ARGS_VAL_TYPE_STRING, 0, NULL, + 'h', "height", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "pixel height of input video" }, { - 'q', "qp", ARGS_VAL_TYPE_STRING, 0, NULL, + 'q', "qp", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "QP value: 0 ~ (63 + (bitdepth - 10)*6) \n" " - 10bit input: 0 ~ 63\n" " - 12bit input and 12C16bit: 0 ~ 75\n" " - 'auto' means that the value is internally determined" }, { - 'z', "fps", ARGS_VAL_TYPE_STRING, 0, NULL, + 'z', "fps", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "frame rate (frames per second)" }, { - 'm', "threads", ARGS_VAL_TYPE_STRING, 0, NULL, + 'm', "threads", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "force use of a specific number of threads\n" " - 'auto' means that the value is internally determined" }, { - ARGS_NO_KEY, "preset", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "preset", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "encoder preset [fastest, fast, medium, slow, placebo]" }, { - 'd', "input-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL, + 'd', "input-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "input bit depth (8, 10-12, 16)\n" " - Note: 8bit input will be converted to 10bit" }, { - ARGS_NO_KEY, "input-csp", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "input-csp", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "input color space (chroma format)\n" " - 0: 400\n" " - 2: 422\n" @@ -112,7 +112,7 @@ static const args_opt_t enc_args_opts[] = { " - 5: P2(Planar Y, Combined CbCr, 422)" }, { - ARGS_NO_KEY, "family", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "family", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "family name for bitrate setting\n" " - 422-LQ: YCbCr422 low quality\n" " - 422-SQ: YCbCr422 standard quality\n" @@ -123,7 +123,7 @@ static const args_opt_t enc_args_opts[] = { " color space, if they coexists." }, { - ARGS_NO_KEY, "profile", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "profile", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "profile string\n" " - 422-10: YCbCr422 10bit (default)\n" " - 422-12: YCbCr422 12bit\n" @@ -139,67 +139,67 @@ static const args_opt_t enc_args_opts[] = { " color space, if they coexists." }, { - ARGS_NO_KEY, "level", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "level", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "level setting (1, 1.1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 6, 6.1, 7, 7.1)\n" " - 'auto' means that the value is internally determined" }, { - ARGS_NO_KEY, "band", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "band", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "band setting (0, 1, 2, 3)\n" " - 'auto' means that the value is internally determined" }, { - ARGS_NO_KEY, "max-au", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "max-au", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "maximum number of access units to be encoded" }, { - ARGS_NO_KEY, "seek", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "seek", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "number of skipped access units before encoding" }, { - ARGS_NO_KEY, "qp-offset-c1", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "qp-offset-c1", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "QP offset value for Component 1 (Cb)" }, { - ARGS_NO_KEY, "qp-offset-c2", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "qp-offset-c2", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "QP offset value for Component 2 (Cr)" }, { - ARGS_NO_KEY, "qp-offset-c3", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "qp-offset-c3", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "QP offset value for Component 3" }, { - ARGS_NO_KEY, "tile-w", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "tile-w", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "width of tile in units of pixels" }, { - ARGS_NO_KEY, "tile-h", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "tile-h", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "height of tile in units of pixels" }, { - ARGS_NO_KEY, "bitrate", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "bitrate", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "enable ABR rate control\n" " bitrate in terms of kbits per second: Kbps(none,K,k), Mbps(M,m)\n" " ex) 100 = 100K = 0.1M" }, { - ARGS_NO_KEY, "q-matrix-c0", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "q-matrix-c0", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "custom quantization matrix for component 0 (Y) \"q1 q2 ... q63 q64\"" }, { - ARGS_NO_KEY, "q-matrix-c1", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "q-matrix-c1", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "custom quantization matrix for component 1 (Cb) \"q1 q2 ... q63 q64\"" }, { - ARGS_NO_KEY, "q-matrix-c2", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "q-matrix-c2", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "custom quantization matrix for component 2 (Cr) \"q1 q2 ... q63 q64\"" }, { - ARGS_NO_KEY, "q-matrix-c3", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "q-matrix-c3", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "custom quantization matrix for component 3 \"q1 q2 ... q63 q64\"" }, { - ARGS_NO_KEY, "color-primaries", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "color-primaries", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "ColourPrimaries value defined in ITU-T H.273\n" " - 1: bt709\n" " - 2: unspecified\n" @@ -218,7 +218,7 @@ static const args_opt_t enc_args_opts[] = { " and 'color-range' should all be set." }, { - ARGS_NO_KEY, "color-transfer", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "color-transfer", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "TransferCharacteristics value defined in ITU-T H.273\n" " - 1: bt709\n" " - 2: unspecified\n" @@ -243,7 +243,7 @@ static const args_opt_t enc_args_opts[] = { }, { - ARGS_NO_KEY, "color-matrix", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "color-matrix", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "MatrixCoefficients value defined in ITU-T H.273\n" " - 0: gbr\n" " - 1: bt709\n" @@ -264,7 +264,7 @@ static const args_opt_t enc_args_opts[] = { " and 'color-range' should all be set." }, { - ARGS_NO_KEY, "color-range", ARGS_VAL_TYPE_INTEGER, 0, NULL, + ARGS_NO_KEY, "color-range", ARGS_VAL_TYPE_INTEGER, 0, NULL, 0, "Color range\n" " - 0: limited color range ('tv' color range) \n" " - 1: full color range ('pc' color range)\n" @@ -273,18 +273,18 @@ static const args_opt_t enc_args_opts[] = { " and 'color-range' should all be set." }, { - ARGS_NO_KEY, "hash", ARGS_VAL_TYPE_NONE, 0, NULL, + ARGS_NO_KEY, "hash", ARGS_VAL_TYPE_NONE, 0, NULL, 0, "embed frame hash value for conformance checking in decoding" }, { - ARGS_NO_KEY, "master-display", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "master-display", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "mastering display color volume metadata" }, { - ARGS_NO_KEY, "max-cll", ARGS_VAL_TYPE_STRING, 0, NULL, + ARGS_NO_KEY, "max-cll", ARGS_VAL_TYPE_STRING, 0, NULL, 0, "content light level information metadata" }, - {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */ + {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, 0, ""} /* termination */ }; // clang-format on @@ -350,63 +350,63 @@ static args_var_t *args_init_vars(args_parser_t *args, oapve_param_t *param) vars->param = param; - /*args_set_variable_by_key_long(opts, "config", args->fname_cfg);*/ - args_set_variable_by_key_long(opts, "input", vars->fname_inp); - args_set_variable_by_key_long(opts, "output", vars->fname_out); - args_set_variable_by_key_long(opts, "recon", vars->fname_rec); - args_set_variable_by_key_long(opts, "max-au", &vars->max_au); - args_set_variable_by_key_long(opts, "hash", &vars->hash); - args_set_variable_by_key_long(opts, "verbose", &op_verbose); + /*args_set_variable_by_key_long(opts, "config", args->fname_cfg, 0);*/ + args_set_variable_by_key_long(opts, "input", vars->fname_inp, sizeof(vars->fname_inp)); + args_set_variable_by_key_long(opts, "output", vars->fname_out, sizeof(vars->fname_out)); + args_set_variable_by_key_long(opts, "recon", vars->fname_rec, sizeof(vars->fname_rec)); + args_set_variable_by_key_long(opts, "max-au", &vars->max_au, 0); + args_set_variable_by_key_long(opts, "hash", &vars->hash, 0); + args_set_variable_by_key_long(opts, "verbose", &op_verbose, 0); op_verbose = VERBOSE_SIMPLE; /* default */ - args_set_variable_by_key_long(opts, "input-depth", &vars->input_depth); + args_set_variable_by_key_long(opts, "input-depth", &vars->input_depth, 0); vars->input_depth = 10; /* default */ - args_set_variable_by_key_long(opts, "input-csp", &vars->input_csp); + args_set_variable_by_key_long(opts, "input-csp", &vars->input_csp, 0); vars->input_csp = -1; - args_set_variable_by_key_long(opts, "seek", &vars->seek); - args_set_variable_by_key_long(opts, "profile", vars->profile); + args_set_variable_by_key_long(opts, "seek", &vars->seek, 0); + args_set_variable_by_key_long(opts, "profile", vars->profile, sizeof(vars->profile)); strcpy(vars->profile, "422-10"); - args_set_variable_by_key_long(opts, "level", vars->level); + args_set_variable_by_key_long(opts, "level", vars->level, sizeof(vars->level)); strcpy(vars->level, "auto"); /* default */ - args_set_variable_by_key_long(opts, "band", vars->band); + args_set_variable_by_key_long(opts, "band", vars->band, sizeof(vars->band)); strcpy(vars->band, "auto"); /* 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); + args_set_variable_by_key_long(opts, "width", vars->width, sizeof(vars->width)); + args_set_variable_by_key_long(opts, "height", vars->height, sizeof(vars->height)); + args_set_variable_by_key_long(opts, "fps", vars->fps, sizeof(vars->fps)); - args_set_variable_by_key_long(opts, "qp", vars->qp); + args_set_variable_by_key_long(opts, "qp", vars->qp, sizeof(vars->qp)); strcpy(vars->qp, "auto"); /* default */ - 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, "qp_offset_c1", vars->qp_offset_c1, sizeof(vars->qp_offset_c1)); + args_set_variable_by_key_long(opts, "qp_offset_c2", vars->qp_offset_c2, sizeof(vars->qp_offset_c2)); + args_set_variable_by_key_long(opts, "qp_offset_c3", vars->qp_offset_c3, sizeof(vars->qp_offset_c3)); - args_set_variable_by_key_long(opts, "family", vars->family); - args_set_variable_by_key_long(opts, "bitrate", vars->bitrate); + args_set_variable_by_key_long(opts, "family", vars->family, sizeof(vars->family)); + args_set_variable_by_key_long(opts, "bitrate", vars->bitrate, sizeof(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, "q-matrix-c0", vars->q_matrix_c0, sizeof(vars->q_matrix_c0)); + args_set_variable_by_key_long(opts, "q-matrix-c1", vars->q_matrix_c1, sizeof(vars->q_matrix_c1)); + args_set_variable_by_key_long(opts, "q-matrix-c2", vars->q_matrix_c2, sizeof(vars->q_matrix_c2)); + args_set_variable_by_key_long(opts, "q-matrix-c3", vars->q_matrix_c3, sizeof(vars->q_matrix_c3)); - args_set_variable_by_key_long(opts, "threads", vars->threads); + args_set_variable_by_key_long(opts, "threads", vars->threads, sizeof(vars->threads)); strcpy(vars->threads, "auto"); - 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, "tile-w", vars->tile_w, sizeof(vars->tile_w)); + args_set_variable_by_key_long(opts, "tile-h", vars->tile_h, sizeof(vars->tile_h)); - args_set_variable_by_key_long(opts, "preset", vars->preset); + args_set_variable_by_key_long(opts, "preset", vars->preset, sizeof(vars->preset)); - args_set_variable_by_key_long(opts, "color-primaries", &vars->color_primaries); + args_set_variable_by_key_long(opts, "color-primaries", &vars->color_primaries, 0); vars->color_primaries = -1; /* unset */ - args_set_variable_by_key_long(opts, "color-transfer", &vars->color_transfer); + args_set_variable_by_key_long(opts, "color-transfer", &vars->color_transfer, 0); vars->color_transfer = -1; /* unset */ - args_set_variable_by_key_long(opts, "color-matrix", &vars->color_matrix); + args_set_variable_by_key_long(opts, "color-matrix", &vars->color_matrix, 0); vars->color_matrix = -1; /* unset */ - args_set_variable_by_key_long(opts, "color-range", &vars->color_range); + args_set_variable_by_key_long(opts, "color-range", &vars->color_range, 0); vars->color_range = -1; /* unset */ - args_set_variable_by_key_long(opts, "master-display", vars->master_display); - args_set_variable_by_key_long(opts, "max-cll", vars->max_cll); + args_set_variable_by_key_long(opts, "master-display", vars->master_display, sizeof(vars->master_display)); + args_set_variable_by_key_long(opts, "max-cll", vars->max_cll, sizeof(vars->max_cll)); return vars; } @@ -1017,7 +1017,14 @@ int main(int argc, const char **argv) cdesc.threads = OAPV_CDESC_THREADS_AUTO; } else { - cdesc.threads = atoi(args_var->threads); + char *endptr; + long threads_val = strtol(args_var->threads, &endptr, 10); + if(endptr == args_var->threads || threads_val <= 0 || threads_val > INT_MAX) { + logerr("ERR: invalid threads value: %s\n", args_var->threads); + ret = -1; + goto ERR; + } + cdesc.threads = (int)threads_val; } if(check_conf(&cdesc, args_var)) { diff --git a/src/oapv.c b/src/oapv.c index 18158313..b15ca9e7 100644 --- a/src/oapv.c +++ b/src/oapv.c @@ -1422,6 +1422,23 @@ static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_tile_info_t * part, oapv_imgb_ return OAPV_ERR_INVALID_ARGUMENT; } + // validate buffer capacity for each component + // calculate required buffer size based on frame header information + int aligned_w = oapv_align_value(ctx->fh.fi.frame_width, OAPV_MB_W); + int aligned_h = oapv_align_value(ctx->fh.fi.frame_height, OAPV_MB_H); + int byte_depth = (ctx->fh.fi.bit_depth + 7) / 8; // bytes per pixel + + for(int c = 0; c < imgb->np; c++) { + int comp_w = aligned_w >> (c > 0 ? get_chroma_sft_w(ctx->fh.fi.chroma_format_idc) : 0); + int comp_h = aligned_h >> (c > 0 ? get_chroma_sft_h(ctx->fh.fi.chroma_format_idc) : 0); + int required_stride = comp_w * byte_depth; + int required_bsize = required_stride * comp_h; + + if(imgb->bsize[c] < required_bsize) { + return OAPV_ERR_INVALID_ARGUMENT; + } + } + ctx->imgb = imgb; imgb_addref(ctx->imgb); // increase reference count diff --git a/src/oapv_param.c b/src/oapv_param.c index 7a164aac..ef43f00c 100644 --- a/src/oapv_param.c +++ b/src/oapv_param.c @@ -95,18 +95,46 @@ static int kbps_str_to_int(const char *str) char *s = (char *)str; if(strchr(s, 'K') || strchr(s, 'k')) { char *tmp = strtok(s, "Kk "); - kbps = (int)(atof(tmp)); + char *endptr; + float fval; + errno = 0; + fval = strtof(tmp, &endptr); + if(endptr == tmp || *endptr != '\0' || errno == ERANGE) { + return -1; + } + kbps = (int)fval; } else if(strchr(s, 'M') || strchr(s, 'm')) { char *tmp = strtok(s, "Mm "); - kbps = (int)(atof(tmp) * 1000); + char *endptr; + float fval; + errno = 0; + fval = strtof(tmp, &endptr); + if(endptr == tmp || *endptr != '\0' || errno == ERANGE) { + return -1; + } + kbps = (int)(fval * 1000); } else if(strchr(s, 'G') || strchr(s, 'g')) { char *tmp = strtok(s, "Gg "); - kbps = (int)(atof(tmp) * 1000000); + char *endptr; + float fval; + errno = 0; + fval = strtof(tmp, &endptr); + if(endptr == tmp || *endptr != '\0' || errno == ERANGE) { + return -1; + } + kbps = (int)(fval * 1000000); } else { - kbps = atoi(s); + char *endptr; + long val; + errno = 0; + val = strtol(s, &endptr, 10); + if(endptr == s || *endptr != '\0' || errno == ERANGE || val < INT_MIN || val > INT_MAX) { + return -1; + } + kbps = (int)val; } return kbps; } diff --git a/src/oapv_port.h b/src/oapv_port.h index a084bc1f..1cdd576c 100644 --- a/src/oapv_port.h +++ b/src/oapv_port.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include From 5da7690237ebbd47fa34c162f35e6596512af9b7 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Thu, 2 Jul 2026 18:13:54 +0900 Subject: [PATCH 28/31] fuzzing protection code Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_args.h | 15 +-------------- app/oapv_app_dec.c | 3 ++- src/oapv_param.c | 1 + 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/app/oapv_app_args.h b/app/oapv_app_args.h index 6ed72582..143207fb 100644 --- a/app/oapv_app_args.h +++ b/app/oapv_app_args.h @@ -68,7 +68,6 @@ struct args_parser { void (*release)(args_parser_t *args); int (*parse)(args_parser_t *args, int argc, const char *argv[], char **errstr); int (*get_help)(args_parser_t *args, int idx, char *help); - int (*get_str)(args_parser_t *args, char *keyl, char *str, int *flag); 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); @@ -140,7 +139,7 @@ static int args_read_value(args_opt_t *ops, const char *argv) strncpy((char *)ops->val, argv, ops->val_size - 1); ((char *)ops->val)[ops->val_size - 1] = '\0'; } else { - strcpy((char *)ops->val, argv); + return -1; /* STRING option without a known buffer size: reject */ } break; @@ -465,17 +464,6 @@ static int args_set_flag(args_parser_t *args, char *keyl, int flag) return -1; } -static int args_get_str(args_parser_t *args, char *keyl, char *str, int *flag) -{ - char *p = NULL; - if(args_get(args, keyl, (void **)&p, flag)) - return -1; - if(p) { - if(str) - strcpy(str, p); - } - return 0; -} static int args_get_int(args_parser_t *args, char *keyl, int *val, int *flag) { @@ -615,7 +603,6 @@ static args_parser_t *args_create(const args_opt_t *opt_table, int num_opt) args->release = args_release; args->parse = args_parse; args->get_help = args_get_help; - args->get_str = args_get_str; args->get_int = args_get_int; args->set_str = args_set_str; args->set_int = args_set_int; diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 33711ead..afa18fd1 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -34,7 +34,8 @@ #include "oapv_app_args.h" #include "oapv_app_y4m.h" -#define MAX_BS_BUF 128 * 1024 * 1024 /* byte */ +#define MAX_BS_BUF 128 * 1024 * 1024 /* byte */ +#define MAX_NUM_METADATA_PLDS 128 /* max number of metadata payloads per access unit */ // check generic frame or not #define IS_NON_AUX_FRM(frm) (((frm)->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) || ((frm)->pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME)) diff --git a/src/oapv_param.c b/src/oapv_param.c index ef43f00c..81b50221 100644 --- a/src/oapv_param.c +++ b/src/oapv_param.c @@ -290,6 +290,7 @@ int oapve_param_parse(oapve_param_t *param, const char *name, const char *value } NAME_CMP("bitrate") { if(strlen(value) > 0) { + if(strlen(value) + 1 > sizeof(str_buf)) return OAPV_ERR_INVALID_ARGUMENT; 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; From 0c654e867868fe9c7ba8ed343c8032feb502bc76 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Fri, 3 Jul 2026 11:01:17 +0900 Subject: [PATCH 29/31] changed to use the safe string parser Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_args.h | 58 +++++++++++++-------------------------------- app/oapv_app_dec.c | 2 +- app/oapv_app_enc.c | 2 +- app/oapv_app_util.h | 6 ++--- src/oapv_port.c | 6 ++--- 5 files changed, 24 insertions(+), 50 deletions(-) diff --git a/app/oapv_app_args.h b/app/oapv_app_args.h index 143207fb..d464e510 100644 --- a/app/oapv_app_args.h +++ b/app/oapv_app_args.h @@ -52,6 +52,12 @@ #define ARGS_MAX_NUM_CONF_FILES (16) #define ARGS_MAX_KEY_LONG (32) +#define ARGS_MAX_DESC (1024) /* max length of an option description */ +/* upper bound of the fixed prefix of a help line: key/key_long, value type, + * "(optional)", default value string and surrounding decoration */ +#define ARGS_HELP_PREFIX_MAX (512) +/* buffer size for a formatted help line: description plus its prefix */ +#define ARGS_HELP_BUF_SIZE (ARGS_MAX_DESC + ARGS_HELP_PREFIX_MAX) typedef struct args_opt { char key; /* option keyword. ex) -f */ @@ -60,7 +66,7 @@ typedef struct args_opt { int flag; /* flag to setting or not */ void *val; /* actual value */ int val_size; /* size of value buffer for STRING type (0 for non-STRING) */ - char desc[1024]; /* description of option */ + char desc[ARGS_MAX_DESC]; /* description of option */ } args_opt_t; typedef struct args_parser args_parser_t; @@ -149,43 +155,6 @@ static int args_read_value(args_opt_t *ops, const char *argv) return 0; } -static int args_get_arg(args_opt_t *ops, int idx, char *result) -{ - char vtype[32]; - char value[512]; - args_opt_t *o = ops + idx; - - switch(ARGS_GET_CMD_OPT_VAL_TYPE(o->val_type)) { - case ARGS_VAL_TYPE_INTEGER: - strncpy(vtype, "INTEGER", sizeof(vtype) - 1); - sprintf(value, "%d", *((int *)o->val)); - break; - - case ARGS_VAL_TYPE_STRING: - strncpy(vtype, "STRING", sizeof(vtype) - 1); - sprintf(value, "%s", (char *)o->val); - break; - - case ARGS_VAL_TYPE_NONE: - default: - strncpy(vtype, "FLAG", sizeof(vtype) - 1); - sprintf(value, "%d", *((int *)o->val)); - break; - } - - if(o->flag) { - strcat(value, " (SET)"); - } - else { - strcat(value, " (DEFAULT)"); - } - - sprintf(result, " -%c(--%s) = %s\n : %s", o->key, o->key_long, - value, o->desc); - - return 0; -} - static int args_parse_int_x_int(char *str, int *num0, int *num1) { char str0_t[64]; @@ -413,7 +382,12 @@ static int args_set_str(args_parser_t *args, char *keyl, char *str) idx = args_search_long_key(args->opts, keyl); if(idx >= 0) { - sprintf((char *)(args->opts[idx].val), "%s", str); + if(args->opts[idx].val_size > 0) { + snprintf((char *)(args->opts[idx].val), args->opts[idx].val_size, "%s", str); + } + else { + return -1; /* STRING option without a known buffer size: reject */ + } args->opts[idx].flag = 1; return 0; } @@ -535,7 +509,7 @@ static int args_get_help(args_parser_t *args, int idx, char *help) case ARGS_VAL_TYPE_STRING: strncpy(vtype, "STRING", sizeof(vtype) - 1); if(o->val != NULL) - sprintf(default_value, " [%s]", strlen((char *)(o->val)) == 0 ? "None" : (char *)(o->val)); + snprintf(default_value, sizeof(default_value), " [%s]", strlen((char *)(o->val)) == 0 ? "None" : (char *)(o->val)); break; case ARGS_VAL_TYPE_NONE: default: @@ -547,11 +521,11 @@ static int args_get_help(args_parser_t *args, int idx, char *help) optional = !(o->val_type & ARGS_VAL_TYPE_MANDATORY); if(o->key != ARGS_NO_KEY) { - sprintf(help, " -%c, --%s [%s]%s%s\n : %s", o->key, o->key_long, + snprintf(help, ARGS_HELP_BUF_SIZE, " -%c, --%s [%s]%s%s\n : %s", o->key, o->key_long, vtype, (optional) ? " (optional)" : "", (optional) ? default_value : "", o->desc); } else { - sprintf(help, " --%s [%s]%s%s\n : %s", o->key_long, + snprintf(help, ARGS_HELP_BUF_SIZE, " --%s [%s]%s%s\n : %s", o->key_long, vtype, (optional) ? " (optional)" : "", (optional) ? default_value : "", o->desc); } diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index afa18fd1..962af00f 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -163,7 +163,7 @@ static args_var_t *args_init_vars(args_parser_t *args) static void print_usage(const char **argv) { int i; - char str[1024]; + char str[ARGS_HELP_BUF_SIZE]; args_var_t *args_var = NULL; args_parser_t *args; diff --git a/app/oapv_app_enc.c b/app/oapv_app_enc.c index 7f3cf397..9ef77ef8 100644 --- a/app/oapv_app_enc.c +++ b/app/oapv_app_enc.c @@ -414,7 +414,7 @@ static args_var_t *args_init_vars(args_parser_t *args, oapve_param_t *param) static void print_usage(const char **argv) { int i; - char str[1024]; + char str[ARGS_HELP_BUF_SIZE]; args_parser_t *args; args_var_t *args_var = NULL; oapve_param_t default_param; diff --git a/app/oapv_app_util.h b/app/oapv_app_util.h index ad77c398..d2f905b2 100644 --- a/app/oapv_app_util.h +++ b/app/oapv_app_util.h @@ -59,10 +59,10 @@ static void log_msg(char *filename, int line, const char *fmt, ...) { char str[1024] = { '\0' }; if(filename != NULL && line >= 0) - sprintf(str, "[%s:%d] ", filename, line); + snprintf(str, sizeof(str), "[%s:%d] ", filename, line); va_list args; va_start(args, fmt); - vsprintf(str + strlen(str), fmt, args); + vsnprintf(str + strlen(str), sizeof(str) - strlen(str), fmt, args); va_end(args); printf("%s", str); } @@ -79,7 +79,7 @@ static void log_line(char *pre) len = (pre == NULL) ? 0 : (int)strlen(pre); if(len > 0) { - sprintf(str + 3, " %s ", pre); + snprintf(str + 3, sizeof(str) - 3, " %s ", pre); len = (int)strlen(str); } diff --git a/src/oapv_port.c b/src/oapv_port.c index 24d60f0f..ed9c2de4 100644 --- a/src/oapv_port.c +++ b/src/oapv_port.c @@ -63,11 +63,11 @@ void oapv_trace0(char *filename, int line, const char *fmt, ...) char str[1024] = { '\0' }; if(filename != NULL && line >= 0) { - sprintf(str, "[%s:%d] ", filename, line); + snprintf(str, sizeof(str), "[%s:%d] ", filename, line); } va_list args; va_start(args, fmt); - vsprintf(str + strlen(str), fmt, args); + vsnprintf(str + strlen(str), sizeof(str) - strlen(str), fmt, args); va_end(args); printf("%s", str); } @@ -79,7 +79,7 @@ void oapv_trace_line(char *pre) int len = (pre == NULL) ? 0 : (int)strlen(pre); if(len > 0) { - sprintf(str, "%s ", pre); + snprintf(str, sizeof(str), "%s ", pre); len = (int)strlen(str); } for(int i = len; i < chars; i++) { From 89838e3e01364727e74906c9d959f73a248c4040 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 6 Jul 2026 09:31:21 +0900 Subject: [PATCH 30/31] add error handling code Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_util.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/oapv_app_util.h b/app/oapv_app_util.h index d2f905b2..9e190579 100644 --- a/app/oapv_app_util.h +++ b/app/oapv_app_util.h @@ -54,6 +54,10 @@ #define VERBOSE_SIMPLE 2 #define VERBOSE_FRAME 3 +/* max image resolution supported by imgb (32K: 2x of 8192x4320) */ +#define IMGB_MAX_W 16384 +#define IMGB_MAX_H 8640 + /* logging functions */ static void log_msg(char *filename, int line, const char *fmt, ...) { @@ -316,6 +320,12 @@ oapv_imgb_t *imgb_create(int w, int h, int cs) bd = OAPV_CS_GET_BYTE_DEPTH(cs); /* byte unit */ + /* reject invalid or out-of-range resolution */ + if(w <= 0 || h <= 0 || w > IMGB_MAX_W || h > IMGB_MAX_H || bd <= 0) { + logerr("invalid image parameter (w=%d, h=%d, byte-depth=%d)\n", w, h, bd); + goto ERR; + } + imgb->w[0] = w; imgb->h[0] = h; switch(OAPV_CS_GET_FORMAT(cs)) { From 34008089afac8d31d0b5e1651f558aaaea0ca888 Mon Sep 17 00:00:00 2001 From: "kp5.choi@samsung.com" Date: Mon, 6 Jul 2026 10:35:00 +0900 Subject: [PATCH 31/31] changed to predefined value MAX_NUM_METADATA_PLDS Signed-off-by: kp5.choi@samsung.com --- app/oapv_app_dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/oapv_app_dec.c b/app/oapv_app_dec.c index 962af00f..2a409044 100644 --- a/app/oapv_app_dec.c +++ b/app/oapv_app_dec.c @@ -599,8 +599,8 @@ int dec_api_set_0(args_var_t *args_var, FILE *fp_bs, int is_y4m) } /* validate number of metadata payloads */ - if(num_plds < 0 || num_plds > 128) { - logerr("ERR: invalid number of metadata payloads (%d), valid range is 0-128\n", num_plds); + if(num_plds < 0 || num_plds > MAX_NUM_METADATA_PLDS) { + logerr("ERR: invalid number of metadata payloads (%d), valid range is 0-%d\n", num_plds, MAX_NUM_METADATA_PLDS); goto END; }