va: allocator: get a surface format from a image format

For the allocator to create surfaces with the correct chroma an
fourcc, it should use a surface format, not necessarily the negotiated
format.

Instead of the previous arbitrary extra formats list, the decoder
extracts the valid pixel formats from the given VA config, and pass
that list to the allocator which stores it (full transfer).

Then, when the allocator allocates a new surface, it looks for a
surface color format chroma-compatible with the negotiated image color
format.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1483>
This commit is contained in:
Víctor Manuel Jáquez Leal 2020-08-01 15:47:19 +02:00 committed by GStreamer Merge Bot
parent 2327ac4a13
commit d3ef3d562a
9 changed files with 100 additions and 29 deletions

View file

@ -558,6 +558,7 @@ struct _GstVaAllocator
GstVaDisplay *display; GstVaDisplay *display;
gboolean use_derived; gboolean use_derived;
GArray *surface_formats;
}; };
typedef struct _GstVaMemory GstVaMemory; typedef struct _GstVaMemory GstVaMemory;
@ -588,6 +589,7 @@ gst_va_allocator_dispose (GObject * object)
GstVaAllocator *self = GST_VA_ALLOCATOR (object); GstVaAllocator *self = GST_VA_ALLOCATOR (object);
gst_clear_object (&self->display); gst_clear_object (&self->display);
g_clear_pointer (&self->surface_formats, g_array_unref);
G_OBJECT_CLASS (gst_va_allocator_parent_class)->dispose (object); G_OBJECT_CLASS (gst_va_allocator_parent_class)->dispose (object);
} }
@ -864,15 +866,20 @@ gst_va_allocator_alloc (GstAllocator * allocator,
self = GST_VA_ALLOCATOR (allocator); self = GST_VA_ALLOCATOR (allocator);
format = GST_VIDEO_INFO_FORMAT (&params->info); format =
if (gst_va_video_format_is_extra (format)) gst_va_video_surface_format_from_image_format (GST_VIDEO_INFO_FORMAT
format = GST_VIDEO_FORMAT_NV12; (&params->info), self->surface_formats);
if (format == GST_VIDEO_FORMAT_UNKNOWN) {
GST_ERROR_OBJECT (allocator, "Unsupported format: %s",
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&params->info)));
return NULL;
}
fourcc = gst_va_fourcc_from_video_format (format); fourcc = gst_va_fourcc_from_video_format (format);
rt_format = gst_va_chroma_from_video_format (format); rt_format = gst_va_chroma_from_video_format (format);
if (fourcc == 0 || rt_format == 0) { if (fourcc == 0 || rt_format == 0) {
GST_ERROR_OBJECT (allocator, "Unsupported format: %s", GST_ERROR_OBJECT (allocator, "Unsupported format: %s",
gst_video_format_to_string (format)); gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&params->info)));
return NULL; return NULL;
} }
@ -902,7 +909,7 @@ gst_va_allocator_alloc (GstAllocator * allocator,
} }
GstAllocator * GstAllocator *
gst_va_allocator_new (GstVaDisplay * display) gst_va_allocator_new (GstVaDisplay * display, GArray * surface_formats)
{ {
GstVaAllocator *self; GstVaAllocator *self;
@ -910,6 +917,7 @@ gst_va_allocator_new (GstVaDisplay * display)
self = g_object_new (GST_TYPE_VA_ALLOCATOR, NULL); self = g_object_new (GST_TYPE_VA_ALLOCATOR, NULL);
self->display = gst_object_ref (display); self->display = gst_object_ref (display);
self->surface_formats = surface_formats;
gst_object_ref_sink (self); gst_object_ref_sink (self);
return GST_ALLOCATOR (self); return GST_ALLOCATOR (self);

View file

@ -50,7 +50,8 @@ G_DECLARE_FINAL_TYPE (GstVaAllocator, gst_va_allocator, GST, VA_ALLOCATOR, GstAl
#define GST_ALLOCATOR_VASURFACE "VAMemory" #define GST_ALLOCATOR_VASURFACE "VAMemory"
GstAllocator * gst_va_allocator_new (GstVaDisplay * display); GstAllocator * gst_va_allocator_new (GstVaDisplay * display,
GArray * surface_formats);
GstMemory * gst_va_allocator_alloc (GstAllocator * allocator, GstMemory * gst_va_allocator_alloc (GstAllocator * allocator,
GstVaAllocationParams * params); GstVaAllocationParams * params);
gboolean gst_va_allocator_try (GstAllocator * allocator, gboolean gst_va_allocator_try (GstAllocator * allocator,

View file

@ -140,25 +140,6 @@ _gst_caps_set_format_array (GstCaps * caps, GArray * formats)
return TRUE; return TRUE;
} }
/* extra formats to add to raw caps bacause *in theory* all drivers
* could create images from surface's native format (NV12) to
* these. */
static const GstVideoFormat extra_formats[] = {
GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YV12
};
gboolean
gst_va_video_format_is_extra (guint format)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (extra_formats); i++) {
if (extra_formats[i] == format)
return TRUE;
}
return FALSE;
}
GstCaps * GstCaps *
gst_va_create_raw_caps_from_config (GstVaDisplay * display, VAConfigID config) gst_va_create_raw_caps_from_config (GstVaDisplay * display, VAConfigID config)
{ {

View file

@ -37,7 +37,5 @@ VASurfaceAttrib * gst_va_get_surface_attribs (GstVaDisplay * displa
GstCaps * gst_va_create_raw_caps_from_config (GstVaDisplay * display, GstCaps * gst_va_create_raw_caps_from_config (GstVaDisplay * display,
VAConfigID config); VAConfigID config);
gboolean gst_va_video_format_is_extra (guint format);
G_END_DECLS G_END_DECLS

View file

@ -26,6 +26,7 @@
#include "gstvacaps.h" #include "gstvacaps.h"
#include "gstvadisplay_wrapped.h" #include "gstvadisplay_wrapped.h"
#include "gstvavideoformat.h"
struct _GstVaDecoder struct _GstVaDecoder
{ {
@ -447,6 +448,50 @@ gst_va_decoder_get_mem_types (GstVaDecoder * self)
return ret; return ret;
} }
GArray *
gst_va_decoder_get_surface_formats (GstVaDecoder * self)
{
GArray *formats;
GstVideoFormat format;
VASurfaceAttrib *attribs;
guint i, attrib_count;
g_return_val_if_fail (GST_IS_VA_DECODER (self), NULL);
if (!gst_va_decoder_is_open (self))
return NULL;
attribs = gst_va_get_surface_attribs (self->display, self->config,
&attrib_count);
if (!attribs)
return NULL;
formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
for (i = 0; i < attrib_count; i++) {
if (attribs[i].value.type != VAGenericValueTypeInteger)
continue;
switch (attribs[i].type) {
case VASurfaceAttribPixelFormat:
format = gst_va_video_format_from_va_fourcc (attribs[i].value.value.i);
if (format != GST_VIDEO_FORMAT_UNKNOWN)
g_array_append_val (formats, format);
break;
default:
break;
}
}
g_free (attribs);
if (formats->len == 0) {
g_array_unref (formats);
return NULL;
}
return formats;
}
gboolean gboolean
gst_va_decoder_add_param_buffer (GstVaDecoder * self, GstVaDecodePicture * pic, gst_va_decoder_add_param_buffer (GstVaDecoder * self, GstVaDecodePicture * pic,
gint type, gpointer data, gsize size) gint type, gpointer data, gsize size)

View file

@ -51,6 +51,7 @@ GstCaps * gst_va_decoder_get_sinkpad_caps (GstVaDecoder * self);
gboolean gst_va_decoder_has_profile (GstVaDecoder * self, gboolean gst_va_decoder_has_profile (GstVaDecoder * self,
VAProfile profile); VAProfile profile);
gint gst_va_decoder_get_mem_types (GstVaDecoder * self); gint gst_va_decoder_get_mem_types (GstVaDecoder * self);
GArray * gst_va_decoder_get_surface_formats (GstVaDecoder * self);
gboolean gst_va_decoder_add_param_buffer (GstVaDecoder * self, gboolean gst_va_decoder_add_param_buffer (GstVaDecoder * self,
GstVaDecodePicture * pic, GstVaDecodePicture * pic,

View file

@ -1104,8 +1104,11 @@ _create_allocator (GstVaH264Dec * self, GstCaps * caps, guint * size)
if (_caps_is_dmabuf (self, caps)) if (_caps_is_dmabuf (self, caps))
allocator = gst_va_dmabuf_allocator_new (display); allocator = gst_va_dmabuf_allocator_new (display);
else else {
allocator = gst_va_allocator_new (display); GArray *surface_formats =
gst_va_decoder_get_surface_formats (self->decoder);
allocator = gst_va_allocator_new (display, surface_formats);
}
gst_object_unref (display); gst_object_unref (display);

View file

@ -204,3 +204,35 @@ gst_va_video_format_from_va_image_format (const VAImageFormat * va_format)
return map ? map->format : GST_VIDEO_FORMAT_UNKNOWN; return map ? map->format : GST_VIDEO_FORMAT_UNKNOWN;
} }
GstVideoFormat
gst_va_video_surface_format_from_image_format (GstVideoFormat image_format,
GArray * surface_formats)
{
GstVideoFormat surface_format;
guint i, image_chroma, surface_chroma;
if (image_format == GST_VIDEO_FORMAT_UNKNOWN)
return GST_VIDEO_FORMAT_UNKNOWN;
if (!surface_formats || surface_formats->len == 0)
return GST_VIDEO_FORMAT_UNKNOWN;
image_chroma = gst_va_chroma_from_video_format (image_format);
if (image_chroma == 0)
return GST_VIDEO_FORMAT_UNKNOWN;
for (i = 0; i < surface_formats->len; i++) {
surface_format = g_array_index (surface_formats, GstVideoFormat, i);
if (surface_format == image_format)
return surface_format;
surface_chroma = gst_va_chroma_from_video_format (surface_format);
if (surface_chroma == image_chroma)
return surface_format;
}
return GST_VIDEO_FORMAT_UNKNOWN;
}

View file

@ -30,5 +30,7 @@ guint gst_va_fourcc_from_video_format (GstVideoFormat format
guint gst_va_chroma_from_video_format (GstVideoFormat format); guint gst_va_chroma_from_video_format (GstVideoFormat format);
const VAImageFormat * gst_va_image_format_from_video_format (GstVideoFormat format); const VAImageFormat * gst_va_image_format_from_video_format (GstVideoFormat format);
GstVideoFormat gst_va_video_format_from_va_image_format (const VAImageFormat * va_format); GstVideoFormat gst_va_video_format_from_va_image_format (const VAImageFormat * va_format);
GstVideoFormat gst_va_video_surface_format_from_image_format (GstVideoFormat image_format,
GArray * surface_formats);
G_END_DECLS G_END_DECLS