mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-06 02:32:23 +00:00
camerabin: add block-after-capture property for viewfinder blocking
Adds block-after-capture property to block running viewfinder after capturing. This property is useful if application wants to display capture preview and avoid running viewfinder on background. Based on a patch by Tommi Myöhänen <ext-tommi.1.myohanen@nokia.com>
This commit is contained in:
parent
17617758c3
commit
55d98ef488
4 changed files with 87 additions and 6 deletions
|
@ -60,7 +60,8 @@ enum
|
||||||
ARG_IMAGE_CAPTURE_SUPPORTED_CAPS,
|
ARG_IMAGE_CAPTURE_SUPPORTED_CAPS,
|
||||||
ARG_VIEWFINDER_FILTER,
|
ARG_VIEWFINDER_FILTER,
|
||||||
ARG_FLICKER_MODE,
|
ARG_FLICKER_MODE,
|
||||||
ARG_FOCUS_MODE
|
ARG_FOCUS_MODE,
|
||||||
|
ARG_BLOCK_VIEWFINDER
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -223,6 +223,8 @@ static guint camerabin_signals[LAST_SIGNAL];
|
||||||
/* FIXME: this is v4l2camsrc specific */
|
/* FIXME: this is v4l2camsrc specific */
|
||||||
#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam"
|
#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam"
|
||||||
|
|
||||||
|
#define DEFAULT_BLOCK_VIEWFINDER FALSE
|
||||||
|
|
||||||
/* message names */
|
/* message names */
|
||||||
#define PREVIEW_MESSAGE_NAME "preview-image"
|
#define PREVIEW_MESSAGE_NAME "preview-image"
|
||||||
#define IMG_CAPTURED_MESSAGE_NAME "image-captured"
|
#define IMG_CAPTURED_MESSAGE_NAME "image-captured"
|
||||||
|
@ -266,6 +268,9 @@ static void gst_camerabin_start_image_capture (GstCameraBin * camera);
|
||||||
|
|
||||||
static void gst_camerabin_start_video_recording (GstCameraBin * camera);
|
static void gst_camerabin_start_video_recording (GstCameraBin * camera);
|
||||||
|
|
||||||
|
static void
|
||||||
|
camerabin_pad_blocked (GstPad * pad, gboolean blocked, gpointer user_data);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_camerabin_have_img_buffer (GstPad * pad, GstBuffer * buffer,
|
gst_camerabin_have_img_buffer (GstPad * pad, GstBuffer * buffer,
|
||||||
gpointer u_data);
|
gpointer u_data);
|
||||||
|
@ -1592,6 +1597,11 @@ gst_camerabin_send_video_eos (GstCameraBin * camera)
|
||||||
videopad = gst_element_get_static_pad (camera->vidbin, "sink");
|
videopad = gst_element_get_static_pad (camera->vidbin, "sink");
|
||||||
gst_pad_send_event (videopad, gst_event_new_eos ());
|
gst_pad_send_event (videopad, gst_event_new_eos ());
|
||||||
gst_object_unref (videopad);
|
gst_object_unref (videopad);
|
||||||
|
/* Block viewfinder after capturing if requested by application */
|
||||||
|
if (camera->block_viewfinder) {
|
||||||
|
gst_pad_set_blocked_async (camera->pad_src_view, TRUE,
|
||||||
|
(GstPadBlockCallback) camerabin_pad_blocked, camera);
|
||||||
|
}
|
||||||
camera->eos_handled = TRUE;
|
camera->eos_handled = TRUE;
|
||||||
} else {
|
} else {
|
||||||
GST_INFO_OBJECT (camera, "dropping duplicate EOS");
|
GST_INFO_OBJECT (camera, "dropping duplicate EOS");
|
||||||
|
@ -1599,15 +1609,15 @@ gst_camerabin_send_video_eos (GstCameraBin * camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* image_pad_blocked:
|
* camerabin_pad_blocked:
|
||||||
* @pad: pad to block/unblock
|
* @pad: pad to block/unblock
|
||||||
* @blocked: TRUE to block, FALSE to unblock
|
* @blocked: TRUE to block, FALSE to unblock
|
||||||
* @u_data: camera bin object
|
* @u_data: camera bin object
|
||||||
*
|
*
|
||||||
* The pad will be unblocked when image bin posts eos message.
|
* Callback function for blocking a pad.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
image_pad_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
|
camerabin_pad_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
|
||||||
{
|
{
|
||||||
GstCameraBin *camera;
|
GstCameraBin *camera;
|
||||||
|
|
||||||
|
@ -1802,6 +1812,12 @@ gst_camerabin_have_src_buffer (GstPad * pad, GstBuffer * buffer,
|
||||||
gst_camerabin_send_img_queue_custom_event (camera,
|
gst_camerabin_send_img_queue_custom_event (camera,
|
||||||
gst_structure_new ("img-eos", NULL));
|
gst_structure_new ("img-eos", NULL));
|
||||||
|
|
||||||
|
/* Prevent video source from pushing frames until we want them */
|
||||||
|
if (camera->block_viewfinder) {
|
||||||
|
gst_pad_set_blocked_async (camera->pad_src_view, TRUE,
|
||||||
|
(GstPadBlockCallback) camerabin_pad_blocked, camera);
|
||||||
|
}
|
||||||
|
|
||||||
/* our work is done, disconnect */
|
/* our work is done, disconnect */
|
||||||
gst_pad_remove_buffer_probe (pad, camera->image_captured_id);
|
gst_pad_remove_buffer_probe (pad, camera->image_captured_id);
|
||||||
|
|
||||||
|
@ -1865,7 +1881,7 @@ gst_camerabin_have_queue_data (GstPad * pad, GstMiniObject * mini_obj,
|
||||||
} else if (evs && gst_structure_has_name (evs, "img-eos")) {
|
} else if (evs && gst_structure_has_name (evs, "img-eos")) {
|
||||||
GST_DEBUG_OBJECT (camera, "queue sending EOS to image pipeline");
|
GST_DEBUG_OBJECT (camera, "queue sending EOS to image pipeline");
|
||||||
gst_pad_set_blocked_async (camera->pad_src_queue, TRUE,
|
gst_pad_set_blocked_async (camera->pad_src_queue, TRUE,
|
||||||
(GstPadBlockCallback) image_pad_blocked, camera);
|
(GstPadBlockCallback) camerabin_pad_blocked, camera);
|
||||||
gst_element_send_event (camera->imgbin, gst_event_new_eos ());
|
gst_element_send_event (camera->imgbin, gst_event_new_eos ());
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2452,6 +2468,39 @@ copy_missing_fields (GQuark field_id, const GValue * value, gpointer user_data)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_camerabin_change_viewfinder_blocking:
|
||||||
|
* @camera: camerabin object
|
||||||
|
* @blocked: new viewfinder blocking state
|
||||||
|
*
|
||||||
|
* Handle viewfinder blocking parameter change.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gst_camerabin_change_viewfinder_blocking (GstCameraBin * camera,
|
||||||
|
gboolean blocked)
|
||||||
|
{
|
||||||
|
gboolean old_value;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (camera);
|
||||||
|
old_value = camera->block_viewfinder;
|
||||||
|
camera->block_viewfinder = blocked;
|
||||||
|
GST_OBJECT_UNLOCK (camera);
|
||||||
|
|
||||||
|
/* "block_viewfinder" is now set and will be checked after capture */
|
||||||
|
GST_DEBUG_OBJECT (camera, "viewfinder blocking set to %d, was %d",
|
||||||
|
camera->block_viewfinder, old_value);
|
||||||
|
|
||||||
|
if (old_value == blocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!blocked && camera->pad_src_view
|
||||||
|
&& gst_pad_is_blocked (camera->pad_src_view)) {
|
||||||
|
/* Unblock viewfinder: the pad is blocked and we need to unblock it */
|
||||||
|
gst_pad_set_blocked_async (camera->pad_src_view, FALSE,
|
||||||
|
(GstPadBlockCallback) camerabin_pad_blocked, camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GObject callback functions implementation
|
* GObject callback functions implementation
|
||||||
*/
|
*/
|
||||||
|
@ -2739,6 +2788,23 @@ gst_camerabin_class_init (GstCameraBinClass * klass)
|
||||||
"viewfinder filter GStreamer element",
|
"viewfinder filter GStreamer element",
|
||||||
GST_TYPE_ELEMENT, G_PARAM_READWRITE));
|
GST_TYPE_ELEMENT, G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstCameraBin:block-after-capture:
|
||||||
|
*
|
||||||
|
* Block viewfinder after capture.
|
||||||
|
* When set to TRUE, camerabin will freeze the viewfinder after capturing.
|
||||||
|
* This is useful if application wants to display the preview image
|
||||||
|
* and running the viewfinder at the same time would be just a waste of
|
||||||
|
* CPU cycles. Viewfinder can be enabled again by setting this property to
|
||||||
|
* FALSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, ARG_BLOCK_VIEWFINDER,
|
||||||
|
g_param_spec_boolean ("block-after-capture",
|
||||||
|
"Block viewfinder after capture",
|
||||||
|
"Block viewfinder after capturing an image or video",
|
||||||
|
DEFAULT_BLOCK_VIEWFINDER, G_PARAM_READWRITE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstCameraBin::capture-start:
|
* GstCameraBin::capture-start:
|
||||||
* @camera: the camera bin element
|
* @camera: the camera bin element
|
||||||
|
@ -3198,6 +3264,10 @@ gst_camerabin_set_property (GObject * object, guint prop_id,
|
||||||
camera->app_viewfinder_filter = g_value_dup_object (value);
|
camera->app_viewfinder_filter = g_value_dup_object (value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ARG_BLOCK_VIEWFINDER:
|
||||||
|
gst_camerabin_change_viewfinder_blocking (camera,
|
||||||
|
g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -3293,6 +3363,9 @@ gst_camerabin_get_property (GObject * object, guint prop_id,
|
||||||
case ARG_VIEWFINDER_FILTER:
|
case ARG_VIEWFINDER_FILTER:
|
||||||
g_value_set_object (value, camera->app_viewfinder_filter);
|
g_value_set_object (value, camera->app_viewfinder_filter);
|
||||||
break;
|
break;
|
||||||
|
case ARG_BLOCK_VIEWFINDER:
|
||||||
|
g_value_set_boolean (value, camera->block_viewfinder);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -3408,7 +3481,7 @@ gst_camerabin_imgbin_finished (gpointer u_data)
|
||||||
|
|
||||||
/* Unblock image queue pad to process next buffer */
|
/* Unblock image queue pad to process next buffer */
|
||||||
gst_pad_set_blocked_async (camera->pad_src_queue, FALSE,
|
gst_pad_set_blocked_async (camera->pad_src_queue, FALSE,
|
||||||
(GstPadBlockCallback) image_pad_blocked, camera);
|
(GstPadBlockCallback) camerabin_pad_blocked, camera);
|
||||||
GST_DEBUG_OBJECT (camera, "Queue srcpad unblocked");
|
GST_DEBUG_OBJECT (camera, "Queue srcpad unblocked");
|
||||||
|
|
||||||
/* disconnect automatically */
|
/* disconnect automatically */
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct _GstCameraBin
|
||||||
GstCameraBinFlags flags;
|
GstCameraBinFlags flags;
|
||||||
gboolean stop_requested; /* TRUE if capturing stop needed */
|
gboolean stop_requested; /* TRUE if capturing stop needed */
|
||||||
gboolean paused; /* TRUE if capturing paused */
|
gboolean paused; /* TRUE if capturing paused */
|
||||||
|
gboolean block_viewfinder; /* TRUE if viewfinder blocks after capture */
|
||||||
|
|
||||||
/* Resolution of the buffers configured to camerabin */
|
/* Resolution of the buffers configured to camerabin */
|
||||||
gint width;
|
gint width;
|
||||||
|
|
|
@ -81,6 +81,9 @@ handle_image_captured_cb (gpointer data)
|
||||||
{
|
{
|
||||||
GMainLoop *loop = (GMainLoop *) data;
|
GMainLoop *loop = (GMainLoop *) data;
|
||||||
|
|
||||||
|
/* unblock viewfinder */
|
||||||
|
g_object_set (camera, "block-after-capture", FALSE, NULL);
|
||||||
|
|
||||||
GST_DEBUG ("handle_image_captured_cb, cycle: %d", cycle_count);
|
GST_DEBUG ("handle_image_captured_cb, cycle: %d", cycle_count);
|
||||||
if (cycle_count == 0) {
|
if (cycle_count == 0) {
|
||||||
GST_DEBUG ("all cycles done");
|
GST_DEBUG ("all cycles done");
|
||||||
|
@ -661,6 +664,9 @@ GST_START_TEST (test_single_image_capture)
|
||||||
g_object_set (camera, "mode", 0,
|
g_object_set (camera, "mode", 0,
|
||||||
"filename", make_test_file_name (SINGLE_IMAGE_FILENAME), NULL);
|
"filename", make_test_file_name (SINGLE_IMAGE_FILENAME), NULL);
|
||||||
|
|
||||||
|
/* don't run viewfinder after capture */
|
||||||
|
g_object_set (camera, "block-after-capture", TRUE, NULL);
|
||||||
|
|
||||||
GST_INFO ("starting capture");
|
GST_INFO ("starting capture");
|
||||||
g_signal_emit_by_name (camera, "capture-start", NULL);
|
g_signal_emit_by_name (camera, "capture-start", NULL);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue