Skip to content

Commit 7cd4e86

Browse files
committed
Merge branch 'cross_comp_pred_444' into 444-format-revive
2 parents 0ad4300 + a6a5c90 commit 7cd4e86

19 files changed

+812
-87
lines changed

.gitlab-ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ test-10bit:
6363
<<: *test-template
6464
variables:
6565
CFLAGS: '-DKVZ_BIT_DEPTH=10'
66+
67+
test-12bit:
68+
<<: *test-template
69+
variables:
70+
CFLAGS: '-DKVZ_BIT_DEPTH=12'

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Input:
7777
- progressive: Progressive scan
7878
- tff: Top field first
7979
- bff: Bottom field first
80-
--input-format <string> : P420 or P400 [P420]
80+
--input-format <string> : P420, P444 or P400 [P420]
8181
--input-bitdepth <int> : 8-16 [8]
8282
--loop-input : Re-read input file forever.
8383
--input-file-format <string> : Input file format [auto]
@@ -293,6 +293,7 @@ Compression tools:
293293
--(no-)implicit-rdpcm : Implicit residual DPCM. Currently only supported
294294
with lossless coding. [disabled]
295295
--(no-)tmvp : Temporal motion vector prediction [enabled]
296+
--(no-)cross-comp-pred : Cross-component prediction for 4:4:4 [disabled]
296297
297298
Parallel processing:
298299
--threads <integer> : Number of threads to use [auto]

doc/kvazaar.1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Source scan type [progressive]
4444
\- bff: Bottom field first
4545
.TP
4646
\fB\-\-input\-format <string>
47-
P420 or P400 [P420]
47+
P420, P444 or P400 [P420]
4848
.TP
4949
\fB\-\-input\-bitdepth <int>
5050
8\-16 [8]
@@ -403,6 +403,9 @@ with lossless coding. [disabled]
403403
.TP
404404
\fB\-\-(no\-)tmvp
405405
Temporal motion vector prediction [enabled]
406+
.TP
407+
\fB\-\-(no\-)cross\-comp\-pred
408+
Cross\-component prediction for 4:4:4 [disabled]
406409

407410
.SS "Parallel processing:"
408411
.TP

src/cabac.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ typedef struct
9797
cabac_ctx_t cu_qt_root_cbf_model;
9898
cabac_ctx_t transform_skip_model_luma;
9999
cabac_ctx_t transform_skip_model_chroma;
100+
cabac_ctx_t cross_component_prediction[10];
100101
} ctx;
101102
} cabac_data_t;
102103

src/cfg.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ int kvz_config_init(kvz_config *cfg)
197197
cfg->chroma_shift = cfg->chroma_shift_w = 1;
198198
cfg->chroma_shift_h = 1;
199199

200+
cfg->enable_cross_component_prediction = 0;
201+
200202
return 1;
201203
}
202204

@@ -1442,6 +1444,9 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value)
14421444
else if OPT("enable-logging") {
14431445
cfg->enable_logging_output = atobool(value);
14441446
}
1447+
else if OPT("cross-comp-pred") {
1448+
cfg->enable_cross_component_prediction = atobool(value);
1449+
}
14451450
else {
14461451
return 0;
14471452
}
@@ -1785,6 +1790,16 @@ int kvz_config_validate(const kvz_config *const cfg)
17851790
error = 1;
17861791
}
17871792

1793+
if (cfg->enable_cross_component_prediction && cfg->chroma_format != KVZ_CSP_444) {
1794+
fprintf(stderr, "Cross-component prediction is only supported in 4:4:4 chroma format.\n");
1795+
error = 1;
1796+
}
1797+
1798+
if (cfg->chroma_format == KVZ_CSP_422) {
1799+
fprintf(stderr, "4:2:2 chroma format is not supported yet.\n");
1800+
error = 1;
1801+
}
1802+
17881803
return !error;
17891804
}
17901805

src/cli.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ static const struct option long_options[] = {
178178
{ "no-fast-bipred", no_argument, NULL, 0 },
179179
{ "enable-logging", no_argument, NULL, 0 },
180180
{ "no-enable-logging", no_argument, NULL, 0 },
181+
{ "cross-comp-pred", no_argument, NULL, 0 },
182+
{ "no-cross-comp-pred", no_argument, NULL, 0 },
181183
{0, 0, 0, 0}
182184
};
183185

@@ -653,6 +655,7 @@ void print_help(void)
653655
" --(no-)implicit-rdpcm : Implicit residual DPCM. Currently only supported\n"
654656
" with lossless coding. [disabled]\n"
655657
" --(no-)tmvp : Temporal motion vector prediction [enabled]\n"
658+
" --(no-)cross-comp-pred : Cross-component prediction for 4:4:4 [disabled]\n"
656659
"\n"
657660
/* Word wrap to this width to stay under 80 characters (including ") *************/
658661
"Parallel processing:\n"

src/context.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,12 @@ static const uint8_t INIT_TRANSFORMSKIP_FLAG[3][2] =
193193
{ 139, 139},
194194
};
195195

196-
196+
static const uint8_t INIT_CROSS_COMPONENT_PREDICTION[3][10] =
197+
{
198+
{ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154 },
199+
{ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154 },
200+
{ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154 },
201+
};
197202

198203

199204
/**
@@ -285,6 +290,12 @@ void kvz_init_contexts(encoder_state_t *state, int8_t QP, int8_t slice)
285290
kvz_ctx_init(&cabac->ctx.cu_one_model_chroma[i], QP, INIT_ONE_FLAG[slice][i+16]);
286291
}
287292

293+
if (state->encoder_control->cfg.chroma_format == KVZ_CSP_444) {
294+
for (i = 0; i < 10; i++) {
295+
kvz_ctx_init(&cabac->ctx.cross_component_prediction[i], QP, INIT_CROSS_COMPONENT_PREDICTION[slice][i]);
296+
}
297+
}
298+
288299
for (i = 0; i < 15; i++) {
289300
kvz_ctx_init(&cabac->ctx.cu_ctx_last_y_luma[i], QP, INIT_LAST[slice][i] );
290301
kvz_ctx_init(&cabac->ctx.cu_ctx_last_x_luma[i], QP, INIT_LAST[slice][i] );

src/cu.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,18 @@ typedef struct {
128128
*/
129129
typedef struct
130130
{
131-
uint8_t type : 2; //!< \brief block type, one of cu_type_t values
132-
uint8_t depth : 3; //!< \brief depth / size of this block
133-
uint8_t part_size : 3; //!< \brief partition mode, one of part_mode_t values
134-
uint8_t tr_depth : 3; //!< \brief transform depth
135-
uint8_t skipped : 1; //!< \brief flag to indicate this block is skipped
136-
uint8_t merged : 1; //!< \brief flag to indicate this block is merged
137-
uint8_t merge_idx : 3; //!< \brief merge index
138-
uint8_t tr_skip : 1; //!< \brief transform skip flag
131+
uint8_t type : 2; //!< \brief block type, one of cu_type_t values
132+
uint8_t depth : 3; //!< \brief depth / size of this block
133+
uint8_t part_size : 3; //!< \brief partition mode, one of part_mode_t values
134+
uint8_t tr_depth : 3; //!< \brief transform depth
135+
uint8_t skipped : 1; //!< \brief flag to indicate this block is skipped
136+
uint8_t merged : 1; //!< \brief flag to indicate this block is merged
137+
uint8_t merge_idx : 3; //!< \brief merge index
138+
uint8_t tr_skip : 1; //!< \brief transform skip flag
139+
uint8_t alpha_u_s : 1; // !< \brief cross-component prediction sign flag for U channel
140+
uint8_t alpha_v_s : 1; // !< \brief cross-component prediction sign flag for V channel
141+
uint8_t alpha_u : 3; // !< \brief cross-component prediction value for U channel
142+
uint8_t alpha_v : 3; // !< \brief cross-component prediction value for V channel
139143

140144
uint16_t cbf;
141145

src/encode_coding_tree.c

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,30 @@
4747
#include "tables.h"
4848
#include "videoframe.h"
4949

50+
/*
51+
* \brief Encode cross component prediction for U or V channel
52+
*/
53+
static void encode_cross_component_prediction(const cu_info_t* cur_pu, cabac_data_t* const cabac, color_t channel)
54+
{
55+
cabac_ctx_t* ctx = &(cabac->ctx.cross_component_prediction[channel == COLOR_V ? 5 : 0]);
56+
cabac->cur_ctx = ctx;
57+
int8_t alpha = (channel == COLOR_V ? cur_pu->alpha_v : cur_pu->alpha_u);
58+
int8_t alpha_sign = (channel == COLOR_V ? cur_pu->alpha_v_s : cur_pu->alpha_u_s);
59+
60+
CABAC_BIN(cabac, (alpha != 0)? 1: 0, "cross_component_prediction_flag");
61+
62+
if(alpha != 0) {
63+
alpha--;
64+
cabac->cur_ctx = &ctx[1];
65+
CABAC_BIN(cabac, (alpha > 0)? 1: 0, "cross_component_prediction_alpha");
66+
if(alpha > 0) {
67+
kvz_cabac_write_unary_max_symbol(cabac, &ctx[2], alpha - 1, 1, 2, NULL);
68+
}
69+
cabac->cur_ctx = &ctx[4];
70+
CABAC_BIN(cabac, alpha_sign, "cross_component_prediction_sign");
71+
}
72+
}
73+
5074
/**
5175
* \brief Encode (X,Y) position of the last significant coefficient
5276
*
@@ -163,24 +187,33 @@ static void encode_transform_unit(encoder_state_t * const state,
163187
}
164188
}
165189

166-
bool chroma_cbf_set = cbf_is_set(cur_pu->cbf, depth, COLOR_U) ||
167-
cbf_is_set(cur_pu->cbf, depth, COLOR_V);
168-
if (chroma_cbf_set) {
190+
if (state->encoder_control->cfg.chroma_format != KVZ_CSP_400) {
169191
int x_local = (x >> SHIFT_W) % (LCU_WIDTH >> SHIFT_W);
170192
int y_local = (y >> SHIFT_H) % (LCU_WIDTH >> SHIFT_H);
171193
scan_idx = kvz_get_scan_order(cur_pu->type, cur_pu->intra.mode_chroma, depth);
172194

173-
const coeff_t *coeff_u = &state->coeff->u[xy_to_zorder(LCU_WIDTH >> SHIFT_W, x_local, y_local)];
174-
const coeff_t *coeff_v = &state->coeff->v[xy_to_zorder(LCU_WIDTH >> SHIFT_W, x_local, y_local)];
195+
bool cross_component_prediction = cbf_y && state->encoder_control->cfg.enable_cross_component_prediction &&
196+
(cur_pu->type == CU_INTER || cur_pu->intra.mode_chroma == cur_pu->intra.mode);
197+
198+
if (cross_component_prediction) {
199+
encode_cross_component_prediction(cur_pu, &state->cabac, COLOR_U);
200+
}
175201

176202
if (cbf_is_set(cur_pu->cbf, depth, COLOR_U)) {
203+
const coeff_t* coeff_u = &state->coeff->u[xy_to_zorder(LCU_WIDTH >> SHIFT_W, x_local, y_local)];
177204
kvz_encode_coeff_nxn(state, &state->cabac, coeff_u, width_c, 2, scan_idx, 0, NULL);
178205
}
179206

207+
if (cross_component_prediction) {
208+
encode_cross_component_prediction(cur_pu, &state->cabac, COLOR_V);
209+
}
210+
180211
if (cbf_is_set(cur_pu->cbf, depth, COLOR_V)) {
212+
const coeff_t* coeff_v = &state->coeff->v[xy_to_zorder(LCU_WIDTH >> SHIFT_W, x_local, y_local)];
181213
kvz_encode_coeff_nxn(state, &state->cabac, coeff_v, width_c, 2, scan_idx, 0, NULL);
182214
}
183215
}
216+
184217
}
185218

186219
/**

src/encoder_state-bitstream.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,16 @@ static void encoder_state_write_bitstream_PTL(bitstream_t *stream,
7676
WRITE_U(stream, 0, 2, "general_profile_space");
7777
WRITE_U(stream, state->encoder_control->cfg.high_tier, 1, "general_tier_flag");
7878
// Main Profile == 1, Main 10 profile == 2
79-
WRITE_U(stream, (state->encoder_control->bitdepth == 8) ? 1 : 2, 5, "general_profile_idc");
79+
int8_t profile = 1;
80+
if (state->encoder_control->cfg.chroma_format == KVZ_CSP_444 || state->encoder_control->cfg.chroma_format == KVZ_CSP_422 ||
81+
state->encoder_control->bitdepth > 10) {
82+
profile = 4; // 4:2:2 and 4:4:4 range extension profiles
83+
} else if (state->encoder_control->bitdepth == 10) {
84+
profile = 2; // Main 10 profile
85+
} else {
86+
profile = 1; // Main profile
87+
}
88+
WRITE_U(stream, profile, 5, "general_profile_idc");
8089
/* Compatibility flags should be set at general_profile_idc
8190
* (so with general_profile_idc = 1, compatibility_flag[1] should be 1)
8291
* According to specification, when compatibility_flag[1] is set,
@@ -358,6 +367,36 @@ static void encoder_state_write_bitstream_SPS_extension(bitstream_t *stream,
358367
}
359368
}
360369

370+
static void encoder_state_write_bitstream_PPS_extension(bitstream_t* stream,
371+
encoder_state_t* const state)
372+
{
373+
const kvz_config* cfg = &state->encoder_control->cfg;
374+
bool need_pps_extension = cfg->enable_cross_component_prediction;
375+
WRITE_U(stream, need_pps_extension, 1, "pps_extension_present_flag");
376+
if (need_pps_extension) {
377+
WRITE_U(stream, 1, 1, "pps_range_extension_flag");
378+
WRITE_U(stream, 0, 1, "pps_multilayer_extension_flag");
379+
WRITE_U(stream, 0, 1, "pps_3d_extension_flag");
380+
WRITE_U(stream, 0, 1, "pps_scc_extension_flag");
381+
WRITE_U(stream, 0, 4, "pps_extension_4bits");
382+
383+
// pps_range_extension_flag
384+
if(cfg->trskip_enable) WRITE_UE(stream, 0, "log2_max_transform_skip_block_size_minus2");
385+
WRITE_U(stream, cfg->enable_cross_component_prediction, 1, "cross_component_prediction_enabled_flag");
386+
WRITE_U(stream, 0, 1, "chroma_qp_offset_list_enabled_flag");
387+
//IF chroma_qp_offset_list_enabled_flag
388+
//WRITE_UE(stream, 0, "diff_cu_chroma_qp_offset_depth");
389+
//WRITE_UE(stream, 0, "chroma_qp_offset_list_len_minus1");
390+
//for (i = 0; i <= chroma_qp_offset_list_len_minus1; i++)
391+
//WRITE_SE(stream, 0, "cb_qp_offset_list[i]");
392+
//WRITE_SE(stream, 0, "cr_qp_offset_list[i]");
393+
//end for
394+
//ENDIF
395+
WRITE_UE(stream, 0, "log2_sao_offset_scale_luma");
396+
WRITE_UE(stream, 0, "log2_sao_offset_scale_chroma");
397+
}
398+
}
399+
361400
static void encoder_state_write_bitstream_seq_parameter_set(bitstream_t* stream,
362401
encoder_state_t * const state)
363402
{
@@ -569,7 +608,8 @@ static void encoder_state_write_bitstream_pic_parameter_set(bitstream_t* stream,
569608
WRITE_U(stream, 0, 1, "lists_modification_present_flag");
570609
WRITE_UE(stream, 0, "log2_parallel_merge_level_minus2");
571610
WRITE_U(stream, 0, 1, "slice_segment_header_extension_present_flag");
572-
WRITE_U(stream, 0, 1, "pps_extension_flag");
611+
612+
encoder_state_write_bitstream_PPS_extension(stream, state);
573613

574614
kvz_bitstream_add_rbsp_trailing_bits(stream);
575615
}

0 commit comments

Comments
 (0)