Handle I420 formats internally in GstVaapiImage.

This commit is contained in:
gb 2010-03-16 08:43:16 +00:00
parent 1c965c3340
commit 69d58a0857
4 changed files with 99 additions and 79 deletions

View file

@ -54,15 +54,53 @@ enum {
};
static void
filter_formats(VAImageFormat *va_formats, unsigned int *pnum_va_formats)
append_format(
VAImageFormat **pva_formats,
unsigned int *pnum_va_formats,
GstVaapiImageFormat format
)
{
const VAImageFormat *va_format;
VAImageFormat *new_va_formats;
va_format = gst_vaapi_image_format_get_va_format(format);
if (!va_format)
return;
new_va_formats = realloc(
*pva_formats,
sizeof(new_va_formats[0]) * (1 + *pnum_va_formats)
);
if (!new_va_formats)
return;
new_va_formats[(*pnum_va_formats)++] = *va_format;
*pva_formats = new_va_formats;
}
static void
filter_formats(VAImageFormat **pva_formats, unsigned int *pnum_va_formats)
{
unsigned int i = 0;
gboolean has_YV12 = FALSE;
gboolean has_I420 = FALSE;
while (i < *pnum_va_formats) {
VAImageFormat * const va_format = &va_formats[i];
VAImageFormat * const va_format = &(*pva_formats)[i];
const GstVaapiImageFormat format = gst_vaapi_image_format(va_format);
if (format)
if (format) {
++i;
switch (format) {
case GST_VAAPI_IMAGE_YV12:
has_YV12 = TRUE;
break;
case GST_VAAPI_IMAGE_I420:
has_I420 = TRUE;
break;
default:
break;
}
}
else {
/* Remove any format that is not supported by libgstvaapi */
GST_DEBUG("unsupported format %c%c%c%c",
@ -70,9 +108,16 @@ filter_formats(VAImageFormat *va_formats, unsigned int *pnum_va_formats)
(va_format->fourcc >> 8) & 0xff,
(va_format->fourcc >> 16) & 0xff,
(va_format->fourcc >> 24) & 0xff);
*va_format = va_formats[--(*pnum_va_formats)];
*va_format = (*pva_formats)[--(*pnum_va_formats)];
}
}
/* Append I420 (resp. YV12) format if YV12 (resp. I420) is not
supported by the underlying driver */
if (has_YV12 && !has_I420)
append_format(pva_formats, pnum_va_formats, GST_VAAPI_IMAGE_I420);
else if (has_I420 && !has_YV12)
append_format(pva_formats, pnum_va_formats, GST_VAAPI_IMAGE_YV12);
}
/* Sort image formats. Prefer YUV formats first */
@ -207,7 +252,7 @@ gst_vaapi_display_create(GstVaapiDisplay *display)
for (i = 0; i < priv->num_image_formats; i++)
GST_DEBUG(" %s", string_of_FOURCC(priv->image_formats[i].fourcc));
filter_formats(priv->image_formats, &priv->num_image_formats);
filter_formats(&priv->image_formats, &priv->num_image_formats);
qsort(
priv->image_formats,
priv->num_image_formats,
@ -232,7 +277,7 @@ gst_vaapi_display_create(GstVaapiDisplay *display)
if (!vaapi_check_status(status, "vaQuerySubpictureFormats()"))
return FALSE;
filter_formats(priv->subpicture_formats, &priv->num_subpicture_formats);
filter_formats(&priv->subpicture_formats, &priv->num_subpicture_formats);
qsort(
priv->subpicture_formats,
priv->num_subpicture_formats,

View file

@ -39,6 +39,7 @@ struct _GstVaapiImagePrivate {
gboolean is_constructed;
VAImage image;
guchar *image_data;
GstVaapiImageFormat internal_format;
GstVaapiImageFormat format;
guint width;
guint height;
@ -77,29 +78,57 @@ gst_vaapi_image_destroy(GstVaapiImage *image)
}
static gboolean
gst_vaapi_image_create(GstVaapiImage *image)
_gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
{
GstVaapiImagePrivate * const priv = image->priv;
const VAImageFormat *format;
const VAImageFormat *va_format;
VAStatus status;
if (!gst_vaapi_display_has_image_format(priv->display, priv->format))
if (!gst_vaapi_display_has_image_format(priv->display, format))
return FALSE;
format = gst_vaapi_image_format_get_va_format(priv->format);
g_return_val_if_fail(format, FALSE);
va_format = gst_vaapi_image_format_get_va_format(format);
if (!va_format)
return FALSE;
status = vaCreateImage(
gst_vaapi_display_get_display(priv->display),
(VAImageFormat *)format,
(VAImageFormat *)va_format,
priv->width,
priv->height,
&priv->image
);
if (!vaapi_check_status(status, "vaCreateImage()"))
return (status == VA_STATUS_SUCCESS &&
priv->image.format.fourcc == va_format->fourcc);
}
static gboolean
gst_vaapi_image_create(GstVaapiImage *image)
{
GstVaapiImagePrivate * const priv = image->priv;
if (_gst_vaapi_image_create(image, priv->format)) {
priv->internal_format = priv->format;
return TRUE;
}
switch (priv->format) {
case GST_VAAPI_IMAGE_I420:
priv->internal_format = GST_VAAPI_IMAGE_YV12;
break;
case GST_VAAPI_IMAGE_YV12:
priv->internal_format = GST_VAAPI_IMAGE_I420;
break;
default:
priv->internal_format = 0;
break;
}
if (!priv->internal_format)
return FALSE;
if (!_gst_vaapi_image_create(image, priv->internal_format))
return FALSE;
GST_DEBUG("image 0x%08x", priv->image.image_id);
return TRUE;
}
@ -462,13 +491,15 @@ gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
return FALSE;
format = gst_vaapi_image_format_from_caps(caps);
swap_YUV = ((format == GST_VAAPI_IMAGE_I420 &&
priv->format == GST_VAAPI_IMAGE_YV12) ||
(format == GST_VAAPI_IMAGE_YV12 &&
priv->format == GST_VAAPI_IMAGE_I420));
if (format != priv->format && !swap_YUV)
if (format != priv->format)
return FALSE;
swap_YUV = (priv->format != priv->internal_format &&
((priv->format == GST_VAAPI_IMAGE_I420 &&
priv->internal_format == GST_VAAPI_IMAGE_YV12) ||
(priv->format == GST_VAAPI_IMAGE_YV12 &&
priv->internal_format == GST_VAAPI_IMAGE_I420)));
structure = gst_caps_get_structure(caps, 0);
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
@ -478,7 +509,7 @@ gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
if (!gst_vaapi_image_map(image))
return FALSE;
if (format == priv->format && data_size == priv->image.data_size)
if (format == priv->internal_format && data_size == priv->image.data_size)
memcpy(priv->image_data, data, data_size);
else {
/* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */

View file

@ -292,41 +292,14 @@ gst_vaapiconvert_transform_caps(
return NULL;
out_caps = gst_caps_from_string(gst_vaapiconvert_yuv_caps_str);
if (convert->display) {
GstVaapiImageFormat fixup_format;
GstCaps *allowed_caps, *new_caps;
GstCaps *allowed_caps, *inter_caps;
allowed_caps = gst_vaapi_display_get_image_caps(convert->display);
if (!allowed_caps)
return NULL;
new_caps = gst_caps_intersect(out_caps, allowed_caps);
inter_caps = gst_caps_intersect(out_caps, allowed_caps);
gst_caps_unref(allowed_caps);
gst_caps_unref(out_caps);
out_caps = new_caps;
convert->has_YV12 = gst_vaapi_display_has_image_format(
convert->display,
GST_VAAPI_IMAGE_YV12
);
convert->has_I420 = gst_vaapi_display_has_image_format(
convert->display,
GST_VAAPI_IMAGE_I420
);
if (convert->has_YV12 && !convert->has_I420)
fixup_format = GST_VAAPI_IMAGE_I420;
else if (convert->has_I420 && !convert->has_YV12)
fixup_format = GST_VAAPI_IMAGE_YV12;
else
fixup_format = 0;
if (fixup_format) {
allowed_caps = gst_vaapi_image_format_get_caps(fixup_format);
if (allowed_caps) {
new_caps = gst_caps_union(out_caps, allowed_caps);
gst_caps_unref(allowed_caps);
gst_caps_unref(out_caps);
out_caps = new_caps;
}
}
out_caps = inter_caps;
}
}
@ -348,34 +321,13 @@ gst_vaapiconvert_set_caps(
)
{
GstVaapiConvert * const convert = GST_VAAPICONVERT(trans);
GstCaps *fixed_incaps = NULL;
GstStructure *structure;
gint width, height;
guint32 format;
structure = gst_caps_get_structure(incaps, 0);
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
#define GST_FORMAT_YV12 GST_MAKE_FOURCC ('Y', 'V', '1', '2')
#define GST_FORMAT_I420 GST_MAKE_FOURCC ('I', '4', '2', '0')
/* Fix I420 and YV12 formats */
if (gst_structure_get_fourcc(structure, "format", &format)) {
if (format == GST_FORMAT_I420 && !convert->has_I420)
format = GST_FORMAT_YV12;
else if (format == GST_FORMAT_YV12 && !convert->has_YV12)
format = GST_FORMAT_I420;
else
format = 0;
if (format) {
fixed_incaps = gst_caps_copy(incaps);
structure = gst_caps_get_structure(fixed_incaps, 0);
gst_structure_set(structure, "format", GST_TYPE_FOURCC, format, NULL);
incaps = fixed_incaps;
}
}
if (width != convert->image_width || height != convert->image_height) {
if (convert->images)
g_object_unref(convert->images);
@ -395,9 +347,6 @@ gst_vaapiconvert_set_caps(
if (!convert->surfaces)
return FALSE;
}
if (fixed_incaps)
gst_caps_unref(fixed_incaps);
return TRUE;
}

View file

@ -65,17 +65,12 @@ struct _GstVaapiConvert {
GstBaseTransform parent_instance;
GstVaapiDisplay *display;
GstVaapiImageFormat image_format;
GstVaapiVideoPool *images;
guint image_width;
guint image_height;
GstVaapiVideoPool *surfaces;
guint surface_width;
guint surface_height;
/* XXX: implement YV12 or I420 formats ourselves */
guint has_YV12 : 1;
guint has_I420 : 1;
};
struct _GstVaapiConvertClass {