struct _GstVaapiImagePrivate {
GstVaapiDisplay *display;
+ gboolean is_constructed;
VAImage image;
guchar *image_data;
+ GstVaapiImageFormat format;
guint width;
guint height;
- GstVaapiImageFormat format;
};
enum {
PROP_DISPLAY,
PROP_IMAGE_ID,
+ PROP_FORMAT,
PROP_WIDTH,
- PROP_HEIGHT,
- PROP_FORMAT
+ PROP_HEIGHT
};
static void
case PROP_DISPLAY:
priv->display = g_object_ref(g_value_get_object(value));
break;
+ case PROP_FORMAT:
+ priv->format = g_value_get_uint(value);
+ break;
case PROP_WIDTH:
priv->width = g_value_get_uint(value);
break;
case PROP_HEIGHT:
priv->height = g_value_get_uint(value);
break;
- case PROP_FORMAT:
- priv->format = g_value_get_uint(value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
case PROP_IMAGE_ID:
g_value_set_uint(value, gst_vaapi_image_get_id(image));
break;
+ case PROP_FORMAT:
+ g_value_set_uint(value, gst_vaapi_image_get_format(image));
+ break;
case PROP_WIDTH:
g_value_set_uint(value, gst_vaapi_image_get_width(image));
break;
case PROP_HEIGHT:
g_value_set_uint(value, gst_vaapi_image_get_height(image));
break;
- case PROP_FORMAT:
- g_value_set_uint(value, gst_vaapi_image_get_format(image));
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
GObjectClass *parent_class;
- gst_vaapi_image_create(image);
+ image->priv->is_constructed = gst_vaapi_image_create(image);
parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
if (parent_class->constructed)
GstVaapiImage *
gst_vaapi_image_new(
GstVaapiDisplay *display,
+ GstVaapiImageFormat format,
guint width,
- guint height,
- GstVaapiImageFormat format
+ guint height
)
{
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
return g_object_new(GST_VAAPI_TYPE_IMAGE,
"display", display,
+ "format", format,
"width", width,
"height", height,
- "format", format,
NULL);
}
gst_vaapi_image_get_id(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->image.image_id;
}
gst_vaapi_image_get_display(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->display;
}
gst_vaapi_image_get_width(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->width;
}
gst_vaapi_image_get_height(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->height;
}
gst_vaapi_image_get_format(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->format;
}
gst_vaapi_image_is_mapped(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
return _gst_vaapi_image_is_mapped(image);
}
VAStatus status;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
if (_gst_vaapi_image_is_mapped(image))
return TRUE;
VAStatus status;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
if (!_gst_vaapi_image_is_mapped(image))
return FALSE;
gst_vaapi_image_get_plane_count(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
return image->priv->image.num_planes;
gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
return image->priv->image.pitches[plane];
}
+
+gboolean
+gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
+{
+ GstVaapiImagePrivate *priv;
+ GstStructure *structure;
+ GstCaps *caps;
+ GstVaapiImageFormat format;
+ gint width, height;
+ guint offsets[3], pitches[3], widths[3], heights[3];
+ guint i, j;
+ guchar *data;
+ guint32 data_size;
+
+ g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+ g_return_val_if_fail(image->priv->is_constructed, FALSE);
+ g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
+
+ priv = image->priv;
+ data = GST_BUFFER_DATA(buffer);
+ data_size = GST_BUFFER_SIZE(buffer);
+ caps = GST_BUFFER_CAPS(buffer);
+
+ if (!caps)
+ return FALSE;
+
+ format = gst_vaapi_image_format_from_caps(caps);
+ if (format != priv->format)
+ return FALSE;
+
+ structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(structure, "width", &width);
+ gst_structure_get_int(structure, "height", &height);
+ if (width != priv->width || height != priv->height)
+ return FALSE;
+
+ if (!gst_vaapi_image_map(image))
+ return FALSE;
+
+ if (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? */
+ const guint width2 = (width + 1) / 2;
+ const guint height2 = (height + 1) / 2;
+ guint size2;
+ switch (format) {
+ case GST_VAAPI_IMAGE_NV12:
+ offsets[0] = 0;
+ pitches[0] = GST_ROUND_UP_4(width);
+ widths [0] = width;
+ heights[0] = height;
+ offsets[1] = offsets[0] + height * pitches[0];
+ pitches[1] = pitches[0];
+ widths [1] = width2 * 2;
+ heights[1] = height2;
+ size2 = offsets[1] + height2 * pitches[1];
+ break;
+ case GST_VAAPI_IMAGE_YV12:
+ case GST_VAAPI_IMAGE_I420:
+ offsets[0] = 0;
+ pitches[0] = GST_ROUND_UP_4(width);
+ widths [0] = width;
+ heights[0] = height;
+ offsets[1] = offsets[0] + height * pitches[0];
+ pitches[1] = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
+ widths [1] = width2;
+ heights[1] = height2;
+ offsets[2] = offsets[1] + height2 * pitches[1];
+ pitches[2] = pitches[1];
+ widths [2] = width2;
+ heights[2] = height2;
+ size2 = offsets[2] + height2 * pitches[2];
+ break;
+ case GST_VAAPI_IMAGE_ARGB:
+ case GST_VAAPI_IMAGE_RGBA:
+ case GST_VAAPI_IMAGE_ABGR:
+ case GST_VAAPI_IMAGE_BGRA:
+ offsets[0] = 0;
+ pitches[0] = width * 4;
+ widths [0] = width * 4;
+ heights[0] = height;
+ size2 = offsets[0] + height * pitches[0];
+ break;
+ default:
+ g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS(format));
+ break;
+ }
+ if (size2 != data_size)
+ g_error("data_size mismatch %d / %u", size2, data_size);
+ for (i = 0; i < priv->image.num_planes; i++) {
+ guchar *src = data + offsets[i];
+ guchar *dst = priv->image_data + priv->image.offsets[i];
+ for (j = 0; j < heights[i]; j++) {
+ memcpy(dst, src, widths[i]);
+ src += pitches[i];
+ dst += priv->image.pitches[i];
+ }
+ }
+ }
+
+ if (!gst_vaapi_image_unmap(image))
+ return FALSE;
+
+ return TRUE;
+}