diff options
author | He Junyan <junyan.he@intel.com> | 2021-01-19 15:17:58 +0800 |
---|---|---|
committer | He Junyan <junyan.he@intel.com> | 2021-02-23 13:52:50 +0800 |
commit | a119a940e4127bb764008b5ec5e8d7eaa9e50b5a (patch) | |
tree | c2a8507117c7ec045f63a32f85ff7d091d611af8 /sys | |
parent | e40e78a7938bbbd675b472f1aba75ef9671b7c49 (diff) | |
download | gstreamer-plugins-bad-a119a940e4127bb764008b5ec5e8d7eaa9e50b5a.tar.gz |
VA: Add the aux surface for gst buffer used by decoder.
The AV1 codec needs to support the film grain feature. When the film
grain feature is enabled, we need two surfaces as the output of the
decoded picture, one without film grain effect and the other one with
it. The first one acts as the reference and is needed for later pictures'
reconstruction, and the second one is the real display output.
So we need to attach another aux surface to the gst buffer/mem and make
that aux surface as the target of vaBeginPicture.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1636>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/va/gstvaallocator.c | 114 | ||||
-rw-r--r-- | sys/va/gstvaallocator.h | 3 | ||||
-rw-r--r-- | sys/va/gstvadecoder.c | 26 | ||||
-rw-r--r-- | sys/va/gstvadecoder.h | 4 |
4 files changed, 144 insertions, 3 deletions
diff --git a/sys/va/gstvaallocator.c b/sys/va/gstvaallocator.c index a2ca9f0c5..9ef3b891a 100644 --- a/sys/va/gstvaallocator.c +++ b/sys/va/gstvaallocator.c @@ -320,6 +320,19 @@ gst_va_drm_mod_quark (void) return drm_mod_quark; } +static GQuark +gst_va_buffer_aux_surface_quark (void) +{ + static gsize surface_quark = 0; + + if (g_once_init_enter (&surface_quark)) { + GQuark quark = g_quark_from_string ("GstVaBufferAuxSurface"); + g_once_init_leave (&surface_quark, quark); + } + + return surface_quark; +} + /*========================= GstVaBufferSurface ===============================*/ typedef struct _GstVaBufferSurface GstVaBufferSurface; @@ -1605,3 +1618,104 @@ gst_va_buffer_get_surface (GstBuffer * buffer) return gst_va_memory_get_surface (mem); } + +gboolean +gst_va_buffer_create_aux_surface (GstBuffer * buffer) +{ + GstMemory *mem; + VASurfaceID surface = VA_INVALID_ID; + GstVaDisplay *display = NULL; + GstVideoFormat format; + gint width, height; + GstVaBufferSurface *surface_buffer; + + mem = gst_buffer_peek_memory (buffer, 0); + if (!mem) + return FALSE; + + /* Already created it. */ + surface_buffer = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem), + gst_va_buffer_aux_surface_quark ()); + if (surface_buffer) + return TRUE; + + if (!mem->allocator) + return FALSE; + + if (GST_IS_VA_DMABUF_ALLOCATOR (mem->allocator)) { + GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (mem->allocator); + guint32 fourcc, rt_format; + + format = GST_VIDEO_INFO_FORMAT (&self->info); + fourcc = gst_va_fourcc_from_video_format (format); + rt_format = gst_va_chroma_from_video_format (format); + if (fourcc == 0 || rt_format == 0) { + GST_ERROR_OBJECT (self, "Unsupported format: %s", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&self->info))); + return FALSE; + } + + display = self->display; + width = GST_VIDEO_INFO_WIDTH (&self->info); + height = GST_VIDEO_INFO_HEIGHT (&self->info); + if (!_create_surfaces (self->display, rt_format, fourcc, + GST_VIDEO_INFO_WIDTH (&self->info), + GST_VIDEO_INFO_HEIGHT (&self->info), self->usage_hint, NULL, + &surface, 1)) + return FALSE; + } else if (GST_IS_VA_ALLOCATOR (mem->allocator)) { + GstVaAllocator *self = GST_VA_ALLOCATOR (mem->allocator); + + if (self->fourcc == 0 || self->rt_format == 0) { + GST_ERROR_OBJECT (self, "Unknown fourcc or chroma format"); + return FALSE; + } + + display = self->display; + width = GST_VIDEO_INFO_WIDTH (&self->info); + height = GST_VIDEO_INFO_HEIGHT (&self->info); + format = GST_VIDEO_INFO_FORMAT (&self->info); + if (!_create_surfaces (self->display, self->rt_format, self->fourcc, + GST_VIDEO_INFO_WIDTH (&self->info), + GST_VIDEO_INFO_HEIGHT (&self->info), self->usage_hint, NULL, + &surface, 1)) + return FALSE; + } else { + g_assert_not_reached (); + } + + if (!display || surface == VA_INVALID_ID) + return FALSE; + + surface_buffer = gst_va_buffer_surface_new (surface, format, width, height); + surface_buffer->display = gst_object_ref (display); + g_atomic_int_add (&surface_buffer->ref_count, 1); + + gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), + gst_va_buffer_aux_surface_quark (), surface_buffer, + gst_va_buffer_surface_unref); + + return TRUE; +} + +VASurfaceID +gst_va_buffer_get_aux_surface (GstBuffer * buffer) +{ + GstVaBufferSurface *surface_buffer; + GstMemory *mem; + + mem = gst_buffer_peek_memory (buffer, 0); + if (!mem) + return VA_INVALID_ID; + + surface_buffer = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem), + gst_va_buffer_aux_surface_quark ()); + if (!surface_buffer) + return VA_INVALID_ID; + + /* No one increments it, and its lifetime is the same with the + gstmemory itself */ + g_assert (g_atomic_int_get (&surface_buffer->ref_count) == 1); + + return surface_buffer->surface; +} diff --git a/sys/va/gstvaallocator.h b/sys/va/gstvaallocator.h index 23e06ee7e..e4123c251 100644 --- a/sys/va/gstvaallocator.h +++ b/sys/va/gstvaallocator.h @@ -77,4 +77,7 @@ gboolean gst_va_allocator_get_format (GstAllocator * alloca VASurfaceID gst_va_memory_get_surface (GstMemory * mem); VASurfaceID gst_va_buffer_get_surface (GstBuffer * buffer); +gboolean gst_va_buffer_create_aux_surface (GstBuffer * buffer); +VASurfaceID gst_va_buffer_get_aux_surface (GstBuffer * buffer); + G_END_DECLS diff --git a/sys/va/gstvadecoder.c b/sys/va/gstvadecoder.c index a75503844..f47728258 100644 --- a/sys/va/gstvadecoder.c +++ b/sys/va/gstvadecoder.c @@ -575,18 +575,23 @@ gst_va_decoder_add_slice_buffer (GstVaDecoder * self, GstVaDecodePicture * pic, } gboolean -gst_va_decoder_decode (GstVaDecoder * self, GstVaDecodePicture * pic) +gst_va_decoder_decode_with_aux_surface (GstVaDecoder * self, + GstVaDecodePicture * pic, gboolean use_aux) { VADisplay dpy; VAStatus status; - VASurfaceID surface; + VASurfaceID surface = VA_INVALID_ID; gboolean ret = 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 (pic, FALSE); - surface = gst_va_decode_picture_get_surface (pic); + if (use_aux) { + surface = gst_va_decode_picture_get_aux_surface (pic); + } else { + surface = gst_va_decode_picture_get_surface (pic); + } if (surface == VA_INVALID_ID) { GST_ERROR_OBJECT (self, "Decode picture without VASurfaceID"); return FALSE; @@ -648,6 +653,12 @@ fail_end_pic: } } +gboolean +gst_va_decoder_decode (GstVaDecoder * self, GstVaDecodePicture * pic) +{ + return gst_va_decoder_decode_with_aux_surface (self, pic, FALSE); +} + static gboolean _destroy_buffers (GstVaDecodePicture * pic) { @@ -716,6 +727,15 @@ gst_va_decode_picture_get_surface (GstVaDecodePicture * pic) return gst_va_buffer_get_surface (pic->gstbuffer); } +VASurfaceID +gst_va_decode_picture_get_aux_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_aux_surface (pic->gstbuffer); +} + void gst_va_decode_picture_free (GstVaDecodePicture * pic) { diff --git a/sys/va/gstvadecoder.h b/sys/va/gstvadecoder.h index 1c683546f..c3a16a354 100644 --- a/sys/va/gstvadecoder.h +++ b/sys/va/gstvadecoder.h @@ -75,10 +75,14 @@ gboolean gst_va_decoder_add_slice_buffer_with_n_params gsize slice_size); gboolean gst_va_decoder_decode (GstVaDecoder * self, GstVaDecodePicture * pic); +gboolean gst_va_decoder_decode_with_aux_surface (GstVaDecoder * self, + GstVaDecodePicture * pic, + gboolean use_aux); GstVaDecodePicture * gst_va_decode_picture_new (GstVaDecoder * self, GstBuffer * buffer); VASurfaceID gst_va_decode_picture_get_surface (GstVaDecodePicture * pic); +VASurfaceID gst_va_decode_picture_get_aux_surface (GstVaDecodePicture * pic); void gst_va_decode_picture_free (GstVaDecodePicture * pic); GstVaDecodePicture * gst_va_decode_picture_dup (GstVaDecodePicture * pic); |