From 3545720d7a6733c97b194e7bcf4371a2ce6dd80d Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 22 Jun 2009 23:25:55 +0200 Subject: [PATCH] vdpau: refactor GstVdpVideoYUV and GstVdpYUVVideo --- sys/vdpau/Makefile.am | 6 +- sys/vdpau/gstvdpdevice.h | 51 -------------- sys/vdpau/gstvdputils.c | 89 ++++++++++++++++++++++++ sys/vdpau/gstvdputils.h | 81 +++++++++++++++++++++ sys/vdpau/gstvdpvideoyuv.c | 139 +++++++++++++++---------------------- sys/vdpau/gstvdpyuvvideo.c | 73 +------------------ 6 files changed, 233 insertions(+), 206 deletions(-) create mode 100644 sys/vdpau/gstvdputils.c create mode 100644 sys/vdpau/gstvdputils.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 93a7513a66..f81f968a7f 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -7,7 +7,8 @@ libgstvdpau_la_SOURCES = \ gstvdpvideoyuv.c \ gstvdpvideobuffer.c \ gstvdp.c \ - gstvdpyuvvideo.c + gstvdpyuvvideo.c \ + gstvdputils.c libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ @@ -22,6 +23,7 @@ noinst_HEADERS = \ mpegutil.h \ gstvdpvideoyuv.h \ gstvdpvideobuffer.h \ - gstvdpyuvvideo.h + gstvdpyuvvideo.h \ + gstvdputils.h diff --git a/sys/vdpau/gstvdpdevice.h b/sys/vdpau/gstvdpdevice.h index 38cd84bb81..19d0a9803b 100644 --- a/sys/vdpau/gstvdpdevice.h +++ b/sys/vdpau/gstvdpdevice.h @@ -70,57 +70,6 @@ struct _GstVdpDevice VdpDecoderGetParameters *vdp_decoder_get_parameters; }; -typedef struct -{ - VdpChromaType chroma_type; - VdpYCbCrFormat format; - guint32 fourcc; -} VdpauFormats; - -#define N_CHROMA_TYPES 3 -#define N_FORMATS 7 - -static const VdpChromaType chroma_types[N_CHROMA_TYPES] = - { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; - -static const VdpauFormats formats[N_FORMATS] = { - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('I', '4', '2', '0') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('Y', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_NV12, - GST_MAKE_FOURCC ('N', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_UYVY, - GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_V8U8Y8A8, - GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_Y8U8V8A8, - GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_YUYV, - GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') - } -}; - GType gst_vdp_device_get_type (void) G_GNUC_CONST; GstVdpDevice *gst_vdp_device_new (const gchar *display_name); diff --git a/sys/vdpau/gstvdputils.c b/sys/vdpau/gstvdputils.c new file mode 100644 index 0000000000..8ac4f4217a --- /dev/null +++ b/sys/vdpau/gstvdputils.c @@ -0,0 +1,89 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gstvdputils.h" + +GstCaps * +gst_vdp_get_video_caps (GstVdpDevice * device, gint chroma_format) +{ + GstCaps *caps; + gint i; + + caps = gst_caps_new_empty (); + for (i = 0; i < N_CHROMA_TYPES; i++) { + VdpStatus status; + VdpBool is_supported; + guint32 max_w, max_h; + + if (chroma_format != chroma_types[i]) + continue; + + status = + device->vdp_video_surface_query_capabilities (device->device, + chroma_types[i], &is_supported, &max_w, &max_h); + + if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { + GST_ERROR_OBJECT (device, + "Could not get query VDPAU video surface capabilites, " + "Error returned from vdpau was: %s", + device->vdp_get_error_string (status)); + + goto error; + } + if (is_supported) { + gint j; + + for (j = 0; j < N_FORMATS; j++) { + if (formats[j].chroma_type != chroma_types[i]) + continue; + + status = + device->vdp_video_surface_query_ycbcr_capabilities (device->device, + formats[j].chroma_type, formats[j].format, &is_supported); + if (status != VDP_STATUS_OK + && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { + GST_ERROR_OBJECT (device, "Could not query VDPAU YCbCr capabilites, " + "Error returned from vdpau was: %s", + device->vdp_get_error_string (status)); + + goto error; + } + + if (is_supported) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[j].fourcc, + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, NULL); + gst_caps_append (caps, format_caps); + } + } + } + } + +error: + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + return NULL; + } + + return caps; +} diff --git a/sys/vdpau/gstvdputils.h b/sys/vdpau/gstvdputils.h new file mode 100644 index 0000000000..cb6a965f14 --- /dev/null +++ b/sys/vdpau/gstvdputils.h @@ -0,0 +1,81 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_VDP_UTILS_H_ +#define _GST_VDP_UTILS_H_ + +#include + +#include "gstvdpdevice.h" + +typedef struct +{ + VdpChromaType chroma_type; + VdpYCbCrFormat format; + guint32 fourcc; +} VdpauFormats; + +#define N_CHROMA_TYPES 3 +#define N_FORMATS 7 + +static const VdpChromaType chroma_types[N_CHROMA_TYPES] = + { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; + +static const VdpauFormats formats[N_FORMATS] = { + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('I', '4', '2', '0') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('Y', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_NV12, + GST_MAKE_FOURCC ('N', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_UYVY, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_V8U8Y8A8, + GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_Y8U8V8A8, + GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_YUYV, + GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') + } +}; + +GstCaps *gst_vdp_get_video_caps (GstVdpDevice *device, gint chroma_format); + +#endif /* _GST_VDP_UTILS_H_ */ \ No newline at end of file diff --git a/sys/vdpau/gstvdpvideoyuv.c b/sys/vdpau/gstvdpvideoyuv.c index 0b576bd5b1..7b3aa9ea87 100644 --- a/sys/vdpau/gstvdpvideoyuv.c +++ b/sys/vdpau/gstvdpvideoyuv.c @@ -26,6 +26,7 @@ #include #include "gstvdpvideobuffer.h" +#include "gstvdputils.h" #include "gstvdpvideoyuv.h" GST_DEBUG_CATEGORY_STATIC (gst_vdp_video_yuv_debug); @@ -63,83 +64,6 @@ GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME, GST_BOILERPLATE_FULL (GstVdpVideoYUV, gst_vdp_video_yuv, GstBaseTransform, GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); -static GstCaps * -gst_vdp_video_yuv_get_src_caps (GstVdpVideoYUV * video_yuv, GstCaps * caps) -{ - GstStructure *structure; - const GValue *value; - GstVdpDevice *device; - gint chroma_type; - gint width, height; - gboolean got_fps; - gint fps_n, fps_d; - gboolean got_par; - gint par_n, par_d; - GstCaps *src_caps; - gint i; - - structure = gst_caps_get_structure (caps, 0); - - value = gst_structure_get_value (structure, "device"); - device = g_value_get_object (value); - - gst_structure_get_int (structure, "chroma-type", &chroma_type); - gst_structure_get_int (structure, "width", &width); - gst_structure_get_int (structure, "height", &height); - - got_fps = gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d); - - got_par = gst_structure_get_fraction (structure, "pixel-aspect-ratio", - &par_n, &par_d); - - src_caps = gst_caps_new_empty (); - - for (i = 0; i < N_FORMATS; i++) { - VdpStatus status; - VdpBool is_supported; - - if (formats[i].chroma_type != chroma_type) - continue; - - status = - device->vdp_video_surface_query_ycbcr_capabilities (device->device, - chroma_type, formats[i].format, &is_supported); - if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { - GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, - ("Could not query VDPAU YCbCr capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - goto done; - } - if (is_supported) { - GstCaps *format_caps; - - format_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, formats[i].fourcc, - "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); - - if (got_fps) - gst_caps_set_simple (format_caps, - "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); - - if (got_par) - gst_caps_set_simple (format_caps, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); - - gst_caps_append (src_caps, format_caps); - } - } - -done: - if (gst_caps_is_empty (src_caps)) { - gst_caps_unref (src_caps); - return NULL; - } - - return src_caps; -} - GstFlowReturn gst_vdp_video_yuv_transform (GstBaseTransform * trans, GstBuffer * inbuf, GstBuffer * outbuf) @@ -330,18 +254,69 @@ GstCaps * gst_vdp_video_yuv_transform_caps (GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps) { - GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans); - GstCaps *new_caps = NULL; + GstCaps *result = NULL; if (direction == GST_PAD_SINK) { - new_caps = gst_vdp_video_yuv_get_src_caps (video_yuv, caps); + GstCaps *new_caps, *allowed_caps = NULL; + gint i; + GstStructure *structure; + gint chroma_type; + const GValue *value; + GstVdpDevice *device = NULL; + + new_caps = gst_caps_new_empty (); + + for (i = 0; i < gst_caps_get_size (caps); i++) { + GSList *fourcc = NULL, *iter; + + structure = gst_caps_get_structure (caps, i); + gst_structure_get_int (structure, "chroma-type", &chroma_type); + /* calculate fourcc from chroma_type */ + for (i = 0; i < N_FORMATS; i++) { + if (formats[i].chroma_type == chroma_type) { + fourcc = g_slist_append (fourcc, GINT_TO_POINTER (formats[i].fourcc)); + } + } + + for (iter = fourcc; iter; iter = iter->next) { + GstStructure *new_struct = gst_structure_copy (structure); + + gst_structure_set_name (new_struct, "video/x-raw-yuv"); + gst_structure_remove_field (new_struct, "chroma-type"); + gst_structure_remove_field (new_struct, "device"); + gst_structure_set (new_struct, "format", GST_TYPE_FOURCC, + GPOINTER_TO_INT (iter->data), NULL); + + gst_caps_append_structure (new_caps, new_struct); + } + + g_slist_free (fourcc); + } + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (structure, "chroma-type", &chroma_type); + value = gst_structure_get_value (structure, "device"); + if (value) + device = g_value_get_object (value); + + if (device) + allowed_caps = gst_vdp_get_video_caps (device, chroma_type); + else + allowed_caps = gst_static_pad_template_get_caps (&src_template); + + result = gst_caps_intersect (new_caps, allowed_caps); + gst_caps_unref (new_caps); + gst_caps_unref (allowed_caps); + + GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, + result); } else if (direction == GST_PAD_SRC) { /* FIXME: upstream negotiation */ - new_caps = gst_static_pad_template_get_caps (&sink_template); + result = gst_static_pad_template_get_caps (&sink_template); } - return new_caps; + return result; } /* GObject vmethod implementations */ diff --git a/sys/vdpau/gstvdpyuvvideo.c b/sys/vdpau/gstvdpyuvvideo.c index 2989ecf255..f602965d3e 100644 --- a/sys/vdpau/gstvdpyuvvideo.c +++ b/sys/vdpau/gstvdpyuvvideo.c @@ -26,6 +26,7 @@ #include #include "gstvdpvideobuffer.h" +#include "gstvdputils.h" #include "gstvdpyuvvideo.h" GST_DEBUG_CATEGORY_STATIC (gst_vdp_yuv_video_debug); @@ -63,76 +64,6 @@ GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME, GST_BOILERPLATE_FULL (GstVdpYUVVideo, gst_vdp_yuv_video, GstBaseTransform, GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); -static GstCaps * -gst_vdp_yuv_video_get_sink_caps (GstVdpYUVVideo * yuv_video) -{ - GstVdpDevice *device; - GstCaps *caps; - gint i; - - device = yuv_video->device; - - caps = gst_caps_new_empty (); - for (i = 0; i < N_CHROMA_TYPES; i++) { - VdpStatus status; - VdpBool is_supported; - guint32 max_w, max_h; - - status = - device->vdp_video_surface_query_capabilities (device->device, - chroma_types[i], &is_supported, &max_w, &max_h); - - if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Could not get query VDPAU video surface capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - goto error; - } - if (is_supported) { - gint j; - - for (j = 0; j < N_FORMATS; j++) { - if (formats[j].chroma_type != chroma_types[i]) - continue; - - status = - device->vdp_video_surface_query_ycbcr_capabilities (device->device, - formats[j].chroma_type, formats[j].format, &is_supported); - if (status != VDP_STATUS_OK - && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Could not query VDPAU YCbCr capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - goto error; - } - - if (is_supported) { - GstCaps *format_caps; - - format_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, formats[j].fourcc, - "width", GST_TYPE_INT_RANGE, 1, max_w, - "height", GST_TYPE_INT_RANGE, 1, max_h, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - gst_caps_append (caps, format_caps); - } - } - } - } - -error: - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - return NULL; - } - - return caps; -} - static GstFlowReturn gst_vdp_yuv_video_prepare_output_buffer (GstBaseTransform * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) @@ -353,7 +284,7 @@ gst_vdp_yuv_video_start (GstBaseTransform * trans) yuv_video->device = gst_vdp_get_device (yuv_video->display); if (!yuv_video->device) return FALSE; - yuv_video->sink_caps = gst_vdp_yuv_video_get_sink_caps (yuv_video); + yuv_video->sink_caps = gst_vdp_get_video_caps (yuv_video->device, -1); return TRUE; }