static void gst_base_camera_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { case PROP_MODE: gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), g_value_get_enum (value)); break; case PROP_ZOOM:{ self->zoom = g_value_get_float (value); /* limit to max-zoom */ if (self->zoom > self->max_zoom) { GST_DEBUG_OBJECT (self, "Clipping zoom %f to max-zoom %f", self->zoom, self->max_zoom); self->zoom = self->max_zoom; } /* does not set it if in NULL, the src is not created yet */ if (GST_STATE (self) != GST_STATE_NULL) gst_base_camera_src_setup_zoom (self); break; } case PROP_POST_PREVIEW: self->post_preview = g_value_get_boolean (value); break; case PROP_PREVIEW_CAPS:{ GstCaps *new_caps = NULL; new_caps = (GstCaps *) gst_value_get_caps (value); if (!gst_caps_is_equal (self->preview_caps, new_caps)) { gst_caps_replace (&self->preview_caps, new_caps); gst_base_camera_src_setup_preview (self, new_caps); } else { GST_DEBUG_OBJECT (self, "New preview caps equal current preview caps"); } } break; case PROP_PREVIEW_FILTER: if (self->preview_filter) gst_object_unref (self->preview_filter); self->preview_filter = g_value_dup_object (value); if (!gst_camerabin_preview_set_filter (self->preview_pipeline, self->preview_filter)) { GST_WARNING_OBJECT (self, "Cannot change preview filter, is element in NULL state?"); } break; case PROP_AUTO_START: self->auto_start = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; } }
/** * gst_wrapper_camera_bin_src_imgsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static gboolean gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d", camerasrc->mode, self->image_capture_count); g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; self->image_capture_count--; /* post preview */ /* TODO This can likely be optimized if the viewfinder caps is the same as * the preview caps, avoiding another scaling of the same buffer. */ GST_DEBUG_OBJECT (self, "Posting preview for image"); gst_base_camera_src_post_preview (camerasrc, buffer); if (self->image_capture_count == 0) { gst_base_camera_src_finish_capture (camerasrc); } } g_mutex_unlock (camerasrc->capturing_mutex); return ret; }
static GstStateChangeReturn gst_base_camera_src_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (element); GST_DEBUG_OBJECT (self, "%d -> %d", GST_STATE_TRANSITION_CURRENT (transition), GST_STATE_TRANSITION_NEXT (transition)); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!construct_pipeline (self)) return GST_STATE_CHANGE_FAILURE; break; case GST_STATE_CHANGE_READY_TO_PAUSED: if (!setup_pipeline (self)) return GST_STATE_CHANGE_FAILURE; break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); return ret; }
static void gst_base_camera_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstBaseCameraBinSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { case PROP_MODE: g_value_set_enum (value, self->mode); break; case PROP_READY_FOR_CAPTURE: g_value_set_boolean (value, !self->capturing); break; case PROP_ZOOM: g_value_set_float (value, self->zoom); break; case PROP_MAX_ZOOM: g_value_set_float (value, self->max_zoom); break; case PROP_POST_PREVIEW: g_value_set_boolean (value, self->post_preview); break; case PROP_PREVIEW_CAPS: if (self->preview_caps) gst_value_set_caps (value, self->preview_caps); break; case PROP_PREVIEW_FILTER: if (self->preview_filter) g_value_set_object (value, self->preview_filter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; } }
static GstStateChangeReturn gst_base_camera_src_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (element); GST_DEBUG_OBJECT (self, "%d -> %d", GST_STATE_TRANSITION_CURRENT (transition), GST_STATE_TRANSITION_NEXT (transition)); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!construct_pipeline (self)) return GST_STATE_CHANGE_FAILURE; if (self->preview_pipeline == NULL) { /* failed to create preview pipeline, fail state change */ return GST_STATE_CHANGE_FAILURE; } if (self->preview_caps) { GST_DEBUG_OBJECT (self, "Setting preview pipeline caps %" GST_PTR_FORMAT, self->preview_caps); gst_camerabin_preview_set_caps (self->preview_pipeline, self->preview_caps); } break; case GST_STATE_CHANGE_READY_TO_PAUSED: if (!setup_pipeline (self)) return GST_STATE_CHANGE_FAILURE; /* without this the preview pipeline will not post buffer * messages on the pipeline */ gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_PLAYING); if (self->auto_start) g_signal_emit_by_name (G_OBJECT (self), "start-capture", NULL); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_READY); if (self->auto_start) g_signal_emit_by_name (G_OBJECT (self), "stop-capture", NULL); break; case GST_STATE_CHANGE_READY_TO_NULL: gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_NULL); break; default: break; } return ret; }
static GstStateChangeReturn gst_base_camera_src_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstBaseCameraBinSrc *self = GST_BASE_CAMERA_SRC (element); GST_DEBUG_OBJECT (self, "%d -> %d", GST_STATE_TRANSITION_CURRENT (transition), GST_STATE_TRANSITION_NEXT (transition)); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!construct_pipeline (self)) return GST_STATE_CHANGE_FAILURE; /* recreate the preview pipeline */ if (self->preview_pipeline && self->preview_filter_changed) { gst_camerabin_destroy_preview_pipeline (self->preview_pipeline); self->preview_pipeline = NULL; } if (self->preview_pipeline == NULL) self->preview_pipeline = gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self), self->preview_filter); g_assert (self->preview_pipeline != NULL); self->preview_filter_changed = FALSE; if (self->preview_caps) { GST_DEBUG_OBJECT (self, "Setting preview pipeline caps %" GST_PTR_FORMAT, self->preview_caps); gst_camerabin_preview_set_caps (self->preview_pipeline, self->preview_caps); } break; case GST_STATE_CHANGE_READY_TO_PAUSED: if (!setup_pipeline (self)) return GST_STATE_CHANGE_FAILURE; gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_PLAYING); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_NULL); break; default: break; } return ret; }
static gboolean start_image_capture (GstWrapperCameraBinSrc * self) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstPhotography *photography = (GstPhotography *) gst_bin_get_by_interface (GST_BIN_CAST (bcamsrc), GST_TYPE_PHOTOGRAPHY); gboolean ret = FALSE; GstCaps *caps; GST_DEBUG_OBJECT (self, "Starting image capture"); gst_element_set_state (self->src_vid_src, GST_STATE_READY); if (self->image_renegotiate) { /* clean capsfilter caps so they don't interfere here */ g_object_set (self->src_filter, "caps", NULL, NULL); if (self->src_zoom_filter) g_object_set (self->src_zoom_filter, "caps", NULL, NULL); caps = gst_pad_get_allowed_caps (self->imgsrc); gst_caps_replace (&self->image_capture_caps, caps); gst_caps_unref (caps); /* FIXME - do we need to update basecamerasrc width/height somehow here? * if not, i think we need to do something about _when_ they get updated * to be sure that set_element_zoom doesn't use the wrong values */ /* We caught this event in the src pad event handler and now we want to * actually push it upstream */ gst_pad_send_event (self->outsel_imgpad, gst_event_new_reconfigure ()); self->image_renegotiate = FALSE; } if (photography) { gst_element_set_state (self->src_vid_src, GST_STATE_PLAYING); GST_DEBUG_OBJECT (self, "prepare image capture caps %" GST_PTR_FORMAT, self->image_capture_caps); ret = gst_photography_prepare_for_capture (photography, (GstPhotographyCapturePrepared) img_capture_prepared, self->image_capture_caps, self); } else { g_mutex_unlock (&bcamsrc->capturing_mutex); gst_wrapper_camera_bin_reset_video_src_caps (self, self->image_capture_caps); g_mutex_lock (&bcamsrc->capturing_mutex); ret = TRUE; gst_element_set_state (self->src_vid_src, GST_STATE_PLAYING); } return ret; }
static void gst_base_camera_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { case PROP_MODE: gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), g_value_get_enum (value)); break; case PROP_ZOOM:{ g_atomic_int_set (&self->zoom, g_value_get_int (value)); /* does not set it if in NULL, the src is not created yet */ if (GST_STATE (self) != GST_STATE_NULL) gst_base_camera_src_setup_zoom (self); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; } }
/** * set_capsfilter_caps: * @self: camerasrc object * @new_caps: pointer to caps object to set * * Set given caps to camerabin capsfilters. */ static void set_capsfilter_caps (GstWrapperCameraBinSrc * self, GstCaps * new_caps) { GST_INFO_OBJECT (self, "new_caps:%" GST_PTR_FORMAT, new_caps); /* Update zoom */ gst_base_camera_src_setup_zoom (GST_BASE_CAMERA_SRC (self)); /* Update capsfilters */ g_object_set (G_OBJECT (self->src_filter), "caps", new_caps, NULL); if (self->src_zoom_filter) g_object_set (G_OBJECT (self->src_zoom_filter), "caps", new_caps, NULL); update_aspect_filter (self, new_caps); GST_INFO_OBJECT (self, "updated"); }
static gboolean set_element_zoom (GstWrapperCameraBinSrc * self, gfloat zoom) { gboolean ret = FALSE; GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); gint w2_crop = 0, h2_crop = 0; GstPad *pad_zoom_sink = NULL; gint left = self->base_crop_left; gint right = self->base_crop_right; gint top = self->base_crop_top; gint bottom = self->base_crop_bottom; if (self->src_zoom_crop) { /* Update capsfilters to apply the zoom */ GST_INFO_OBJECT (self, "zoom: %f, orig size: %dx%d", zoom, bcamsrc->width, bcamsrc->height); if (zoom != ZOOM_1X) { w2_crop = (bcamsrc->width - (gint) (bcamsrc->width * ZOOM_1X / zoom)) / 2; h2_crop = (bcamsrc->height - (gint) (bcamsrc->height * ZOOM_1X / zoom)) / 2; left += w2_crop; right += w2_crop; top += h2_crop; bottom += h2_crop; /* force number of pixels cropped from left to be even, to avoid slow code * path on videoscale */ left &= 0xFFFE; } pad_zoom_sink = gst_element_get_static_pad (self->src_zoom_crop, "sink"); GST_INFO_OBJECT (self, "sw cropping: left:%d, right:%d, top:%d, bottom:%d", left, right, top, bottom); GST_PAD_STREAM_LOCK (pad_zoom_sink); g_object_set (self->src_zoom_crop, "left", left, "right", right, "top", top, "bottom", bottom, NULL); GST_PAD_STREAM_UNLOCK (pad_zoom_sink); gst_object_unref (pad_zoom_sink); ret = TRUE; } return ret; }
static void gst_wrapper_camera_bin_src_caps_cb (GObject * gobject, GParamSpec * pspec, gpointer user_data) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (user_data); GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (user_data); GstPad *src_caps_src_pad; GstCaps *caps = NULL; GstStructure *in_st = NULL; /* get the new caps that were set on the capsfilter that configures the * source */ src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src"); caps = gst_pad_query_caps (src_caps_src_pad, NULL); gst_object_unref (src_caps_src_pad); GST_DEBUG_OBJECT (self, "src-filter caps changed to %s", gst_caps_to_string (caps)); if (gst_caps_get_size (caps)) { in_st = gst_caps_get_structure (caps, 0); if (in_st) { gst_structure_get_int (in_st, "width", &bcamsrc->width); gst_structure_get_int (in_st, "height", &bcamsrc->height); GST_DEBUG_OBJECT (self, "Source dimensions now: %dx%d", bcamsrc->width, bcamsrc->height); } } /* Update zoom */ gst_base_camera_src_setup_zoom (bcamsrc); /* Update post-zoom capsfilter */ if (self->src_zoom_filter) { GstCaps *filtercaps; g_object_get (G_OBJECT (self->src_zoom_filter), "caps", &filtercaps, NULL); if (!gst_caps_is_equal (filtercaps, caps)) g_object_set (G_OBJECT (self->src_zoom_filter), "caps", caps, NULL); gst_caps_unref (filtercaps); } /* drop our ref on the caps */ gst_caps_unref (caps); };
static void gst_wrapper_camera_bin_src_caps_cb (GstPad * pad, GParamSpec * pspec, gpointer user_data) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (user_data); GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (user_data); GstCaps *caps; GstStructure *in_st = NULL; caps = gst_pad_get_current_caps (pad); GST_DEBUG_OBJECT (self, "src-filter caps changed to %" GST_PTR_FORMAT, caps); if (caps && gst_caps_get_size (caps)) { in_st = gst_caps_get_structure (caps, 0); if (in_st) { gst_structure_get_int (in_st, "width", &bcamsrc->width); gst_structure_get_int (in_st, "height", &bcamsrc->height); GST_DEBUG_OBJECT (self, "Source dimensions now: %dx%d", bcamsrc->width, bcamsrc->height); } } /* Update zoom */ gst_base_camera_src_setup_zoom (bcamsrc); /* Update post-zoom capsfilter */ if (self->src_zoom_filter) { GstCaps *filtercaps; g_object_get (G_OBJECT (self->src_zoom_filter), "caps", &filtercaps, NULL); if (caps != filtercaps && (caps == NULL || filtercaps == NULL || !gst_caps_is_equal (filtercaps, caps))) g_object_set (G_OBJECT (self->src_zoom_filter), "caps", caps, NULL); if (filtercaps) gst_caps_unref (filtercaps); } if (caps) gst_caps_unref (caps); };
static gboolean start_image_capture (GstWrapperCameraBinSrc * self) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); gboolean ret = FALSE; GstCaps *caps; GST_DEBUG_OBJECT (self, "Starting image capture"); if (self->image_renegotiate) { /* clean capsfilter caps so they don't interfere here */ g_object_set (self->src_filter, "caps", NULL, NULL); if (self->src_zoom_filter) g_object_set (self->src_zoom_filter, "caps", NULL, NULL); caps = gst_pad_get_allowed_caps (self->imgsrc); caps = gst_caps_make_writable (caps); gst_pad_fixate_caps (self->imgsrc, caps); gst_caps_replace (&self->image_capture_caps, caps); gst_caps_unref (caps); self->image_renegotiate = FALSE; } if (photography) { GST_DEBUG_OBJECT (self, "prepare image capture caps %" GST_PTR_FORMAT, self->image_capture_caps); ret = gst_photography_prepare_for_capture (photography, (GstPhotoCapturePrepared) img_capture_prepared, self->image_capture_caps, self); } else { g_mutex_unlock (bcamsrc->capturing_mutex); gst_wrapper_camera_bin_reset_video_src_caps (self, self->image_capture_caps); g_mutex_lock (bcamsrc->capturing_mutex); ret = TRUE; } return ret; }
static void gst_base_camera_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { case PROP_MODE: g_value_set_enum (value, self->mode); break; case PROP_READY_FOR_CAPTURE: g_value_set_boolean (value, !self->capturing); break; case PROP_ZOOM: g_value_set_int (value, g_atomic_int_get (&self->zoom)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; } }
/** * gst_wrapper_camera_bin_src_imgsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static gboolean gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d", camerasrc->mode, self->image_capture_count); g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; self->image_capture_count--; if (self->image_capture_count == 0) { gst_base_camera_src_finish_capture (camerasrc); } } g_mutex_unlock (camerasrc->capturing_mutex); return ret; }
/** * gst_wrapper_camera_bin_src_imgsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static GstPadProbeReturn gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); GstBuffer *buffer = GST_BUFFER (info->data); GstPadProbeReturn ret = GST_PAD_PROBE_DROP; GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d bufsize: %" G_GSIZE_FORMAT, camerasrc->mode, self->image_capture_count, gst_buffer_get_size (buffer)); g_mutex_lock (&camerasrc->capturing_mutex); if (self->image_capture_count > 0) { GstSample *sample; GstCaps *caps; ret = GST_PAD_PROBE_OK; self->image_capture_count--; /* post preview */ /* TODO This can likely be optimized if the viewfinder caps is the same as * the preview caps, avoiding another scaling of the same buffer. */ GST_DEBUG_OBJECT (self, "Posting preview for image"); caps = gst_pad_get_current_caps (pad); sample = gst_sample_new (buffer, caps, NULL, NULL); gst_base_camera_src_post_preview (camerasrc, sample); gst_caps_unref (caps); gst_sample_unref (sample); if (self->image_capture_count == 0) { gst_base_camera_src_finish_capture (camerasrc); } } g_mutex_unlock (&camerasrc->capturing_mutex); return ret; }
/** * adapt_image_capture: * @self: camerasrc object * @in_caps: caps object that describes incoming image format * * Adjust capsfilters and crop according image capture caps if necessary. * The captured image format from video source might be different from * what application requested, so we can try to fix that in camerabin. * */ static void adapt_image_capture (GstWrapperCameraBinSrc * self, GstCaps * in_caps) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstStructure *in_st, *new_st, *req_st; gint in_width = 0, in_height = 0, req_width = 0, req_height = 0, crop = 0; gdouble ratio_w, ratio_h; GstCaps *filter_caps = NULL; GST_LOG_OBJECT (self, "in caps: %" GST_PTR_FORMAT, in_caps); GST_LOG_OBJECT (self, "requested caps: %" GST_PTR_FORMAT, self->image_capture_caps); in_st = gst_caps_get_structure (in_caps, 0); gst_structure_get_int (in_st, "width", &in_width); gst_structure_get_int (in_st, "height", &in_height); req_st = gst_caps_get_structure (self->image_capture_caps, 0); gst_structure_get_int (req_st, "width", &req_width); gst_structure_get_int (req_st, "height", &req_height); GST_INFO_OBJECT (self, "we requested %dx%d, and got %dx%d", req_width, req_height, in_width, in_height); new_st = gst_structure_copy (req_st); /* If new fields have been added, we need to copy them */ gst_structure_foreach (in_st, copy_missing_fields, new_st); gst_structure_set (new_st, "width", G_TYPE_INT, in_width, "height", G_TYPE_INT, in_height, NULL); GST_LOG_OBJECT (self, "new image capture caps: %" GST_PTR_FORMAT, new_st); /* Crop if requested aspect ratio differs from incoming frame aspect ratio */ if (self->src_zoom_crop) { ratio_w = (gdouble) in_width / req_width; ratio_h = (gdouble) in_height / req_height; if (ratio_w < ratio_h) { crop = in_height - (req_height * ratio_w); self->base_crop_top = crop / 2; self->base_crop_bottom = crop / 2; } else { crop = in_width - (req_width * ratio_h); self->base_crop_left = crop / 2; self->base_crop_right += crop / 2; } GST_INFO_OBJECT (self, "setting base crop: left:%d, right:%d, top:%d, bottom:%d", self->base_crop_left, self->base_crop_right, self->base_crop_top, self->base_crop_bottom); g_object_set (G_OBJECT (self->src_zoom_crop), "top", self->base_crop_top, "bottom", self->base_crop_bottom, "left", self->base_crop_left, "right", self->base_crop_right, NULL); } /* Update capsfilters */ if (self->image_capture_caps) { gst_caps_unref (self->image_capture_caps); } self->image_capture_caps = gst_caps_new_full (new_st, NULL); set_capsfilter_caps (self, self->image_capture_caps); /* Adjust the capsfilter before crop and videoscale elements if necessary */ if (in_width == bcamsrc->width && in_height == bcamsrc->height) { GST_DEBUG_OBJECT (self, "no adaptation with resolution needed"); } else { GST_DEBUG_OBJECT (self, "changing %" GST_PTR_FORMAT " from %dx%d to %dx%d", self->src_filter, bcamsrc->width, bcamsrc->height, in_width, in_height); /* Apply the width and height to filter caps */ g_object_get (G_OBJECT (self->src_filter), "caps", &filter_caps, NULL); filter_caps = gst_caps_make_writable (filter_caps); gst_caps_set_simple (filter_caps, "width", G_TYPE_INT, in_width, "height", G_TYPE_INT, in_height, NULL); g_object_set (G_OBJECT (self->src_filter), "caps", filter_caps, NULL); gst_caps_unref (filter_caps); } }
static gboolean start_image_capture (GstWrapperCameraBinSrc * self) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstPhotography *photography = (GstPhotography *) gst_bin_get_by_interface (GST_BIN_CAST (bcamsrc), GST_TYPE_PHOTOGRAPHY); gboolean ret = FALSE; GstCaps *caps; GstPad *pad, *peer; GST_DEBUG_OBJECT (self, "Starting image capture"); gst_element_set_state (self->src_vid_src, GST_STATE_READY); /* FIXME - V4L2 source will not close the device until all buffers have came * back. Flushing the pipeline, will ensure it's properly closed, and that * setting it back to PLAYING will work. This is more a workaround then a * solution to buffer reclaiming. */ pad = gst_element_get_static_pad (self->src_vid_src, "src"); peer = gst_pad_get_peer (pad); gst_object_unref (pad); gst_pad_send_event (peer, gst_event_new_flush_start ()); gst_pad_send_event (peer, gst_event_new_flush_stop (TRUE)); gst_object_unref (peer); if (self->image_renegotiate) { /* clean capsfilter caps so they don't interfere here */ g_object_set (self->src_filter, "caps", NULL, NULL); if (self->src_zoom_filter) g_object_set (self->src_zoom_filter, "caps", NULL, NULL); caps = gst_pad_get_allowed_caps (self->imgsrc); gst_caps_replace (&self->image_capture_caps, caps); gst_caps_unref (caps); /* FIXME - do we need to update basecamerasrc width/height somehow here? * if not, i think we need to do something about _when_ they get updated * to be sure that set_element_zoom doesn't use the wrong values */ /* We caught this event in the src pad event handler and now we want to * actually push it upstream */ gst_pad_send_event (self->outsel_imgpad, gst_event_new_reconfigure ()); self->image_renegotiate = FALSE; } if (photography) { gst_element_set_state (self->src_vid_src, GST_STATE_PLAYING); GST_DEBUG_OBJECT (self, "prepare image capture caps %" GST_PTR_FORMAT, self->image_capture_caps); ret = gst_photography_prepare_for_capture (photography, (GstPhotographyCapturePrepared) img_capture_prepared, self->image_capture_caps, self); } else { g_mutex_unlock (&bcamsrc->capturing_mutex); gst_wrapper_camera_bin_reset_video_src_caps (self, self->image_capture_caps); g_mutex_lock (&bcamsrc->capturing_mutex); ret = TRUE; gst_element_set_state (self->src_vid_src, GST_STATE_PLAYING); } return ret; }