diff --git a/sys/vdpau/gstvdputils.c b/sys/vdpau/gstvdputils.c index 8ac4f4217a..fc8d46e641 100644 --- a/sys/vdpau/gstvdputils.c +++ b/sys/vdpau/gstvdputils.c @@ -20,8 +20,8 @@ #include "gstvdputils.h" -GstCaps * -gst_vdp_get_video_caps (GstVdpDevice * device, gint chroma_format) +static GstCaps * +gst_vdp_get_allowed_yuv_caps (GstVdpDevice * device) { GstCaps *caps; gint i; @@ -32,9 +32,6 @@ gst_vdp_get_video_caps (GstVdpDevice * device, gint chroma_format) 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); @@ -80,10 +77,154 @@ gst_vdp_get_video_caps (GstVdpDevice * device, gint chroma_format) } error: - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - return NULL; - } - return caps; } + +GstCaps * +gst_vdp_video_to_yuv_caps (GstCaps * caps) +{ + GstCaps *new_caps, *allowed_caps, *result; + gint i; + GstStructure *structure; + const GValue *value; + GstVdpDevice *device = NULL; + + new_caps = gst_caps_new_empty (); + + for (i = 0; i < gst_caps_get_size (caps); i++) { + gint chroma_type; + GSList *fourcc = NULL, *iter; + + structure = gst_caps_get_structure (caps, i); + + if (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)); + } + } + } else { + for (i = 0; i < N_FORMATS; i++) { + 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); + + value = gst_structure_get_value (structure, "device"); + if (value) + device = g_value_get_object (value); + + if (device) { + allowed_caps = gst_vdp_get_allowed_yuv_caps (device); + result = gst_caps_intersect (new_caps, allowed_caps); + + gst_caps_unref (new_caps); + gst_caps_unref (allowed_caps); + } else + result = new_caps; + + return result; +} + +static GstCaps * +gst_vdp_get_allowed_video_caps (GstVdpDevice * device) +{ + 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; + + 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) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-vdpau-video", + "chroma-type", G_TYPE_INT, chroma_types[i], + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, NULL); + gst_caps_append (caps, format_caps); + } + } + +error: + return caps; +} + +GstCaps * +gst_vdp_yuv_to_video_caps (GstCaps * caps, GstVdpDevice * device) +{ + GstCaps *new_caps, *result; + gint i; + + new_caps = gst_caps_copy (caps); + for (i = 0; i < gst_caps_get_size (new_caps); i++) { + GstStructure *structure = gst_caps_get_structure (new_caps, i); + guint32 fourcc; + + if (gst_structure_get_fourcc (structure, "format", &fourcc)) { + gint chroma_type = -1; + + /* calculate chroma type from fourcc */ + for (i = 0; i < N_FORMATS; i++) { + if (formats[i].fourcc == fourcc) { + chroma_type = formats[i].chroma_type; + break; + } + } + gst_structure_remove_field (structure, "format"); + gst_structure_set (structure, "chroma-type", G_TYPE_INT, chroma_type, + NULL); + } else + gst_structure_set (structure, "chroma-type", GST_TYPE_INT_RANGE, 0, 2, + NULL); + + gst_structure_set_name (structure, "video/x-vdpau-video"); + if (device) + gst_structure_set (structure, "device", G_TYPE_OBJECT, device, NULL); + } + + if (device) { + GstCaps *allowed_caps; + + allowed_caps = gst_vdp_get_allowed_video_caps (device); + result = gst_caps_intersect (new_caps, allowed_caps); + + gst_caps_unref (new_caps); + gst_caps_unref (allowed_caps); + } else + result = new_caps; + + return result; +} diff --git a/sys/vdpau/gstvdputils.h b/sys/vdpau/gstvdputils.h index cb6a965f14..530a4adea8 100644 --- a/sys/vdpau/gstvdputils.h +++ b/sys/vdpau/gstvdputils.h @@ -76,6 +76,7 @@ static const VdpauFormats formats[N_FORMATS] = { } }; -GstCaps *gst_vdp_get_video_caps (GstVdpDevice *device, gint chroma_format); +GstCaps *gst_vdp_video_to_yuv_caps (GstCaps *caps); +GstCaps *gst_vdp_yuv_to_video_caps (GstCaps *caps, GstVdpDevice *device); #endif /* _GST_VDP_UTILS_H_ */ \ No newline at end of file diff --git a/sys/vdpau/gstvdpvideoyuv.c b/sys/vdpau/gstvdpvideoyuv.c index 7b3aa9ea87..1810f9e06d 100644 --- a/sys/vdpau/gstvdpvideoyuv.c +++ b/sys/vdpau/gstvdpvideoyuv.c @@ -51,12 +51,11 @@ GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME, GST_STATIC_CAPS (GST_VDP_VIDEO_CAPS)); static GstStaticPadTemplate src_template = -GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME, + GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME, GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "framerate = (fraction) [ 0, MAX ], " - "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";" + GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("NV12"))); #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdp_video_yuv_debug, "vdpauvideoyuv", 0, "VDPAU VdpSurface to YUV"); @@ -254,67 +253,15 @@ GstCaps * gst_vdp_video_yuv_transform_caps (GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps) { - GstCaps *result = NULL; + GstCaps *result; - if (direction == GST_PAD_SINK) { - GstCaps *new_caps, *allowed_caps = NULL; - gint i; - GstStructure *structure; - gint chroma_type; - const GValue *value; - GstVdpDevice *device = NULL; + if (direction == GST_PAD_SINK) + result = gst_vdp_video_to_yuv_caps (caps); - new_caps = gst_caps_new_empty (); + else if (direction == GST_PAD_SRC) + result = gst_vdp_yuv_to_video_caps (caps, NULL); - 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 */ - result = gst_static_pad_template_get_caps (&sink_template); - } + GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, result); return result; } diff --git a/sys/vdpau/gstvdpyuvvideo.c b/sys/vdpau/gstvdpyuvvideo.c index f602965d3e..04c5fe5a0f 100644 --- a/sys/vdpau/gstvdpyuvvideo.c +++ b/sys/vdpau/gstvdpyuvvideo.c @@ -235,44 +235,16 @@ gst_vdp_yuv_video_transform_caps (GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps) { GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (trans); - GstCaps *result = NULL; + GstCaps *result; if (direction == GST_PAD_SINK) { - gint i; - - /* Intersect with the allowed caps */ - if (yuv_video->sink_caps) - result = gst_caps_intersect (caps, yuv_video->sink_caps); - else - result = gst_caps_copy (caps); - - for (i = 0; i < gst_caps_get_size (result); i++) { - GstStructure *structure = gst_caps_get_structure (result, i); - guint32 fourcc; - gint chroma_type; - - gst_structure_get_fourcc (structure, "format", &fourcc); - /* calculate chroma type from fourcc */ - for (i = 0; i < N_FORMATS; i++) { - if (formats[i].fourcc == fourcc) { - chroma_type = formats[i].chroma_type; - break; - } - } - - gst_structure_set_name (structure, "video/x-vdpau-video"); - gst_structure_remove_field (structure, "format"); - gst_structure_set (structure, "chroma-type", G_TYPE_INT, chroma_type, - "device", G_TYPE_OBJECT, yuv_video->device, NULL); - } - gst_caps_do_simplify (result); - GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, - result); + result = gst_vdp_yuv_to_video_caps (caps, yuv_video->device); } else if (direction == GST_PAD_SRC) { - /* FIXME: upstream negotiation */ - result = gst_static_pad_template_get_caps (&sink_template); + result = gst_vdp_video_to_yuv_caps (caps); } + GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, result); + return result; } @@ -284,7 +256,6 @@ 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_get_video_caps (yuv_video->device, -1); return TRUE; } @@ -295,8 +266,6 @@ gst_vdp_yuv_video_stop (GstBaseTransform * trans) GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (trans); g_object_unref (yuv_video->device); - gst_caps_unref (yuv_video->sink_caps); - yuv_video->sink_caps = NULL; return TRUE; } @@ -390,7 +359,5 @@ gst_vdp_yuv_video_class_init (GstVdpYUVVideoClass * klass) static void gst_vdp_yuv_video_init (GstVdpYUVVideo * yuv_video, GstVdpYUVVideoClass * klass) { - yuv_video->sink_caps = NULL; - yuv_video->display = NULL; } diff --git a/sys/vdpau/gstvdpyuvvideo.h b/sys/vdpau/gstvdpyuvvideo.h index 891756afce..8851ce443a 100644 --- a/sys/vdpau/gstvdpyuvvideo.h +++ b/sys/vdpau/gstvdpyuvvideo.h @@ -41,8 +41,6 @@ typedef struct _GstVdpYUVVideoClass GstVdpYUVVideoClass; struct _GstVdpYUVVideo { GstBaseTransform trans; - GstCaps *sink_caps; - gchar *display; GstVdpDevice *device;