From 4dd36435a768d0355a364d59f38a7f5e46917a96 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 22 Nov 2009 22:29:58 +0100 Subject: [PATCH] vdpau: add functions to GstVdpOutputBuffer needed for rgb download --- sys/vdpau/gstvdpoutputbuffer.c | 199 +++++++++++++++++++++++++++++++-- sys/vdpau/gstvdpoutputbuffer.h | 8 ++ 2 files changed, 198 insertions(+), 9 deletions(-) diff --git a/sys/vdpau/gstvdpoutputbuffer.c b/sys/vdpau/gstvdpoutputbuffer.c index 2d235f024a..f97a581f34 100644 --- a/sys/vdpau/gstvdpoutputbuffer.c +++ b/sys/vdpau/gstvdpoutputbuffer.c @@ -51,6 +51,10 @@ gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format, (GstVdpOutputBuffer *) gst_mini_object_new (GST_TYPE_VDP_OUTPUT_BUFFER); buffer->device = g_object_ref (device); + buffer->rgba_format = rgba_format; + buffer->width = width; + buffer->height = height; + buffer->surface = surface; return buffer; @@ -133,8 +137,8 @@ GstVdpOutputBufferFormats rgba_formats[] = { {VDP_RGBA_FORMAT_A8, GST_STATIC_CAPS ("video/x-raw-rgb, " "bpp = (int)8, " - "depth = (int)0, " - "endianness = G_BIG_ENDIAN, " + "depth = (int)8, " + "endianness = (int)4321, " "red_mask = (int)0x00, " "green_mask = (int)0x00, " "blue_mask = (int)0x00, " "alpha_mask = (int)0xff")}, @@ -142,7 +146,7 @@ GstVdpOutputBufferFormats rgba_formats[] = { GST_STATIC_CAPS ("video/x-raw-rgb, " "bpp = (int)32, " "depth = (int)30, " - "endianness = G_BIG_ENDIAN, " + "endianness = (int)4321, " "red_mask = (int)0x000003fc, " "green_mask = (int)0x003ff000, " "blue_mask = (int)0xffc00000, " "alpha_mask = (int)0x00000003")}, @@ -150,7 +154,7 @@ GstVdpOutputBufferFormats rgba_formats[] = { GST_STATIC_CAPS ("video/x-raw-rgb, " "bpp = (int)32, " "depth = (int)24, " - "endianness = G_BIG_ENDIAN, " + "endianness = (int)4321, " "red_mask = (int)0x0000ff00, " "green_mask = (int)0x00ff0000, " "blue_mask = (int)0xff000000, " "alpha_mask = (int)0x000000ff")}, @@ -158,7 +162,7 @@ GstVdpOutputBufferFormats rgba_formats[] = { GST_STATIC_CAPS ("video/x-raw-rgb, " "bpp = (int)32, " "depth = (int)30, " - "endianness = G_BIG_ENDIAN, " + "endianness = (int)4321, " "red_mask = (int)0xffc00000, " "green_mask = (int)0x003ff000, " "blue_mask = (int)0x000003fc, " "alpha_mask = (int)0x00000003")}, @@ -166,25 +170,57 @@ GstVdpOutputBufferFormats rgba_formats[] = { GST_STATIC_CAPS ("video/x-raw-rgb, " "bpp = (int)32, " "depth = (int)24, " - "endianness = G_BIG_ENDIAN" + "endianness = (int)4321, " "red_mask = (int)0xff000000, " "green_mask = (int)0x00ff0000, " "blue_mask = (int)0x0000ff00, " "alpha_mask = (int)0x000000ff")}, }; -int n_rgba_formats = G_N_ELEMENTS (rgba_formats); + +GstCaps * +gst_vdp_output_buffer_get_template_caps () +{ + GstCaps *caps, *rgb_caps; + gint i; + + caps = gst_caps_new_empty (); + rgb_caps = gst_caps_new_empty (); + + for (i = 0; i < G_N_ELEMENTS (rgba_formats); i++) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-vdpau-output", + "rgba-format", G_TYPE_INT, rgba_formats[i].format, + "width", GST_TYPE_INT_RANGE, 1, 8192, + "height", GST_TYPE_INT_RANGE, 1, 8192, NULL); + gst_caps_append (caps, format_caps); + + format_caps = gst_static_caps_get (&rgba_formats[i].caps); + format_caps = gst_caps_copy (format_caps); + gst_caps_set_simple (format_caps, + "width", GST_TYPE_INT_RANGE, 1, 8192, + "height", GST_TYPE_INT_RANGE, 1, 8192, NULL); + gst_caps_append (rgb_caps, format_caps); + + } + + gst_caps_append (caps, rgb_caps); + + return caps; +} GstCaps * gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice * device) { - GstCaps *caps; + GstCaps *caps, *rgb_caps; gint i; g_return_val_if_fail (GST_IS_VDP_DEVICE (device), NULL); caps = gst_caps_new_empty (); + rgb_caps = gst_caps_new_empty (); - for (i = 0; i < n_rgba_formats; i++) { + for (i = 0; i < G_N_ELEMENTS (rgba_formats); i++) { VdpStatus status; VdpBool is_supported; guint max_w, max_h; @@ -208,10 +244,155 @@ gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice * device) "width", GST_TYPE_INT_RANGE, 1, max_w, "height", GST_TYPE_INT_RANGE, 1, max_h, NULL); gst_caps_append (caps, format_caps); + + format_caps = gst_static_caps_get (&rgba_formats[i].caps); + format_caps = gst_caps_copy (format_caps); + gst_caps_set_simple (format_caps, + "width", GST_TYPE_INT_RANGE, 1, 8192, + "height", GST_TYPE_INT_RANGE, 1, 8192, NULL); + gst_caps_append (rgb_caps, format_caps); } } + gst_caps_append (caps, rgb_caps); + error: return caps; } + +gboolean +gst_vdp_caps_to_rgba_format (GstCaps * caps, VdpRGBAFormat * rgba_format) +{ + GstStructure *structure; + gint c_bpp, c_depth, c_endianness, c_red_mask, c_green_mask, c_blue_mask, + c_alpha_mask; + + gint i; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + if (!gst_caps_is_fixed (caps)) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + if (!gst_structure_has_name (structure, "video/x-raw-rgb")) + return FALSE; + + if (!gst_structure_get_int (structure, "bpp", &c_bpp) || + !gst_structure_get_int (structure, "depth", &c_depth) || + !gst_structure_get_int (structure, "endianness", &c_endianness) || + !gst_structure_get_int (structure, "red_mask", &c_red_mask) || + !gst_structure_get_int (structure, "green_mask", &c_green_mask) || + !gst_structure_get_int (structure, "blue_mask", &c_blue_mask) || + !gst_structure_get_int (structure, "alpha_mask", &c_alpha_mask)) + return FALSE; + + for (i = 0; i < G_N_ELEMENTS (rgba_formats); i++) { + gint bpp, depth, endianness, red_mask, green_mask, blue_mask, alpha_mask; + + GstCaps *rgb_caps = gst_static_caps_get (&rgba_formats[i].caps); + structure = gst_caps_get_structure (rgb_caps, 0); + + gst_structure_get_int (structure, "bpp", &bpp); + gst_structure_get_int (structure, "depth", &depth); + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get_int (structure, "red_mask", &red_mask); + gst_structure_get_int (structure, "green_mask", &green_mask); + gst_structure_get_int (structure, "blue_mask", &blue_mask); + gst_structure_get_int (structure, "alpha_mask", &alpha_mask); + + if (c_bpp == bpp && c_depth == depth && c_endianness == endianness && + c_red_mask == red_mask && c_green_mask == green_mask && + c_blue_mask == blue_mask && c_alpha_mask == alpha_mask) { + gst_caps_unref (rgb_caps); + *rgba_format = rgba_formats[i].format; + return TRUE; + } + + gst_caps_unref (rgb_caps); + } + + return FALSE; +} + +gboolean +gst_vdp_output_buffer_calculate_size (GstVdpOutputBuffer * output_buf, + guint * size) +{ + g_return_val_if_fail (GST_IS_VDP_OUTPUT_BUFFER (output_buf), FALSE); + + switch (output_buf->rgba_format) { + case VDP_RGBA_FORMAT_A8: + { + *size = output_buf->width * output_buf->height; + break; + } + + case VDP_RGBA_FORMAT_B10G10R10A2: + case VDP_RGBA_FORMAT_B8G8R8A8: + case VDP_RGBA_FORMAT_R10G10B10A2: + case VDP_RGBA_FORMAT_R8G8B8A8: + { + *size = output_buf->width * output_buf->height * 4; + break; + } + + default: + return FALSE; + } + + return TRUE; +} + +gboolean +gst_vdp_output_buffer_download (GstVdpOutputBuffer * output_buf, + GstBuffer * outbuf) +{ + guint8 *data[1]; + guint32 stride[1]; + GstVdpDevice *device; + VdpOutputSurface surface; + VdpStatus status; + + g_return_val_if_fail (GST_IS_VDP_OUTPUT_BUFFER (output_buf), FALSE); + + switch (output_buf->rgba_format) { + case VDP_RGBA_FORMAT_A8: + { + stride[0] = output_buf->width; + break; + } + + case VDP_RGBA_FORMAT_B10G10R10A2: + case VDP_RGBA_FORMAT_B8G8R8A8: + case VDP_RGBA_FORMAT_R10G10B10A2: + case VDP_RGBA_FORMAT_R8G8B8A8: + { + stride[0] = output_buf->width * 4; + break; + } + + default: + return FALSE; + } + + device = output_buf->device; + surface = output_buf->surface; + data[0] = GST_BUFFER_DATA (outbuf); + + GST_LOG_OBJECT (output_buf, "Entering vdp_output_surface_get_bits_native"); + status = + device->vdp_output_surface_get_bits_native (surface, NULL, (void *) data, + stride); + GST_LOG_OBJECT (output_buf, + "Got status %d from vdp_output_get_bits_native", status); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ERROR_OBJECT (output_buf, + "Couldn't get data from vdpau, Error returned from vdpau was: %s", + device->vdp_get_error_string (status)); + return FALSE; + } + + return TRUE; +} diff --git a/sys/vdpau/gstvdpoutputbuffer.h b/sys/vdpau/gstvdpoutputbuffer.h index afa159f623..89eab0edc5 100644 --- a/sys/vdpau/gstvdpoutputbuffer.h +++ b/sys/vdpau/gstvdpoutputbuffer.h @@ -35,6 +35,9 @@ struct _GstVdpOutputBuffer { GstBuffer buffer; GstVdpDevice *device; + VdpRGBAFormat rgba_format; + gint width, height; + VdpOutputSurface surface; }; @@ -42,7 +45,12 @@ GType gst_vdp_output_buffer_get_type (void); GstVdpOutputBuffer* gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format, gint width, gint height); +GstCaps *gst_vdp_output_buffer_get_template_caps (); GstCaps *gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice *device); +gboolean gst_vdp_caps_to_rgba_format (GstCaps *caps, VdpRGBAFormat *rgba_format); + +gboolean gst_vdp_output_buffer_calculate_size (GstVdpOutputBuffer *output_buf, guint *size); +gboolean gst_vdp_output_buffer_download (GstVdpOutputBuffer *output_buf, GstBuffer *outbuf); #define GST_VDP_OUTPUT_CAPS \ "video/x-vdpau-output, " \