summaryrefslogtreecommitdiff
path: root/gst
diff options
context:
space:
mode:
Diffstat (limited to 'gst')
-rw-r--r--gst/videocrop/gstvideocrop.c159
-rw-r--r--gst/videocrop/gstvideocrop.h5
2 files changed, 129 insertions, 35 deletions
diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c
index 14c7bac25..082ca1184 100644
--- a/gst/videocrop/gstvideocrop.c
+++ b/gst/videocrop/gstvideocrop.c
@@ -210,17 +210,21 @@ gst_video_crop_class_init (GstVideoCropClass * klass)
gobject_class->get_property = gst_video_crop_get_property;
g_object_class_install_property (gobject_class, ARG_LEFT,
- g_param_spec_int ("left", "Left", "Pixels to crop at left",
- 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_param_spec_int ("left", "Left",
+ "Pixels to crop at left (-1 to auto-crop)", -1, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_RIGHT,
- g_param_spec_int ("right", "Right", "Pixels to crop at right",
- 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_param_spec_int ("right", "Right",
+ "Pixels to crop at right (-1 to auto-crop)", -1, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_TOP,
- g_param_spec_int ("top", "Top", "Pixels to crop at top",
- 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_param_spec_int ("top", "Top",
+ "Pixels to crop at top (-1 to auto-crop)", -1, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_BOTTOM,
- g_param_spec_int ("bottom", "Bottom", "Pixels to crop at bottom",
- 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_param_spec_int ("bottom", "Bottom",
+ "Pixels to crop at bottom (-1 to auto-crop)", -1, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
basetransform_class->transform = GST_DEBUG_FUNCPTR (gst_video_crop_transform);
basetransform_class->transform_caps =
@@ -236,6 +240,10 @@ gst_video_crop_class_init (GstVideoCropClass * klass)
static void
gst_video_crop_init (GstVideoCrop * vcrop, GstVideoCropClass * klass)
{
+ vcrop->prop_right = 0;
+ vcrop->prop_left = 0;
+ vcrop->prop_top = 0;
+ vcrop->prop_bottom = 0;
vcrop->crop_right = 0;
vcrop->crop_left = 0;
vcrop->crop_top = 0;
@@ -507,33 +515,69 @@ gst_video_crop_transform_dimension (gint val, gint delta)
static gboolean
gst_video_crop_transform_dimension_value (const GValue * src_val,
- gint delta, GValue * dest_val)
+ gint delta, GValue * dest_val, GstPadDirection direction, gboolean dynamic)
{
gboolean ret = TRUE;
- g_value_init (dest_val, G_VALUE_TYPE (src_val));
-
if (G_VALUE_HOLDS_INT (src_val)) {
gint ival = g_value_get_int (src_val);
-
ival = gst_video_crop_transform_dimension (ival, delta);
- g_value_set_int (dest_val, ival);
+
+ if (dynamic) {
+ if (direction == GST_PAD_SRC) {
+ if (ival == G_MAXINT) {
+ g_value_init (dest_val, G_TYPE_INT);
+ g_value_set_int (dest_val, ival);
+ } else {
+ g_value_init (dest_val, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (dest_val, ival, G_MAXINT);
+ }
+ } else {
+ if (ival == 1) {
+ g_value_init (dest_val, G_TYPE_INT);
+ g_value_set_int (dest_val, ival);
+ } else {
+ g_value_init (dest_val, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (dest_val, 1, ival);
+ }
+ }
+ } else {
+ g_value_init (dest_val, G_TYPE_INT);
+ g_value_set_int (dest_val, ival);
+ }
} else if (GST_VALUE_HOLDS_INT_RANGE (src_val)) {
gint min = gst_value_get_int_range_min (src_val);
gint max = gst_value_get_int_range_max (src_val);
min = gst_video_crop_transform_dimension (min, delta);
max = gst_video_crop_transform_dimension (max, delta);
- gst_value_set_int_range (dest_val, min, max);
+
+ if (dynamic) {
+ if (direction == GST_PAD_SRC)
+ max = G_MAXINT;
+ else
+ min = 1;
+ }
+
+ if (min == max) {
+ g_value_init (dest_val, G_TYPE_INT);
+ g_value_set_int (dest_val, min);
+ } else {
+ g_value_init (dest_val, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (dest_val, min, max);
+ }
} else if (GST_VALUE_HOLDS_LIST (src_val)) {
gint i;
+ g_value_init (dest_val, GST_TYPE_LIST);
+
for (i = 0; i < gst_value_list_get_size (src_val); ++i) {
const GValue *list_val;
GValue newval = { 0, };
list_val = gst_value_list_get_value (src_val, i);
- if (gst_video_crop_transform_dimension_value (list_val, delta, &newval))
+ if (gst_video_crop_transform_dimension_value (list_val, delta, &newval,
+ direction, dynamic))
gst_value_list_append_value (dest_val, &newval);
g_value_unset (&newval);
}
@@ -543,7 +587,6 @@ gst_video_crop_transform_dimension_value (const GValue * src_val,
ret = FALSE;
}
} else {
- g_value_unset (dest_val);
ret = FALSE;
}
@@ -556,21 +599,30 @@ gst_video_crop_transform_caps (GstBaseTransform * trans,
{
GstVideoCrop *vcrop;
GstCaps *other_caps;
- gint dy, dx, i;
+ gint dy, dx, i, left, right, bottom, top;
+ gboolean w_dynamic, h_dynamic;
vcrop = GST_VIDEO_CROP (trans);
GST_OBJECT_LOCK (vcrop);
GST_LOG_OBJECT (vcrop, "l=%d,r=%d,b=%d,t=%d",
- vcrop->crop_left, vcrop->crop_right, vcrop->crop_bottom, vcrop->crop_top);
+ vcrop->prop_left, vcrop->prop_right, vcrop->prop_bottom, vcrop->prop_top);
+
+ w_dynamic = (vcrop->prop_left == -1 || vcrop->prop_right == -1);
+ h_dynamic = (vcrop->prop_top == -1 || vcrop->prop_bottom == -1);
+
+ left = (vcrop->prop_left == -1) ? 0 : vcrop->prop_left;
+ right = (vcrop->prop_right == -1) ? 0 : vcrop->prop_right;
+ bottom = (vcrop->prop_bottom == -1) ? 0 : vcrop->prop_bottom;
+ top = (vcrop->prop_top == -1) ? 0 : vcrop->prop_top;
if (direction == GST_PAD_SRC) {
- dx = vcrop->crop_left + vcrop->crop_right;
- dy = vcrop->crop_top + vcrop->crop_bottom;
+ dx = left + right;
+ dy = top + bottom;
} else {
- dx = 0 - (vcrop->crop_left + vcrop->crop_right);
- dy = 0 - (vcrop->crop_top + vcrop->crop_bottom);
+ dx = 0 - (left + right);
+ dy = 0 - (top + bottom);
}
GST_OBJECT_UNLOCK (vcrop);
@@ -587,14 +639,16 @@ gst_video_crop_transform_caps (GstBaseTransform * trans,
structure = gst_caps_get_structure (caps, i);
v = gst_structure_get_value (structure, "width");
- if (!gst_video_crop_transform_dimension_value (v, dx, &w_val)) {
+ if (!gst_video_crop_transform_dimension_value (v, dx, &w_val, direction,
+ w_dynamic)) {
GST_WARNING_OBJECT (vcrop, "could not tranform width value with dx=%d"
", caps structure=%" GST_PTR_FORMAT, dx, structure);
continue;
}
v = gst_structure_get_value (structure, "height");
- if (!gst_video_crop_transform_dimension_value (v, dy, &h_val)) {
+ if (!gst_video_crop_transform_dimension_value (v, dy, &h_val, direction,
+ h_dynamic)) {
g_value_unset (&w_val);
GST_WARNING_OBJECT (vcrop, "could not tranform height value with dy=%d"
", caps structure=%" GST_PTR_FORMAT, dy, structure);
@@ -624,6 +678,7 @@ gst_video_crop_set_caps (GstBaseTransform * trans, GstCaps * incaps,
GstCaps * outcaps)
{
GstVideoCrop *crop = GST_VIDEO_CROP (trans);
+ int dx, dy;
if (!gst_video_crop_get_image_details_from_caps (crop, &crop->in, incaps))
goto wrong_input;
@@ -631,6 +686,40 @@ gst_video_crop_set_caps (GstBaseTransform * trans, GstCaps * incaps,
if (!gst_video_crop_get_image_details_from_caps (crop, &crop->out, outcaps))
goto wrong_output;
+ crop->crop_left = crop->prop_left;
+ crop->crop_right = crop->prop_right;
+ crop->crop_top = crop->prop_top;
+ crop->crop_bottom = crop->prop_bottom;
+
+ dx = crop->in.width - crop->out.width;
+ dy = crop->in.height - crop->out.height;
+
+ if (crop->prop_left == -1 && crop->prop_right == -1) {
+ crop->crop_left = dx / 2;
+ crop->crop_right = dx / 2 + (dx & 1);
+ } else if (crop->prop_left == -1) {
+ if (G_UNLIKELY (crop->prop_right > dx))
+ goto cropping_too_much;
+ crop->crop_left = dx - crop->prop_right;
+ } else if (crop->prop_right == -1) {
+ if (G_UNLIKELY (crop->prop_left > dx))
+ goto cropping_too_much;
+ crop->crop_right = dx - crop->prop_left;
+ }
+
+ if (crop->prop_top == -1 && crop->prop_bottom == -1) {
+ crop->crop_top = dy / 2;
+ crop->crop_bottom = dy / 2 + (dy & 1);
+ } else if (crop->prop_top == -1) {
+ if (G_UNLIKELY (crop->prop_bottom > dy))
+ goto cropping_too_much;
+ crop->crop_top = dy - crop->prop_bottom;
+ } else if (crop->prop_bottom == -1) {
+ if (G_UNLIKELY (crop->prop_top > dy))
+ goto cropping_too_much;
+ crop->crop_bottom = dy - crop->prop_top;
+ }
+
if (G_UNLIKELY ((crop->crop_left + crop->crop_right) >= crop->in.width ||
(crop->crop_top + crop->crop_bottom) >= crop->in.height))
goto cropping_too_much;
@@ -652,19 +741,19 @@ gst_video_crop_set_caps (GstBaseTransform * trans, GstCaps * incaps,
/* ERROR */
wrong_input:
{
- GST_DEBUG_OBJECT (crop, "failed to parse input caps %" GST_PTR_FORMAT,
+ GST_WARNING_OBJECT (crop, "failed to parse input caps %" GST_PTR_FORMAT,
incaps);
return FALSE;
}
wrong_output:
{
- GST_DEBUG_OBJECT (crop, "failed to parse output caps %" GST_PTR_FORMAT,
+ GST_WARNING_OBJECT (crop, "failed to parse output caps %" GST_PTR_FORMAT,
outcaps);
return FALSE;
}
cropping_too_much:
{
- GST_DEBUG_OBJECT (crop, "we are cropping too much");
+ GST_WARNING_OBJECT (crop, "we are cropping too much");
return FALSE;
}
}
@@ -684,16 +773,16 @@ gst_video_crop_set_property (GObject * object, guint prop_id,
GST_OBJECT_LOCK (video_crop);
switch (prop_id) {
case ARG_LEFT:
- video_crop->crop_left = g_value_get_int (value);
+ video_crop->prop_left = g_value_get_int (value);
break;
case ARG_RIGHT:
- video_crop->crop_right = g_value_get_int (value);
+ video_crop->prop_right = g_value_get_int (value);
break;
case ARG_TOP:
- video_crop->crop_top = g_value_get_int (value);
+ video_crop->prop_top = g_value_get_int (value);
break;
case ARG_BOTTOM:
- video_crop->crop_bottom = g_value_get_int (value);
+ video_crop->prop_bottom = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -720,16 +809,16 @@ gst_video_crop_get_property (GObject * object, guint prop_id, GValue * value,
GST_OBJECT_LOCK (video_crop);
switch (prop_id) {
case ARG_LEFT:
- g_value_set_int (value, video_crop->crop_left);
+ g_value_set_int (value, video_crop->prop_left);
break;
case ARG_RIGHT:
- g_value_set_int (value, video_crop->crop_right);
+ g_value_set_int (value, video_crop->prop_right);
break;
case ARG_TOP:
- g_value_set_int (value, video_crop->crop_top);
+ g_value_set_int (value, video_crop->prop_top);
break;
case ARG_BOTTOM:
- g_value_set_int (value, video_crop->crop_bottom);
+ g_value_set_int (value, video_crop->prop_bottom);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h
index 477f21b06..d13ca9b2d 100644
--- a/gst/videocrop/gstvideocrop.h
+++ b/gst/videocrop/gstvideocrop.h
@@ -70,6 +70,11 @@ struct _GstVideoCrop
GstBaseTransform basetransform;
/*< private >*/
+ gint prop_left;
+ gint prop_right;
+ gint prop_top;
+ gint prop_bottom;
+
gint crop_left;
gint crop_right;
gint crop_top;