static void gst_wrapper_camera_bin_src_init (GstWrapperCameraBinSrc * self) { self->vfsrc = gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, GST_PAD_SRC); gst_element_add_pad (GST_ELEMENT (self), self->vfsrc); self->imgsrc = gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME, GST_PAD_SRC); gst_element_add_pad (GST_ELEMENT (self), self->imgsrc); self->vidsrc = gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME, GST_PAD_SRC); gst_element_add_pad (GST_ELEMENT (self), self->vidsrc); gst_pad_set_event_function (self->imgsrc, GST_DEBUG_FUNCPTR (gst_wrapper_camera_bin_src_src_event)); gst_pad_set_event_function (self->vidsrc, GST_DEBUG_FUNCPTR (gst_wrapper_camera_bin_src_src_event)); /* TODO where are variables reset? */ self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; self->video_renegotiate = TRUE; self->image_renegotiate = TRUE; self->mode = GST_BASE_CAMERA_SRC_CAST (self)->mode; self->app_vid_filter = NULL; }
static void gst_base_camera_src_dispose (GObject * object) { GstBaseCameraSrc *src = GST_BASE_CAMERA_SRC_CAST (object); g_mutex_free (src->capturing_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); }
/** * gst_wrapper_camera_bin_src_vidsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static gboolean gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); gboolean ret = FALSE; GST_LOG_OBJECT (self, "Video probe, mode %d, capture status %d", camerasrc->mode, self->video_rec_status); /* TODO do we want to lock for every buffer? */ /* * Note that we can use gst_pad_push_event here because we are a buffer * probe. */ /* TODO shouldn't access this directly */ g_mutex_lock (camerasrc->capturing_mutex); if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { /* NOP */ } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { GstClockTime ts; GST_DEBUG_OBJECT (self, "Starting video recording"); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; ts = GST_BUFFER_TIMESTAMP (buffer); if (!GST_CLOCK_TIME_IS_VALID (ts)) ts = 0; gst_pad_push_event (self->vidsrc, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, ts, -1, 0)); /* post preview */ GST_DEBUG_OBJECT (self, "Posting preview for video"); gst_base_camera_src_post_preview (camerasrc, buffer); ret = TRUE; } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { /* send eos */ GST_DEBUG_OBJECT (self, "Finishing video recording, pushing eos"); gst_pad_push_event (pad, gst_event_new_eos ()); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; gst_base_camera_src_finish_capture (camerasrc); } else { ret = TRUE; } g_mutex_unlock (camerasrc->capturing_mutex); return ret; }
static void gst_base_camera_src_dispose (GObject * object) { GstBaseCameraBinSrc *src = GST_BASE_CAMERA_SRC_CAST (object); g_mutex_free (src->capturing_mutex); if (src->preview_pipeline) { gst_camerabin_destroy_preview_pipeline (src->preview_pipeline); src->preview_pipeline = NULL; } if (src->preview_caps) gst_caps_replace (&src->preview_caps, NULL); if (src->preview_filter) { gst_object_unref (src->preview_filter); src->preview_filter = NULL; } G_OBJECT_CLASS (parent_class)->dispose (object); }
/** * check_and_replace_src * @self: #GstWrapperCamerabinSrcCameraSrc object * * Checks if the current videosrc needs to be replaced */ static gboolean check_and_replace_src (GstWrapperCameraBinSrc * self) { GstBin *cbin = GST_BIN_CAST (self); GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC_CAST (self); if (self->src_vid_src && self->src_vid_src == self->app_vid_src) { GST_DEBUG_OBJECT (self, "No need to change current videosrc"); return TRUE; } if (self->src_vid_src) { GST_DEBUG_OBJECT (self, "Removing old video source"); if (self->src_max_zoom_signal_id) { g_signal_handler_disconnect (self->src_vid_src, self->src_max_zoom_signal_id); self->src_max_zoom_signal_id = 0; } if (self->src_event_probe_id) { GstPad *pad; pad = gst_element_get_static_pad (self->src_vid_src, "src"); gst_pad_remove_probe (pad, self->src_event_probe_id); gst_object_unref (pad); self->src_event_probe_id = 0; } gst_bin_remove (GST_BIN_CAST (self), self->src_vid_src); self->src_vid_src = NULL; } GST_DEBUG_OBJECT (self, "Adding new video source"); /* Add application set or default video src element */ if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, "camerasrc-real-src"))) { self->src_vid_src = NULL; return FALSE; } else { GstElement *videoconvert; if (!gst_bin_add (cbin, self->src_vid_src)) { return FALSE; } /* check if we already have the next element to link to */ videoconvert = gst_bin_get_by_name (cbin, "src-videoconvert"); if (videoconvert) { if (!gst_element_link_pads (self->src_vid_src, "src", videoconvert, "sink")) { return FALSE; } } } /* we listen for changes to max-zoom in the video src so that * we can proxy them to the basecamerasrc property */ if (g_object_class_find_property (G_OBJECT_GET_CLASS (bcamsrc), "max-zoom")) { self->src_max_zoom_signal_id = g_signal_connect (G_OBJECT (self->src_vid_src), "notify::max-zoom", (GCallback) gst_wrapper_camera_bin_src_max_zoom_cb, bcamsrc); } /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ { GstPad *pad; pad = gst_element_get_static_pad (self->src_vid_src, "src"); self->src_event_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, gst_wrapper_camera_src_src_event_probe, gst_object_ref (self), gst_object_unref); gst_object_unref (pad); } return TRUE; }
/** * gst_wrapper_camera_bin_src_vidsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static GstPadProbeReturn gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); GstPadProbeReturn ret = GST_PAD_PROBE_DROP; GstBuffer *buffer = GST_BUFFER (info->data); GST_LOG_OBJECT (self, "Video probe, mode %d, capture status %d", camerasrc->mode, self->video_rec_status); /* TODO do we want to lock for every buffer? */ /* * Note that we can use gst_pad_push_event here because we are a buffer * probe. */ /* TODO shouldn't access this directly */ g_mutex_lock (&camerasrc->capturing_mutex); if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { /* NOP */ } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { GstClockTime ts; GstSegment segment; GstCaps *caps; GstSample *sample; GST_DEBUG_OBJECT (self, "Starting video recording"); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; ts = GST_BUFFER_TIMESTAMP (buffer); if (!GST_CLOCK_TIME_IS_VALID (ts)) ts = 0; gst_segment_init (&segment, GST_FORMAT_TIME); segment.start = ts; gst_pad_push_event (self->vidsrc, gst_event_new_segment (&segment)); /* post preview */ GST_DEBUG_OBJECT (self, "Posting preview for video"); 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); ret = GST_PAD_PROBE_OK; } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { GstPad *peer; /* send eos */ GST_DEBUG_OBJECT (self, "Finishing video recording, pushing eos"); peer = gst_pad_get_peer (self->vidsrc); if (peer) { /* send to the peer as we don't want our pads with eos flag */ gst_pad_send_event (peer, gst_event_new_eos ()); gst_object_unref (peer); } else { GST_WARNING_OBJECT (camerasrc, "No peer pad for vidsrc"); } self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; gst_base_camera_src_finish_capture (camerasrc); } else { ret = GST_PAD_PROBE_OK; } g_mutex_unlock (&camerasrc->capturing_mutex); return ret; }