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

Anton Khirnov anton at khirnov.net
Tue Aug 27 18:04:47 EEST 2024


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 --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;
-- 
2.43.0



More information about the ffmpeg-devel mailing list