va: decoder: store output buffer rather than surface

GstVaDecodePicture stored the processed VASurfaceID, under the
assumption that the bufferpool with keep the referenced buffers, but
this approach is fragil.

This patch changes GstVaDecodePicture to store the output buffer,
which already contains its VASurfaceID, and provides a new method to
retrieve the VASurfaceID directly from picture.

Based on He Junyan <junyan.he@intel.com> patches for
https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1587

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1594>
This commit is contained in:
Víctor Manuel Jáquez Leal 2020-09-24 12:29:49 +02:00
parent 6c26d0e1a0
commit 755d769045
3 changed files with 40 additions and 16 deletions

View file

@ -24,6 +24,7 @@
#include "gstvadecoder.h" #include "gstvadecoder.h"
#include "gstvaallocator.h"
#include "gstvacaps.h" #include "gstvacaps.h"
#include "gstvadisplay_wrapped.h" #include "gstvadisplay_wrapped.h"
#include "gstvavideoformat.h" #include "gstvavideoformat.h"
@ -568,18 +569,25 @@ gst_va_decoder_decode (GstVaDecoder * self, GstVaDecodePicture * pic)
{ {
VADisplay dpy; VADisplay dpy;
VAStatus status; VAStatus status;
VASurfaceID surface;
gboolean ret = FALSE; gboolean ret = FALSE;
g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE); g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE); g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE);
g_return_val_if_fail (pic && pic->surface != VA_INVALID_ID, FALSE); g_return_val_if_fail (pic, FALSE);
GST_TRACE_OBJECT (self, "Decode to surface %#x", pic->surface); surface = gst_va_decode_picture_get_surface (pic);
if (surface == VA_INVALID_ID) {
GST_ERROR_OBJECT (self, "Decode picture without VASurfaceID");
return FALSE;
}
GST_TRACE_OBJECT (self, "Decode to surface %#x", surface);
dpy = gst_va_display_get_va_dpy (self->display); dpy = gst_va_display_get_va_dpy (self->display);
gst_va_display_lock (self->display); gst_va_display_lock (self->display);
status = vaBeginPicture (dpy, self->context, pic->surface); status = vaBeginPicture (dpy, self->context, surface);
gst_va_display_unlock (self->display); gst_va_display_unlock (self->display);
if (status != VA_STATUS_SUCCESS) { if (status != VA_STATUS_SUCCESS) {
GST_WARNING_OBJECT (self, "vaBeginPicture: %s", vaErrorStr (status)); GST_WARNING_OBJECT (self, "vaBeginPicture: %s", vaErrorStr (status));
@ -638,13 +646,20 @@ gst_va_decoder_destroy_buffers (GstVaDecoder * self, GstVaDecodePicture * pic)
VABufferID buffer; VABufferID buffer;
VADisplay dpy; VADisplay dpy;
VAStatus status; VAStatus status;
VASurfaceID surface;
guint i; guint i;
gboolean ret = TRUE; gboolean ret = TRUE;
g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE); g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
g_return_val_if_fail (pic && pic->surface != VA_INVALID_ID, FALSE); g_return_val_if_fail (pic, FALSE);
GST_TRACE_OBJECT (self, "Destroy buffers of surface %#x", pic->surface); surface = gst_va_decode_picture_get_surface (pic);
if (surface == VA_INVALID_ID) {
GST_ERROR_OBJECT (self, "Decode picture without VASurfaceID");
return FALSE;
}
GST_TRACE_OBJECT (self, "Destroy buffers of surface %#x", surface);
dpy = gst_va_display_get_va_dpy (self->display); dpy = gst_va_display_get_va_dpy (self->display);
@ -679,20 +694,29 @@ gst_va_decoder_destroy_buffers (GstVaDecoder * self, GstVaDecodePicture * pic)
GstVaDecodePicture * GstVaDecodePicture *
gst_va_decode_picture_new (VASurfaceID surface) gst_va_decode_picture_new (GstBuffer * buffer)
{ {
GstVaDecodePicture *pic; GstVaDecodePicture *pic;
g_return_val_if_fail (surface != VA_INVALID_ID, NULL); g_return_val_if_fail (buffer && GST_IS_BUFFER (buffer), NULL);
pic = g_slice_new (GstVaDecodePicture); pic = g_slice_new (GstVaDecodePicture);
pic->surface = surface; pic->gstbuffer = gst_buffer_ref (buffer);
pic->buffers = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 16); pic->buffers = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 16);
pic->slices = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 64); pic->slices = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 64);
return pic; return pic;
} }
VASurfaceID
gst_va_decode_picture_get_surface (GstVaDecodePicture * pic)
{
g_return_val_if_fail (pic, VA_INVALID_ID);
g_return_val_if_fail (pic->gstbuffer, VA_INVALID_ID);
return gst_va_buffer_get_surface (pic->gstbuffer, NULL);
}
void void
gst_va_decode_picture_free (GstVaDecodePicture * pic) gst_va_decode_picture_free (GstVaDecodePicture * pic)
{ {
@ -701,6 +725,7 @@ gst_va_decode_picture_free (GstVaDecodePicture * pic)
if (pic->buffers->len > 0 || pic->slices->len > 0) if (pic->buffers->len > 0 || pic->slices->len > 0)
GST_WARNING ("VABufferID are leaked"); GST_WARNING ("VABufferID are leaked");
gst_buffer_unref (pic->gstbuffer);
g_clear_pointer (&pic->buffers, g_array_unref); g_clear_pointer (&pic->buffers, g_array_unref);
g_clear_pointer (&pic->slices, g_array_unref); g_clear_pointer (&pic->slices, g_array_unref);

View file

@ -29,7 +29,7 @@ struct _GstVaDecodePicture
{ {
GArray *buffers; GArray *buffers;
GArray *slices; GArray *slices;
VASurfaceID surface; GstBuffer *gstbuffer;
}; };
#define GST_TYPE_VA_DECODER (gst_va_decoder_get_type()) #define GST_TYPE_VA_DECODER (gst_va_decoder_get_type())
@ -69,7 +69,8 @@ gboolean gst_va_decoder_decode (GstVaDecoder * self,
gboolean gst_va_decoder_destroy_buffers (GstVaDecoder * self, gboolean gst_va_decoder_destroy_buffers (GstVaDecoder * self,
GstVaDecodePicture * pic); GstVaDecodePicture * pic);
GstVaDecodePicture * gst_va_decode_picture_new (VASurfaceID surface); GstVaDecodePicture * gst_va_decode_picture_new (GstBuffer * buffer);
VASurfaceID gst_va_decode_picture_get_surface (GstVaDecodePicture * pic);
void gst_va_decode_picture_free (GstVaDecodePicture * pic); void gst_va_decode_picture_free (GstVaDecodePicture * pic);
G_END_DECLS G_END_DECLS

View file

@ -240,7 +240,7 @@ _fill_vaapi_pic (VAPictureH264 * va_picture, GstH264Picture * picture)
return; return;
} }
va_picture->picture_id = va_pic->surface; va_picture->picture_id = gst_va_decode_picture_get_surface (va_pic);
va_picture->flags = 0; va_picture->flags = 0;
if (picture->ref && picture->long_term) { if (picture->ref && picture->long_term) {
@ -553,19 +553,17 @@ gst_va_h264_dec_new_picture (GstH264Decoder * decoder,
GstVaH264Dec *self = GST_VA_H264_DEC (decoder); GstVaH264Dec *self = GST_VA_H264_DEC (decoder);
GstVaDecodePicture *pic; GstVaDecodePicture *pic;
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
VASurfaceID surface;
self->last_ret = gst_video_decoder_allocate_output_frame (vdec, frame); self->last_ret = gst_video_decoder_allocate_output_frame (vdec, frame);
if (self->last_ret != GST_FLOW_OK) if (self->last_ret != GST_FLOW_OK)
goto error; goto error;
surface = gst_va_buffer_get_surface (frame->output_buffer, NULL); pic = gst_va_decode_picture_new (frame->output_buffer);
pic = gst_va_decode_picture_new (surface);
gst_h264_picture_set_user_data (picture, pic, gst_h264_picture_set_user_data (picture, pic,
(GDestroyNotify) gst_va_decode_picture_free); (GDestroyNotify) gst_va_decode_picture_free);
GST_LOG_OBJECT (self, "New va decode picture %p - %#x", pic, pic->surface); GST_LOG_OBJECT (self, "New va decode picture %p - %#x", pic,
gst_va_decode_picture_get_surface (pic));
return TRUE; return TRUE;