frontend/va: Keep surface buf addr before reallocation
authorRuijing Dong <ruijing.dong@amd.com>
Mon, 24 Jan 2022 17:42:58 +0000 (12:42 -0500)
committerMarge Bot <emma+marge@anholt.net>
Wed, 26 Jan 2022 15:28:55 +0000 (15:28 +0000)
The reference buffer address is used as the indication in h264 DPB
Tier2, when reference buffer was reallocated, h264 DPB would lose
track of that reference picture. Adding a pointer obsolete_buf in
vlVaSurface data structure for tracking this released buffer, also
in h264_picture_desc adding a private field, which contains
past_ref[16] for tracking previously released buffer vs current
buffer for reference frames.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5868

Signed-off-by: Ruijing Dong <ruijing.dong@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14646>

src/gallium/frontends/va/picture_h264.c [changed mode: 0644->0755]
src/gallium/frontends/va/surface.c [changed mode: 0644->0755]
src/gallium/frontends/va/va_private.h [changed mode: 0644->0755]
src/gallium/include/pipe/p_video_state.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 13f567d..c63b914
  **************************************************************************/
 
 #include "util/u_video.h"
+#include "util/u_handle_table.h"
 #include "va_private.h"
 
+static void vlVaGetPastReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id,
+                      struct pipe_video_buffer **ref_frame)
+{
+   vlVaSurface *surf = handle_table_get(drv->htab, surface_id);
+   if (surf) {
+      *ref_frame = surf->obsolete_buf;
+      surf->obsolete_buf = NULL;
+   }
+   else
+      *ref_frame = NULL;
+}
+
 static void resetReferencePictureDesc(struct pipe_h264_picture_desc *h264,
                                       unsigned int i)
 {
+   struct h264_private *private = h264->private;
+
    h264->ref[i] = NULL;
    h264->frame_num_list[i] = 0;
    h264->is_long_term[i] = 0;
@@ -39,17 +54,21 @@ static void resetReferencePictureDesc(struct pipe_h264_picture_desc *h264,
    h264->bottom_is_reference[i] = 0;
    h264->field_order_cnt_list[i][0] = 0;
    h264->field_order_cnt_list[i][1] = 0;
+
+   private->past_ref[i] = NULL;
 }
 
 void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
 {
    VAPictureParameterBufferH264 *h264 = buf->data;
+   struct h264_private *private = &context->h264;
    unsigned int top_or_bottom_field;
    bool is_ref;
    unsigned i;
 
    assert(buf->size >= sizeof(VAPictureParameterBufferH264) && buf->num_elements == 1);
    context->desc.h264.slice_count = 0;
+   context->desc.h264.private = private;
    /*CurrPic*/
    context->desc.h264.field_order_cnt[0] = h264->CurrPic.TopFieldOrderCnt;
    context->desc.h264.field_order_cnt[1] = h264->CurrPic.BottomFieldOrderCnt;
@@ -123,6 +142,7 @@ void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context,
       }
 
       vlVaGetReferenceFrame(drv, h264->ReferenceFrames[i].picture_id, &context->desc.h264.ref[i]);
+      vlVaGetPastReferenceFrame(drv, h264->ReferenceFrames[i].picture_id, &private->past_ref[i]);
       context->desc.h264.frame_num_list[i] = h264->ReferenceFrames[i].frame_idx;
 
       top_or_bottom_field = h264->ReferenceFrames[i].flags &
old mode 100644 (file)
new mode 100755 (executable)
index 07f564b..403d741
@@ -1233,6 +1233,7 @@ vlVaExportSurfaceHandle(VADriverContextP ctx,
       struct u_rect src_rect, dst_rect;
 
       surf->templat.interlaced = false;
+      surf->obsolete_buf = surf->buffer;
 
       ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0);
       if (ret != VA_STATUS_SUCCESS) {
@@ -1251,7 +1252,8 @@ vlVaExportSurfaceHandle(VADriverContextP ctx,
                                    VL_COMPOSITOR_WEAVE);
 
       interlaced->destroy(interlaced);
-   }
+   } else
+      surf->obsolete_buf = NULL;
 
    surfaces = surf->buffer->get_surfaces(surf->buffer);
 
old mode 100644 (file)
new mode 100755 (executable)
index 531bda0..d511686
@@ -310,6 +310,7 @@ typedef struct {
       unsigned int slice_header_size;
    } mjpeg;
 
+   struct h264_private h264;
    struct vl_deint_filter *deint;
    vlVaBuffer *coded_buf;
    int target_id;
@@ -335,6 +336,7 @@ typedef struct {
    void *feedback;
    unsigned int frame_num_cnt;
    bool force_flushed;
+   struct pipe_video_buffer *obsolete_buf;
 } vlVaSurface;
 
 // Public functions:
old mode 100644 (file)
new mode 100755 (executable)
index e268f0c..46ea61c
@@ -322,6 +322,10 @@ struct pipe_h264_pps
    int8_t   second_chroma_qp_index_offset;
 };
 
+struct h264_private {
+   struct pipe_video_buffer *past_ref[16];
+};
+
 struct pipe_h264_picture_desc
 {
    struct pipe_picture_desc base;
@@ -347,6 +351,7 @@ struct pipe_h264_picture_desc
    uint32_t frame_num_list[16];
 
    struct pipe_video_buffer *ref[16];
+   void    *private;
 };
 
 struct pipe_h264_enc_rate_control