You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-04 22:03:09 +02:00
avcodec/vvc/ctu: add palette support
Signed-off-by: Wu Jianhua <toqsxw@outlook.com>
This commit is contained in:
@ -25,6 +25,7 @@
|
|||||||
#include "cabac.h"
|
#include "cabac.h"
|
||||||
#include "ctu.h"
|
#include "ctu.h"
|
||||||
#include "inter.h"
|
#include "inter.h"
|
||||||
|
#include "intra.h"
|
||||||
#include "mvs.h"
|
#include "mvs.h"
|
||||||
|
|
||||||
#define PROF_TEMP_SIZE (PROF_BLOCK_SIZE) * sizeof(int16_t)
|
#define PROF_TEMP_SIZE (PROF_BLOCK_SIZE) * sizeof(int16_t)
|
||||||
@ -1046,13 +1047,15 @@ static PredMode pred_mode_decode(VVCLocalContext *lc,
|
|||||||
const H266RawSliceHeader *rsh = lc->sc->sh.r;
|
const H266RawSliceHeader *rsh = lc->sc->sh.r;
|
||||||
const int ch_type = tree_type == DUAL_TREE_CHROMA ? 1 : 0;
|
const int ch_type = tree_type == DUAL_TREE_CHROMA ? 1 : 0;
|
||||||
const int is_4x4 = cu->cb_width == 4 && cu->cb_height == 4;
|
const int is_4x4 = cu->cb_width == 4 && cu->cb_height == 4;
|
||||||
|
const int is_128 = cu->cb_width == 128 || cu->cb_height == 128;
|
||||||
|
const int hs = sps->hshift[CHROMA];
|
||||||
|
const int vs = sps->vshift[CHROMA];
|
||||||
int pred_mode_flag;
|
int pred_mode_flag;
|
||||||
int pred_mode_ibc_flag;
|
int pred_mode_ibc_flag;
|
||||||
PredMode pred_mode;
|
PredMode pred_mode;
|
||||||
|
|
||||||
cu->skip_flag = 0;
|
cu->skip_flag = 0;
|
||||||
if (!IS_I(rsh) || sps->r->sps_ibc_enabled_flag) {
|
if (!IS_I(rsh) || sps->r->sps_ibc_enabled_flag) {
|
||||||
const int is_128 = cu->cb_width == 128 || cu->cb_height == 128;
|
|
||||||
if (tree_type != DUAL_TREE_CHROMA &&
|
if (tree_type != DUAL_TREE_CHROMA &&
|
||||||
((!is_4x4 && mode_type != MODE_TYPE_INTRA) ||
|
((!is_4x4 && mode_type != MODE_TYPE_INTRA) ||
|
||||||
(sps->r->sps_ibc_enabled_flag && !is_128))) {
|
(sps->r->sps_ibc_enabled_flag && !is_128))) {
|
||||||
@ -1087,6 +1090,14 @@ static PredMode pred_mode_decode(VVCLocalContext *lc,
|
|||||||
pred_mode = MODE_INTRA;
|
pred_mode = MODE_INTRA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pred_mode == MODE_INTRA && sps->r->sps_palette_enabled_flag && !is_128 && !cu->skip_flag &&
|
||||||
|
mode_type != MODE_TYPE_INTER && ((cu->cb_width * cu->cb_height) >
|
||||||
|
(tree_type != DUAL_TREE_CHROMA ? 16 : (16 << hs << vs))) &&
|
||||||
|
(mode_type != MODE_TYPE_INTRA || tree_type != DUAL_TREE_CHROMA)) {
|
||||||
|
if (ff_vvc_pred_mode_plt_flag(lc))
|
||||||
|
pred_mode = MODE_PLT;
|
||||||
|
}
|
||||||
|
|
||||||
set_cb_tab(lc, fc->tab.cpm[cu->ch_type], pred_mode);
|
set_cb_tab(lc, fc->tab.cpm[cu->ch_type], pred_mode);
|
||||||
if (tree_type == SINGLE_TREE)
|
if (tree_type == SINGLE_TREE)
|
||||||
set_cb_tab(lc, fc->tab.cpm[CHROMA], pred_mode);
|
set_cb_tab(lc, fc->tab.cpm[CHROMA], pred_mode);
|
||||||
@ -1755,8 +1766,8 @@ static void fill_dmvr_info(const VVCLocalContext *lc)
|
|||||||
const VVCFrameContext *fc = lc->fc;
|
const VVCFrameContext *fc = lc->fc;
|
||||||
const CodingUnit *cu = lc->cu;
|
const CodingUnit *cu = lc->cu;
|
||||||
|
|
||||||
if (cu->pred_mode == MODE_IBC) {
|
if (cu->pred_mode == MODE_IBC || cu->pred_mode == MODE_PLT) {
|
||||||
ff_vvc_set_intra_mvf(lc, true, PF_IBC, false);
|
ff_vvc_set_intra_mvf(lc, true, cu->pred_mode == MODE_IBC ? PF_IBC : PF_PLT, false);
|
||||||
} else {
|
} else {
|
||||||
const VVCPPS *pps = fc->ps.pps;
|
const VVCPPS *pps = fc->ps.pps;
|
||||||
const int w = cu->cb_width >> MIN_PU_LOG2;
|
const int w = cu->cb_width >> MIN_PU_LOG2;
|
||||||
@ -1805,9 +1816,291 @@ static int inter_data(VVCLocalContext *lc)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TransformUnit* palette_add_tu(VVCLocalContext *lc, const int start, const int end, const VVCTreeType tree_type)
|
||||||
|
{
|
||||||
|
CodingUnit *cu = lc->cu;
|
||||||
|
const VVCSPS *sps = lc->fc->ps.sps;
|
||||||
|
TransformUnit *tu = add_tu(lc->fc, cu, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
|
||||||
|
|
||||||
|
if (!tu)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (int c = start; c < end; c++) {
|
||||||
|
const int w = tu->width >> sps->hshift[c];
|
||||||
|
const int h = tu->height >> sps->vshift[c];
|
||||||
|
TransformBlock *tb = add_tb(tu, lc, tu->x0, tu->y0, w, h, c);
|
||||||
|
if (c != CR)
|
||||||
|
set_tb_size(lc->fc, tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < FF_ARRAY_ELEMS(cu->plt); i++)
|
||||||
|
cu->plt[i].size = 0;
|
||||||
|
|
||||||
|
return tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void palette_predicted(VVCLocalContext *lc, const bool local_dual_tree, int start, int end,
|
||||||
|
bool *predictor_reused, const int predictor_size, const int max_entries)
|
||||||
|
{
|
||||||
|
CodingUnit *cu = lc->cu;
|
||||||
|
int nb_predicted = 0;
|
||||||
|
|
||||||
|
if (local_dual_tree) {
|
||||||
|
start = LUMA;
|
||||||
|
end = VVC_MAX_SAMPLE_ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < predictor_size && nb_predicted < max_entries; i++) {
|
||||||
|
const int run = ff_vvc_palette_predictor_run(lc);
|
||||||
|
if (run == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (run > 1)
|
||||||
|
i += run - 1;
|
||||||
|
predictor_reused[i] = true;
|
||||||
|
for (int c = start; c < end; c++)
|
||||||
|
cu->plt[c].entries[nb_predicted] = lc->ep->pp[c].entries[i];
|
||||||
|
nb_predicted++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int c = start; c < end; c++)
|
||||||
|
cu->plt[c].size = nb_predicted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void palette_signaled(VVCLocalContext *lc, const bool local_dual_tree,
|
||||||
|
const int start, const int end, const int max_entries)
|
||||||
|
{
|
||||||
|
const VVCSPS *sps = lc->fc->ps.sps;
|
||||||
|
CodingUnit *cu = lc->cu;
|
||||||
|
const int nb_predicted = cu->plt[start].size;
|
||||||
|
const int nb_signaled = nb_predicted < max_entries ? ff_vvc_num_signalled_palette_entries(lc) : 0;
|
||||||
|
const int size = nb_predicted + nb_signaled;
|
||||||
|
const bool dual_tree_luma = local_dual_tree && cu->tree_type == DUAL_TREE_LUMA;
|
||||||
|
|
||||||
|
for (int c = start; c < end; c++) {
|
||||||
|
Palette *plt = cu->plt + c;
|
||||||
|
for (int i = nb_predicted; i < size; i++) {
|
||||||
|
plt->entries[i] = ff_vvc_new_palette_entries(lc, sps->bit_depth);
|
||||||
|
if (dual_tree_luma) {
|
||||||
|
plt[CB].entries[i] = 1 << (sps->bit_depth - 1);
|
||||||
|
plt[CR].entries[i] = 1 << (sps->bit_depth - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plt->size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void palette_update_predictor(VVCLocalContext *lc, const bool local_dual_tree, int start, int end,
|
||||||
|
bool *predictor_reused, const int predictor_size)
|
||||||
|
{
|
||||||
|
CodingUnit *cu = lc->cu;
|
||||||
|
const int max_predictor = VVC_MAX_NUM_PALETTE_PREDICTOR_SIZE >> (cu->tree_type != SINGLE_TREE && !local_dual_tree);
|
||||||
|
|
||||||
|
if (local_dual_tree) {
|
||||||
|
start = LUMA;
|
||||||
|
end = VVC_MAX_SAMPLE_ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int c = start; c < end; c++) {
|
||||||
|
Palette *pp = lc->ep->pp + c;
|
||||||
|
Palette *plt = cu->plt + c;
|
||||||
|
int i = cu->plt[start].size;;
|
||||||
|
|
||||||
|
// copy unused predictors to the end of plt
|
||||||
|
for (int j = 0; j < predictor_size && i < max_predictor; j++) {
|
||||||
|
if (!predictor_reused[j]) {
|
||||||
|
plt->entries[i] = pp->entries[j];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pp->entries, plt->entries, i * sizeof(pp->entries[0]));
|
||||||
|
pp->size = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void palette_qp(VVCLocalContext *lc, VVCTreeType tree_type, const bool escape_present)
|
||||||
|
{
|
||||||
|
const VVCFrameContext *fc = lc->fc;
|
||||||
|
const VVCPPS *pps = fc->ps.pps;
|
||||||
|
const H266RawSliceHeader *rsh = lc->sc->sh.r;
|
||||||
|
const CodingUnit *cu = lc->cu;
|
||||||
|
|
||||||
|
if (tree_type != DUAL_TREE_CHROMA) {
|
||||||
|
const bool has_qp_delta = escape_present &&
|
||||||
|
pps->r->pps_cu_qp_delta_enabled_flag && !lc->parse.is_cu_qp_delta_coded;
|
||||||
|
set_qp_y(lc, cu->x0, cu->y0, has_qp_delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tree_type != DUAL_TREE_LUMA) {
|
||||||
|
if (rsh->sh_cu_chroma_qp_offset_enabled_flag && !lc->parse.is_cu_chroma_qp_offset_coded)
|
||||||
|
chroma_qp_offset_decode(lc, 0, 1);
|
||||||
|
set_qp_c(lc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PALETTE_SET_PIXEL(xc, yc, pix) \
|
||||||
|
do { \
|
||||||
|
const int off = ((xc) >> hs) + ((yc) >> vs) * tb->tb_width; \
|
||||||
|
if (sps->bit_depth == 8) \
|
||||||
|
u8[off] = pix; \
|
||||||
|
else \
|
||||||
|
u16[off] = pix; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define PALETTE_INDEX(x, y) index[(y) * cu->cb_width + (x)]
|
||||||
|
|
||||||
|
// 6.5.3 Horizontal and vertical traverse scan order array initialization process
|
||||||
|
// The hTravScan and vTravScan tables require approximately 576 KB of memory.
|
||||||
|
// To save space, we use a macro to achieve the same functionality.
|
||||||
|
#define TRAV_COL(p, wlog, mask) ((p & mask) ^ (-((p >> wlog) & 1) & mask))
|
||||||
|
#define TRAV_ROW(p, hlog) (p >> hlog)
|
||||||
|
#define TRAV(trans, p, wlog, hlog, mask) (trans ? TRAV_ROW((p), hlog) : TRAV_COL((p), wlog, mask))
|
||||||
|
#define TRAV_X(pos) TRAV(transpose, pos, wlog2, hlog2, wmask)
|
||||||
|
#define TRAV_Y(pos) TRAV(!transpose, pos, hlog2, wlog2, hmask)
|
||||||
|
|
||||||
|
static int palette_subblock_data(VVCLocalContext *lc,
|
||||||
|
const int max_index, const int subset_id, const bool transpose,
|
||||||
|
uint8_t *run_type, uint8_t *index, int *prev_run_pos, bool *adjust)
|
||||||
|
{
|
||||||
|
const CodingUnit *cu = lc->cu;
|
||||||
|
TransformUnit *tu = cu->tus.head;
|
||||||
|
const VVCSPS *sps = lc->fc->ps.sps;
|
||||||
|
const int min_pos = subset_id << 4;
|
||||||
|
const int max_pos = FFMIN(min_pos + 16, cu->cb_width * cu->cb_height);
|
||||||
|
const int wmask = cu->cb_width - 1;
|
||||||
|
const int hmask = cu->cb_height - 1;
|
||||||
|
const int wlog2 = av_log2(cu->cb_width);
|
||||||
|
const int hlog2 = av_log2(cu->cb_height);
|
||||||
|
const uint8_t esc = cu->plt[tu->tbs[0].c_idx].size;
|
||||||
|
uint8_t run_copy[16] = { 0 };
|
||||||
|
|
||||||
|
for (int i = min_pos; i < max_pos; i++) {
|
||||||
|
const int xc = TRAV_X(i);
|
||||||
|
const int yc = TRAV_Y(i);
|
||||||
|
|
||||||
|
if (i > 0 && max_index > 0)
|
||||||
|
run_copy[i - min_pos] = ff_vvc_run_copy_flag(lc, run_type[i - 1], *prev_run_pos, i);
|
||||||
|
|
||||||
|
run_type[i] = 0;
|
||||||
|
if (max_index > 0 && !run_copy[i - min_pos]) {
|
||||||
|
if (((!transpose && yc > 0) || (transpose && xc > 0))
|
||||||
|
&& i > 0 && !run_type[i - 1]) {
|
||||||
|
run_type[i] = ff_vvc_copy_above_palette_indices_flag(lc);
|
||||||
|
}
|
||||||
|
*prev_run_pos = i;
|
||||||
|
} else if (i > 0) {
|
||||||
|
run_type[i] = run_type[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = min_pos; i < max_pos; i++) {
|
||||||
|
const int xc = TRAV_X(i);
|
||||||
|
const int yc = TRAV_Y(i);
|
||||||
|
const int prev_xc = i > 0 ? TRAV_X(i - 1) : 0;
|
||||||
|
const int prev_yc = i > 0 ? TRAV_Y(i - 1) : 0;
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
if (max_index > 0 && !run_copy[i - min_pos] && !run_type[i]) {
|
||||||
|
if (max_index - *adjust > 0)
|
||||||
|
idx = ff_vvc_palette_idx_idc(lc, max_index, *adjust);
|
||||||
|
if (i > 0) {
|
||||||
|
const int ref_idx = !run_type[i - 1] ?
|
||||||
|
PALETTE_INDEX(prev_xc, prev_yc) : PALETTE_INDEX(xc - transpose, yc - !transpose);
|
||||||
|
idx += (idx >= ref_idx);
|
||||||
|
}
|
||||||
|
*adjust = true;
|
||||||
|
} else {
|
||||||
|
idx = PALETTE_INDEX(prev_xc, prev_yc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!run_type[i])
|
||||||
|
PALETTE_INDEX(xc, yc) = idx;
|
||||||
|
else
|
||||||
|
PALETTE_INDEX(xc, yc) = PALETTE_INDEX(xc - transpose, yc - !transpose);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int c = 0; c < tu->nb_tbs; c++) {
|
||||||
|
TransformBlock *tb = &tu->tbs[c];
|
||||||
|
const Palette *plt = cu->plt + tb->c_idx;
|
||||||
|
const int scale = ff_vvc_palette_derive_scale(lc, tu, tb);
|
||||||
|
const int hs = sps->hshift[c];
|
||||||
|
const int vs = sps->vshift[c];
|
||||||
|
uint8_t *u8 = (uint8_t *)tb->coeffs;
|
||||||
|
uint16_t *u16 = (uint16_t *)tb->coeffs;
|
||||||
|
|
||||||
|
for (int i = min_pos; i < max_pos; i++) {
|
||||||
|
const int xc = TRAV_X(i);
|
||||||
|
const int yc = TRAV_Y(i);
|
||||||
|
if (!(xc & hs) && !(yc & vs)) {
|
||||||
|
const int v = PALETTE_INDEX(xc, yc);
|
||||||
|
if (v == esc) {
|
||||||
|
const int coeff = ff_vvc_palette_escape_val(lc);
|
||||||
|
const int pixel = av_clip_intp2(RSHIFT(coeff * scale, 6), sps->bit_depth);
|
||||||
|
PALETTE_SET_PIXEL(xc, yc, pixel);
|
||||||
|
} else {
|
||||||
|
PALETTE_SET_PIXEL(xc, yc, plt->entries[v]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hls_palette_coding(VVCLocalContext *lc, const VVCTreeType tree_type)
|
||||||
|
{
|
||||||
|
const VVCFrameContext *fc = lc->fc;
|
||||||
|
const VVCSPS *sps = fc->ps.sps;
|
||||||
|
const H266RawSliceHeader *rsh = lc->sc->sh.r;
|
||||||
|
CodingUnit *cu = lc->cu;
|
||||||
|
Palette *pp = lc->ep->pp;
|
||||||
|
const int max_entries = tree_type == SINGLE_TREE ? 31 : 15;
|
||||||
|
const bool local_dual_tree = tree_type != SINGLE_TREE &&
|
||||||
|
(!IS_I(rsh) || (IS_I(rsh) && !sps->r->sps_qtbtt_dual_tree_intra_flag));
|
||||||
|
bool escape_present = false;
|
||||||
|
bool transpose = false;
|
||||||
|
bool adjust = false;
|
||||||
|
int max_index = 0;
|
||||||
|
int prev_run_pos = 0;
|
||||||
|
|
||||||
|
int predictor_size, start, end;
|
||||||
|
bool reused[VVC_MAX_NUM_PALETTE_PREDICTOR_SIZE];
|
||||||
|
uint8_t run_type[MAX_PALETTE_CU_SIZE * MAX_PALETTE_CU_SIZE];
|
||||||
|
uint8_t index[MAX_PALETTE_CU_SIZE * MAX_PALETTE_CU_SIZE];
|
||||||
|
|
||||||
|
ff_vvc_channel_range(&start, &end, tree_type, sps->r->sps_chroma_format_idc);
|
||||||
|
|
||||||
|
if (!palette_add_tu(lc, start, end, tree_type))
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
predictor_size = pp[start].size;
|
||||||
|
memset(reused, 0, sizeof(reused[0]) * predictor_size);
|
||||||
|
palette_predicted(lc, local_dual_tree, start, end, reused, predictor_size, max_entries);
|
||||||
|
palette_signaled(lc, local_dual_tree, start, end, max_entries);
|
||||||
|
palette_update_predictor(lc, local_dual_tree, start, end, reused, predictor_size);
|
||||||
|
|
||||||
|
if (cu->plt[start].size > 0)
|
||||||
|
escape_present = ff_vvc_palette_escape_val_present_flag(lc);
|
||||||
|
|
||||||
|
max_index = cu->plt[start].size - 1 + escape_present;
|
||||||
|
if (max_index > 0) {
|
||||||
|
adjust = false;
|
||||||
|
transpose = ff_vvc_palette_transpose_flag(lc);
|
||||||
|
}
|
||||||
|
|
||||||
|
palette_qp(lc, tree_type, escape_present);
|
||||||
|
|
||||||
|
index[0] = 0;
|
||||||
|
for (int i = 0; i <= (cu->cb_width * cu->cb_height - 1) >> 4; i++)
|
||||||
|
palette_subblock_data(lc, max_index, i, transpose,
|
||||||
|
run_type, index, &prev_run_pos, &adjust);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int intra_data(VVCLocalContext *lc)
|
static int intra_data(VVCLocalContext *lc)
|
||||||
{
|
{
|
||||||
const VVCFrameContext *fc = lc->fc;
|
|
||||||
const VVCSPS *sps = lc->fc->ps.sps;
|
const VVCSPS *sps = lc->fc->ps.sps;
|
||||||
const CodingUnit *cu = lc->cu;
|
const CodingUnit *cu = lc->cu;
|
||||||
const VVCTreeType tree_type = cu->tree_type;
|
const VVCTreeType tree_type = cu->tree_type;
|
||||||
@ -1816,8 +2109,9 @@ static int intra_data(VVCLocalContext *lc)
|
|||||||
|
|
||||||
if (tree_type == SINGLE_TREE || tree_type == DUAL_TREE_LUMA) {
|
if (tree_type == SINGLE_TREE || tree_type == DUAL_TREE_LUMA) {
|
||||||
if (pred_mode_plt_flag) {
|
if (pred_mode_plt_flag) {
|
||||||
avpriv_report_missing_feature(fc->log_ctx, "Palette");
|
if ((ret = hls_palette_coding(lc, tree_type)) < 0)
|
||||||
return AVERROR_PATCHWELCOME;
|
return ret;
|
||||||
|
ff_vvc_set_intra_mvf(lc, false, PF_PLT, false);
|
||||||
} else {
|
} else {
|
||||||
intra_luma_pred_modes(lc);
|
intra_luma_pred_modes(lc);
|
||||||
ff_vvc_set_intra_mvf(lc, false, PF_INTRA, cu->ciip_flag);
|
ff_vvc_set_intra_mvf(lc, false, PF_INTRA, cu->ciip_flag);
|
||||||
@ -1825,8 +2119,8 @@ static int intra_data(VVCLocalContext *lc)
|
|||||||
}
|
}
|
||||||
if ((tree_type == SINGLE_TREE || tree_type == DUAL_TREE_CHROMA) && sps->r->sps_chroma_format_idc) {
|
if ((tree_type == SINGLE_TREE || tree_type == DUAL_TREE_CHROMA) && sps->r->sps_chroma_format_idc) {
|
||||||
if (pred_mode_plt_flag && tree_type == DUAL_TREE_CHROMA) {
|
if (pred_mode_plt_flag && tree_type == DUAL_TREE_CHROMA) {
|
||||||
avpriv_report_missing_feature(fc->log_ctx, "Palette");
|
if ((ret = hls_palette_coding(lc, tree_type)) < 0)
|
||||||
return AVERROR_PATCHWELCOME;
|
return ret;
|
||||||
} else if (!pred_mode_plt_flag) {
|
} else if (!pred_mode_plt_flag) {
|
||||||
if (!cu->act_enabled_flag)
|
if (!cu->act_enabled_flag)
|
||||||
intra_chroma_pred_modes(lc);
|
intra_chroma_pred_modes(lc);
|
||||||
@ -1839,14 +2133,11 @@ static int intra_data(VVCLocalContext *lc)
|
|||||||
static int hls_coding_unit(VVCLocalContext *lc, int x0, int y0, int cb_width, int cb_height,
|
static int hls_coding_unit(VVCLocalContext *lc, int x0, int y0, int cb_width, int cb_height,
|
||||||
int cqt_depth, const VVCTreeType tree_type, VVCModeType mode_type)
|
int cqt_depth, const VVCTreeType tree_type, VVCModeType mode_type)
|
||||||
{
|
{
|
||||||
const VVCFrameContext *fc = lc->fc;
|
const VVCFrameContext *fc = lc->fc;
|
||||||
const VVCSPS *sps = fc->ps.sps;
|
const VVCSPS *sps = fc->ps.sps;
|
||||||
const H266RawSliceHeader *rsh = lc->sc->sh.r;
|
const H266RawSliceHeader *rsh = lc->sc->sh.r;
|
||||||
const int hs = sps->hshift[CHROMA];
|
const int is_128 = cb_width > 64 || cb_height > 64;
|
||||||
const int vs = sps->vshift[CHROMA];
|
int ret = 0;
|
||||||
const int is_128 = cb_width > 64 || cb_height > 64;
|
|
||||||
int pred_mode_plt_flag = 0;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
CodingUnit *cu = add_cu(lc, x0, y0, cb_width, cb_height, cqt_depth, tree_type);
|
CodingUnit *cu = add_cu(lc, x0, y0, cb_width, cb_height, cqt_depth, tree_type);
|
||||||
|
|
||||||
@ -1859,16 +2150,6 @@ static int hls_coding_unit(VVCLocalContext *lc, int x0, int y0, int cb_width, in
|
|||||||
mode_type = MODE_TYPE_INTRA;
|
mode_type = MODE_TYPE_INTRA;
|
||||||
cu->pred_mode = pred_mode_decode(lc, tree_type, mode_type);
|
cu->pred_mode = pred_mode_decode(lc, tree_type, mode_type);
|
||||||
|
|
||||||
if (cu->pred_mode == MODE_INTRA && sps->r->sps_palette_enabled_flag && !is_128 && !cu->skip_flag &&
|
|
||||||
mode_type != MODE_TYPE_INTER && ((cb_width * cb_height) >
|
|
||||||
(tree_type != DUAL_TREE_CHROMA ? 16 : (16 << hs << vs))) &&
|
|
||||||
(mode_type != MODE_TYPE_INTRA || tree_type != DUAL_TREE_CHROMA)) {
|
|
||||||
pred_mode_plt_flag = ff_vvc_pred_mode_plt_flag(lc);
|
|
||||||
if (pred_mode_plt_flag) {
|
|
||||||
avpriv_report_missing_feature(fc->log_ctx, "Palette");
|
|
||||||
return AVERROR_PATCHWELCOME;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cu->pred_mode == MODE_INTRA && sps->r->sps_act_enabled_flag && tree_type == SINGLE_TREE) {
|
if (cu->pred_mode == MODE_INTRA && sps->r->sps_act_enabled_flag && tree_type == SINGLE_TREE) {
|
||||||
avpriv_report_missing_feature(fc->log_ctx, "Adaptive Color Transform");
|
avpriv_report_missing_feature(fc->log_ctx, "Adaptive Color Transform");
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
@ -1881,10 +2162,10 @@ static int hls_coding_unit(VVCLocalContext *lc, int x0, int y0, int cb_width, in
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (cu->pred_mode != MODE_INTRA && !pred_mode_plt_flag && !lc->cu->pu.general_merge_flag)
|
if (cu->pred_mode != MODE_INTRA && cu->pred_mode != MODE_PLT && !lc->cu->pu.general_merge_flag)
|
||||||
cu->coded_flag = ff_vvc_cu_coded_flag(lc);
|
cu->coded_flag = ff_vvc_cu_coded_flag(lc);
|
||||||
else
|
else
|
||||||
cu->coded_flag = !(cu->skip_flag || pred_mode_plt_flag);
|
cu->coded_flag = !(cu->skip_flag || cu->pred_mode == MODE_PLT);
|
||||||
|
|
||||||
if (cu->coded_flag) {
|
if (cu->coded_flag) {
|
||||||
sbt_info(lc, sps);
|
sbt_info(lc, sps);
|
||||||
@ -1902,7 +2183,7 @@ static int hls_coding_unit(VVCLocalContext *lc, int x0, int y0, int cb_width, in
|
|||||||
cu->lfnst_idx = lfnst_idx_decode(lc);
|
cu->lfnst_idx = lfnst_idx_decode(lc);
|
||||||
cu->mts_idx = mts_idx_decode(lc);
|
cu->mts_idx = mts_idx_decode(lc);
|
||||||
set_qp_c(lc);
|
set_qp_c(lc);
|
||||||
} else {
|
} else if (cu->pred_mode != MODE_PLT) {
|
||||||
ret = skipped_transform_tree_unit(lc);
|
ret = skipped_transform_tree_unit(lc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#define MIN_CU_SIZE 4
|
#define MIN_CU_SIZE 4
|
||||||
#define MIN_CU_LOG2 2
|
#define MIN_CU_LOG2 2
|
||||||
#define MAX_CU_DEPTH 7
|
#define MAX_CU_DEPTH 7
|
||||||
|
#define MAX_PALETTE_CU_SIZE 64
|
||||||
|
|
||||||
#define MAX_PARTS_IN_CTU ((MAX_CTU_SIZE >> MIN_CU_LOG2) * (MAX_CTU_SIZE >> MIN_CU_LOG2))
|
#define MAX_PARTS_IN_CTU ((MAX_CTU_SIZE >> MIN_CU_LOG2) * (MAX_CTU_SIZE >> MIN_CU_LOG2))
|
||||||
|
|
||||||
@ -224,6 +225,7 @@ typedef enum PredFlag {
|
|||||||
PF_L1 = 0x2,
|
PF_L1 = 0x2,
|
||||||
PF_BI = 0x3,
|
PF_BI = 0x3,
|
||||||
PF_IBC = PF_L0 | 0x4,
|
PF_IBC = PF_L0 | 0x4,
|
||||||
|
PF_PLT = 0x8,
|
||||||
} PredFlag;
|
} PredFlag;
|
||||||
|
|
||||||
typedef enum IntraPredMode {
|
typedef enum IntraPredMode {
|
||||||
@ -277,6 +279,11 @@ typedef struct PredictionUnit {
|
|||||||
int cb_prof_flag[2];
|
int cb_prof_flag[2];
|
||||||
} PredictionUnit;
|
} PredictionUnit;
|
||||||
|
|
||||||
|
typedef struct Palette {
|
||||||
|
uint8_t size;
|
||||||
|
uint16_t entries[VVC_MAX_NUM_PALETTE_PREDICTOR_SIZE];
|
||||||
|
} Palette;
|
||||||
|
|
||||||
typedef struct CodingUnit {
|
typedef struct CodingUnit {
|
||||||
VVCTreeType tree_type;
|
VVCTreeType tree_type;
|
||||||
int x0;
|
int x0;
|
||||||
@ -326,6 +333,8 @@ typedef struct CodingUnit {
|
|||||||
|
|
||||||
int8_t qp[4]; ///< QpY, Qp′Cb, Qp′Cr, Qp′CbCr
|
int8_t qp[4]; ///< QpY, Qp′Cb, Qp′Cr, Qp′CbCr
|
||||||
|
|
||||||
|
Palette plt[VVC_MAX_SAMPLE_ARRAYS];
|
||||||
|
|
||||||
PredictionUnit pu;
|
PredictionUnit pu;
|
||||||
|
|
||||||
struct CodingUnit *next; ///< RefStruct reference
|
struct CodingUnit *next; ///< RefStruct reference
|
||||||
@ -356,6 +365,8 @@ typedef struct EntryPoint {
|
|||||||
|
|
||||||
int stat_coeff[VVC_MAX_SAMPLE_ARRAYS]; ///< StatCoeff
|
int stat_coeff[VVC_MAX_SAMPLE_ARRAYS]; ///< StatCoeff
|
||||||
|
|
||||||
|
Palette pp[VVC_MAX_SAMPLE_ARRAYS]; // PalettePredictor
|
||||||
|
|
||||||
VVCCabacState cabac_state[VVC_CONTEXTS];
|
VVCCabacState cabac_state[VVC_CONTEXTS];
|
||||||
CABACContext cc;
|
CABACContext cc;
|
||||||
|
|
||||||
|
@ -551,6 +551,9 @@ static int ep_init(EntryPoint *ep, const int ctu_addr, const int ctu_end, GetBit
|
|||||||
ep->ctu_start = ctu_addr;
|
ep->ctu_start = ctu_addr;
|
||||||
ep->ctu_end = ctu_end;
|
ep->ctu_end = ctu_end;
|
||||||
|
|
||||||
|
for (int c_idx = LUMA; c_idx <= CR; c_idx++)
|
||||||
|
ep->pp[c_idx].size = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,8 @@ static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp
|
|||||||
RefPicList* refPicList = sc->rpl;
|
RefPicList* refPicList = sc->rpl;
|
||||||
|
|
||||||
if (temp_col.pred_flag == PF_INTRA ||
|
if (temp_col.pred_flag == PF_INTRA ||
|
||||||
temp_col.pred_flag == PF_IBC)
|
temp_col.pred_flag == PF_IBC ||
|
||||||
|
temp_col.pred_flag == PF_PLT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (sb_flag){
|
if (sb_flag){
|
||||||
|
@ -286,6 +286,7 @@ static void add_progress_listener(VVCFrame *ref, ProgressListener *l,
|
|||||||
static void ep_init_wpp(EntryPoint *next, const EntryPoint *ep, const VVCSPS *sps)
|
static void ep_init_wpp(EntryPoint *next, const EntryPoint *ep, const VVCSPS *sps)
|
||||||
{
|
{
|
||||||
memcpy(next->cabac_state, ep->cabac_state, sizeof(next->cabac_state));
|
memcpy(next->cabac_state, ep->cabac_state, sizeof(next->cabac_state));
|
||||||
|
memcpy(next->pp, ep->pp, sizeof(next->pp));
|
||||||
ff_vvc_ep_init_stat_coeff(next, sps->bit_depth, sps->r->sps_persistent_rice_adaptation_enabled_flag);
|
ff_vvc_ep_init_stat_coeff(next, sps->bit_depth, sps->r->sps_persistent_rice_adaptation_enabled_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user