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));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
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);
}
ret = FALSE;
}
} else {
- g_value_unset (dest_val);
ret = FALSE;
}
{
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);
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);
GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info)
{
GstVideoCrop *crop = GST_VIDEO_CROP (vfilter);
+ int dx, dy;
+
+ 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 = GST_VIDEO_INFO_WIDTH (in_info) - GST_VIDEO_INFO_WIDTH (out_info);
+ dy = GST_VIDEO_INFO_HEIGHT (in_info) - GST_VIDEO_INFO_HEIGHT (out_info);
+
+ 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) >=
GST_VIDEO_INFO_WIDTH (in_info)
/* ERROR */
cropping_too_much:
{
- GST_DEBUG_OBJECT (crop, "we are cropping too much");
+ GST_WARNING_OBJECT (crop, "we are cropping too much");
return FALSE;
}
unknown_format:
{
- GST_DEBUG_OBJECT (crop, "Unsupported format");
+ GST_WARNING_OBJECT (crop, "Unsupported format");
return FALSE;
}
}
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);
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);
GstElement *src;
GstElement *filter;
GstElement *crop;
+ GstElement *filter2;
GstElement *sink;
GstBuffer *last_buf;
GstCaps *last_caps;
fail_unless (ctx->filter != NULL, "Failed to create capsfilter element");
ctx->crop = gst_element_factory_make ("videocrop", "crop");
fail_unless (ctx->crop != NULL, "Failed to create videocrop element");
+ ctx->filter2 = gst_element_factory_make ("capsfilter", "filter2");
+ fail_unless (ctx->filter2 != NULL,
+ "Failed to create second capsfilter element");
ctx->sink = gst_element_factory_make ("fakesink", "sink");
fail_unless (ctx->sink != NULL, "Failed to create fakesink element");
gst_bin_add_many (GST_BIN (ctx->pipeline), ctx->src, ctx->filter,
- ctx->crop, ctx->sink, NULL);
- gst_element_link_many (ctx->src, ctx->filter, ctx->crop, ctx->sink, NULL);
+ ctx->crop, ctx->filter2, ctx->sink, NULL);
+ gst_element_link_many (ctx->src, ctx->filter, ctx->crop, ctx->filter2,
+ ctx->sink, NULL);
/* set pattern to 'red' - for our purposes it doesn't matter anyway */
g_object_set (ctx->src, "pattern", 4, NULL);
static void
videocrop_test_cropping (GstVideoCropTestContext * ctx, GstCaps * in_caps,
- gint left, gint right, gint top, gint bottom,
+ GstCaps * out_caps, gint left, gint right, gint top, gint bottom,
GstVideoCropTestBufferFunc func)
{
- GST_LOG ("lrtb = %03u %03u %03u %03u, caps = %" GST_PTR_FORMAT, left, right,
- top, bottom, in_caps);
+ GST_LOG ("lrtb = %03u %03u %03u %03u, in_caps = %" GST_PTR_FORMAT
+ ", out_caps = %" GST_PTR_FORMAT, left, right, top, bottom, in_caps,
+ out_caps);
g_object_set (ctx->filter, "caps", in_caps, NULL);
+ g_object_set (ctx->filter2, "caps", out_caps, NULL);
g_object_set (ctx->crop, "left", left, "right", right, "top", top,
"bottom", bottom, NULL);
gst_structure_set (s, "width", G_TYPE_INT, 160,
"height", G_TYPE_INT, 160, NULL);
- videocrop_test_cropping (&ctx, caps, 159, 0, 159, 0, check_1x1_buffer);
+ videocrop_test_cropping (&ctx, caps, NULL, 159, 0, 159, 0,
+ check_1x1_buffer);
/* commented out because they don't really add anything useful check-wise:
- videocrop_test_cropping (&ctx, caps, 0, 159, 0, 159, check_1x1_buffer);
- videocrop_test_cropping (&ctx, caps, 159, 0, 0, 159, check_1x1_buffer);
- videocrop_test_cropping (&ctx, caps, 0, 159, 159, 0, check_1x1_buffer);
+ videocrop_test_cropping (&ctx, caps, NULL, 0, 159, 0, 159, check_1x1_buffer);
+ videocrop_test_cropping (&ctx, caps, NULL, 159, 0, 0, 159, check_1x1_buffer);
+ videocrop_test_cropping (&ctx, caps, NULL, 0, 159, 159, 0, check_1x1_buffer);
*/
gst_caps_unref (caps);
}
GST_INFO ("testing format: %" GST_PTR_FORMAT, caps);
for (i = 0; i < G_N_ELEMENTS (sizes_to_try); ++i) {
- GstCaps *in_caps;
+ GstCaps *in_caps, *out_caps;
GST_INFO (" - %d x %d", sizes_to_try[i].width, sizes_to_try[i].height);
"height", G_TYPE_INT, sizes_to_try[i].height, NULL);
in_caps = gst_caps_copy (caps);
- videocrop_test_cropping (&ctx, in_caps, 0, 0, 0, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 1, 0, 0, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 1, 0, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 0, 1, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 0, 0, 1, NULL);
- videocrop_test_cropping (&ctx, in_caps, 63, 0, 0, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 63, 0, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 0, 63, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 0, 0, 63, NULL);
- videocrop_test_cropping (&ctx, in_caps, 63, 0, 0, 1, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 63, 1, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 1, 63, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 1, 0, 0, 63, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 0, 0, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 32, 0, 0, 128, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 32, 128, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 0, 128, 32, 0, NULL);
- videocrop_test_cropping (&ctx, in_caps, 128, 0, 0, 32, NULL);
- videocrop_test_cropping (&ctx, in_caps, 1, 1, 1, 1, NULL);
- videocrop_test_cropping (&ctx, in_caps, 63, 63, 63, 63, NULL);
- videocrop_test_cropping (&ctx, in_caps, 64, 64, 64, 64, NULL);
+ gst_structure_set (s, "width", G_TYPE_INT, 1, "height", G_TYPE_INT, 1,
+ NULL);
+ out_caps = gst_caps_copy (caps);
+
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 0, 0, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 1, 0, 0, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 1, 0, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 0, 1, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 0, 0, 1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 63, 0, 0, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 63, 0, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 0, 63, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 0, 0, 63, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 63, 0, 0, 1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 63, 1, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 1, 63, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 1, 0, 0, 63, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 0, 0, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 32, 0, 0, 128, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 32, 128, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 0, 128, 32, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 128, 0, 0, 32, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 1, 1, 1, 1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 63, 63, 63, 63, NULL);
+ videocrop_test_cropping (&ctx, in_caps, NULL, 64, 64, 64, 64, NULL);
+
+ /* Dynamic cropping */
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, -1, -1, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, 0, -1, -1, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, 0, -1, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, -1, 0, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, -1, -1, 0, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, 10, -1, 10, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, 10, -1, 10, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps,
+ sizes_to_try[i].width - 1, -1, -1, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1,
+ sizes_to_try[i].width - 1, -1, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, -1,
+ sizes_to_try[i].height - 1, -1, NULL);
+ videocrop_test_cropping (&ctx, in_caps, out_caps, -1, -1, -1,
+ sizes_to_try[i].height - 1, NULL);
gst_caps_unref (in_caps);
+ gst_caps_unref (out_caps);
}
gst_caps_unref (caps);