From: Wu Jianhua <toq...@outlook.com>

Signed-off-by: Wu Jianhua <toq...@outlook.com>
---
 libavcodec/vvc/ctu.c    | 339 ++++++++++++++++++++++++++++++++++++----
 libavcodec/vvc/ctu.h    |  11 ++
 libavcodec/vvc/dec.c    |   3 +
 libavcodec/vvc/mvs.c    |   3 +-
 libavcodec/vvc/thread.c |   1 +
 5 files changed, 327 insertions(+), 30 deletions(-)

diff --git a/libavcodec/vvc/ctu.c b/libavcodec/vvc/ctu.c
index c5df898f7b..979a27c6ad 100644
--- a/libavcodec/vvc/ctu.c
+++ b/libavcodec/vvc/ctu.c
@@ -25,6 +25,7 @@
 #include "cabac.h"
 #include "ctu.h"
 #include "inter.h"
+#include "intra.h"
 #include "mvs.h"
 
 #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 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_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_ibc_flag;
     PredMode pred_mode;
 
     cu->skip_flag = 0;
     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 &&
             ((!is_4x4 && mode_type != MODE_TYPE_INTRA) ||
             (sps->r->sps_ibc_enabled_flag && !is_128))) {
@@ -1087,6 +1090,14 @@ static PredMode pred_mode_decode(VVCLocalContext *lc,
         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);
     if (tree_type == SINGLE_TREE)
         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 CodingUnit *cu      = lc->cu;
 
-    if (cu->pred_mode == MODE_IBC) {
-        ff_vvc_set_intra_mvf(lc, true, PF_IBC, false);
+    if (cu->pred_mode == MODE_IBC || cu->pred_mode == MODE_PLT) {
+        ff_vvc_set_intra_mvf(lc, true, cu->pred_mode == MODE_IBC ? PF_IBC : 
PF_PLT, false);
     } else {
         const VVCPPS *pps = fc->ps.pps;
         const int w       = cu->cb_width >> MIN_PU_LOG2;
@@ -1805,9 +1816,291 @@ static int inter_data(VVCLocalContext *lc)
     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)
 {
-    const VVCFrameContext *fc      = lc->fc;
     const VVCSPS *sps              = lc->fc->ps.sps;
     const CodingUnit *cu           = lc->cu;
     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 (pred_mode_plt_flag) {
-            avpriv_report_missing_feature(fc->log_ctx, "Palette");
-            return AVERROR_PATCHWELCOME;
+            if ((ret = hls_palette_coding(lc, tree_type)) < 0)
+                return ret;
+            ff_vvc_set_intra_mvf(lc, false, PF_PLT, false);
         } else {
             intra_luma_pred_modes(lc);
             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 (pred_mode_plt_flag && tree_type == DUAL_TREE_CHROMA) {
-            avpriv_report_missing_feature(fc->log_ctx, "Palette");
-            return AVERROR_PATCHWELCOME;
+            if ((ret = hls_palette_coding(lc, tree_type)) < 0)
+                return ret;
         } else if (!pred_mode_plt_flag) {
             if (!cu->act_enabled_flag)
                 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,
     int cqt_depth, const VVCTreeType tree_type, VVCModeType mode_type)
 {
-    const VVCFrameContext *fc       = lc->fc;
-    const VVCSPS *sps               = fc->ps.sps;
-    const H266RawSliceHeader *rsh   = lc->sc->sh.r;
-    const int hs                    = sps->hshift[CHROMA];
-    const int vs                    = sps->vshift[CHROMA];
-    const int is_128                = cb_width > 64 || cb_height > 64;
-    int pred_mode_plt_flag          = 0;
-    int ret                         = 0;
+    const VVCFrameContext *fc     = lc->fc;
+    const VVCSPS *sps             = fc->ps.sps;
+    const H266RawSliceHeader *rsh = lc->sc->sh.r;
+    const int is_128              = cb_width > 64 || cb_height > 64;
+    int ret                       = 0;
 
     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;
     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) {
         avpriv_report_missing_feature(fc->log_ctx, "Adaptive Color Transform");
         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)
         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);
     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) {
         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->mts_idx = mts_idx_decode(lc);
         set_qp_c(lc);
-    } else {
+    } else if (cu->pred_mode != MODE_PLT) {
         ret = skipped_transform_tree_unit(lc);
         if (ret < 0)
             return ret;
diff --git a/libavcodec/vvc/ctu.h b/libavcodec/vvc/ctu.h
index dab6f453f1..e37bacf9dd 100644
--- a/libavcodec/vvc/ctu.h
+++ b/libavcodec/vvc/ctu.h
@@ -36,6 +36,7 @@
 #define MIN_CU_SIZE             4
 #define MIN_CU_LOG2             2
 #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))
 
@@ -224,6 +225,7 @@ typedef enum PredFlag {
     PF_L1    = 0x2,
     PF_BI    = 0x3,
     PF_IBC   = PF_L0 | 0x4,
+    PF_PLT   = 0x8,
 } PredFlag;
 
 typedef enum IntraPredMode {
@@ -277,6 +279,11 @@ typedef struct PredictionUnit {
     int cb_prof_flag[2];
 } PredictionUnit;
 
+typedef struct Palette {
+    uint8_t size;
+    uint16_t entries[VVC_MAX_NUM_PALETTE_PREDICTOR_SIZE];
+} Palette;
+
 typedef struct CodingUnit {
     VVCTreeType tree_type;
     int x0;
@@ -326,6 +333,8 @@ typedef struct CodingUnit {
 
     int8_t qp[4];                                   ///< QpY, Qp′Cb, Qp′Cr, 
Qp′CbCr
 
+    Palette plt[VVC_MAX_SAMPLE_ARRAYS];
+
     PredictionUnit pu;
 
     struct CodingUnit *next;                        ///< RefStruct reference
@@ -356,6 +365,8 @@ typedef struct EntryPoint {
 
     int stat_coeff[VVC_MAX_SAMPLE_ARRAYS];          ///< StatCoeff
 
+    Palette pp[VVC_MAX_SAMPLE_ARRAYS];              // PalettePredictor
+
     VVCCabacState cabac_state[VVC_CONTEXTS];
     CABACContext cc;
 
diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index 09b0053703..3db2c9955c 100644
--- a/libavcodec/vvc/dec.c
+++ b/libavcodec/vvc/dec.c
@@ -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_end   = ctu_end;
 
+    for (int c_idx = LUMA; c_idx <= CR; c_idx++)
+        ep->pp[c_idx].size = 0;
+
     return 0;
 }
 
diff --git a/libavcodec/vvc/mvs.c b/libavcodec/vvc/mvs.c
index 8946b00b5b..2cf67def7b 100644
--- a/libavcodec/vvc/mvs.c
+++ b/libavcodec/vvc/mvs.c
@@ -145,7 +145,8 @@ static int derive_temporal_colocated_mvs(const 
VVCLocalContext *lc, MvField temp
     RefPicList* refPicList      = sc->rpl;
 
     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;
 
     if (sb_flag){
diff --git a/libavcodec/vvc/thread.c b/libavcodec/vvc/thread.c
index e1d64bd3d2..2138341b0f 100644
--- a/libavcodec/vvc/thread.c
+++ b/libavcodec/vvc/thread.c
@@ -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)
 {
     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);
 }
 
-- 
2.44.0.windows.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to