summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLasse Laukkanen <ext-lasse.2.laukkanen@nokia.com>2009-02-20 12:07:33 +0200
committerRené Stadler <rene.stadler@nokia.com>2009-02-23 14:20:12 +0200
commit24d99bbe5642f37aeca0adaff6d2fd4dd2e15388 (patch)
tree9b6bb6ea1c6e1dd813d077657b66f72cb1f1ff65
parent617f34895c99c41b4515ecc4c499576773599883 (diff)
camerabin: Scale incoming frames if their size does not match requested size
If capture preparation in videosrc results in frame size different from requested size, then we need to scale them.
-rw-r--r--gst/camerabin/gstcamerabin.c91
1 files changed, 71 insertions, 20 deletions
diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c
index c54a909b3..ffa7575a5 100644
--- a/gst/camerabin/gstcamerabin.c
+++ b/gst/camerabin/gstcamerabin.c
@@ -1266,24 +1266,75 @@ gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps)
g_object_set (G_OBJECT (camera->src_zoom_filter), "caps", new_caps, NULL);
}
+static void
+gst_camerabin_adapt_video_resolution (GstCameraBin * camera, GstCaps * caps)
+{
+ GstStructure *st;
+ gint width = 0, height = 0;
+ GstCaps *filter_caps = NULL;
+
+ /* Get width and height from caps */
+ st = gst_caps_get_structure (caps, 0);
+ gst_structure_get_int (st, "width", &width);
+ gst_structure_get_int (st, "height", &height);
+
+ GST_DEBUG_OBJECT (camera,
+ "changing %dx%d -> %dx%d filter to %" GST_PTR_FORMAT,
+ camera->width, camera->height, width, height, camera->src_filter);
+
+ /* Apply the width and height to filter caps */
+ g_object_get (G_OBJECT (camera->src_filter), "caps", &filter_caps, NULL);
+ filter_caps = gst_caps_make_writable (filter_caps);
+ gst_caps_set_simple (filter_caps, "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height, NULL);
+ g_object_set (G_OBJECT (camera->src_filter), "caps", filter_caps, NULL);
+ gst_caps_unref (filter_caps);
+ /* FIXME: implement cropping according to requested aspect ratio */
+}
+
/*
* img_capture_prepared:
* @data: camerabin object
+ * @caps: caps describing the prepared image format
*
* Callback which is called after image capture has been prepared.
*/
static void
-img_capture_prepared (gpointer data)
+img_capture_prepared (gpointer data, GstCaps * caps)
{
GstCameraBin *camera = GST_CAMERABIN (data);
+ GstStructure *st, *new_st;
+ gint i;
+ const gchar *field_name;
GST_INFO_OBJECT (camera, "image capture prepared");
- if (camera->image_capture_caps) {
- /* Set capsfilters to match arriving image data */
- gst_camerabin_set_capsfilter_caps (camera, camera->image_capture_caps);
+ /* It is possible we are about to get something else that we requested */
+ if (!gst_caps_is_equal (camera->image_capture_caps, caps)) {
+ /* If capture preparation has added new fields to requested caps,
+ we need to copy them */
+ st = gst_caps_get_structure (camera->image_capture_caps, 0);
+ new_st = gst_structure_copy (st);
+ st = gst_caps_get_structure (caps, 0);
+ for (i = 0; i < gst_structure_n_fields (st); i++) {
+ field_name = gst_structure_nth_field_name (st, i);
+ if (!gst_structure_has_field (new_st, field_name)) {
+ GST_DEBUG_OBJECT (camera, "new field in prepared caps: %s", field_name);
+ gst_structure_set_value (new_st, field_name,
+ gst_structure_get_value (st, field_name));
+ }
+ }
+ gst_caps_replace (&camera->image_capture_caps,
+ gst_caps_new_full (new_st, NULL));
}
+ /* Update capsfilters */
+ gst_camerabin_set_capsfilter_caps (camera, camera->image_capture_caps);
+
+ /* If incoming buffer resolution is different from what application
+ requested, then we need to fix this in camerabin */
+ gst_camerabin_adapt_video_resolution (camera, caps);
+
g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE,
"active-pad", camera->pad_src_img, NULL);
gst_camerabin_rewrite_tags (camera);
@@ -1300,9 +1351,7 @@ static void
gst_camerabin_start_image_capture (GstCameraBin * camera)
{
GstStateChangeReturn state_ret;
- gboolean wait_for_prepare = FALSE;
- gint width = 0, height = 0, fps_n = 0, fps_d = 0;
- GstStructure *st;
+ gboolean wait_for_prepare = FALSE, ret = FALSE;
GST_INFO_OBJECT (camera, "starting image capture");
@@ -1312,17 +1361,6 @@ gst_camerabin_start_image_capture (GstCameraBin * camera)
/* Start image capture preparations using photography iface */
wait_for_prepare = TRUE;
g_mutex_lock (camera->capture_mutex);
- if (camera->image_capture_caps) {
- st = gst_caps_get_structure (camera->image_capture_caps, 0);
- } else {
- st = gst_caps_get_structure (camera->view_finder_caps, 0);
- }
- gst_structure_get_int (st, "width", &width);
- gst_structure_get_int (st, "height", &height);
- gst_structure_get_fraction (st, "framerate", &fps_n, &fps_d);
- /* Set image capture resolution and frame rate */
- g_signal_emit_by_name (camera->src_vid_src, "user-res-fps",
- width, height, fps_n, fps_d, 0);
/* Enable still image capture mode in v4l2camsrc */
if (g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src),
@@ -1330,9 +1368,17 @@ gst_camerabin_start_image_capture (GstCameraBin * camera)
g_object_set (G_OBJECT (camera->src_vid_src), "capture-mode", 1, NULL);
}
+ if (!camera->image_capture_caps) {
+ camera->image_capture_caps = gst_caps_copy (camera->view_finder_caps);
+ }
+
/* Start preparations for image capture */
- gst_photography_prepare_for_capture (GST_PHOTOGRAPHY (camera->src_vid_src),
- (GstPhotoCapturePrepared) img_capture_prepared, camera);
+ GST_DEBUG_OBJECT (camera, "prepare image capture caps %" GST_PTR_FORMAT,
+ camera->image_capture_caps);
+ ret =
+ gst_photography_prepare_for_capture (GST_PHOTOGRAPHY
+ (camera->src_vid_src), (GstPhotoCapturePrepared) img_capture_prepared,
+ camera->image_capture_caps, camera);
camera->capturing = TRUE;
g_mutex_unlock (camera->capture_mutex);
}
@@ -1345,12 +1391,17 @@ gst_camerabin_start_image_capture (GstCameraBin * camera)
g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", TRUE,
"active-pad", camera->pad_src_img, NULL);
camera->capturing = TRUE;
+ ret = TRUE;
g_mutex_unlock (camera->capture_mutex);
} else {
GST_WARNING_OBJECT (camera, "imagebin state change failed");
gst_element_set_state (camera->imgbin, GST_STATE_NULL);
}
}
+
+ if (!ret) {
+ GST_WARNING_OBJECT (camera, "starting image capture failed");
+ }
}
/*