mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-24 16:18:16 +00:00
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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1667>
This commit is contained in:
parent
482e93b4d8
commit
fbbf9c629a
7 changed files with 287 additions and 250 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue