mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 17:51:16 +00:00
glvideomixer: Add xalign and yalign properties
With the addition of the 'keep-aspect-ratio' sizing policy, content that doesn't fit the target size is downscaled according to its own aspect ratio to fit that target size, and centered. Centering might not always be the desired behaviour, however; consumers of this API might want to align the resulting picture to the left or to the right. To account for any of these cases, add two new properties to the glvideomixer pad: xalign, and yalign. They operate on normalized coordinates (0.0 for start, 1.0 for end), and default to 0.5 which centers content. <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3762> Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3762>
This commit is contained in:
parent
c5d211d45a
commit
a8a7ee6d83
2 changed files with 224 additions and 5 deletions
|
@ -7657,6 +7657,20 @@
|
|||
"type": "gint",
|
||||
"writable": true
|
||||
},
|
||||
"xalign": {
|
||||
"blurb": "X alignment of the picture",
|
||||
"conditionally-available": false,
|
||||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": true,
|
||||
"default": "0",
|
||||
"max": "1",
|
||||
"min": "0",
|
||||
"mutable": "null",
|
||||
"readable": true,
|
||||
"type": "gdouble",
|
||||
"writable": true
|
||||
},
|
||||
"xpos": {
|
||||
"blurb": "X Position of the picture",
|
||||
"conditionally-available": false,
|
||||
|
@ -7671,6 +7685,20 @@
|
|||
"type": "gint",
|
||||
"writable": true
|
||||
},
|
||||
"yalign": {
|
||||
"blurb": "Y alignment of the picture",
|
||||
"conditionally-available": false,
|
||||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": true,
|
||||
"default": "0",
|
||||
"max": "1",
|
||||
"min": "0",
|
||||
"mutable": "null",
|
||||
"readable": true,
|
||||
"type": "gdouble",
|
||||
"writable": true
|
||||
},
|
||||
"ypos": {
|
||||
"blurb": "Y Position of the picture",
|
||||
"conditionally-available": false,
|
||||
|
@ -7953,6 +7981,20 @@
|
|||
"type": "gint",
|
||||
"writable": true
|
||||
},
|
||||
"xalign": {
|
||||
"blurb": "X alignment of the picture",
|
||||
"conditionally-available": false,
|
||||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": true,
|
||||
"default": "0.5",
|
||||
"max": "1",
|
||||
"min": "0",
|
||||
"mutable": "null",
|
||||
"readable": true,
|
||||
"type": "gdouble",
|
||||
"writable": true
|
||||
},
|
||||
"xpos": {
|
||||
"blurb": "X Position of the picture",
|
||||
"conditionally-available": false,
|
||||
|
@ -7967,6 +8009,20 @@
|
|||
"type": "gint",
|
||||
"writable": true
|
||||
},
|
||||
"yalign": {
|
||||
"blurb": "Y alignment of the picture",
|
||||
"conditionally-available": false,
|
||||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": true,
|
||||
"default": "0.5",
|
||||
"max": "1",
|
||||
"min": "0",
|
||||
"mutable": "null",
|
||||
"readable": true,
|
||||
"type": "gdouble",
|
||||
"writable": true
|
||||
},
|
||||
"ypos": {
|
||||
"blurb": "Y Position of the picture",
|
||||
"conditionally-available": false,
|
||||
|
@ -7993,7 +8049,7 @@
|
|||
"value": "0"
|
||||
},
|
||||
{
|
||||
"desc": "Keep Aspect Ratio: Image is scaled to fit destination rectangle specified by GstGLVideoMixerPad:{xpos, ypos, width, height} with preserved aspect ratio. Resulting image will be centered in the destination rectangle with padding if necessary",
|
||||
"desc": "Keep Aspect Ratio: Image is scaled to fit destination rectangle specified by GstGLVideoMixerPad:{xpos, ypos, width, height} with preserved aspect ratio. The empty space of the resulting image will be distributed in the destination rectangle according to the GstGLVideoMixerPad:{xalign, yalign} values",
|
||||
"name": "keep-aspect-ratio",
|
||||
"value": "1"
|
||||
}
|
||||
|
|
|
@ -167,8 +167,9 @@ gst_gl_video_mixer_sizing_policy_get_type (void)
|
|||
{GST_GL_VIDEO_MIXER_SIZING_POLICY_KEEP_ASPECT_RATIO,
|
||||
"Keep Aspect Ratio: Image is scaled to fit destination rectangle "
|
||||
"specified by GstGLVideoMixerPad:{xpos, ypos, width, height} "
|
||||
"with preserved aspect ratio. Resulting image will be centered in "
|
||||
"the destination rectangle with padding if necessary",
|
||||
"with preserved aspect ratio. The empty space of the resulting image "
|
||||
"will be distributed in the destination rectangle according to the "
|
||||
"GstGLVideoMixerPad:{xalign, yalign} values",
|
||||
"keep-aspect-ratio"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
|
@ -195,6 +196,8 @@ gst_gl_video_mixer_sizing_policy_get_type (void)
|
|||
#define DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA
|
||||
#define DEFAULT_PAD_CROP 0
|
||||
#define DEFAULT_PAD_SIZING_POLICY GST_GL_VIDEO_MIXER_SIZING_POLICY_NONE
|
||||
#define DEFAULT_PAD_XALIGN 0.5
|
||||
#define DEFAULT_PAD_YALIGN 0.5
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -221,6 +224,8 @@ enum
|
|||
PROP_INPUT_CROP_TOP,
|
||||
PROP_INPUT_CROP_BOTTOM,
|
||||
PROP_INPUT_SIZING_POLICY,
|
||||
PROP_INPUT_XALIGN,
|
||||
PROP_INPUT_YALIGN,
|
||||
};
|
||||
|
||||
static void gst_gl_video_mixer_input_get_property (GObject * object,
|
||||
|
@ -417,6 +422,54 @@ gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass)
|
|||
"Sizing policy to use for image scaling",
|
||||
GST_TYPE_GL_VIDEO_MIXER_SIZING_POLICY, DEFAULT_PAD_SIZING_POLICY,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstGLVideoMixerInput:xalign:
|
||||
*
|
||||
* Defines the alignment of the input within the available horizontal space,
|
||||
* relative to #GstGLVideoMixerPad:width and #GstGLVideoMixerPad:height.
|
||||
* Values range from 0.0 (left) to 1.0 (right).
|
||||
*
|
||||
* The image is aligned in the available space as if the pivot point is
|
||||
* matching the alignment. For example, setting the `xalign` property to 0.0
|
||||
* will align the left edge of the image with the left edge of the bounding
|
||||
* box; 0.5 aligns the horizontal center of the image with the horizontal
|
||||
* center of the bounding box; 1.0 aligns the right edge of the image with the
|
||||
* right edge of the bounding box; and so it goes.
|
||||
*
|
||||
* This property is only effective when #GstGLVideoMixerInput:sizing-policy
|
||||
* is set to 'keep-aspect-ratio'.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_XALIGN,
|
||||
g_param_spec_double ("xalign", "X alignment",
|
||||
"X alignment of the picture", 0.0, 1.0, DEFAULT_PAD_XALIGN,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstGLVideoMixerInput:yalign:
|
||||
*
|
||||
* Defines the alignment of the input within the available vertical space,
|
||||
* relative to #GstGLVideoMixerPad:width and #GstGLVideoMixerPad:height.
|
||||
* Values range from 0.0 (top) to 1.0 (bottom).
|
||||
*
|
||||
* The image is aligned in the available space as if the pivot point is
|
||||
* matching the alignment. For example, setting the `xalign` property to 0.0
|
||||
* will align the left edge of the image with the left edge of the bounding
|
||||
* box; 0.5 aligns the horizontal center of the image with the horizontal
|
||||
* center of the bounding box; 1.0 aligns the right edge of the image with the
|
||||
* right edge of the bounding box; and so it goes.
|
||||
*
|
||||
* This property is only effective when #GstGLVideoMixerInput:sizing-policy
|
||||
* is set to 'keep-aspect-ratio'.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_YALIGN,
|
||||
g_param_spec_double ("yalign", "Y alignment",
|
||||
"Y alignment of the picture", 0.0, 1.0, DEFAULT_PAD_YALIGN,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -468,6 +521,8 @@ _create_video_mixer_input (GstGLMixerBin * self, GstPad * mixer_pad)
|
|||
ADD_BINDING (mixer_pad, input, "blend-constant-color-blue");
|
||||
ADD_BINDING (mixer_pad, input, "blend-constant-color-alpha");
|
||||
ADD_BINDING (mixer_pad, input, "sizing-policy");
|
||||
ADD_BINDING (mixer_pad, input, "xalign");
|
||||
ADD_BINDING (mixer_pad, input, "yalign");
|
||||
#undef ADD_BINDING
|
||||
|
||||
input->mixer_pad = mixer_pad;
|
||||
|
@ -665,6 +720,7 @@ struct _GstGLVideoMixerPad
|
|||
/* properties */
|
||||
gint xpos, ypos;
|
||||
gint width, height;
|
||||
gdouble xalign, yalign;
|
||||
gdouble alpha;
|
||||
GstGLVideoMixerSizingPolicy sizing_policy;
|
||||
|
||||
|
@ -724,6 +780,8 @@ enum
|
|||
PROP_PAD_CROP_TOP,
|
||||
PROP_PAD_CROP_BOTTOM,
|
||||
PROP_PAD_SIZING_POLICY,
|
||||
PROP_PAD_XALIGN,
|
||||
PROP_PAD_YALIGN,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -737,6 +795,8 @@ gst_gl_video_mixer_pad_init (GstGLVideoMixerPad * pad)
|
|||
pad->blend_function_dst_rgb = DEFAULT_PAD_BLEND_FUNCTION_DST_RGB;
|
||||
pad->blend_function_dst_alpha = DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA;
|
||||
pad->sizing_policy = DEFAULT_PAD_SIZING_POLICY;
|
||||
pad->xalign = DEFAULT_PAD_XALIGN;
|
||||
pad->yalign = DEFAULT_PAD_YALIGN;
|
||||
memset (pad->m_matrix, 0, sizeof (gfloat) * 4 * 4);
|
||||
pad->m_matrix[0] = 1.0;
|
||||
pad->m_matrix[5] = 1.0;
|
||||
|
@ -901,6 +961,54 @@ gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass)
|
|||
"Sizing policy to use for image scaling",
|
||||
GST_TYPE_GL_VIDEO_MIXER_SIZING_POLICY, DEFAULT_PAD_SIZING_POLICY,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstGLVideoMixerPad:xalign:
|
||||
*
|
||||
* Defines the alignment of the input within the available horizontal space,
|
||||
* relative to #GstGLVideoMixerPad:width and #GstGLVideoMixerPad:height.
|
||||
* Values range from 0.0 (left) to 1.0 (right).
|
||||
*
|
||||
* The image is aligned in the available space as if the pivot point is
|
||||
* matching the alignment. For example, setting the `xalign` property to 0.0
|
||||
* will align the left edge of the image with the left edge of the bounding
|
||||
* box; 0.5 aligns the horizontal center of the image with the horizontal
|
||||
* center of the bounding box; 1.0 aligns the right edge of the image with the
|
||||
* right edge of the bounding box; and so it goes.
|
||||
*
|
||||
* This property is only effective when #GstGLVideoMixerInput:sizing-policy
|
||||
* is set to 'keep-aspect-ratio'.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_PAD_XALIGN,
|
||||
g_param_spec_double ("xalign", "X alignment",
|
||||
"X alignment of the picture", 0.0, 1.0, DEFAULT_PAD_XALIGN,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstGLVideoMixerPad:yalign:
|
||||
*
|
||||
* Defines the alignment of the input within the available vertical space,
|
||||
* relative to #GstGLVideoMixerPad:width and #GstGLVideoMixerPad:height.
|
||||
* Values range from 0.0 (top) to 1.0 (bottom).
|
||||
*
|
||||
* The image is aligned in the available space as if the pivot point is
|
||||
* matching the alignment. For example, setting the `yalign` property to 0.0
|
||||
* will align the top edge of the image with the top edge of the bounding box;
|
||||
* 0.5 aligns the vertical center of the image with the vertical center of the
|
||||
* bounding box; 1.0 aligns the bottom edge of the image with the bottom edge
|
||||
* of the bounding box; and so it goes.
|
||||
*
|
||||
* This property is only effective when #GstGLVideoMixerInput:sizing-policy
|
||||
* is set to 'keep-aspect-ratio'.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_PAD_YALIGN,
|
||||
g_param_spec_double ("yalign", "Y alignment",
|
||||
"Y alignment of the picture", 0.0, 1.0, DEFAULT_PAD_YALIGN,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -970,6 +1078,12 @@ gst_gl_video_mixer_pad_get_property (GObject * object, guint prop_id,
|
|||
case PROP_PAD_SIZING_POLICY:
|
||||
g_value_set_enum (value, pad->sizing_policy);
|
||||
break;
|
||||
case PROP_PAD_XALIGN:
|
||||
g_value_set_double (value, pad->xalign);
|
||||
break;
|
||||
case PROP_PAD_YALIGN:
|
||||
g_value_set_double (value, pad->yalign);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1072,6 +1186,18 @@ gst_gl_video_mixer_pad_set_property (GObject * object, guint prop_id,
|
|||
pad->sizing_policy = val;
|
||||
break;
|
||||
}
|
||||
case PROP_PAD_XALIGN:{
|
||||
gdouble val = g_value_get_double (value);
|
||||
pad->geometry_change |= !G_APPROX_VALUE (val, pad->xalign, DBL_EPSILON);
|
||||
pad->xalign = val;
|
||||
break;
|
||||
}
|
||||
case PROP_PAD_YALIGN:{
|
||||
gdouble val = g_value_get_double (value);
|
||||
pad->geometry_change |= !G_APPROX_VALUE (val, pad->yalign, DBL_EPSILON);
|
||||
pad->yalign = val;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1242,6 +1368,41 @@ gst_gl_video_mixer_propose_allocation (GstAggregator * agg,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
align_rect (const GstVideoRectangle * src,
|
||||
const GstVideoRectangle * dst, GstVideoRectangle * result, gdouble xalign,
|
||||
gdouble yalign)
|
||||
{
|
||||
gdouble src_ratio, dst_ratio;
|
||||
|
||||
g_return_if_fail (src->h != 0);
|
||||
g_return_if_fail (dst->h != 0);
|
||||
|
||||
src_ratio = (gdouble) src->w / src->h;
|
||||
dst_ratio = (gdouble) dst->w / dst->h;
|
||||
|
||||
if (src_ratio > dst_ratio) {
|
||||
result->w = dst->w;
|
||||
result->h = dst->w / src_ratio;
|
||||
result->x = dst->x;
|
||||
result->y = dst->y + (dst->h - result->h) * yalign;
|
||||
} else if (src_ratio < dst_ratio) {
|
||||
result->w = dst->h * src_ratio;
|
||||
result->h = dst->h;
|
||||
result->x = dst->x + (dst->w - result->w) * xalign;
|
||||
result->y = dst->y;
|
||||
} else {
|
||||
result->x = dst->x;
|
||||
result->y = dst->y;
|
||||
result->w = dst->w;
|
||||
result->h = dst->h;
|
||||
}
|
||||
|
||||
GST_DEBUG ("source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
|
||||
src->w, src->h, dst->w, dst->h,
|
||||
result->w, result->h, result->x, result->y);
|
||||
}
|
||||
|
||||
static void
|
||||
_mixer_pad_get_output_size (GstGLVideoMixer * mix,
|
||||
GstGLVideoMixerPad * mix_pad, gint out_par_n, gint out_par_d, gint * width,
|
||||
|
@ -1332,7 +1493,8 @@ _mixer_pad_get_output_size (GstGLVideoMixer * mix,
|
|||
if (from_dar_n != -1 && from_dar_d != -1
|
||||
&& gst_util_fraction_multiply (from_dar_n, from_dar_d,
|
||||
out_par_d, out_par_n, &num, &den)) {
|
||||
GstVideoRectangle src_rect, dst_rect, rst_rect;
|
||||
GstVideoRectangle src_rect, dst_rect;
|
||||
GstVideoRectangle rst_rect = { 0, 0, 0, 0 };
|
||||
|
||||
src_rect.h = gst_util_uint64_scale_int (pad_width, den, num);
|
||||
if (src_rect.h == 0) {
|
||||
|
@ -1349,7 +1511,8 @@ _mixer_pad_get_output_size (GstGLVideoMixer * mix,
|
|||
dst_rect.h = pad_height;
|
||||
|
||||
/* Scale rect to be centered in destination rect */
|
||||
gst_video_center_rect (&src_rect, &dst_rect, &rst_rect, TRUE);
|
||||
align_rect (&src_rect, &dst_rect, &rst_rect, mix_pad->xalign,
|
||||
mix_pad->yalign);
|
||||
|
||||
GST_LOG_OBJECT (mix_pad,
|
||||
"Re-calculated size %dx%d -> %dx%d (x-offset %d, y-offset %d)",
|
||||
|
|
Loading…
Reference in a new issue