3 * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
25 #include "gstvdpoutputbuffer.h"
27 GST_DEBUG_CATEGORY_STATIC (gst_vdp_output_buffer_debug);
28 #define GST_CAT_DEFAULT gst_vdp_output_buffer_debug
30 #define DEBUG_INIT(bla) \
31 GST_DEBUG_CATEGORY_INIT (gst_vdp_output_buffer_debug, "vdpoutputbuffer", 0, "VDPAU output buffer");
34 gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format,
35 gint width, gint height, GError ** error)
37 GstVdpOutputBuffer *buffer;
39 VdpOutputSurface surface;
42 device->vdp_output_surface_create (device->device, rgba_format, width,
44 if (status != VDP_STATUS_OK)
48 (GstVdpOutputBuffer *) gst_mini_object_new (GST_TYPE_VDP_OUTPUT_BUFFER);
50 buffer->device = g_object_ref (device);
51 buffer->rgba_format = rgba_format;
52 buffer->width = width;
53 buffer->height = height;
55 buffer->surface = surface;
60 g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
61 "Couldn't create a VdpOutputSurface, error returned from vdpau was: %s",
62 device->vdp_get_error_string (status));
66 static GObjectClass *gst_vdp_output_buffer_parent_class;
69 gst_vdp_output_buffer_finalize (GstVdpOutputBuffer * buffer)
74 if (gst_vdp_buffer_revive (GST_VDP_BUFFER_CAST (buffer)))
77 device = buffer->device;
79 status = device->vdp_output_surface_destroy (buffer->surface);
80 if (status != VDP_STATUS_OK)
82 ("Couldn't destroy the buffers VdpOutputSurface, error returned was: %s",
83 device->vdp_get_error_string (status));
85 g_object_unref (buffer->device);
87 GST_MINI_OBJECT_CLASS (gst_vdp_output_buffer_parent_class)->finalize
88 (GST_MINI_OBJECT (buffer));
92 gst_vdp_output_buffer_init (GstVdpOutputBuffer * buffer, gpointer g_class)
94 buffer->device = NULL;
95 buffer->surface = VDP_INVALID_HANDLE;
99 gst_vdp_output_buffer_class_init (gpointer g_class, gpointer class_data)
101 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
103 gst_vdp_output_buffer_parent_class = g_type_class_peek_parent (g_class);
105 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
106 gst_vdp_output_buffer_finalize;
111 gst_vdp_output_buffer_get_type (void)
113 static GType _gst_vdp_output_buffer_type;
115 if (G_UNLIKELY (_gst_vdp_output_buffer_type == 0)) {
116 static const GTypeInfo info = {
117 sizeof (GstBufferClass),
120 gst_vdp_output_buffer_class_init,
123 sizeof (GstVdpOutputBuffer),
125 (GInstanceInitFunc) gst_vdp_output_buffer_init,
128 _gst_vdp_output_buffer_type = g_type_register_static (GST_TYPE_VDP_BUFFER,
129 "GstVdpOutputBuffer", &info, 0);
133 return _gst_vdp_output_buffer_type;
138 VdpRGBAFormat format;
140 } GstVdpOutputBufferFormats;
142 GstVdpOutputBufferFormats rgba_formats[] = {
144 GST_STATIC_CAPS ("video/x-raw-rgb, "
147 "endianness = (int)4321, "
148 "red_mask = (int)0x00, "
149 "green_mask = (int)0x00, "
150 "blue_mask = (int)0x00, " "alpha_mask = (int)0xff")},
151 {VDP_RGBA_FORMAT_B10G10R10A2,
152 GST_STATIC_CAPS ("video/x-raw-rgb, "
155 "endianness = (int)4321, "
156 "red_mask = (int)0x000003fc, "
157 "green_mask = (int)0x003ff000, "
158 "blue_mask = (int)0xffc00000, " "alpha_mask = (int)0x00000003")},
159 {VDP_RGBA_FORMAT_B8G8R8A8,
160 GST_STATIC_CAPS ("video/x-raw-rgb, "
163 "endianness = (int)4321, "
164 "red_mask = (int)0x0000ff00, "
165 "green_mask = (int)0x00ff0000, "
166 "blue_mask = (int)0xff000000, " "alpha_mask = (int)0x000000ff")},
167 {VDP_RGBA_FORMAT_R10G10B10A2,
168 GST_STATIC_CAPS ("video/x-raw-rgb, "
171 "endianness = (int)4321, "
172 "red_mask = (int)0xffc00000, "
173 "green_mask = (int)0x003ff000, "
174 "blue_mask = (int)0x000003fc, " "alpha_mask = (int)0x00000003")},
175 {VDP_RGBA_FORMAT_R8G8B8A8,
176 GST_STATIC_CAPS ("video/x-raw-rgb, "
179 "endianness = (int)4321, "
180 "red_mask = (int)0xff000000, "
181 "green_mask = (int)0x00ff0000, "
182 "blue_mask = (int)0x0000ff00, " "alpha_mask = (int)0x000000ff")},
187 gst_vdp_output_buffer_get_template_caps (void)
189 GstCaps *caps, *rgb_caps;
192 caps = gst_caps_new_empty ();
193 rgb_caps = gst_caps_new_empty ();
195 for (i = 0; i < G_N_ELEMENTS (rgba_formats); i++) {
196 GstCaps *format_caps;
198 format_caps = gst_caps_new_simple ("video/x-vdpau-output",
199 "rgba-format", G_TYPE_INT, rgba_formats[i].format,
200 "width", GST_TYPE_INT_RANGE, 1, 8192,
201 "height", GST_TYPE_INT_RANGE, 1, 8192, NULL);
202 gst_caps_append (caps, format_caps);
204 format_caps = gst_static_caps_get (&rgba_formats[i].caps);
205 format_caps = gst_caps_copy (format_caps);
206 gst_caps_set_simple (format_caps,
207 "width", GST_TYPE_INT_RANGE, 1, 8192,
208 "height", GST_TYPE_INT_RANGE, 1, 8192, NULL);
209 gst_caps_append (rgb_caps, format_caps);
213 gst_caps_append (caps, rgb_caps);
219 gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice * device)
221 GstCaps *caps, *rgb_caps;
224 g_return_val_if_fail (GST_IS_VDP_DEVICE (device), NULL);
226 caps = gst_caps_new_empty ();
227 rgb_caps = gst_caps_new_empty ();
229 for (i = 0; i < G_N_ELEMENTS (rgba_formats); i++) {
231 VdpBool is_supported;
234 status = device->vdp_output_surface_query_capabilities (device->device,
235 rgba_formats[i].format, &is_supported, &max_w, &max_h);
236 if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_RGBA_FORMAT) {
237 GST_ERROR_OBJECT (device,
238 "Could not get query VDPAU output surface capabilites, "
239 "Error returned from vdpau was: %s",
240 device->vdp_get_error_string (status));
246 GstCaps *format_caps;
248 format_caps = gst_caps_new_simple ("video/x-vdpau-output",
249 "rgba-format", G_TYPE_INT, rgba_formats[i].format,
250 "width", GST_TYPE_INT_RANGE, 1, max_w,
251 "height", GST_TYPE_INT_RANGE, 1, max_h, NULL);
252 gst_caps_append (caps, format_caps);
254 format_caps = gst_static_caps_get (&rgba_formats[i].caps);
255 format_caps = gst_caps_copy (format_caps);
256 gst_caps_set_simple (format_caps,
257 "width", GST_TYPE_INT_RANGE, 1, 8192,
258 "height", GST_TYPE_INT_RANGE, 1, 8192, NULL);
259 gst_caps_append (rgb_caps, format_caps);
263 gst_caps_append (caps, rgb_caps);
271 gst_vdp_caps_to_rgba_format (GstCaps * caps, VdpRGBAFormat * rgba_format)
273 GstStructure *structure;
274 gint c_bpp, c_depth, c_endianness, c_red_mask, c_green_mask, c_blue_mask,
279 g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
281 if (!gst_caps_is_fixed (caps))
284 structure = gst_caps_get_structure (caps, 0);
285 if (!gst_structure_has_name (structure, "video/x-raw-rgb"))
288 if (!gst_structure_get_int (structure, "bpp", &c_bpp) ||
289 !gst_structure_get_int (structure, "depth", &c_depth) ||
290 !gst_structure_get_int (structure, "endianness", &c_endianness) ||
291 !gst_structure_get_int (structure, "red_mask", &c_red_mask) ||
292 !gst_structure_get_int (structure, "green_mask", &c_green_mask) ||
293 !gst_structure_get_int (structure, "blue_mask", &c_blue_mask) ||
294 !gst_structure_get_int (structure, "alpha_mask", &c_alpha_mask))
297 for (i = 0; i < G_N_ELEMENTS (rgba_formats); i++) {
298 gint bpp, depth, endianness, red_mask, green_mask, blue_mask, alpha_mask;
300 GstCaps *rgb_caps = gst_static_caps_get (&rgba_formats[i].caps);
301 structure = gst_caps_get_structure (rgb_caps, 0);
303 gst_structure_get_int (structure, "bpp", &bpp);
304 gst_structure_get_int (structure, "depth", &depth);
305 gst_structure_get_int (structure, "endianness", &endianness);
306 gst_structure_get_int (structure, "red_mask", &red_mask);
307 gst_structure_get_int (structure, "green_mask", &green_mask);
308 gst_structure_get_int (structure, "blue_mask", &blue_mask);
309 gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
311 if (c_bpp == bpp && c_depth == depth && c_endianness == endianness &&
312 c_red_mask == red_mask && c_green_mask == green_mask &&
313 c_blue_mask == blue_mask && c_alpha_mask == alpha_mask) {
314 gst_caps_unref (rgb_caps);
315 *rgba_format = rgba_formats[i].format;
319 gst_caps_unref (rgb_caps);
326 gst_vdp_output_buffer_calculate_size (GstVdpOutputBuffer * output_buf,
329 g_return_val_if_fail (GST_IS_VDP_OUTPUT_BUFFER (output_buf), FALSE);
331 switch (output_buf->rgba_format) {
332 case VDP_RGBA_FORMAT_A8:
334 *size = output_buf->width * output_buf->height;
338 case VDP_RGBA_FORMAT_B10G10R10A2:
339 case VDP_RGBA_FORMAT_B8G8R8A8:
340 case VDP_RGBA_FORMAT_R10G10B10A2:
341 case VDP_RGBA_FORMAT_R8G8B8A8:
343 *size = output_buf->width * output_buf->height * 4;
348 g_assert_not_reached ();
356 gst_vdp_output_buffer_download (GstVdpOutputBuffer * output_buf,
357 GstBuffer * outbuf, GError ** error)
361 GstVdpDevice *device;
362 VdpOutputSurface surface;
365 g_return_val_if_fail (GST_IS_VDP_OUTPUT_BUFFER (output_buf), FALSE);
367 switch (output_buf->rgba_format) {
368 case VDP_RGBA_FORMAT_A8:
370 stride[0] = output_buf->width;
374 case VDP_RGBA_FORMAT_B10G10R10A2:
375 case VDP_RGBA_FORMAT_B8G8R8A8:
376 case VDP_RGBA_FORMAT_R10G10B10A2:
377 case VDP_RGBA_FORMAT_R8G8B8A8:
379 stride[0] = output_buf->width * 4;
387 device = output_buf->device;
388 surface = output_buf->surface;
389 data[0] = GST_BUFFER_DATA (outbuf);
391 GST_LOG_OBJECT (output_buf, "Entering vdp_output_surface_get_bits_native");
393 device->vdp_output_surface_get_bits_native (surface, NULL, (void *) data,
395 GST_LOG_OBJECT (output_buf,
396 "Got status %d from vdp_output_get_bits_native", status);
398 if (G_UNLIKELY (status != VDP_STATUS_OK)) {
399 g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
400 "Couldn't get data from vdpau, error returned from vdpau was: %s",
401 device->vdp_get_error_string (status));