diff --git a/gst/videoscale/gstvideoscale.c b/gst/videoscale/gstvideoscale.c index 9f072a3458..60dd5ff65b 100644 --- a/gst/videoscale/gstvideoscale.c +++ b/gst/videoscale/gstvideoscale.c @@ -424,10 +424,118 @@ gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value, } } +#define NEAREST (1 << GST_VIDEO_SCALE_NEAREST) +#define BILINEAR (1 << GST_VIDEO_SCALE_BILINEAR) +#define FOURTAP (1 << GST_VIDEO_SCALE_4TAP) +#define LANCZOS (1 << GST_VIDEO_SCALE_LANCZOS) + +/* or we could just do lookups via table[format] if we could be bothered.. */ +static const struct +{ + GstVideoFormat format; + guint8 methods; +} formats_methods_table[] = { + { + GST_VIDEO_FORMAT_RGBx, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_xRGB, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_BGRx, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_xBGR, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_RGBA, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_ARGB, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_BGRA, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_ABGR, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_AYUV, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_ARGB64, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_AYUV64, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_RGB, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_BGR, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_v308, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_YUY2, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_YVYU, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_UYVY, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_Y800, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_GRAY8, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_GRAY16_LE, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_GRAY16_BE, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_Y16, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_I420, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_YV12, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_Y444, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_Y42B, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_Y41B, NEAREST | BILINEAR | FOURTAP | LANCZOS}, { + GST_VIDEO_FORMAT_NV12, NEAREST | BILINEAR}, { + GST_VIDEO_FORMAT_RGB16, NEAREST | BILINEAR | FOURTAP}, { + GST_VIDEO_FORMAT_RGB15, NEAREST | BILINEAR | FOURTAP} +}; + +static gboolean +gst_video_scale_format_supported_for_method (GstVideoFormat format, + GstVideoScaleMethod method) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (formats_methods_table); ++i) { + if (formats_methods_table[i].format == format) + return ((formats_methods_table[i].methods & (1 << method)) != 0); + } + return FALSE; +} + +static gboolean +gst_video_scale_transform_supported (GstVideoScale * videoscale, + GstVideoScaleMethod method, GstStructure * structure) +{ + const GValue *val; + GstVideoFormat fmt; + gboolean supported = TRUE; + GstStructure *s; + GstCaps *c; + + /* we support these methods for all formats */ + if (method == GST_VIDEO_SCALE_NEAREST || method == GST_VIDEO_SCALE_BILINEAR) + return TRUE; + + /* we need fixed caps if we want to use gst_video_parse_caps() */ + s = gst_structure_new (gst_structure_get_name (structure), + "width", G_TYPE_INT, 1, "height", G_TYPE_INT, 1, NULL); + + if ((val = gst_structure_get_value (structure, "format"))) { + gst_structure_set_value (s, "format", val); + } else { + if ((val = gst_structure_get_value (structure, "endianness"))) + gst_structure_set_value (s, "endianness", val); + if ((val = gst_structure_get_value (structure, "red_mask"))) + gst_structure_set_value (s, "red_mask", val); + if ((val = gst_structure_get_value (structure, "blue_mask"))) + gst_structure_set_value (s, "blue_mask", val); + if ((val = gst_structure_get_value (structure, "green_mask"))) + gst_structure_set_value (s, "green_mask", val); + if ((val = gst_structure_get_value (structure, "alpha_mask"))) + gst_structure_set_value (s, "alpha_mask", val); + if ((val = gst_structure_get_value (structure, "depth"))) + gst_structure_set_value (s, "depth", val); + if ((val = gst_structure_get_value (structure, "bpp"))) + gst_structure_set_value (s, "bpp", val); + } + c = gst_caps_new_full (s, NULL); + if (!gst_video_format_parse_caps (c, &fmt, NULL, NULL)) { + GST_ERROR_OBJECT (videoscale, "couldn't parse %" GST_PTR_FORMAT, c); + } else if (!gst_video_scale_format_supported_for_method (fmt, method)) { + supported = FALSE; + } + GST_LOG_OBJECT (videoscale, "method %d %ssupported for format %d", + method, (supported) ? "" : "not ", fmt); + gst_caps_unref (c); + + return supported; +} + static GstCaps * gst_video_scale_transform_caps (GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps) { + GstVideoScale *videoscale = GST_VIDEO_SCALE (trans); + GstVideoScaleMethod method; GstCaps *ret; GstStructure *structure; @@ -441,6 +549,13 @@ gst_video_scale_transform_caps (GstBaseTransform * trans, ret = gst_caps_copy (caps); structure = gst_structure_copy (gst_caps_get_structure (ret, 0)); + GST_OBJECT_LOCK (videoscale); + method = videoscale->method; + GST_OBJECT_UNLOCK (videoscale); + + if (!gst_video_scale_transform_supported (videoscale, method, structure)) + goto format_not_supported; + gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); @@ -452,9 +567,19 @@ gst_video_scale_transform_caps (GstBaseTransform * trans, } gst_caps_append_structure (ret, structure); +done: + GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret); return ret; + +format_not_supported: + { + gst_structure_free (structure); + gst_caps_unref (ret); + ret = gst_caps_new_empty (); + goto done; + } } static gboolean diff --git a/tests/check/elements/videoscale.c b/tests/check/elements/videoscale.c index fc528f1bd6..e2b65628a1 100644 --- a/tests/check/elements/videoscale.c +++ b/tests/check/elements/videoscale.c @@ -221,7 +221,7 @@ test_passthrough (int method) /* skip formats that ffmpegcolorspace can't handle */ if (caps_are_64bpp (caps)) - continue; + goto skip; GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'" " from %dx%u to %dx%d with method %d", caps, src_width, src_height, @@ -251,6 +251,8 @@ test_passthrough (int method) g_list_free (sink_buffers); sink_buffers = NULL; + skip: + gst_caps_unref (caps); p++; }