diff options
Diffstat (limited to 'gst')
-rw-r--r-- | gst/videocrop/gstvideocrop.c | 159 | ||||
-rw-r--r-- | gst/videocrop/gstvideocrop.h | 5 |
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; |