}
}
+#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;
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);
}
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