From fbbf9c629a79d20731fee03b645b88f0039824bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Wed, 7 Oct 2020 18:03:20 +0200 Subject: [PATCH] va: allocator: add _set_format() and _get_format() Since allocators keep an available memory queue to reuse, video format and usage hint are now persistant while allocator's memories are around. This patch adds _set_format() and _get_format() for both VA allocators. _set_format() validates if given format can be used or reused. If no allocated surface previously it creates a dummy one to fetch its offsets and strides. Updated info is returned to callee. GstVaPool uses _set_format() at config to verify the allocator capacity and to get the surfaces offsets and strides, which are going to be used by the video meta. Allocator extracted caps are compared with caps from config and if they have different strides or offsets, force_videometa is set. A new bufferpool method gst_va_pool_requires_video_meta() is added return the value of force_videometa. This value is checked in order to know if decoders need to copy the surface if downstream doesn't announce video meta support. Part-of: --- sys/va/gstvaallocator.c | 270 ++++++++++++++++++++++++++++++---------- sys/va/gstvaallocator.h | 29 +++-- sys/va/gstvah264dec.c | 77 ++---------- sys/va/gstvapool.c | 60 ++++++--- sys/va/gstvapool.h | 1 + sys/va/gstvavp8dec.c | 74 ++--------- sys/va/gstvavpp.c | 26 ---- 7 files changed, 287 insertions(+), 250 deletions(-) diff --git a/sys/va/gstvaallocator.c b/sys/va/gstvaallocator.c index f249913ac3..7e68ba4332 100644 --- a/sys/va/gstvaallocator.c +++ b/sys/va/gstvaallocator.c @@ -400,6 +400,9 @@ struct _GstVaDmabufAllocator GstMemoryMapFunction parent_map; GCond buffer_cond; + + GstVideoInfo info; + guint usage_hint; }; #define gst_va_dmabuf_allocator_parent_class dmabuf_parent_class @@ -514,11 +517,15 @@ gst_va_dmabuf_memory_release (GstMiniObject * mini_object) return FALSE; } -/* creates an exported VASurface and adds it as @buffer's memories - * qdata */ -gboolean -gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, - GstBuffer * buffer, GstVaAllocationParams * params) +/* Creates an exported VASurface and adds it as @buffer's memories + * qdata + * + * If @info is not NULL, a dummy (non-pooled) buffer is created to + * update offsets and strides, and it has to be unrefed immediately. + */ +static gboolean +gst_va_dmabuf_allocator_setup_buffer_full (GstAllocator * allocator, + GstBuffer * buffer, GstVideoInfo * info) { GstVaBufferSurface *buf; GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (allocator); @@ -528,20 +535,19 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, guint32 i, fourcc, rt_format, export_flags; g_return_val_if_fail (GST_IS_VA_DMABUF_ALLOCATOR (allocator), FALSE); - g_return_val_if_fail (params, FALSE); - format = GST_VIDEO_INFO_FORMAT (¶ms->info); + 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 (allocator, "Unsupported format: %s", - gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (¶ms->info))); + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&self->info))); return FALSE; } if (!_create_surfaces (self->display, rt_format, fourcc, - GST_VIDEO_INFO_WIDTH (¶ms->info), - GST_VIDEO_INFO_HEIGHT (¶ms->info), params->usage_hint, NULL, + GST_VIDEO_INFO_WIDTH (&self->info), + GST_VIDEO_INFO_HEIGHT (&self->info), self->usage_hint, NULL, &surface, 1)) return FALSE; @@ -561,7 +567,7 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, if (!_export_surface_to_dmabuf (self->display, surface, export_flags, &desc)) goto failed; - g_assert (GST_VIDEO_INFO_N_PLANES (¶ms->info) == desc.num_layers); + g_assert (GST_VIDEO_INFO_N_PLANES (&self->info) == desc.num_layers); if (fourcc != desc.fourcc) { GST_ERROR ("Unsupported fourcc: %" GST_FOURCC_FORMAT, @@ -570,7 +576,10 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, } buf = gst_va_buffer_surface_new (surface, format, desc.width, desc.height); - GST_VIDEO_INFO_SIZE (¶ms->info) = 0; + if (G_UNLIKELY (info)) { + *info = self->info; + GST_VIDEO_INFO_SIZE (info) = 0; + } for (i = 0; i < desc.num_objects; i++) { gint fd = desc.objects[i].fd; @@ -581,7 +590,8 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, gst_buffer_append_memory (buffer, mem); - GST_MINI_OBJECT (mem)->dispose = gst_va_dmabuf_memory_release; + if (G_LIKELY (!info)) + GST_MINI_OBJECT (mem)->dispose = gst_va_dmabuf_memory_release; g_atomic_int_add (&buf->ref_count, 1); gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), @@ -591,21 +601,23 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), gst_va_drm_mod_quark (), drm_mod, g_free); - GST_VIDEO_INFO_SIZE (¶ms->info) += size; + if (G_UNLIKELY (info)) + GST_VIDEO_INFO_SIZE (info) += size; } - for (i = 0; i < desc.num_layers; i++) { - g_assert (desc.layers[i].num_planes == 1); - GST_VIDEO_INFO_PLANE_OFFSET (¶ms->info, i) = desc.layers[i].offset[0]; - GST_VIDEO_INFO_PLANE_STRIDE (¶ms->info, i) = desc.layers[i].pitch[0]; + if (G_UNLIKELY (info)) { + for (i = 0; i < desc.num_layers; i++) { + g_assert (desc.layers[i].num_planes == 1); + GST_VIDEO_INFO_PLANE_OFFSET (info, i) = desc.layers[i].offset[0]; + GST_VIDEO_INFO_PLANE_STRIDE (info, i) = desc.layers[i].pitch[0]; + } + } else { + g_atomic_int_inc (&self->surface_count); } - g_atomic_int_inc (&self->surface_count); - GST_LOG_OBJECT (self, "Created surface %#x [%dx%d] size %" G_GSIZE_FORMAT, - buf->surface, GST_VIDEO_INFO_WIDTH (¶ms->info), - GST_VIDEO_INFO_HEIGHT (¶ms->info), - GST_VIDEO_INFO_SIZE (¶ms->info)); + buf->surface, GST_VIDEO_INFO_WIDTH (&self->info), + GST_VIDEO_INFO_HEIGHT (&self->info), GST_VIDEO_INFO_SIZE (&self->info)); return TRUE; @@ -616,6 +628,13 @@ failed: } } +gboolean +gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, + GstBuffer * buffer) +{ + return gst_va_dmabuf_allocator_setup_buffer_full (allocator, buffer, NULL); +} + gboolean gst_va_dmabuf_allocator_prepare_buffer (GstAllocator * allocator, GstBuffer * buffer) @@ -669,27 +688,75 @@ gst_va_dmabuf_allocator_flush (GstAllocator * allocator) GST_OBJECT_UNLOCK (self); } -gboolean -gst_va_dmabuf_try (GstAllocator * allocator, GstVaAllocationParams * params) +static gboolean +gst_va_dmabuf_allocator_try (GstAllocator * allocator) { - GstBuffer *buffer = gst_buffer_new (); - GstMapInfo map_info; + GstBuffer *buffer; + GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (allocator); + GstVideoInfo info = self->info; gboolean ret; - ret = gst_va_dmabuf_allocator_setup_buffer (allocator, buffer, params); - if (ret) { - /* XXX: radeonsi for kadaveri cannot map dmabufs to user space */ - if (!gst_buffer_map (buffer, &map_info, GST_MAP_READWRITE)) { - GST_WARNING_OBJECT (allocator, - "DMABuf backend cannot map frames to user space."); - } - gst_buffer_unmap (buffer, &map_info); - } + buffer = gst_buffer_new (); + ret = gst_va_dmabuf_allocator_setup_buffer_full (allocator, buffer, &info); gst_buffer_unref (buffer); + if (ret) + self->info = info; + return ret; } +gboolean +gst_va_dmabuf_allocator_set_format (GstAllocator * allocator, + GstVideoInfo * info, guint usage_hint) +{ + GstVaDmabufAllocator *self; + gboolean ret; + + g_return_val_if_fail (GST_IS_VA_DMABUF_ALLOCATOR (allocator), FALSE); + g_return_val_if_fail (info, FALSE); + + self = GST_VA_DMABUF_ALLOCATOR (allocator); + + if (self->surface_count != 0) { + if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_INFO_FORMAT (&self->info) + && GST_VIDEO_INFO_WIDTH (info) == GST_VIDEO_INFO_WIDTH (&self->info) + && GST_VIDEO_INFO_HEIGHT (info) == GST_VIDEO_INFO_HEIGHT (&self->info) + && usage_hint == self->usage_hint) { + *info = self->info; /* update callee info (offset & stride) */ + return TRUE; + } + return FALSE; + } + + self->usage_hint = usage_hint; + self->info = *info; + + ret = gst_va_dmabuf_allocator_try (allocator); + + if (ret) + *info = self->info; + + return ret; +} + +gboolean +gst_va_dmabuf_allocator_get_format (GstAllocator * allocator, + GstVideoInfo * info, guint * usage_hint) +{ + GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (allocator); + + if (GST_VIDEO_INFO_FORMAT (&self->info) == GST_VIDEO_FORMAT_UNKNOWN) + return FALSE; + + if (info) + *info = self->info; + if (usage_hint) + *usage_hint = self->usage_hint; + + return TRUE; +} + /* XXX: use a surface pool to control the created surfaces */ gboolean gst_va_dmabuf_memories_setup (GstVaDisplay * display, GstVideoInfo * info, @@ -773,6 +840,9 @@ struct _GstVaAllocator GArray *surface_formats; GCond buffer_cond; + + GstVideoInfo info; + guint usage_hint; }; typedef struct _GstVaMemory GstVaMemory; @@ -780,7 +850,6 @@ struct _GstVaMemory { GstMemory mem; - GstVideoInfo info; VASurfaceID surface; GstVideoFormat surface_format; VAImage image; @@ -886,7 +955,7 @@ _reset_mem (GstVaMemory * mem, GstAllocator * allocator, gsize size) static inline gboolean _ensure_image (GstVaDisplay * display, VASurfaceID surface, GstVideoInfo * info, - VAImage * image, gboolean * derived) + VAImage * image, gboolean * derived, gboolean update_info) { gint i; gboolean try_derived; @@ -909,12 +978,14 @@ _ensure_image (GstVaDisplay * display, VASurfaceID surface, GstVideoInfo * info, *derived = FALSE; bail: - for (i = 0; i < image->num_planes; i++) { - GST_VIDEO_INFO_PLANE_OFFSET (info, i) = image->offsets[i]; - GST_VIDEO_INFO_PLANE_STRIDE (info, i) = image->pitches[i]; - } + if (G_UNLIKELY (update_info)) { + for (i = 0; i < image->num_planes; i++) { + GST_VIDEO_INFO_PLANE_OFFSET (info, i) = image->offsets[i]; + GST_VIDEO_INFO_PLANE_STRIDE (info, i) = image->pitches[i]; + } - GST_VIDEO_INFO_SIZE (info) = image->data_size; + GST_VIDEO_INFO_SIZE (info) = image->data_size; + } return TRUE; } @@ -945,7 +1016,7 @@ _va_map_unlocked (GstVaMemory * mem, GstMapFlags flags) } else { /* GST_MAP_READ only */ mem->is_dirty = FALSE; mem->is_derived = va_allocator->use_derived && - (GST_VIDEO_INFO_FORMAT (&mem->info) == mem->surface_format); + (GST_VIDEO_INFO_FORMAT (&va_allocator->info) == mem->surface_format); } if (flags & GST_MAP_VA) { @@ -953,8 +1024,8 @@ _va_map_unlocked (GstVaMemory * mem, GstMapFlags flags) goto success; } - if (!_ensure_image (display, mem->surface, &mem->info, &mem->image, - &mem->is_derived)) + if (!_ensure_image (display, mem->surface, &va_allocator->info, &mem->image, + &mem->is_derived, FALSE)) return NULL; va_allocator->use_derived = mem->is_derived; @@ -1063,7 +1134,6 @@ _va_share (GstMemory * mem, gssize offset, gssize size) sub->surface = vamem->surface; sub->surface_format = vamem->surface_format; - sub->info = vamem->info; _clean_mem (sub); @@ -1110,14 +1180,16 @@ gst_va_memory_release (GstMiniObject * mini_object) return FALSE; } -GstMemory * -gst_va_allocator_alloc (GstAllocator * allocator, - GstVaAllocationParams * params) +/* If @info is not NULL, a dummy (non-pooled) memory and its VAImage + * are created, to update offsets and strides. The memory has to be + * unrefed immediately. + */ +static GstMemory * +gst_va_allocator_alloc_full (GstAllocator * allocator, GstVideoInfo * info) { GstVaAllocator *self; GstVaMemory *mem; GstVideoFormat format, img_format; - VAImage image = { 0, }; VASurfaceID surface; guint32 fourcc, rt_format; @@ -1125,7 +1197,7 @@ gst_va_allocator_alloc (GstAllocator * allocator, self = GST_VA_ALLOCATOR (allocator); - img_format = GST_VIDEO_INFO_FORMAT (¶ms->info); + img_format = GST_VIDEO_INFO_FORMAT (&self->info); format = gst_va_video_surface_format_from_image_format (img_format, self->surface_formats); @@ -1145,35 +1217,43 @@ gst_va_allocator_alloc (GstAllocator * allocator, } if (!_create_surfaces (self->display, rt_format, fourcc, - GST_VIDEO_INFO_WIDTH (¶ms->info), - GST_VIDEO_INFO_HEIGHT (¶ms->info), params->usage_hint, NULL, + GST_VIDEO_INFO_WIDTH (&self->info), + GST_VIDEO_INFO_HEIGHT (&self->info), self->usage_hint, NULL, &surface, 1)) return NULL; - image.image_id = VA_INVALID_ID; - if (!_ensure_image (self->display, surface, ¶ms->info, &image, NULL)) - return NULL; - _destroy_image (self->display, image.image_id); + if (G_UNLIKELY (info)) { + VAImage image = {.image_id = VA_INVALID_ID, }; + + if (!_ensure_image (self->display, surface, info, &image, NULL, TRUE)) + return NULL; + _destroy_image (self->display, image.image_id); + } mem = g_slice_new (GstVaMemory); mem->surface = surface; mem->surface_format = format; - mem->info = params->info; - _reset_mem (mem, allocator, GST_VIDEO_INFO_SIZE (¶ms->info)); + _reset_mem (mem, allocator, GST_VIDEO_INFO_SIZE (&self->info)); - GST_MINI_OBJECT (mem)->dispose = gst_va_memory_release; - - g_atomic_int_inc (&self->surface_count); + if (G_LIKELY (!info)) { + GST_MINI_OBJECT (mem)->dispose = gst_va_memory_release; + g_atomic_int_inc (&self->surface_count); + } GST_LOG_OBJECT (self, "Created surface %#x [%dx%d]", mem->surface, - GST_VIDEO_INFO_WIDTH (¶ms->info), - GST_VIDEO_INFO_HEIGHT (¶ms->info)); + GST_VIDEO_INFO_WIDTH (&self->info), GST_VIDEO_INFO_HEIGHT (&self->info)); return GST_MEMORY_CAST (mem); } +GstMemory * +gst_va_allocator_alloc (GstAllocator * allocator) +{ + return gst_va_allocator_alloc_full (allocator, NULL); +} + GstAllocator * gst_va_allocator_new (GstVaDisplay * display, GArray * surface_formats) { @@ -1224,15 +1304,69 @@ gst_va_allocator_flush (GstAllocator * allocator) GST_OBJECT_UNLOCK (self); } -gboolean -gst_va_allocator_try (GstAllocator * allocator, GstVaAllocationParams * params) +static gboolean +gst_va_allocator_try (GstAllocator * allocator) { GstMemory *mem; + GstVaAllocator *self = GST_VA_ALLOCATOR (allocator); + GstVideoInfo info = self->info; - mem = gst_va_allocator_alloc (allocator, params); + mem = gst_va_allocator_alloc_full (allocator, &info); if (!mem) return FALSE; gst_memory_unref (mem); + + self->info = info; + return TRUE; +} + +gboolean +gst_va_allocator_set_format (GstAllocator * allocator, GstVideoInfo * info, + guint usage_hint) +{ + GstVaAllocator *self; + gboolean ret; + + g_return_val_if_fail (GST_IS_VA_ALLOCATOR (allocator), FALSE); + g_return_val_if_fail (info, FALSE); + + self = GST_VA_ALLOCATOR (allocator); + + if (self->surface_count != 0) { + if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_INFO_FORMAT (&self->info) + && GST_VIDEO_INFO_WIDTH (info) == GST_VIDEO_INFO_WIDTH (&self->info) + && GST_VIDEO_INFO_HEIGHT (info) == GST_VIDEO_INFO_HEIGHT (&self->info) + && usage_hint == self->usage_hint) { + *info = self->info; /* update callee info (offset & stride) */ + return TRUE; + } + return FALSE; + } + + self->usage_hint = usage_hint; + self->info = *info; + + ret = gst_va_allocator_try (allocator); + if (ret) + *info = self->info; + + return ret; +} + +gboolean +gst_va_allocator_get_format (GstAllocator * allocator, GstVideoInfo * info, + guint * usage_hint) +{ + GstVaAllocator *self = GST_VA_ALLOCATOR (allocator); + + if (GST_VIDEO_INFO_FORMAT (&self->info) == GST_VIDEO_FORMAT_UNKNOWN) + return FALSE; + + if (info) + *info = self->info; + if (usage_hint) + *usage_hint = self->usage_hint; + return TRUE; } diff --git a/sys/va/gstvaallocator.h b/sys/va/gstvaallocator.h index 7040139b92..bbe364cb94 100644 --- a/sys/va/gstvaallocator.h +++ b/sys/va/gstvaallocator.h @@ -27,26 +27,22 @@ G_BEGIN_DECLS -typedef struct _GstVaAllocationParams GstVaAllocationParams; -struct _GstVaAllocationParams -{ - GstVideoInfo info; - guint32 usage_hint; -}; - #define GST_TYPE_VA_DMABUF_ALLOCATOR (gst_va_dmabuf_allocator_get_type()) G_DECLARE_FINAL_TYPE (GstVaDmabufAllocator, gst_va_dmabuf_allocator, GST, VA_DMABUF_ALLOCATOR, GstDmaBufAllocator); GstAllocator * gst_va_dmabuf_allocator_new (GstVaDisplay * display); gboolean gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator, - GstBuffer * buffer, - GstVaAllocationParams * params); + GstBuffer * buffer); gboolean gst_va_dmabuf_allocator_prepare_buffer (GstAllocator * allocator, GstBuffer * buffer); void gst_va_dmabuf_allocator_flush (GstAllocator * allocator); -gboolean gst_va_dmabuf_try (GstAllocator * allocator, - GstVaAllocationParams * params); +gboolean gst_va_dmabuf_allocator_set_format (GstAllocator * allocator, + GstVideoInfo * info, + guint usage_hint); +gboolean gst_va_dmabuf_allocator_get_format (GstAllocator * allocator, + GstVideoInfo * info, + guint * usage_hint); gboolean gst_va_dmabuf_memories_setup (GstVaDisplay * display, GstVideoInfo * info, @@ -65,13 +61,16 @@ G_DECLARE_FINAL_TYPE (GstVaAllocator, gst_va_allocator, GST, VA_ALLOCATOR, GstAl GstAllocator * gst_va_allocator_new (GstVaDisplay * display, GArray * surface_formats); -GstMemory * gst_va_allocator_alloc (GstAllocator * allocator, - GstVaAllocationParams * params); +GstMemory * gst_va_allocator_alloc (GstAllocator * allocator); gboolean gst_va_allocator_prepare_buffer (GstAllocator * allocator, GstBuffer * buffer); void gst_va_allocator_flush (GstAllocator * allocator); -gboolean gst_va_allocator_try (GstAllocator * allocator, - GstVaAllocationParams * params); +gboolean gst_va_allocator_set_format (GstAllocator * allocator, + GstVideoInfo * info, + guint usage_hint); +gboolean gst_va_allocator_get_format (GstAllocator * allocator, + GstVideoInfo * info, + guint * usage_hint); VASurfaceID gst_va_memory_get_surface (GstMemory * mem); VASurfaceID gst_va_buffer_get_surface (GstBuffer * buffer); diff --git a/sys/va/gstvah264dec.c b/sys/va/gstvah264dec.c index 88b7a9dc5f..102d716fb3 100644 --- a/sys/va/gstvah264dec.c +++ b/sys/va/gstvah264dec.c @@ -745,6 +745,17 @@ gst_va_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps, } } + if (!self->has_videometa) { + GstBufferPool *pool; + + pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self)); + self->copy_frames = gst_va_pool_requires_video_meta (pool); + gst_object_unref (pool); + + if (self->copy_frames) + GST_INFO_OBJECT (self, "Raw frame copy enabled."); + } + return TRUE; } @@ -1048,81 +1059,19 @@ gst_va_h264_dec_negotiate (GstVideoDecoder * decoder) return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder); } -static inline void -_shall_copy_frames (GstVaH264Dec * self, GstVideoInfo * info) -{ - GstVideoInfo ref_info; - guint i; - - self->copy_frames = FALSE; - - if (self->has_videometa) - return; - - gst_video_info_set_format (&ref_info, GST_VIDEO_INFO_FORMAT (info), - self->display_width, self->display_height); - - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - if (info->stride[i] != ref_info.stride[i] || - info->offset[i] != ref_info.offset[i]) { - GST_WARNING_OBJECT (self, - "GstVideoMeta support required, copying frames."); - self->copy_frames = TRUE; - break; - } - } -} - -static gboolean -_try_allocator (GstVaH264Dec * self, GstAllocator * allocator, GstCaps * caps) -{ - GstVaAllocationParams params = { - .usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_DECODER, - }; - - if (!gst_video_info_from_caps (¶ms.info, caps)) - return FALSE; - if (self->need_cropping) { - GST_VIDEO_INFO_WIDTH (¶ms.info) = self->coded_width; - GST_VIDEO_INFO_HEIGHT (¶ms.info) = self->coded_height; - } - - if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) { - if (!gst_va_dmabuf_try (allocator, ¶ms)) - return FALSE; - } else if (GST_IS_VA_ALLOCATOR (allocator)) { - if (!gst_va_allocator_try (allocator, ¶ms)) - return FALSE; - if (!gst_caps_is_vamemory (caps)) - _shall_copy_frames (self, ¶ms.info); - } else { - return FALSE; - } - - return TRUE; -} - static GstAllocator * _create_allocator (GstVaH264Dec * self, GstCaps * caps) { GstAllocator *allocator = NULL; - GstVaDisplay *display = NULL; - - g_object_get (self->decoder, "display", &display, NULL); if (gst_caps_is_dmabuf (caps)) - allocator = gst_va_dmabuf_allocator_new (display); + allocator = gst_va_dmabuf_allocator_new (self->display); else { GArray *surface_formats = gst_va_decoder_get_surface_formats (self->decoder); - allocator = gst_va_allocator_new (display, surface_formats); + allocator = gst_va_allocator_new (self->display, surface_formats); } - gst_object_unref (display); - - if (!_try_allocator (self, allocator, caps)) - gst_clear_object (&allocator); - return allocator; } diff --git a/sys/va/gstvapool.c b/sys/va/gstvapool.c index b86a115a78..63257bdc85 100644 --- a/sys/va/gstvapool.c +++ b/sys/va/gstvapool.c @@ -25,6 +25,7 @@ #include "gstvapool.h" #include "gstvaallocator.h" +#include "gstvacaps.h" GST_DEBUG_CATEGORY_STATIC (gst_va_pool_debug); #define GST_CAT_DEFAULT gst_va_pool_debug @@ -36,7 +37,7 @@ struct _GstVaPool GstVideoInfo alloc_info; GstVideoInfo caps_info; GstAllocator *allocator; - guint32 usage_hint; + gboolean force_videometa; gboolean add_videometa; gboolean need_alignment; GstVideoAlignment video_align; @@ -74,9 +75,9 @@ gst_va_pool_set_config (GstBufferPool * pool, GstStructure * config) GstCaps *caps; GstVaPool *vpool = GST_VA_POOL (pool); GstVideoAlignment video_align = { 0, }; - GstVideoInfo caps_info, alloc_info; + GstVideoInfo caps_info, alloc_info, orig_info; gint width, height; - guint min_buffers, max_buffers; + guint i, min_buffers, max_buffers; guint32 usage_hint; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, @@ -99,14 +100,12 @@ gst_va_pool_set_config (GstBufferPool * pool, GstStructure * config) if (!gst_buffer_pool_config_get_va_allocation_params (config, &usage_hint)) goto wrong_config; + orig_info = caps_info; width = GST_VIDEO_INFO_WIDTH (&caps_info); height = GST_VIDEO_INFO_HEIGHT (&caps_info); GST_LOG_OBJECT (vpool, "%dx%d | %" GST_PTR_FORMAT, width, height, caps); - gst_object_replace ((GstObject **) & vpool->allocator, - GST_OBJECT (allocator)); - /* enable metadata based on config of the pool */ vpool->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); @@ -128,15 +127,40 @@ gst_va_pool_set_config (GstBufferPool * pool, GstStructure * config) gst_buffer_pool_config_set_video_alignment (config, &video_align); } + /* update allocation info with aligned size */ alloc_info = caps_info; GST_VIDEO_INFO_WIDTH (&alloc_info) = width; GST_VIDEO_INFO_HEIGHT (&alloc_info) = height; + if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) { + if (!gst_va_dmabuf_allocator_set_format (allocator, &alloc_info, + usage_hint)) + goto failed_allocator; + } else if (GST_IS_VA_ALLOCATOR (allocator)) { + if (!gst_va_allocator_set_format (allocator, &alloc_info, usage_hint)) + goto failed_allocator; + } + + gst_object_replace ((GstObject **) & vpool->allocator, + GST_OBJECT (allocator)); + vpool->caps_info = caps_info; vpool->alloc_info = alloc_info; - vpool->usage_hint = usage_hint; vpool->video_align = video_align; + if (gst_caps_is_raw (caps)) { + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&caps_info); i++) { + if (GST_VIDEO_INFO_PLANE_STRIDE (&orig_info, i) != + GST_VIDEO_INFO_PLANE_STRIDE (&alloc_info, i) || + GST_VIDEO_INFO_PLANE_OFFSET (&orig_info, i) != + GST_VIDEO_INFO_PLANE_OFFSET (&alloc_info, i)) { + GST_INFO_OBJECT (vpool, "Video meta is required in buffer."); + vpool->force_videometa = TRUE; + break; + } + } + } + /* with pooled allocators bufferpool->release_buffer() is cheated * because the memories are removed from the buffer at * reset_buffer(), then buffer is an empty holder with size 0 while @@ -167,6 +191,11 @@ failed_to_align: GST_WARNING_OBJECT (vpool, "Failed to align"); return FALSE; } +failed_allocator: + { + GST_WARNING_OBJECT (vpool, "Failed to set format to allocator"); + return FALSE; + } } static GstFlowReturn @@ -176,19 +205,14 @@ gst_va_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer, GstBuffer *buf; GstVideoMeta *vmeta; GstVaPool *vpool = GST_VA_POOL (pool); - GstVaAllocationParams alloc_params = { - .info = vpool->alloc_info, - .usage_hint = vpool->usage_hint, - }; buf = gst_buffer_new (); if (GST_IS_VA_DMABUF_ALLOCATOR (vpool->allocator)) { - if (!gst_va_dmabuf_allocator_setup_buffer (vpool->allocator, buf, - &alloc_params)) + if (!gst_va_dmabuf_allocator_setup_buffer (vpool->allocator, buf)) goto no_memory; } else if (GST_IS_VA_ALLOCATOR (vpool->allocator)) { - GstMemory *mem = gst_va_allocator_alloc (vpool->allocator, &alloc_params); + GstMemory *mem = gst_va_allocator_alloc (vpool->allocator); if (!mem) goto no_memory; gst_buffer_append_memory (buf, mem); @@ -203,7 +227,7 @@ gst_va_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer, GST_VIDEO_INFO_WIDTH (&vpool->caps_info), GST_VIDEO_INFO_HEIGHT (&vpool->caps_info), GST_VIDEO_INFO_N_PLANES (&vpool->caps_info), - alloc_params.info.offset, alloc_params.info.stride); + vpool->alloc_info.offset, vpool->alloc_info.stride); if (vpool->need_alignment) gst_video_meta_set_alignment (vmeta, vpool->video_align); @@ -342,3 +366,9 @@ gst_buffer_pool_config_set_va_allocation_params (GstStructure * config, { gst_structure_set (config, "usage-hint", G_TYPE_UINT, usage_hint, NULL); } + +gboolean +gst_va_pool_requires_video_meta (GstBufferPool * pool) +{ + return GST_VA_POOL (pool)->force_videometa; +} diff --git a/sys/va/gstvapool.h b/sys/va/gstvapool.h index 38e73fe72e..af8416965b 100644 --- a/sys/va/gstvapool.h +++ b/sys/va/gstvapool.h @@ -28,6 +28,7 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GstVaPool, gst_va_pool, GST, VA_POOL, GstBufferPool) GstBufferPool * gst_va_pool_new (void); +gboolean gst_va_pool_requires_video_meta (GstBufferPool * pool); void gst_buffer_pool_config_set_va_allocation_params (GstStructure * config, guint usage_hint); G_END_DECLS diff --git a/sys/va/gstvavp8dec.c b/sys/va/gstvavp8dec.c index e9f2d4033e..dfcc71f7e8 100644 --- a/sys/va/gstvavp8dec.c +++ b/sys/va/gstvavp8dec.c @@ -367,77 +367,19 @@ gst_va_vp8_dec_negotiate (GstVideoDecoder * decoder) return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder); } -static inline void -_shall_copy_frames (GstVaVp8Dec * self, GstVideoInfo * info) -{ - GstVideoInfo ref_info; - guint i; - - self->copy_frames = FALSE; - - if (self->has_videometa) - return; - - gst_video_info_set_format (&ref_info, GST_VIDEO_INFO_FORMAT (info), - self->width, self->height); - - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - if (info->stride[i] != ref_info.stride[i] || - info->offset[i] != ref_info.offset[i]) { - GST_WARNING_OBJECT (self, - "GstVideoMeta support required, copying frames."); - self->copy_frames = TRUE; - break; - } - } -} - -static gboolean -_try_allocator (GstVaVp8Dec * self, GstAllocator * allocator, GstCaps * caps) -{ - GstVaAllocationParams params = { - .usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_DECODER, - }; - - if (!gst_video_info_from_caps (¶ms.info, caps)) - return FALSE; - - if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) { - if (!gst_va_dmabuf_try (allocator, ¶ms)) - return FALSE; - } else if (GST_IS_VA_ALLOCATOR (allocator)) { - if (!gst_va_allocator_try (allocator, ¶ms)) - return FALSE; - if (!gst_caps_is_vamemory (caps)) - _shall_copy_frames (self, ¶ms.info); - } else { - return FALSE; - } - - return TRUE; -} - static GstAllocator * _create_allocator (GstVaVp8Dec * self, GstCaps * caps) { GstAllocator *allocator = NULL; - GstVaDisplay *display = NULL; - g_object_get (self->decoder, "display", &display, NULL); - - if (gst_caps_is_dmabuf (caps)) - allocator = gst_va_dmabuf_allocator_new (display); - else { + if (gst_caps_is_dmabuf (caps)) { + allocator = gst_va_dmabuf_allocator_new (self->display); + } else { GArray *surface_formats = gst_va_decoder_get_surface_formats (self->decoder); - allocator = gst_va_allocator_new (display, surface_formats); + allocator = gst_va_allocator_new (self->display, surface_formats); } - gst_object_unref (display); - - if (!_try_allocator (self, allocator, caps)) - gst_clear_object (&allocator); - return allocator; } @@ -657,6 +599,14 @@ gst_va_vp8_dec_new_sequence (GstVp8Decoder * decoder, } } + if (!self->has_videometa) { + GstBufferPool *pool; + + pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self)); + self->copy_frames = gst_va_pool_requires_video_meta (pool); + gst_object_unref (pool); + } + return TRUE; } diff --git a/sys/va/gstvavpp.c b/sys/va/gstvavpp.c index 022c33f99b..b5f944c670 100644 --- a/sys/va/gstvavpp.c +++ b/sys/va/gstvavpp.c @@ -395,29 +395,6 @@ gst_va_vpp_set_context (GstElement * element, GstContext * context) GST_ELEMENT_CLASS (parent_class)->set_context (element, context); } -static gboolean -_try_allocator (GstVaVpp * self, GstAllocator * allocator, GstCaps * caps, - guint usage_hint) -{ - GstVaAllocationParams params = { - .usage_hint = usage_hint, - }; - - if (!gst_video_info_from_caps (¶ms.info, caps)) - return FALSE; - if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) { - if (!gst_va_dmabuf_try (allocator, ¶ms)) - return FALSE; - } else if (GST_IS_VA_ALLOCATOR (allocator)) { - if (!gst_va_allocator_try (allocator, ¶ms)) - return FALSE; - } else { - return FALSE; - } - - return TRUE; -} - static GstAllocator * _create_allocator (GstVaVpp * self, GstCaps * caps, guint usage_hint) { @@ -430,9 +407,6 @@ _create_allocator (GstVaVpp * self, GstCaps * caps, guint usage_hint) allocator = gst_va_allocator_new (self->display, surface_formats); } - if (!_try_allocator (self, allocator, caps, usage_hint)) - gst_clear_object (&allocator); - return allocator; }