camerabin: crop still image capture frame if necessary

If incoming still image capture frame aspect ratio differs from aspect
ratio that application requested, then apply crop to the frame.
This commit is contained in:
Lasse Laukkanen 2009-03-09 18:00:45 +02:00 committed by Stefan Kost
parent 2d4469c984
commit 53e6e4b0d5

View file

@ -1313,18 +1313,36 @@ gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps)
gst_camerabin_update_aspect_filter (camera, new_caps); gst_camerabin_update_aspect_filter (camera, new_caps);
} }
/*
* gst_camerabin_adapt_video_resolution:
* @camera: camerabin object
* @caps: caps describing the next incoming buffer format
*
* This function adjusts capsfilter and crop elements in order to modify
* the incoming buffer to the resolution that application requested.
*
*/
static void static void
gst_camerabin_adapt_video_resolution (GstCameraBin * camera, GstCaps * caps) gst_camerabin_adapt_video_resolution (GstCameraBin * camera, GstCaps * caps)
{ {
GstStructure *st; GstStructure *st;
gint width = 0, height = 0; gint width = 0, height = 0;
GstCaps *filter_caps = NULL; GstCaps *filter_caps = NULL;
gint top, bottom, left, right, crop;
gdouble ratio_w, ratio_h;
g_return_if_fail (camera->width != 0 && camera->height != 0);
/* Get width and height from caps */ /* Get width and height from caps */
st = gst_caps_get_structure (caps, 0); st = gst_caps_get_structure (caps, 0);
gst_structure_get_int (st, "width", &width); gst_structure_get_int (st, "width", &width);
gst_structure_get_int (st, "height", &height); gst_structure_get_int (st, "height", &height);
if (width == camera->width && height == camera->height) {
GST_DEBUG_OBJECT (camera, "no adaptation with resolution needed");
return;
}
GST_DEBUG_OBJECT (camera, GST_DEBUG_OBJECT (camera,
"changing %dx%d -> %dx%d filter to %" GST_PTR_FORMAT, "changing %dx%d -> %dx%d filter to %" GST_PTR_FORMAT,
camera->width, camera->height, width, height, camera->src_filter); camera->width, camera->height, width, height, camera->src_filter);
@ -1336,7 +1354,31 @@ gst_camerabin_adapt_video_resolution (GstCameraBin * camera, GstCaps * caps)
"height", G_TYPE_INT, height, NULL); "height", G_TYPE_INT, height, NULL);
g_object_set (G_OBJECT (camera->src_filter), "caps", filter_caps, NULL); g_object_set (G_OBJECT (camera->src_filter), "caps", filter_caps, NULL);
gst_caps_unref (filter_caps); gst_caps_unref (filter_caps);
/* FIXME: implement cropping according to requested aspect ratio */
/* Crop if requested aspect ratio differs from incoming frame aspect ratio */
/* Don't override original crop values in case we have zoom applied */
g_object_get (G_OBJECT (camera->src_zoom_crop), "top", &top, "bottom",
&bottom, "left", &left, "right", &right, NULL);
ratio_w = (gdouble) width / camera->width;
ratio_h = (gdouble) height / camera->height;
if (ratio_w < ratio_h) {
crop = height - (camera->height * ratio_w);
top += crop / 2;
bottom += crop / 2;
} else {
crop = width - (camera->width * ratio_h);
left += crop / 2;
right += crop / 2;
}
GST_INFO_OBJECT (camera,
"updating crop: left:%d, right:%d, top:%d, bottom:%d", left, right, top,
bottom);
g_object_set (G_OBJECT (camera->src_zoom_crop), "top", top, "bottom", bottom,
"left", left, "right", right, NULL);
} }
/* /*
@ -1353,11 +1395,13 @@ img_capture_prepared (gpointer data, GstCaps * caps)
GstStructure *st, *new_st; GstStructure *st, *new_st;
gint i; gint i;
const gchar *field_name; const gchar *field_name;
gboolean adapt = FALSE;
GST_INFO_OBJECT (camera, "image capture prepared"); GST_INFO_OBJECT (camera, "image capture prepared");
/* It is possible we are about to get something else that we requested */ /* It is possible we are about to get something else that we requested */
if (!gst_caps_is_equal (camera->image_capture_caps, caps)) { if (!gst_caps_is_equal (camera->image_capture_caps, caps)) {
adapt = TRUE;
/* If capture preparation has added new fields to requested caps, /* If capture preparation has added new fields to requested caps,
we need to copy them */ we need to copy them */
st = gst_caps_get_structure (camera->image_capture_caps, 0); st = gst_caps_get_structure (camera->image_capture_caps, 0);
@ -1378,10 +1422,11 @@ img_capture_prepared (gpointer data, GstCaps * caps)
/* Update capsfilters */ /* Update capsfilters */
gst_camerabin_set_capsfilter_caps (camera, camera->image_capture_caps); gst_camerabin_set_capsfilter_caps (camera, camera->image_capture_caps);
/* If incoming buffer resolution is different from what application if (adapt) {
requested, then we need to fix this in camerabin */ /* If incoming buffer resolution is different from what application
gst_camerabin_adapt_video_resolution (camera, caps); requested, then we can fix this in camerabin */
gst_camerabin_adapt_video_resolution (camera, caps);
}
g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE, g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE,
"active-pad", camera->pad_src_img, NULL); "active-pad", camera->pad_src_img, NULL);
gst_camerabin_rewrite_tags (camera); gst_camerabin_rewrite_tags (camera);
@ -2756,8 +2801,13 @@ gst_camerabin_handle_message_func (GstBin * bin, GstMessage * msg)
/* Image eos */ /* Image eos */
GST_DEBUG_OBJECT (camera, "got image eos message"); GST_DEBUG_OBJECT (camera, "got image eos message");
/* Still image capture buffer handled, restore filter caps */ /* HACK: v4l2camsrc changes to view finder resolution automatically
after one captured still image */
if (camera->image_capture_caps) { if (camera->image_capture_caps) {
GST_DEBUG_OBJECT (camera, "resetting crop in camerabin");
g_object_set (camera->src_zoom_crop, "left", 0, "right", 0,
"top", 0, "bottom", 0, NULL);
/* Still image capture buffer handled, restore filter caps */
gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps); gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps);
} }