glupload: always add texture-target field to GL caps

1. Various elements/base classes only perform a subset check on accept-caps
2. Some GL elements have texture-target in their pad template
3. When checking subsets, only the caps to check are allowed to contain extra
   fields.  If the 'template' caps have extra fields, the subset fails.
Thus without texture-target on the caps, various accept-caps implementations
were failing.

Also, add some convenience functions for setting and retrieving
texture targets to/from GValue.

https://bugzilla.gnome.org/show_bug.cgi?id=759860
This commit is contained in:
Matthew Waters 2016-01-04 20:26:09 +11:00 committed by Tim-Philipp Müller
parent ec5eb678d0
commit 86110c4765
4 changed files with 200 additions and 37 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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__ */