diff mbox series

[FFmpeg-devel,07/42] lavc/hevcdec: add a per-layer context

Message ID 20240827154041.13846-9-anton@khirnov.net
State New
Headers show
Series [FFmpeg-devel,01/42] lavu/opt: add API for setting array-type option values | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov Aug. 27, 2024, 3:04 p.m. UTC
Start by moving the DPB to it.

Only one context exists for now, so decoder behaviour should not change
with this commit, but that will change in the future.
---
 libavcodec/dxva2_hevc.c   |  7 ++--
 libavcodec/hevc/hevcdec.c | 63 +++++++++++++++++-------------
 libavcodec/hevc/hevcdec.h | 19 +++++++---
 libavcodec/hevc/refs.c    | 80 +++++++++++++++++++++------------------
 libavcodec/nvdec_hevc.c   |  5 ++-
 libavcodec/vaapi_hevc.c   | 14 ++++---
 libavcodec/vdpau_hevc.c   |  5 ++-
 libavcodec/vulkan_hevc.c  | 17 +++++----
 8 files changed, 120 insertions(+), 90 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
index 97e51d15de..d01d1e76e8 100644
--- a/libavcodec/dxva2_hevc.c
+++ b/libavcodec/dxva2_hevc.c
@@ -61,6 +61,7 @@  void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
                                     DXVA_PicParams_HEVC *pp)
 {
     const HEVCContext *h = avctx->priv_data;
+    const HEVCLayerContext *l = &h->layers[h->cur_layer];
     const HEVCFrame *current_picture = h->cur_frame;
     const HEVCPPS *pps = h->pps;
     const HEVCSPS *sps = pps->sps;
@@ -163,9 +164,9 @@  void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
     // fill RefPicList from the DPB
     for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) {
         const HEVCFrame *frame = NULL;
-        while (!frame && j < FF_ARRAY_ELEMS(h->DPB)) {
-            if (&h->DPB[j] != current_picture && (h->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF)))
-                frame = &h->DPB[j];
+        while (!frame && j < FF_ARRAY_ELEMS(l->DPB)) {
+            if (&l->DPB[j] != current_picture && (l->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF)))
+                frame = &l->DPB[j];
             j++;
         }
 
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 4077ed3ac5..669c8f550b 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -2902,7 +2902,7 @@  static int set_side_data(HEVCContext *s)
     return 0;
 }
 
-static int hevc_frame_start(HEVCContext *s)
+static int hevc_frame_start(HEVCContext *s, HEVCLayerContext *l)
 {
     const HEVCPPS *const pps = s->ps.pps_list[s->sh.pps_id];
     const HEVCSPS *const sps = pps->sps;
@@ -2915,7 +2915,7 @@  static int hevc_frame_start(HEVCContext *s)
     if (s->ps.sps != sps) {
         enum AVPixelFormat pix_fmt;
 
-        ff_hevc_clear_refs(s);
+        ff_hevc_clear_refs(l);
 
         ret = set_sps(s, sps);
         if (ret < 0)
@@ -2938,7 +2938,7 @@  static int hevc_frame_start(HEVCContext *s)
     memset(s->tab_slice_address, -1, pic_size_in_ctb * sizeof(*s->tab_slice_address));
 
     if (IS_IDR(s))
-        ff_hevc_clear_refs(s);
+        ff_hevc_clear_refs(l);
 
     s->slice_idx         = 0;
     s->first_nal_type    = s->nal_unit_type;
@@ -2963,7 +2963,7 @@  static int hevc_frame_start(HEVCContext *s)
         s->local_ctx[0].end_of_tiles_x = pps->column_width[0] << sps->log2_ctb_size;
 
     if (new_sequence) {
-        ret = ff_hevc_output_frames(s, 0, 0, s->sh.no_output_of_prior_pics_flag);
+        ret = ff_hevc_output_frames(s, l, 0, 0, s->sh.no_output_of_prior_pics_flag);
         if (ret < 0)
             return ret;
     }
@@ -2972,11 +2972,11 @@  static int hevc_frame_start(HEVCContext *s)
     if (ret < 0)
         return ret;
 
-    ret = ff_hevc_set_new_ref(s, s->poc);
+    ret = ff_hevc_set_new_ref(s, l, s->poc);
     if (ret < 0)
         goto fail;
 
-    ret = ff_hevc_frame_rps(s);
+    ret = ff_hevc_frame_rps(s, l);
     if (ret < 0) {
         av_log(s->avctx, AV_LOG_ERROR, "Error constructing the frame RPS.\n");
         goto fail;
@@ -3020,7 +3020,7 @@  static int hevc_frame_start(HEVCContext *s)
 
     s->cur_frame->f->pict_type = 3 - s->sh.slice_type;
 
-    ret = ff_hevc_output_frames(s, sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
+    ret = ff_hevc_output_frames(s, l, sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
                                 sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering, 0);
     if (ret < 0)
         goto fail;
@@ -3158,7 +3158,8 @@  static int hevc_frame_end(HEVCContext *s)
     return 0;
 }
 
-static int decode_slice(HEVCContext *s, const H2645NAL *nal, GetBitContext *gb)
+static int decode_slice(HEVCContext *s, HEVCLayerContext *l,
+                        const H2645NAL *nal, GetBitContext *gb)
 {
     int ret;
 
@@ -3183,7 +3184,7 @@  static int decode_slice(HEVCContext *s, const H2645NAL *nal, GetBitContext *gb)
             return AVERROR_INVALIDDATA;
         }
 
-        ret = hevc_frame_start(s);
+        ret = hevc_frame_start(s, l);
         if (ret < 0)
             return ret;
     } else if (!s->cur_frame) {
@@ -3207,6 +3208,7 @@  static int decode_slice(HEVCContext *s, const H2645NAL *nal, GetBitContext *gb)
 
 static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
 {
+    HEVCLayerContext  *l = &s->layers[0];
     GetBitContext     gb = nal->gb;
     int ret;
 
@@ -3264,7 +3266,7 @@  static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
     case HEVC_NAL_RADL_R:
     case HEVC_NAL_RASL_N:
     case HEVC_NAL_RASL_R:
-        ret = decode_slice(s, nal, &gb);
+        ret = decode_slice(s, l, nal, &gb);
         if (ret < 0)
             goto fail;
         break;
@@ -3427,7 +3429,7 @@  static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     av_packet_unref(avpkt);
     ret = ff_decode_get_packet(avctx, avpkt);
     if (ret == AVERROR_EOF) {
-        ret = ff_hevc_output_frames(s, 0, 0, 0);
+        ret = ff_hevc_output_frames(s, &s->layers[0], 0, 0, 0);
         if (ret < 0)
             return ret;
         goto do_output;
@@ -3517,9 +3519,12 @@  static av_cold int hevc_decode_free(AVCodecContext *avctx)
 
     ff_container_fifo_free(&s->output_fifo);
 
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        ff_hevc_unref_frame(&s->DPB[i], ~0);
-        av_frame_free(&s->DPB[i].frame_grain);
+    for (int layer = 0; layer < FF_ARRAY_ELEMS(s->layers); layer++) {
+        HEVCLayerContext *l = &s->layers[layer];
+        for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+            ff_hevc_unref_frame(&l->DPB[i], ~0);
+            av_frame_free(&l->DPB[i].frame_grain);
+        }
     }
 
     ff_hevc_ps_uninit(&s->ps);
@@ -3540,7 +3545,6 @@  static av_cold int hevc_decode_free(AVCodecContext *avctx)
 static av_cold int hevc_init_context(AVCodecContext *avctx)
 {
     HEVCContext *s = avctx->priv_data;
-    int i;
 
     s->avctx = avctx;
 
@@ -3557,10 +3561,13 @@  static av_cold int hevc_init_context(AVCodecContext *avctx)
     if (!s->output_fifo)
         return AVERROR(ENOMEM);
 
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        s->DPB[i].frame_grain = av_frame_alloc();
-        if (!s->DPB[i].frame_grain)
-            return AVERROR(ENOMEM);
+    for (int layer = 0; layer < FF_ARRAY_ELEMS(s->layers); layer++) {
+        HEVCLayerContext *l = &s->layers[layer];
+        for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+            l->DPB[i].frame_grain = av_frame_alloc();
+            if (!l->DPB[i].frame_grain)
+                return AVERROR(ENOMEM);
+        }
     }
 
     s->md5_ctx = av_md5_alloc();
@@ -3583,14 +3590,18 @@  static int hevc_update_thread_context(AVCodecContext *dst,
 {
     HEVCContext *s  = dst->priv_data;
     HEVCContext *s0 = src->priv_data;
-    int i, ret;
+    int ret;
 
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        ff_hevc_unref_frame(&s->DPB[i], ~0);
-        if (s0->DPB[i].f) {
-            ret = hevc_ref_frame(&s->DPB[i], &s0->DPB[i]);
-            if (ret < 0)
-                return ret;
+    for (int layer = 0; layer < FF_ARRAY_ELEMS(s->layers); layer++) {
+        HEVCLayerContext        *l = &s->layers[layer];
+        const HEVCLayerContext *l0 = &s0->layers[layer];
+        for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+            ff_hevc_unref_frame(&l->DPB[i], ~0);
+            if (l0->DPB[i].f) {
+                ret = hevc_ref_frame(&l->DPB[i], &l0->DPB[i]);
+                if (ret < 0)
+                    return ret;
+            }
         }
     }
 
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 656a3ab94b..aab09bfd94 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -438,6 +438,10 @@  typedef struct HEVCLocalContext {
     char padding[128];
 } HEVCLocalContext;
 
+typedef struct HEVCLayerContext {
+    HEVCFrame               DPB[32];
+} HEVCLayerContext;
+
 typedef struct HEVCContext {
     const AVClass *c;  // needed by private avoptions
     AVCodecContext *avctx;
@@ -445,6 +449,10 @@  typedef struct HEVCContext {
     HEVCLocalContext     *local_ctx;
     unsigned           nb_local_ctx;
 
+    HEVCLayerContext      layers[1];
+    // index in layers of the layer currently being decoded
+    unsigned              cur_layer;
+
     /** 1 if the independent slice segment header was successfully parsed */
     uint8_t slice_initialized;
 
@@ -470,7 +478,6 @@  typedef struct HEVCContext {
     int temporal_id;  ///< temporal_id_plus1 - 1
     HEVCFrame *cur_frame;
     HEVCFrame *collocated_ref;
-    HEVCFrame DPB[32];
     int poc;
     int poc_tid0;
     int slice_idx; ///< number of the slice being currently decoded
@@ -536,7 +543,7 @@  typedef struct HEVCContext {
 /**
  * Mark all frames in DPB as unused for reference.
  */
-void ff_hevc_clear_refs(HEVCContext *s);
+void ff_hevc_clear_refs(HEVCLayerContext *l);
 
 /**
  * Drop all frames currently in DPB.
@@ -549,7 +556,7 @@  const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s, const HEVCFrame *fr
 /**
  * Construct the reference picture sets for the current frame.
  */
-int ff_hevc_frame_rps(HEVCContext *s);
+int ff_hevc_frame_rps(HEVCContext *s, HEVCLayerContext *l);
 
 /**
  * Construct the reference picture list(s) for the current slice.
@@ -597,7 +604,7 @@  int ff_hevc_res_scale_sign_flag(HEVCLocalContext *lc, int idx);
  */
 int ff_hevc_frame_nb_refs(const SliceHeader *sh, const HEVCPPS *pps);
 
-int ff_hevc_set_new_ref(HEVCContext *s, int poc);
+int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext *l, int poc);
 
 static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type)
 {
@@ -625,8 +632,8 @@  static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type)
  * @param max_dpb maximum number of any frames that can be present in the DPB
  *                before output is triggered
  */
-int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
-                          unsigned max_dpb, int discard);
+int ff_hevc_output_frames(HEVCContext *s, HEVCLayerContext *l,
+                          unsigned max_output, unsigned max_dpb, int discard);
 
 void ff_hevc_unref_frame(HEVCFrame *frame, int flags);
 
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 65abd09a21..4d123d6d8d 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -59,27 +59,29 @@  const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s,
     return &ref->rpl_tab[ctb_addr_ts]->refPicList[0];
 }
 
-void ff_hevc_clear_refs(HEVCContext *s)
+void ff_hevc_clear_refs(HEVCLayerContext *l)
 {
     int i;
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++)
-        ff_hevc_unref_frame(&s->DPB[i],
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++)
+        ff_hevc_unref_frame(&l->DPB[i],
                             HEVC_FRAME_FLAG_SHORT_REF |
                             HEVC_FRAME_FLAG_LONG_REF);
 }
 
 void ff_hevc_flush_dpb(HEVCContext *s)
 {
-    int i;
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++)
-        ff_hevc_unref_frame(&s->DPB[i], ~0);
+    for (int layer = 0; layer < FF_ARRAY_ELEMS(s->layers); layer++) {
+        HEVCLayerContext *l = &s->layers[layer];
+        for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++)
+            ff_hevc_unref_frame(&l->DPB[i], ~0);
+    }
 }
 
-static HEVCFrame *alloc_frame(HEVCContext *s)
+static HEVCFrame *alloc_frame(HEVCContext *s, HEVCLayerContext *l)
 {
     int i, j, ret;
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        HEVCFrame *frame = &s->DPB[i];
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        HEVCFrame *frame = &l->DPB[i];
         if (frame->f)
             continue;
 
@@ -123,14 +125,14 @@  fail:
     return NULL;
 }
 
-int ff_hevc_set_new_ref(HEVCContext *s, int poc)
+int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext *l, int poc)
 {
     HEVCFrame *ref;
     int i;
 
     /* check that this POC doesn't already exist */
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        HEVCFrame *frame = &s->DPB[i];
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        HEVCFrame *frame = &l->DPB[i];
 
         if (frame->f && frame->poc == poc) {
             av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n",
@@ -139,7 +141,7 @@  int ff_hevc_set_new_ref(HEVCContext *s, int poc)
         }
     }
 
-    ref = alloc_frame(s);
+    ref = alloc_frame(s, l);
     if (!ref)
         return AVERROR(ENOMEM);
 
@@ -160,18 +162,18 @@  int ff_hevc_set_new_ref(HEVCContext *s, int poc)
     return 0;
 }
 
-static void unref_missing_refs(HEVCContext *s)
+static void unref_missing_refs(HEVCLayerContext *l)
 {
-    for (int i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-         HEVCFrame *frame = &s->DPB[i];
+    for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+         HEVCFrame *frame = &l->DPB[i];
          if (frame->flags & HEVC_FRAME_FLAG_UNAVAILABLE) {
              ff_hevc_unref_frame(frame, ~0);
          }
     }
 }
 
-int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
-                          unsigned max_dpb, int discard)
+int ff_hevc_output_frames(HEVCContext *s, HEVCLayerContext *l,
+                          unsigned max_output, unsigned max_dpb, int discard)
 {
     while (1) {
         int nb_dpb    = 0;
@@ -179,8 +181,8 @@  int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
         int min_poc   = INT_MAX;
         int i, min_idx, ret;
 
-        for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-            HEVCFrame *frame = &s->DPB[i];
+        for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+            HEVCFrame *frame = &l->DPB[i];
             if (frame->flags & HEVC_FRAME_FLAG_OUTPUT) {
                 nb_output++;
                 if (frame->poc < min_poc || nb_output == 1) {
@@ -193,7 +195,7 @@  int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
 
         if (nb_output > max_output ||
             (nb_output && nb_dpb > max_dpb)) {
-            HEVCFrame *frame = &s->DPB[min_idx];
+            HEVCFrame *frame = &l->DPB[min_idx];
 
             ret = discard ? 0 :
                   ff_container_fifo_write(s->output_fifo,
@@ -313,13 +315,14 @@  int ff_hevc_slice_rpl(HEVCContext *s)
     return 0;
 }
 
-static HEVCFrame *find_ref_idx(HEVCContext *s, int poc, uint8_t use_msb)
+static HEVCFrame *find_ref_idx(HEVCContext *s, HEVCLayerContext *l,
+                               int poc, uint8_t use_msb)
 {
     int mask = use_msb ? ~0 : (1 << s->ps.sps->log2_max_poc_lsb) - 1;
     int i;
 
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        HEVCFrame *ref = &s->DPB[i];
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        HEVCFrame *ref = &l->DPB[i];
         if (ref->f) {
             if ((ref->poc & mask) == poc && (use_msb || ref->poc != s->poc))
                 return ref;
@@ -338,12 +341,12 @@  static void mark_ref(HEVCFrame *frame, int flag)
     frame->flags |= flag;
 }
 
-static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc)
+static HEVCFrame *generate_missing_ref(HEVCContext *s, HEVCLayerContext *l, int poc)
 {
     HEVCFrame *frame;
     int i, y;
 
-    frame = alloc_frame(s);
+    frame = alloc_frame(s, l);
     if (!frame)
         return NULL;
 
@@ -372,16 +375,17 @@  static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc)
 }
 
 /* add a reference with the given poc to the list and mark it as used in DPB */
-static int add_candidate_ref(HEVCContext *s, RefPicList *list,
+static int add_candidate_ref(HEVCContext *s, HEVCLayerContext *l,
+                             RefPicList *list,
                              int poc, int ref_flag, uint8_t use_msb)
 {
-    HEVCFrame *ref = find_ref_idx(s, poc, use_msb);
+    HEVCFrame *ref = find_ref_idx(s, l, poc, use_msb);
 
     if (ref == s->cur_frame || list->nb_refs >= HEVC_MAX_REFS)
         return AVERROR_INVALIDDATA;
 
     if (!ref) {
-        ref = generate_missing_ref(s, poc);
+        ref = generate_missing_ref(s, l, poc);
         if (!ref)
             return AVERROR(ENOMEM);
     }
@@ -394,7 +398,7 @@  static int add_candidate_ref(HEVCContext *s, RefPicList *list,
     return 0;
 }
 
-int ff_hevc_frame_rps(HEVCContext *s)
+int ff_hevc_frame_rps(HEVCContext *s, HEVCLayerContext *l)
 {
     const ShortTermRPS *short_rps = s->sh.short_term_rps;
     const LongTermRPS  *long_rps  = &s->sh.long_term_rps;
@@ -406,11 +410,11 @@  int ff_hevc_frame_rps(HEVCContext *s)
         return 0;
     }
 
-    unref_missing_refs(s);
+    unref_missing_refs(l);
 
     /* clear the reference flags on all frames except the current one */
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        HEVCFrame *frame = &s->DPB[i];
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        HEVCFrame *frame = &l->DPB[i];
 
         if (frame == s->cur_frame)
             continue;
@@ -433,7 +437,8 @@  int ff_hevc_frame_rps(HEVCContext *s)
         else
             list = ST_CURR_AFT;
 
-        ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF, 1);
+        ret = add_candidate_ref(s, l, &rps[list], poc,
+                                HEVC_FRAME_FLAG_SHORT_REF, 1);
         if (ret < 0)
             goto fail;
     }
@@ -443,15 +448,16 @@  int ff_hevc_frame_rps(HEVCContext *s)
         int poc  = long_rps->poc[i];
         int list = long_rps->used[i] ? LT_CURR : LT_FOLL;
 
-        ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF, long_rps->poc_msb_present[i]);
+        ret = add_candidate_ref(s, l, &rps[list], poc,
+                                HEVC_FRAME_FLAG_LONG_REF, long_rps->poc_msb_present[i]);
         if (ret < 0)
             goto fail;
     }
 
 fail:
     /* release any frames that are now unused */
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++)
-        ff_hevc_unref_frame(&s->DPB[i], 0);
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++)
+        ff_hevc_unref_frame(&l->DPB[i], 0);
 
     return ret;
 }
diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c
index ce66ddcfb7..6888507535 100644
--- a/libavcodec/nvdec_hevc.c
+++ b/libavcodec/nvdec_hevc.c
@@ -73,6 +73,7 @@  static int nvdec_hevc_start_frame(AVCodecContext *avctx,
                                   const uint8_t *buffer, uint32_t size)
 {
     const HEVCContext *s = avctx->priv_data;
+    const HEVCLayerContext *l = &s->layers[s->cur_layer];
     const HEVCPPS *pps = s->pps;
     const HEVCSPS *sps = pps->sps;
 
@@ -225,8 +226,8 @@  static int nvdec_hevc_start_frame(AVCodecContext *avctx,
     }
 
     dpb_size = 0;
-    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
-        const HEVCFrame *ref = &s->DPB[i];
+    for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        const HEVCFrame *ref = &l->DPB[i];
         if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF)))
             continue;
         if (dpb_size >= FF_ARRAY_ELEMS(ppc->RefPicIdx)) {
diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
index ad4cd35b26..b97e7c0343 100644
--- a/libavcodec/vaapi_hevc.c
+++ b/libavcodec/vaapi_hevc.c
@@ -96,7 +96,8 @@  static int find_frame_rps_type(const HEVCContext *h, const HEVCFrame *pic)
     return 0;
 }
 
-static void fill_vaapi_reference_frames(const HEVCContext *h, VAPictureParameterBufferHEVC *pp)
+static void fill_vaapi_reference_frames(const HEVCContext *h, const HEVCLayerContext *l,
+                                        VAPictureParameterBufferHEVC *pp)
 {
     const HEVCFrame *current_picture = h->cur_frame;
     int i, j, rps_type;
@@ -104,10 +105,10 @@  static void fill_vaapi_reference_frames(const HEVCContext *h, VAPictureParameter
     for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->ReferenceFrames); i++) {
         const HEVCFrame *frame = NULL;
 
-        while (!frame && j < FF_ARRAY_ELEMS(h->DPB)) {
-            if ((&h->DPB[j] != current_picture || h->pps->pps_curr_pic_ref_enabled_flag) &&
-                (h->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF)))
-                frame = &h->DPB[j];
+        while (!frame && j < FF_ARRAY_ELEMS(l->DPB)) {
+            if ((&l->DPB[j] != current_picture || h->pps->pps_curr_pic_ref_enabled_flag) &&
+                (l->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF)))
+                frame = &l->DPB[j];
             j++;
         }
 
@@ -125,6 +126,7 @@  static int vaapi_hevc_start_frame(AVCodecContext          *avctx,
                                   av_unused uint32_t       size)
 {
     const HEVCContext        *h = avctx->priv_data;
+    const HEVCLayerContext   *l = &h->layers[h->cur_layer];
     VAAPIDecodePictureHEVC *pic = h->cur_frame->hwaccel_picture_private;
     const HEVCPPS          *pps = h->pps;
     const HEVCSPS          *sps = pps->sps;
@@ -208,7 +210,7 @@  static int vaapi_hevc_start_frame(AVCodecContext          *avctx,
     };
 
     fill_vaapi_pic(&pic_param->CurrPic, h->cur_frame, 0);
-    fill_vaapi_reference_frames(h, pic_param);
+    fill_vaapi_reference_frames(h, l, pic_param);
 
     if (pps->tiles_enabled_flag) {
         pic_param->num_tile_columns_minus1 = pps->num_tile_columns - 1;
diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c
index b9e922ecfc..e6232567e0 100644
--- a/libavcodec/vdpau_hevc.c
+++ b/libavcodec/vdpau_hevc.c
@@ -35,6 +35,7 @@  static int vdpau_hevc_start_frame(AVCodecContext *avctx,
                                   const uint8_t *buffer, uint32_t size)
 {
     HEVCContext *h = avctx->priv_data;
+    const HEVCLayerContext *l = &h->layers[h->cur_layer];
     HEVCFrame *pic = h->cur_frame;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
 
@@ -236,8 +237,8 @@  static int vdpau_hevc_start_frame(AVCodecContext *avctx,
         info->PicOrderCntVal[i] = 0;
         info->IsLongTerm[i] = 0;
     }
-    for (size_t i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
-        const HEVCFrame *frame = &h->DPB[i];
+    for (size_t i = 0, j = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        const HEVCFrame *frame = &l->DPB[i];
         if (frame != h->cur_frame && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF |
                                                 HEVC_FRAME_FLAG_SHORT_REF))) {
             if (j > 15) {
diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c
index 5228e41ad5..f4c8da2d61 100644
--- a/libavcodec/vulkan_hevc.c
+++ b/libavcodec/vulkan_hevc.c
@@ -731,6 +731,7 @@  static int vk_hevc_start_frame(AVCodecContext          *avctx,
 {
     int err;
     HEVCContext *h = avctx->priv_data;
+    HEVCLayerContext *l = &h->layers[h->cur_layer];
     HEVCFrame *pic = h->cur_frame;
     FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
     HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
@@ -762,8 +763,8 @@  static int vk_hevc_start_frame(AVCodecContext          *avctx,
     };
 
     /* Fill in references */
-    for (int i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
-        const HEVCFrame *ref = &h->DPB[i];
+    for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        const HEVCFrame *ref = &l->DPB[i];
         int idx = nb_refs;
 
         if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF)))
@@ -790,8 +791,8 @@  static int vk_hevc_start_frame(AVCodecContext          *avctx,
     memset(hp->h265pic.RefPicSetStCurrBefore, 0xff, 8);
     for (int i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
         HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];
-        for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) {
-            const HEVCFrame *ref = &h->DPB[j];
+        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
+            const HEVCFrame *ref = &l->DPB[j];
             if (ref == frame) {
                 hp->h265pic.RefPicSetStCurrBefore[i] = j;
                 break;
@@ -801,8 +802,8 @@  static int vk_hevc_start_frame(AVCodecContext          *avctx,
     memset(hp->h265pic.RefPicSetStCurrAfter, 0xff, 8);
     for (int i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
         HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];
-        for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) {
-            const HEVCFrame *ref = &h->DPB[j];
+        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
+            const HEVCFrame *ref = &l->DPB[j];
             if (ref == frame) {
                 hp->h265pic.RefPicSetStCurrAfter[i] = j;
                 break;
@@ -812,8 +813,8 @@  static int vk_hevc_start_frame(AVCodecContext          *avctx,
     memset(hp->h265pic.RefPicSetLtCurr, 0xff, 8);
     for (int i = 0; i < h->rps[LT_CURR].nb_refs; i++) {
         HEVCFrame *frame = h->rps[LT_CURR].ref[i];
-        for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) {
-            const HEVCFrame *ref = &h->DPB[j];
+        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
+            const HEVCFrame *ref = &l->DPB[j];
             if (ref == frame) {
                 hp->h265pic.RefPicSetLtCurr[i] = j;
                 break;