diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c index ae0557a9e7..99d264d94c 100644 --- a/gst-libs/gst/gl/gstglcolorconvert.c +++ b/gst-libs/gst/gl/gstglcolorconvert.c @@ -701,41 +701,6 @@ gst_gl_color_convert_set_caps (GstGLColorConvert * convert, return ret; } -static guint -_get_target_bitmask_from_g_value (const GValue * targets) -{ - guint new_targets = 0; - - if (targets == NULL) { - new_targets = 1 << GST_GL_TEXTURE_TARGET_2D; - } else if (G_TYPE_CHECK_VALUE_TYPE (targets, G_TYPE_STRING)) { - GstGLTextureTarget target; - const gchar *str; - - str = g_value_get_string (targets); - target = gst_gl_texture_target_from_string (str); - - if (target) - new_targets |= 1 << target; - } else if (G_TYPE_CHECK_VALUE_TYPE (targets, GST_TYPE_LIST)) { - gint j, m; - - m = gst_value_list_get_size (targets); - for (j = 0; j < m; j++) { - const GValue *val = gst_value_list_get_value (targets, j); - GstGLTextureTarget target; - const gchar *str; - - str = g_value_get_string (val); - target = gst_gl_texture_target_from_string (str); - if (target) - new_targets |= 1 << target; - } - } - - return new_targets; -} - /* copies the given caps */ static GstCaps * gst_gl_color_convert_caps_remove_format_info (GstCaps * caps) @@ -809,8 +774,8 @@ gst_gl_color_convert_fixate_caps (GstGLContext * convert, targets = gst_structure_get_value (s, "texture-target"); other_targets = gst_structure_get_value (s_other, "texture-target"); - targets_mask = _get_target_bitmask_from_g_value (targets); - other_targets_mask = _get_target_bitmask_from_g_value (other_targets); + targets_mask = gst_gl_value_get_texture_target_mask (targets); + other_targets_mask = gst_gl_value_get_texture_target_mask (other_targets); /* XXX: attempt to fixate the format/colorimetry/etc */ other = gst_caps_fixate (other); diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index c484d989ac..16ed5eaab0 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -142,6 +142,22 @@ _set_caps_features_with_passthrough (const GstCaps * caps, return tmp; } +static GstCaps * +_caps_intersect_texture_target (GstCaps * caps, GstGLTextureTarget target_mask) +{ + GValue targets = G_VALUE_INIT; + GstCaps *ret, *target; + + target = gst_caps_copy (caps); + gst_gl_value_set_texture_target_from_mask (&targets, target_mask); + gst_caps_set_value (target, "texture-target", &targets); + + ret = gst_caps_intersect_full (caps, target, GST_CAPS_INTERSECT_FIRST); + + gst_caps_unref (target); + return ret; +} + typedef enum { METHOD_FLAG_CAN_SHARE_CONTEXT = 1, @@ -196,6 +212,27 @@ _gl_memory_upload_transform_caps (GstGLContext * context, gst_caps_features_free (passthrough); + if (direction == GST_PAD_SINK) { + GstGLTextureTarget target_mask = 0; + GstCaps *tmp; + + target_mask |= 1 << GST_GL_TEXTURE_TARGET_2D; + target_mask |= 1 << GST_GL_TEXTURE_TARGET_RECTANGLE; + target_mask |= 1 << GST_GL_TEXTURE_TARGET_EXTERNAL_OES; + tmp = _caps_intersect_texture_target (ret, target_mask); + gst_caps_unref (ret); + ret = tmp; + } else { + gint i, n; + + n = gst_caps_get_size (ret); + for (i = 0; i < n; i++) { + GstStructure *s = gst_caps_get_structure (ret, i); + + gst_structure_remove_fields (s, "texture-target", NULL); + } + } + return ret; } @@ -407,9 +444,15 @@ _egl_image_upload_transform_caps (GstGLContext * context, GstCaps *ret; if (direction == GST_PAD_SINK) { + GstCaps *tmp; + ret = _set_caps_features_with_passthrough (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY, passthrough); + + tmp = _caps_intersect_texture_target (ret, 1 << GST_GL_TEXTURE_TARGET_2D); + gst_caps_unref (ret); + ret = tmp; } else { gint i, n; @@ -622,9 +665,15 @@ _dma_buf_upload_transform_caps (GstGLContext * context, GstCaps *ret; if (direction == GST_PAD_SINK) { + GstCaps *tmp; + ret = _set_caps_features_with_passthrough (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY, passthrough); + + tmp = _caps_intersect_texture_target (ret, 1 << GST_GL_TEXTURE_TARGET_2D); + gst_caps_unref (ret); + ret = tmp; } else { gint i, n; @@ -888,9 +937,15 @@ _upload_meta_upload_transform_caps (GstGLContext * context, GstCaps *ret; if (direction == GST_PAD_SINK) { + GstCaps *tmp; + ret = _set_caps_features_with_passthrough (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY, passthrough); + + tmp = _caps_intersect_texture_target (ret, 1 << GST_GL_TEXTURE_TARGET_2D); + gst_caps_unref (ret); + ret = tmp; } else { gint i, n; @@ -1176,9 +1231,18 @@ _raw_data_upload_transform_caps (GstGLContext * context, GstCaps *ret; if (direction == GST_PAD_SINK) { + GstGLTextureTarget target_mask = 0; + GstCaps *tmp; + ret = _set_caps_features_with_passthrough (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY, passthrough); + + target_mask |= 1 << GST_GL_TEXTURE_TARGET_2D; + target_mask |= 1 << GST_GL_TEXTURE_TARGET_RECTANGLE; + tmp = _caps_intersect_texture_target (ret, target_mask); + gst_caps_unref (ret); + ret = tmp; } else { gint i, n; diff --git a/gst-libs/gst/gl/gstglutils.c b/gst-libs/gst/gl/gstglutils.c index 080c17b400..2b0104f538 100644 --- a/gst-libs/gst/gl/gstglutils.c +++ b/gst-libs/gst/gl/gstglutils.c @@ -947,3 +947,132 @@ gst_gl_caps_replace_all_caps_features (const GstCaps * caps, return tmp; } + +/** + * gst_gl_value_get_texture_target_mask: + * @value: an initialized #GValue of type G_TYPE_STRING + * + * See gst_gl_value_set_texture_target_mask() for what entails a mask + * + * Returns: the mask of #GstGLTextureTarget's in @value + */ +GstGLTextureTarget +gst_gl_value_get_texture_target_mask (const GValue * targets) +{ + guint new_targets = 0; + + g_return_val_if_fail (targets != NULL, GST_GL_TEXTURE_TARGET_NONE); + + if (G_TYPE_CHECK_VALUE_TYPE (targets, G_TYPE_STRING)) { + GstGLTextureTarget target; + const gchar *str; + + str = g_value_get_string (targets); + target = gst_gl_texture_target_from_string (str); + + if (target) + new_targets |= 1 << target; + } else if (G_TYPE_CHECK_VALUE_TYPE (targets, GST_TYPE_LIST)) { + gint j, m; + + m = gst_value_list_get_size (targets); + for (j = 0; j < m; j++) { + const GValue *val = gst_value_list_get_value (targets, j); + GstGLTextureTarget target; + const gchar *str; + + str = g_value_get_string (val); + target = gst_gl_texture_target_from_string (str); + if (target) + new_targets |= 1 << target; + } + } + + return new_targets; +} + +/** + * gst_gl_value_set_texture_target: + * @value: an initialized #GValue of type G_TYPE_STRING + * @target: a #GstGLTextureTarget's + * + * Returns: whether the @target could be set on @value + */ +gboolean +gst_gl_value_set_texture_target (GValue * value, GstGLTextureTarget target) +{ + g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (target != GST_GL_TEXTURE_TARGET_NONE, FALSE); + + if (target == GST_GL_TEXTURE_TARGET_2D) { + g_value_set_static_string (value, GST_GL_TEXTURE_TARGET_2D_STR); + } else if (target == GST_GL_TEXTURE_TARGET_RECTANGLE) { + g_value_set_static_string (value, GST_GL_TEXTURE_TARGET_RECTANGLE_STR); + } else if (target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) { + g_value_set_static_string (value, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR); + } else { + return FALSE; + } + + return TRUE; +} + +static guint64 +_gst_gl_log2_int64 (guint64 value) +{ + guint64 ret = 0; + + while (value >>= 1) + ret++; + + return ret; +} + +/** + * gst_gl_value_set_texture_target_from_mask: + * @value: an uninitialized #GValue + * @target_mask: a bitwise mask of #GstGLTextureTarget's + * + * A mask is a bitwise OR of (1 << target) where target is a valid + * #GstGLTextureTarget + * + * Returns: whether the @target_mask could be set on @value + */ +gboolean +gst_gl_value_set_texture_target_from_mask (GValue * value, + GstGLTextureTarget target_mask) +{ + g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (target_mask != GST_GL_TEXTURE_TARGET_NONE, FALSE); + + if ((target_mask & (target_mask - 1)) == 0) { + /* only one texture target set */ + g_value_init (value, G_TYPE_STRING); + return gst_gl_value_set_texture_target (value, + _gst_gl_log2_int64 (target_mask)); + } else { + GValue item = G_VALUE_INIT; + gboolean ret = FALSE; + + g_value_init (value, GST_TYPE_LIST); + g_value_init (&item, G_TYPE_STRING); + if (target_mask & (1 << GST_GL_TEXTURE_TARGET_2D)) { + gst_gl_value_set_texture_target (&item, GST_GL_TEXTURE_TARGET_2D); + gst_value_list_append_value (value, &item); + ret = TRUE; + } + if (target_mask & (1 << GST_GL_TEXTURE_TARGET_RECTANGLE)) { + gst_gl_value_set_texture_target (&item, GST_GL_TEXTURE_TARGET_RECTANGLE); + gst_value_list_append_value (value, &item); + ret = TRUE; + } + if (target_mask & (1 << GST_GL_TEXTURE_TARGET_EXTERNAL_OES)) { + gst_gl_value_set_texture_target (&item, + GST_GL_TEXTURE_TARGET_EXTERNAL_OES); + gst_value_list_append_value (value, &item); + ret = TRUE; + } + + return ret; + } +} diff --git a/gst-libs/gst/gl/gstglutils.h b/gst-libs/gst/gl/gstglutils.h index 3c8460b795..1c5ab12344 100644 --- a/gst-libs/gst/gl/gstglutils.h +++ b/gst-libs/gst/gl/gstglutils.h @@ -111,6 +111,11 @@ gsize gst_gl_get_plane_start (GstVideoInfo * info, GstVideoAlignment * valign, GstCaps * gst_gl_caps_replace_all_caps_features (const GstCaps * caps, const gchar * feature_name); +gboolean gst_gl_value_set_texture_target_from_mask (GValue * value, + GstGLTextureTarget target_mask); +gboolean gst_gl_value_set_texture_target (GValue * value, GstGLTextureTarget target); +GstGLTextureTarget gst_gl_value_get_texture_target_mask (const GValue * value); + G_END_DECLS #endif /* __GST_GL_UTILS_H__ */