3 * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * 2006 Edgard Lima <edgard.lima@indt.org.br>
5 * 2008-2010 Nokia Corporation <multimedia@maemo.org>
6 * 2010 Intel Corporation <http://meego.com/>
8 * gstcamerasrc.c: Abstract camera base class
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
27 * SECTION:gstcamerasrc
28 * @short_description: Base class for camera sources
31 * camerasrc is a generic base class for video source elements.
34 * <title>Capturing modes</title>
36 * GstCameraSrc provides three different operating modes: VIEWFINDER, IMAGE and
37 * VIDEO capturing. This mode is selected by using "capture-mode" property.
38 * Viewfinder mode is used for capturing preview frames before performing the
39 * high-quality image capture, or before starting video recording. Image and
40 * video modes should be switched just before starting the corresponding
41 * action. GstCameraSrc itself doesn't make any difference between these modes,
42 * and this setting is mainly targeted for subclasses (see below).
46 * <title>Image capture</title>
48 * In order to capture and image of higher quality than negotiated in element's
49 * source pad, #GstPhotography's prepare_for_capture() must be called. It
50 * Takes a #GstCaps object as a parameter. These caps will define the desired
51 * high-quality capture resolution. However, this resolution is just a
52 * suggestion; GstCameraSrc uses the given #GstPhotoCapturePrepared callback
53 * to inform the selected capturing resolution back to the application. During
54 * this callback application also has responsibility to adjust image pipeline
55 * capsfilters according to this resolution. After HQ image is captured and
56 * pushed, GstCameraSrc switches automatically back to old viewfinder resolution.
60 * <title>Video capture</title>
62 * By default GstCameraSrc works just like v4l2src, so it can be used for normal
63 * video stream capturing as well. There is no separate GstPhotography API
64 * function for starting video capturing (in contrary to image capturing), but
65 * the notification is just given by setting the #GstCameraSrc:capture-mode
70 * <title>Messages</title>
72 * During capturing process GstCameraSrc sends a bunch of GstMessages to bus:
76 * GST_PHOTOGRAPHY_AUTOFOCUS_DONE is sent when application has started
77 * autofocus operation and it finishes. This message contains following fields:
78 * "status" is an integer which contains GstFocusStatus enumeration value.
79 * It tells whether the focusing succeeded or failed.
80 * "focus-window-rows" and "focus-window-columns" are integers and they tell
81 * the focus matrix size.
82 * "focus-windows" is a GArray containing a list of integers. They define
83 * window numbers where the focus is. Window numbering starts from one, which
84 * is top-left window, increasing from left-to-right, top-to-bottom order. This
85 * field is only valid when focusing status is SUCCESS.
86 * "focus-window-coverage" field is an integer and it tells the percentage how
87 * big area from wiewfinder window was used for autofocusing.
92 * GST_PHOTOGRAPHY_SHAKE_RISK is sent during autofocusing process. It keeps
93 * application updated about the possible risk for shaken image. Sending of
94 * this message is done in subclasses, so it is implementation-specific and
95 * may not be always sent.
100 * "photo-capture-start" is sent just before the actual high-quality capture
101 * operation is about to happen.
106 * "photo-capture-end" is sent immediately after high-quality image has been
107 * captured. This can be used for example for playing the shutter sound
108 * in sync with the capture operation.
113 * "caf-update" messages are sent when camera subsystem supports continuous
114 * autofocusing (CAF). The message contains information about CAF status. It
115 * has one G_TYPE_INT field called "status" and its content is one of the
116 * values defined in GstPhotography API's GstFocusStatus enumeration.
123 * <title>Supported formats</title>
125 * Currently GstCameraSrc only supports UYVY and YUY2 color formats.
129 * <title>Subclasses</title>
131 * Hardware-specific imaging functionalities are implemented in subclasses.
132 * GstCameraSrc provides vmethods for this purpose. Subclasses tasks are to
133 * are handle e.g. autofocusing, flash, image capturing,
134 * post-processing and all other non-V4L2 standard operations. Subclass
135 * can also implement the API only partially; by default GstCameraSrc uses dummy
136 * functions for all vmethods that are not implemented by the subclass.
146 #include <sys/time.h>
149 #include <gst/tag/tag.h>
151 #include "gstmfldcameracolorbalance.h"
152 #include "gstmfldcameraphotoiface.h"
153 #include "gstmfldcameracontroliface.h"
154 #include <linux/videodev2.h>
157 GST_DEBUG_CATEGORY (gst_camerasrc_debug);
158 #define GST_CAT_DEFAULT gst_camerasrc_debug
161 #define DEFAULT_PROP_ALWAYS_COPY FALSE
164 #define MAX_ZOOM 1000.0
165 #define ZOOM_1X 100.0
167 GST_IMPLEMENT_CAMERA_SRC_COLOR_BALANCE_METHODS (GstCameraSrc, gst_camsrc);
168 GST_IMPLEMENT_CAMERA_SRC_PHOTO_METHODS (GstCameraSrc, gst_camsrc);
169 GST_IMPLEMENT_CAMERA_SRC_CAMERA_CONTROL_METHODS (GstCameraSrc, gst_camsrc);
171 guint gst_camerasrc_signals[CAMERA_IN_LAST_SIGNAL] = { 0 };
174 gst_camerasrc_iface_supported (GstImplementsInterface * iface, GType iface_type)
176 GstCameraSrc *camsrc;
177 GstCameraSrcClass *bclass;
179 camsrc = GST_CAMERA_SRC (iface);
180 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
182 g_assert (iface_type == GST_TYPE_PHOTOGRAPHY ||
183 iface_type == GST_TYPE_COLOR_BALANCE || iface_type == GST_TYPE_CAMERA_CONTROL );
185 /* We implement GstPhotography in NULL state as well */
186 if (iface_type == GST_TYPE_PHOTOGRAPHY)
189 else if (!bclass->is_open (camsrc))
196 gst_camerasrc_interface_init (GstImplementsInterfaceClass * klass)
199 * default virtual functions
201 klass->supported = gst_camerasrc_iface_supported;
205 gst_camerasrc_init_interfaces (GType type)
207 static const GInterfaceInfo camsrc_iface_info = {
208 (GInterfaceInitFunc) gst_camerasrc_interface_init,
212 static const GInterfaceInfo camsrc_photo_info = {
213 (GInterfaceInitFunc) gst_camsrc_photo_interface_init,
217 static const GInterfaceInfo camsrc_colorbalance_info = {
218 (GInterfaceInitFunc) gst_camsrc_color_balance_interface_init,
223 static const GInterfaceInfo camsrc_cameracontrol_info = {
224 (GInterfaceInitFunc) gst_camsrc_camera_control_interface_init,
229 g_type_add_interface_static (type,
230 GST_TYPE_IMPLEMENTS_INTERFACE, &camsrc_iface_info);
231 g_type_add_interface_static (type, GST_TYPE_PHOTOGRAPHY, &camsrc_photo_info);
232 g_type_add_interface_static (type,
233 GST_TYPE_COLOR_BALANCE, &camsrc_colorbalance_info);
234 g_type_add_interface_static (type,
235 GST_TYPE_CAMERA_CONTROL, &camsrc_cameracontrol_info);
240 gst_camerasrc_capture_mode_get_type (void)
242 static GType gst_camerasrc_capture_mode_type = 0;
243 static GEnumValue gst_camerasrc_capture_modes[] = {
244 {GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER, "Viewfinder mode", "viewfinder"},
245 {GST_CAMERA_SRC_CAPTURE_MODE_STILL, "Still image capture mode", "still"},
246 {GST_CAMERA_SRC_CAPTURE_MODE_VIDEO, "Video capturing mode", "video"},
250 if (G_UNLIKELY (!gst_camerasrc_capture_mode_type)) {
251 gst_camerasrc_capture_mode_type =
252 g_enum_register_static ("GstCameraCaptureMode",
253 gst_camerasrc_capture_modes);
255 return gst_camerasrc_capture_mode_type;
259 gst_camerasrc_viewfinder_mode_get_type (void)
261 static GType gst_camerasrc_viewfinder_mode_type = 0;
262 static GEnumValue gst_camerasrc_viewfinder_modes[] = {
263 {GST_CAMERA_SRC_VIEWFINDER_MODE_STILL, "Still image capture mode", "still"},
264 {GST_CAMERA_SRC_VIEWFINDER_MODE_VIDEO, "Video capturing mode", "video"},
268 if (G_UNLIKELY (!gst_camerasrc_viewfinder_mode_type)) {
269 gst_camerasrc_viewfinder_mode_type =
270 g_enum_register_static ("GstCameraViewfinderMode",
271 gst_camerasrc_viewfinder_modes);
273 return gst_camerasrc_viewfinder_mode_type;
276 GST_BOILERPLATE_FULL (GstCameraSrc, gst_camerasrc, GstPushSrc,
277 GST_TYPE_PUSH_SRC, gst_camerasrc_init_interfaces);
279 static void gst_camerasrc_dispose (GObject * object);
281 /* element methods */
282 static GstStateChangeReturn
283 gst_camerasrc_change_state (GstElement * element, GstStateChange transition);
285 /* basesrc methods */
286 static gboolean gst_camerasrc_start (GstBaseSrc * src);
288 static gboolean gst_camerasrc_unlock (GstBaseSrc * src);
290 static gboolean gst_camerasrc_unlock_stop (GstBaseSrc * src);
292 static gboolean gst_camerasrc_stop (GstBaseSrc * src);
294 static gboolean gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps);
296 static GstCaps *gst_camerasrc_get_caps (GstBaseSrc * src);
298 static gboolean gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query);
300 static GstFlowReturn gst_camerasrc_create (GstPushSrc * src, GstBuffer ** out);
302 static void gst_camerasrc_fixate (GstBaseSrc * basesrc, GstCaps * caps);
304 static gboolean gst_camerasrc_negotiate (GstBaseSrc * basesrc);
306 static void gst_camerasrc_set_property (GObject * object, guint prop_id,
307 const GValue * value, GParamSpec * pspec);
309 static void gst_camerasrc_get_property (GObject * object, guint prop_id,
310 GValue * value, GParamSpec * pspec);
312 static void gst_camerasrc_override_photo_properties (GObjectClass *
315 static void gst_camerasrc_default_functions_init (GstCameraSrcClass *
318 static gboolean gst_camerasrc_event (GstBaseSrc * src, GstEvent * event);
320 static gboolean gst_camerasrc_send_event (GstElement * element,
323 static void gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc);
328 gst_camerasrc_base_init (gpointer g_class)
330 // GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
331 gst_tag_register_musicbrainz_tags ();
333 GST_DEBUG_CATEGORY_INIT (gst_camerasrc_debug, "camerasrc", 0,
334 "camerasrc element");
338 /* VOID:OBJECT,OBJECT (generated by 'glib-genmarshal') */
339 #define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
340 void gst_camerasrc_VOID__OBJECT_OBJECT(GClosure *closure,
341 GValue *return_value,
342 guint n_param_values,
343 const GValue *param_values,
344 gpointer invocation_hint,
345 gpointer marshal_data)
347 typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT)(gpointer data1,
352 register GMarshalFunc_VOID__OBJECT_OBJECT callback;
353 register GCClosure *cc = (GCClosure*) closure;
354 register gpointer data1, data2;
356 g_return_if_fail (n_param_values == 4);
358 if (G_CCLOSURE_SWAP_DATA(closure)) {
359 data1 = closure->data;
360 data2 = g_value_peek_pointer(param_values + 0);
362 data1 = g_value_peek_pointer(param_values + 0);
363 data2 = closure->data;
366 callback = (GMarshalFunc_VOID__OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback);
369 g_marshal_value_peek_object(param_values + 1),
370 g_marshal_value_peek_object(param_values + 2),
371 g_marshal_value_peek_object(param_values + 3),
375 void gst_camerasrc_VOID__OBJECT_USRPTR_BUFFER(GClosure *closure,
376 GValue *return_value,
377 guint n_param_values,
378 const GValue *param_values,
379 gpointer invocation_hint,
380 gpointer marshal_data)
382 typedef void (*GMarshalFunc_VOID__OBJECT_USRPTR_BUFFER)(gpointer data1,
383 gpointer arg_1, gpointer data2);
384 register GMarshalFunc_VOID__OBJECT_USRPTR_BUFFER callback;
385 register GCClosure *cc = (GCClosure*) closure;
386 register gpointer data1, data2;
388 g_return_if_fail (n_param_values == 2);
390 if (G_CCLOSURE_SWAP_DATA(closure)) {
391 data1 = closure->data;
392 data2 = g_value_peek_pointer(param_values + 0);
394 data1 = g_value_peek_pointer(param_values + 0);
395 data2 = closure->data;
398 callback = (GMarshalFunc_VOID__OBJECT_USRPTR_BUFFER)(marshal_data ? marshal_data : cc->callback);
400 callback(data1, g_marshal_value_peek_object(param_values + 1), data2);
403 int gst_camerasrc_send_af_status(GstCameraSrc *camsrc , int state)
405 GstMessage *m = NULL;
406 GstStructure *s = NULL;
408 GST_INFO_OBJECT(camsrc, "autofocus callback: state [%d]", state);
410 s = gst_structure_new("camerasrc-AF",
411 "focus-state", G_TYPE_INT, state,
414 m = gst_message_new_element(GST_OBJECT(camsrc), s);
415 gst_element_post_message(GST_ELEMENT(camsrc), m);
422 gst_camerasrc_class_init (GstCameraSrcClass * klass)
424 GObjectClass *gobject_class;
425 GstElementClass *element_class;
426 GstBaseSrcClass *basesrc_class;
427 GstPushSrcClass *pushsrc_class;
429 gobject_class = G_OBJECT_CLASS (klass);
430 element_class = GST_ELEMENT_CLASS (klass);
431 basesrc_class = GST_BASE_SRC_CLASS (klass);
432 pushsrc_class = GST_PUSH_SRC_CLASS (klass);
434 gobject_class->dispose = gst_camerasrc_dispose;
435 gobject_class->set_property = gst_camerasrc_set_property;
436 gobject_class->get_property = gst_camerasrc_get_property;
438 element_class->change_state = gst_camerasrc_change_state;
439 element_class->send_event = gst_camerasrc_send_event;
441 g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
442 g_param_spec_boolean ("always-copy", "Always Copy",
443 "If the buffer will or not be used directly from mmap",
444 DEFAULT_PROP_ALWAYS_COPY,
445 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
447 g_object_class_install_property (gobject_class, PROP_MAKER_NOTE,
448 g_param_spec_boolean ("maker-note", "Maker Note",
449 "Whether send the maker note with image during the capture",
450 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
451 GST_PARAM_CONTROLLABLE));
453 g_object_class_install_property (gobject_class, PROP_CAPTURE_WIDTH,
454 g_param_spec_int ("capture-width", "Capture Widht",
455 "Image width used in capture mode.In case capture is done when pipeline is already running in viewfinder mode", 0,
457 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
459 g_object_class_install_property (gobject_class, PROP_CAPTURE_HEIGHT,
460 g_param_spec_int ("capture-height", "Capture Height",
461 "Image height used in capture mode. In case capture is done when pipeline is already running in viewfinder mode", 0,
463 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
465 g_object_class_install_property(gobject_class, PROP_CAPTURE_FOURCC,
466 g_param_spec_uint("capture-fourcc", "Capture format",
467 "Fourcc value for capture format",0,
469 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
471 g_object_class_install_property(gobject_class, PROP_CAPTURE_COUNT,
472 g_param_spec_uint("capture-count", "Capture count",
473 "image count taken in capture",0,
475 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
477 g_object_class_install_property(gobject_class, PROP_REQ_NEGOTIATION,
478 g_param_spec_boolean("req-negotiation", "Request re-negotiation",
479 "Request to negotiate while on playing",
481 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ));
483 g_object_class_install_property(gobject_class, PROP_SIGNAL_STILL_CAPTURE,
484 g_param_spec_boolean("signal-still-capture", "Signal Still Capture",
485 "Send a signal before pushing the buffer",
487 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ));
490 * GstCameraSrc:capture-mode:
492 * Defines capturing mode to be used. This information is needed by extension
493 * modules, which control hardware-specific functionality.
495 g_object_class_install_property (gobject_class, PROP_CAPTURE_MODE,
496 g_param_spec_enum ("capture-mode", "Capturing mode",
497 "Defines what kind of capturing mode to be used",
498 GST_TYPE_CAMERA_SRC_CAPTURE_MODE,
499 GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER,
500 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
503 * GstCameraSrc:viewfinder-mode:
505 * Defines which mode viewfinder should run in. This information is needed
506 * by extension modules, which control hardware-specific functionality.
508 g_object_class_install_property (gobject_class, PROP_VIEWFINDER_MODE,
509 g_param_spec_enum ("viewfinder-mode", "Viewfinder mode",
510 "Defines in what mode viewfinder should be run",
511 GST_TYPE_CAMERA_SRC_VIEWFINDER_MODE,
512 GST_CAMERA_SRC_VIEWFINDER_MODE_STILL,
513 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
517 * GstCameraSrc::nego-complete:
518 * @camerasrc: the camerasrc instance
519 * @start: when re-negotiation is finished.
522 gst_camerasrc_signals[CAMERA_IN_SIGNAL_NEGO_COMPLETE] =
523 g_signal_new("nego-complete",
524 G_TYPE_FROM_CLASS (klass),
526 G_STRUCT_OFFSET(GstCameraSrcClass, nego_complete),
529 gst_marshal_VOID__VOID,
533 * GstCameraSrc::still-capture:
534 * @camerasrc: the camerasrc instance
535 * @buffer: the buffer that will be pushed - Main
536 * @buffer: the buffer that will be pushed - Thumbnail
537 * @buffer: the buffer that will be pushed - Screennail
539 * This signal gets emitted before sending the buffer.
541 gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_CAPTURE] =
542 g_signal_new("still-capture",
543 G_TYPE_FROM_CLASS(klass),
545 G_STRUCT_OFFSET(GstCameraSrcClass, still_capture),
548 gst_camerasrc_VOID__OBJECT_OBJECT,
550 3, /* Number of parameter */
551 GST_TYPE_BUFFER, /* Main image buffer */
552 GST_TYPE_BUFFER, /* Thumbnail image buffer */
553 GST_TYPE_BUFFER); /* Screennail image buffer */
556 * GstCameraSrc::still-capture:
557 * @camerasrc: the camerasrc instance
558 * @buffer: the usrprt buffer that will be pulled
560 * This signal gets emitted before creating the buffer.
562 gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_USRPTR_BUFFER] =
563 g_signal_new("still-capture-usrptr-buffer",
564 G_TYPE_FROM_CLASS(klass),
566 G_STRUCT_OFFSET(GstCameraSrcClass, still_capture_usrptr_buffer),
569 gst_camerasrc_VOID__OBJECT_USRPTR_BUFFER,
571 1, /* Number of parameter */
572 GST_TYPE_BUFFER); /* user ptr image buffer */
575 gst_camerasrc_override_photo_properties (gobject_class);
577 basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_camerasrc_get_caps);
578 basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_camerasrc_set_caps);
579 basesrc_class->start = GST_DEBUG_FUNCPTR (gst_camerasrc_start);
580 basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_camerasrc_unlock);
581 basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_camerasrc_unlock_stop);
582 basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_camerasrc_stop);
583 basesrc_class->query = GST_DEBUG_FUNCPTR (gst_camerasrc_query);
584 basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_camerasrc_fixate);
585 basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_camerasrc_negotiate);
586 basesrc_class->event = GST_DEBUG_FUNCPTR (gst_camerasrc_event);
588 pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_camerasrc_create);
590 /* Initialize vmethods with default implementations */
591 gst_camerasrc_default_functions_init (klass);
597 gst_camerasrc_init (GstCameraSrc * camerasrc, GstCameraSrcClass * klass)
599 /* number of buffers requested */
600 camerasrc->always_copy = DEFAULT_PROP_ALWAYS_COPY;
602 camerasrc->state_lock = g_mutex_new ();
603 camerasrc->af_lock = g_mutex_new ();
605 gst_base_src_set_format (GST_BASE_SRC (camerasrc), GST_FORMAT_TIME);
606 gst_base_src_set_live (GST_BASE_SRC (camerasrc), TRUE);
608 /* Photo interface */
609 camerasrc->photoconf.zoom = 1.0;
610 camerasrc->photoconf.ev_compensation = 0.0;
611 camerasrc->photoconf.exposure = 0; /* 0 = auto */
612 camerasrc->photoconf.aperture = 0; /* 0 = auto */
613 camerasrc->photoconf.iso_speed = 0; /* 0 = auto */
614 camerasrc->photoconf.wb_mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
615 camerasrc->photoconf.scene_mode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL;
616 camerasrc->photoconf.flash_mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
617 camerasrc->photoconf.tone_mode = GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NORMAL;
618 camerasrc->photoconf.flicker_mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ;
619 camerasrc->photoconf.focus_mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
620 camerasrc->photoconf.noise_reduction = GST_PHOTOGRAPHY_NOISE_REDUCTION_YCC |
621 GST_PHOTOGRAPHY_NOISE_REDUCTION_BAYER;
623 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
624 camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
625 camerasrc->viewfinder_mode = GST_CAMERA_SRC_VIEWFINDER_MODE_STILL;
626 camerasrc->capture_resolution_set = FALSE;
627 camerasrc->preview_resolution_set = FALSE;
628 camerasrc->req_negotiation = FALSE;
629 camerasrc->signal_still_capture = FALSE;
631 camerasrc->capture_w = 0;
632 camerasrc->capture_h = 0;
633 camerasrc->capture_fps_n = 0;
634 camerasrc->capture_fps_d = 0;
635 camerasrc->capture_fourcc = 0;
636 camerasrc->capture_count = 1;
637 camerasrc->capture_counter = 1;
639 camerasrc->preview_w = 0;
640 camerasrc->preview_h = 0;
641 camerasrc->preview_fourcc = 0;
643 camerasrc->requested_af_mode = AF_NONE_REQUESTED;
644 camerasrc->maker_note = FALSE;
650 gst_camerasrc_dispose (GObject * object)
652 GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (object);
654 if (camerasrc->vf_caps) {
655 gst_caps_unref (camerasrc->vf_caps);
656 camerasrc->vf_caps = NULL;
658 if (camerasrc->state_lock) {
659 g_mutex_free (camerasrc->state_lock);
660 camerasrc->state_lock = NULL;
662 if (camerasrc->af_lock) {
663 g_mutex_free (camerasrc->af_lock);
664 camerasrc->af_lock = NULL;
666 gst_camerasrc_clear_color_channels (camerasrc);
668 gst_camerasrc_clear_cameracontrol_channels (camerasrc);
670 G_OBJECT_CLASS (parent_class)->dispose (object);
674 gst_camerasrc_override_photo_properties (GObjectClass * gobject_class)
676 g_object_class_override_property (gobject_class, PROP_WB_MODE,
677 GST_PHOTOGRAPHY_PROP_WB_MODE);
679 g_object_class_override_property (gobject_class, PROP_COLOUR_TONE,
680 GST_PHOTOGRAPHY_PROP_COLOUR_TONE);
682 g_object_class_override_property (gobject_class, PROP_SCENE_MODE,
683 GST_PHOTOGRAPHY_PROP_SCENE_MODE);
685 g_object_class_override_property (gobject_class, PROP_FLASH_MODE,
686 GST_PHOTOGRAPHY_PROP_FLASH_MODE);
688 g_object_class_override_property (gobject_class, PROP_CAPABILITIES,
689 GST_PHOTOGRAPHY_PROP_CAPABILITIES);
691 g_object_class_override_property (gobject_class, PROP_EV_COMP,
692 GST_PHOTOGRAPHY_PROP_EV_COMP);
694 g_object_class_override_property (gobject_class, PROP_ISO_SPEED,
695 GST_PHOTOGRAPHY_PROP_ISO_SPEED);
697 g_object_class_override_property (gobject_class, PROP_APERTURE,
698 GST_PHOTOGRAPHY_PROP_APERTURE);
700 g_object_class_override_property (gobject_class, PROP_EXPOSURE,
701 GST_PHOTOGRAPHY_PROP_EXPOSURE);
703 g_object_class_override_property (gobject_class, PROP_ZOOM,
704 GST_PHOTOGRAPHY_PROP_ZOOM);
706 g_object_class_override_property (gobject_class, PROP_FLICKER_MODE,
707 GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
709 g_object_class_override_property (gobject_class, PROP_FOCUS_MODE,
710 GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
712 g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION,
713 GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
715 g_object_class_override_property (gobject_class, PROP_IMAGE_CAPTURE_CAPS,
716 GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
718 g_object_class_override_property (gobject_class, PROP_IMAGE_PREVIEW_CAPS,
719 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
721 g_object_class_override_property (gobject_class, PROP_AUTOFOCUS,
722 GST_PHOTOGRAPHY_PROP_AUTOFOCUS);
729 gst_camerasrc_set_property (GObject * object,
730 guint prop_id, const GValue * value, GParamSpec * pspec)
732 GstCameraSrc *camerasrc;
733 GstCameraSrcClass *bclass;
735 camerasrc = GST_CAMERA_SRC_CAST (object);
736 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
738 if (gst_camerasrc_photo_set_property (camerasrc, prop_id, value))
742 case PROP_ALWAYS_COPY:
743 camerasrc->always_copy = g_value_get_boolean (value);
745 case PROP_MAKER_NOTE:
746 camerasrc->maker_note = g_value_get_boolean (value);
748 case PROP_CAPTURE_MODE:
749 camerasrc->capture_mode = g_value_get_enum (value);
750 GST_INFO_OBJECT (camerasrc, "Setting capture mode: %d",
751 camerasrc->capture_mode);
753 if (camerasrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_VIDEO &&
754 bclass->is_active (camerasrc)) {
756 if (bclass->set_capture_mode) {
757 bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
761 case PROP_VIEWFINDER_MODE:
762 camerasrc->viewfinder_mode = g_value_get_enum (value);
763 GST_INFO_OBJECT (camerasrc, "Setting viewfinder mode: %d",
764 camerasrc->viewfinder_mode);
766 if (bclass->set_vfinder_mode) {
767 bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
770 case PROP_CAPTURE_WIDTH:
771 camerasrc->capture_w = g_value_get_int (value);
772 GST_DEBUG_OBJECT (camerasrc, "Capture width %d",
773 camerasrc->capture_w);
774 /* both width & height should be set before setting flag to TRUE */
775 if(camerasrc->capture_h != 0)
776 camerasrc->capture_resolution_set = TRUE;
778 case PROP_CAPTURE_HEIGHT:
779 camerasrc->capture_h = g_value_get_int (value);
780 GST_DEBUG_OBJECT (camerasrc, "Capture Height: %d",
781 camerasrc->capture_h);
782 /* both width & height should be set before setting flag to TRUE */
783 if(camerasrc->capture_w != 0)
784 camerasrc->capture_resolution_set = TRUE;
786 case PROP_CAPTURE_FOURCC:
787 camerasrc->capture_fourcc = g_value_get_uint (value);
788 GST_DEBUG_OBJECT (camerasrc, "Capture fourcc: %d",
789 camerasrc->capture_fourcc);
791 case PROP_CAPTURE_COUNT:
792 camerasrc->capture_count = g_value_get_uint (value);
793 GST_DEBUG_OBJECT (camerasrc, "Capture count: %d",
794 camerasrc->capture_count);
796 case PROP_REQ_NEGOTIATION:
797 camerasrc->req_negotiation = g_value_get_boolean(value);
798 GST_DEBUG_OBJECT (camerasrc, "negotaion request %d",
799 camerasrc->req_negotiation);
801 case PROP_SIGNAL_STILL_CAPTURE:
802 camerasrc->signal_still_capture = g_value_get_boolean(value);
805 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
813 gst_camerasrc_get_property (GObject * object,
814 guint prop_id, GValue * value, GParamSpec * pspec)
816 GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (object);
818 if (gst_camerasrc_photo_get_property (camerasrc, prop_id, value))
822 case PROP_ALWAYS_COPY:
823 g_value_set_boolean (value, camerasrc->always_copy);
825 case PROP_MAKER_NOTE:
826 g_value_set_boolean (value, camerasrc->maker_note);
828 case PROP_CAPTURE_MODE:
829 g_value_set_enum (value, camerasrc->capture_mode);
831 case PROP_VIEWFINDER_MODE:
832 g_value_set_enum (value, camerasrc->viewfinder_mode);
834 case PROP_CAPTURE_WIDTH:
835 g_value_set_int (value, camerasrc->capture_w);
837 case PROP_CAPTURE_HEIGHT:
838 g_value_set_int (value, camerasrc->capture_h);
840 case PROP_CAPTURE_FOURCC:
841 g_value_set_uint (value, camerasrc->capture_fourcc);
843 case PROP_CAPTURE_COUNT:
844 g_value_set_uint (value, camerasrc->capture_count);
846 case PROP_REQ_NEGOTIATION:
847 g_value_set_boolean(value, camerasrc->req_negotiation);
849 case PROP_SIGNAL_STILL_CAPTURE:
850 g_value_set_boolean (value, camerasrc->signal_still_capture);
853 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
858 /* this function is a bit of a last resort */
860 gst_camerasrc_fixate (GstBaseSrc * basesrc, GstCaps * caps)
862 GstStructure *structure;
866 GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
868 for (i = 0; i < gst_caps_get_size (caps); ++i) {
871 structure = gst_caps_get_structure (caps, i);
873 /* FIXME such sizes? we usually fixate to something in the 320x200
875 /* We are fixating to greatest possble size (limited to GST_CAMERA_SRC_MAX_SIZE)
876 and the maximum framerate resolution for that size */
877 gst_structure_fixate_field_nearest_int (structure, "width",
878 GST_CAMERA_SRC_MAX_SIZE);
879 gst_structure_fixate_field_nearest_int (structure, "height",
880 GST_CAMERA_SRC_MAX_SIZE);
881 gst_structure_fixate_field_nearest_fraction (structure, "framerate",
884 v = gst_structure_get_value (structure, "format");
885 if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
888 g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
890 fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
891 gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
895 GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
901 gst_camerasrc_negotiate (GstBaseSrc * basesrc)
905 GstCaps *caps = NULL;
907 GstCaps *peercaps = NULL;
909 gboolean result = FALSE;
911 /* first see what is possible on our source pad */
912 thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
913 GST_DEBUG_OBJECT (basesrc, "caps of src suppressed on DEBUG (>= 5 to see)");
914 GST_LOG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
915 /* nothing or anything is allowed, we're done */
916 if (thiscaps == NULL || gst_caps_is_any (thiscaps))
919 /* get the peer caps */
920 peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
921 GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
922 if (peercaps && !gst_caps_is_any (peercaps)) {
923 GstCaps *icaps = NULL;
926 /* Prefer the first caps we are compatible with that the peer proposed */
927 for (i = 0; i < gst_caps_get_size (peercaps); i++) {
928 /* get intersection */
929 GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
931 GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
933 icaps = gst_caps_intersect (thiscaps, ipcaps);
934 gst_caps_unref (ipcaps);
936 if (!gst_caps_is_empty (icaps))
939 gst_caps_unref (icaps);
943 GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
945 /* If there are multiple intersections pick the one with the smallest
946 * resolution strictly bigger then the first peer caps */
947 if (gst_caps_get_size (icaps) > 1) {
948 GstStructure *s = gst_caps_get_structure (peercaps, 0);
954 int width = G_MAXINT, height = G_MAXINT;
956 if (gst_structure_get_int (s, "width", &twidth)
957 && gst_structure_get_int (s, "height", &theight)) {
959 /* Walk the structure backwards to get the first entry of the
960 * smallest resolution bigger (or equal to) the preferred resolution)
962 for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
963 GstStructure *is = gst_caps_get_structure (icaps, i);
967 if (gst_structure_get_int (is, "width", &w)
968 && gst_structure_get_int (is, "height", &h)) {
969 if (w >= twidth && w <= width && h >= theight && h <= height) {
978 caps = gst_caps_copy_nth (icaps, best);
979 gst_caps_unref (icaps);
984 gst_caps_unref (thiscaps);
985 gst_caps_unref (peercaps);
987 /* no peer or peer have ANY caps, work with our own caps then */
991 caps = gst_caps_make_writable (caps);
992 gst_caps_truncate (caps);
995 if (!gst_caps_is_empty (caps)) {
996 gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
997 GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
999 if (gst_caps_is_any (caps)) {
1000 /* hmm, still anything, so element can do anything and
1001 * nego is not needed */
1003 } else if (gst_caps_is_fixed (caps)) {
1004 /* yay, fixed caps, use those then */
1005 result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
1006 GST_DEBUG_OBJECT (basesrc, "Set caps returned: %d", result);
1009 gst_caps_unref (caps);
1015 GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
1017 gst_caps_unref (thiscaps);
1026 gst_camerasrc_get_caps (GstBaseSrc * src)
1028 GstCameraSrc *camerasrc;
1029 GstCameraSrcClass *bclass;
1031 camerasrc = GST_CAMERA_SRC_CAST (src);
1032 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1034 if (!bclass->is_open (camerasrc) || !bclass->get_caps) {
1035 return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
1039 return bclass->get_caps (camerasrc);
1044 * gst_camerasrc_get_caps_info:
1045 * @caps: given input caps
1046 * @four_cc: location for the fourcc
1047 * @w/@h: location for width and height
1048 * @fps_n/@fps_d: location for framerate
1050 * Collect data for the given caps.
1053 gst_camerasrc_get_caps_info (GstCameraSrc * camerasrc, GstCaps * caps,
1054 guint32 * four_cc, guint * w, guint * h, guint * fps_n, guint * fps_d,
1057 GstCameraSrcClass *bclass;
1058 GstStructure *structure;
1059 const GValue *framerate;
1060 const gchar *mimetype;
1064 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1066 /* default unknown values */
1070 structure = gst_caps_get_structure (caps, 0);
1072 mimetype = gst_structure_get_name (structure);
1074 if (!gst_structure_get_int (structure, "width", (gint *) w))
1077 if (!gst_structure_get_int (structure, "height", (gint *) h))
1080 framerate = gst_structure_get_value (structure, "framerate");
1084 *fps_n = gst_value_get_fraction_numerator (framerate);
1085 *fps_d = gst_value_get_fraction_denominator (framerate);
1087 if (!strcmp (mimetype, "video/x-vaapi-sharing")) {
1088 fourcc = V4L2_PIX_FMT_NV12;
1089 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1090 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1091 } else if (!strcmp (mimetype, "video/x-raw-yuv")) {
1092 gst_structure_get_fourcc (structure, "format", &fourcc);
1095 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1096 case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
1097 fourcc = V4L2_PIX_FMT_YUV420;
1098 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1099 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1101 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1102 fourcc = V4L2_PIX_FMT_YUYV;
1103 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1105 case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
1106 fourcc = V4L2_PIX_FMT_Y41P;
1107 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1109 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1110 fourcc = V4L2_PIX_FMT_UYVY;
1111 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1113 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1114 fourcc = V4L2_PIX_FMT_YVU420;
1115 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1116 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1118 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
1119 fourcc = V4L2_PIX_FMT_YUV411P;
1120 outsize = GST_ROUND_UP_4 (*w) * *h;
1121 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1123 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
1124 fourcc = V4L2_PIX_FMT_YUV422P;
1125 outsize = GST_ROUND_UP_4 (*w) * *h;
1126 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1128 case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1129 fourcc = V4L2_PIX_FMT_NV12;
1130 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1131 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1133 case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1134 fourcc = V4L2_PIX_FMT_NV21;
1135 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1136 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1138 #ifdef V4L2_PIX_FMT_YVYU
1139 case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
1140 fourcc = V4L2_PIX_FMT_YVYU;
1141 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1145 } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
1146 gint depth, endianness, r_mask;
1148 gst_structure_get_int (structure, "depth", &depth);
1149 gst_structure_get_int (structure, "endianness", &endianness);
1150 gst_structure_get_int (structure, "red_mask", &r_mask);
1154 fourcc = V4L2_PIX_FMT_RGB332;
1157 fourcc = (endianness == G_LITTLE_ENDIAN) ?
1158 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
1161 fourcc = (endianness == G_LITTLE_ENDIAN) ?
1162 V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
1165 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
1168 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
1171 } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
1172 gst_structure_get_fourcc (structure, "format", &fourcc);
1174 case GST_MAKE_FOURCC ('B', 'A', '8', '1'):
1175 fourcc = V4L2_PIX_FMT_SBGGR8;
1177 case GST_MAKE_FOURCC ('G', 'B', 'R', 'G'):
1178 fourcc = V4L2_PIX_FMT_SGBRG8;
1180 case GST_MAKE_FOURCC ('G', 'R', 'B', 'G'):
1181 fourcc = V4L2_PIX_FMT_SGRBG8;
1183 case GST_MAKE_FOURCC ('R', 'G', 'G', 'B'):
1184 fourcc = V4L2_PIX_FMT_SRGGB8;
1186 case GST_MAKE_FOURCC ('B', 'G', '1', '0'):
1187 fourcc = V4L2_PIX_FMT_SBGGR10;
1189 case GST_MAKE_FOURCC ('G', 'B', '1', '0'):
1190 fourcc = V4L2_PIX_FMT_SGBRG10;
1192 case GST_MAKE_FOURCC ('B', 'A', '1', '0'):
1193 fourcc = V4L2_PIX_FMT_SGRBG10;
1195 case GST_MAKE_FOURCC ('R', 'G', '1', '0'):
1196 fourcc = V4L2_PIX_FMT_SRGGB10;
1198 case GST_MAKE_FOURCC ('B', 'Y', 'R', '2'):
1199 fourcc = V4L2_PIX_FMT_SBGGR16;
1202 } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
1203 fourcc = V4L2_PIX_FMT_GREY;
1216 * gst_camerasrc_get_caps_from_info:
1217 * @camsrc: #GstCameraSrc object
1218 * @fourcc: fourcc code
1219 * @width: width to be set
1220 * @height: height to be set
1221 * @fps_n: FPS numerator to be set or 0
1222 * @fps_d: FPS denominator to be set or 0
1224 * Converts given parameters into GstCaps structure.
1226 * Returns: GstCaps representing the given values.
1229 gst_camerasrc_get_caps_from_info (GstCameraSrc * camsrc, guint32 fourcc,
1230 guint width, guint height, guint fps_n, guint fps_d)
1235 s = gst_structure_new ("video/x-raw-yuv",
1236 "format", GST_TYPE_FOURCC, fourcc,
1237 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
1239 if (fps_n != 0 && fps_d != 0) {
1240 gst_structure_set (s, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
1243 newcaps = gst_caps_new_empty ();
1244 gst_caps_append_structure (newcaps, s);
1253 gst_camerasrc_configure_device (GstCameraSrc * camerasrc, guint * w, guint * h,
1254 guint32 * fourcc, guint * fps_n, guint * fps_d, GstCaps * buffer_caps)
1256 GstCameraSrcClass *bclass;
1257 GstOperationMode opmode;
1259 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1261 /* Stop the capturing */
1262 if (!bclass->stop (camerasrc))
1265 GST_DEBUG_OBJECT (camerasrc, "trying to set_capture %dx%d at %d/%d fps",
1266 *w, *h, *fps_n, *fps_d);
1268 if (bclass->set_vfinder_mode) {
1269 bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
1271 if (bclass->set_capture_mode) {
1272 bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
1275 opmode = camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE ?
1276 GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE :
1277 GST_PHOTOGRAPHY_OPERATION_MODE_VIEWFINDER;
1279 if (!bclass->set_capture (camerasrc, opmode, FALSE, fourcc, w, h,
1281 GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1282 ("Failed configuring device for capturing"), (NULL));
1286 gst_camerasrc_update_max_zoom (camerasrc);
1288 /* Only start the driver when not in HQ capture mode, since in HQ mode */
1289 /* we have already called start_capture() above */
1291 if (!bclass->start (camerasrc, buffer_caps))
1294 if (camerasrc->photo_capture_phase != GST_CAMERA_CAPTURE) {
1296 if (!bclass->write_settings (camerasrc, &camerasrc->photoconf, FALSE)) {
1297 GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1298 ("Failed to configure driver module"), (NULL));
1311 gst_camerasrc_init_from_caps (GstCameraSrc * camerasrc, GstCaps * caps)
1319 /* we want our own type of fourcc codes */
1320 if (!gst_camerasrc_get_caps_info (camerasrc, caps, &fourcc, &w, &h, &fps_n,
1322 GST_DEBUG_OBJECT (camerasrc,
1323 "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1327 ret = gst_camerasrc_configure_device (camerasrc, &w, &h, &fourcc,
1328 &fps_n, &fps_d, caps);
1331 camerasrc->current_w = w;
1332 camerasrc->current_h = h;
1333 camerasrc->fps_n = fps_n;
1334 camerasrc->fps_d = fps_d;
1335 camerasrc->current_fourcc = fourcc;
1337 camerasrc->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
1338 GST_DEBUG_OBJECT (camerasrc, "Buffer duration: %" GST_TIME_FORMAT,
1339 GST_TIME_ARGS (camerasrc->duration));
1341 // camerasrc->frame_byte_size = size;
1350 gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps)
1352 GstCameraSrc *camerasrc;
1353 GstCameraSrcClass *bclass;
1355 camerasrc = GST_CAMERA_SRC_CAST (src);
1356 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1358 GST_DEBUG_OBJECT (camerasrc, "set_caps called: %" GST_PTR_FORMAT, caps);
1360 /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1361 if (!bclass->is_open (camerasrc))
1364 return gst_camerasrc_init_from_caps (camerasrc, caps);
1370 gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query)
1373 GstCameraSrcClass *bclass;
1374 gboolean res = FALSE;
1377 src = GST_CAMERA_SRC_CAST (bsrc);
1378 bclass = GST_CAMERA_SRC_GET_CLASS (src);
1380 switch (GST_QUERY_TYPE (query)) {
1381 case GST_QUERY_LATENCY:{
1382 GstClockTime max_latency;
1384 /* device must be open */
1385 if (!bclass->is_open (src)) {
1386 GST_WARNING_OBJECT (src,
1387 "Can't give latency since device isn't open !");
1391 /* we must have a framerate */
1392 if (src->fps_n <= 0 || src->fps_d <= 0) {
1393 GST_WARNING_OBJECT (src,
1394 "Can't give latency since framerate isn't fixated !");
1398 num_buffers = bclass->get_num_buffers (src);
1399 /* max latency is total duration of the frame buffer */
1400 max_latency = num_buffers * src->duration;
1402 GST_DEBUG_OBJECT (bsrc,
1403 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1404 GST_TIME_ARGS (src->duration), GST_TIME_ARGS (max_latency));
1406 /* we are always live, the min latency is 1 frame and the max latency is
1407 * the complete buffer of frames. */
1408 gst_query_set_latency (query, TRUE, src->duration, max_latency);
1414 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1424 gst_camerasrc_start (GstBaseSrc * src)
1426 // GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (src);
1434 gst_camerasrc_stop (GstBaseSrc * src)
1436 GstCameraSrc *camerasrc;
1437 GstCameraSrcClass *bclass;
1439 camerasrc = GST_CAMERA_SRC_CAST (src);
1440 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1442 GST_DEBUG_OBJECT (camerasrc, "Stopping");
1444 bclass->stop (camerasrc);
1446 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1452 gst_camerasrc_unlock (GstBaseSrc * src)
1454 GstCameraSrcClass *pclass;
1455 GstCameraSrc *camerasrc;
1456 gboolean ret = TRUE;
1458 camerasrc = GST_CAMERA_SRC_CAST (src);
1459 pclass = GST_CAMERA_SRC_GET_CLASS (src);
1461 GST_DEBUG_OBJECT (camerasrc, "Unlock");
1464 ret = pclass->unlock (camerasrc);
1470 gst_camerasrc_unlock_stop (GstBaseSrc * src)
1472 GstCameraSrcClass *pclass;
1473 GstCameraSrc *camerasrc;
1474 gboolean ret = TRUE;
1476 camerasrc = GST_CAMERA_SRC_CAST (src);
1477 pclass = GST_CAMERA_SRC_GET_CLASS (src);
1479 GST_DEBUG_OBJECT (camerasrc, "Unlock stop");
1481 if (pclass->unlock_stop)
1482 ret = pclass->unlock_stop (camerasrc);
1489 * gst_camerasrc_send_image_tags:
1490 * @camerasrc: #GstCameraSrc object.
1494 gst_camerasrc_send_image_tags (GstCameraSrc * camerasrc)
1496 GstTagMergeMode mode;
1497 GstCameraSrcClass *bclass;
1498 guint iso, wbalance;
1503 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1505 tlist = gst_tag_list_new ();
1506 zoom = camerasrc->photoconf.zoom;
1507 iso = camerasrc->photoconf.iso_speed;
1509 (camerasrc->photoconf.wb_mode == GST_PHOTOGRAPHY_WB_MODE_AUTO) ? 0 : 1;
1511 gst_tag_register_musicbrainz_tags();
1513 mode = GST_TAG_MERGE_REPLACE;
1514 gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, (gdouble)zoom, NULL);
1515 gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_ISO_SPEED, iso, NULL);
1517 if(camerasrc->maker_note)
1521 GstBuffer *pmakerbuf = NULL;
1523 unsigned num_afwindows, num_awbgrid;
1527 ret = bclass->makernote_init(camerasrc, &buf_size, num_afwindows, 0, 0, num_awbgrid, &handle);
1530 pmakerbuf = gst_buffer_new_and_alloc(buf_size);
1532 ret = bclass->makernote_deal(camerasrc, pmakerbuf, num_afwindows, num_awbgrid, handle);
1535 gst_tag_list_add(tlist, mode, GST_TAG_APPLICATION_DATA, pmakerbuf, NULL);
1538 bclass->makernote_uninit(camerasrc, handle);
1539 gst_buffer_unref(pmakerbuf);
1543 if (bclass->fill_image_tags)
1544 bclass->fill_image_tags (camerasrc, tlist);
1546 tagevent = gst_event_new_tag (gst_tag_list_copy (tlist));
1547 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc), tagevent);
1548 GST_DEBUG_OBJECT (camerasrc, "image tags sent: %" GST_PTR_FORMAT, tlist);
1549 gst_tag_list_free (tlist);
1556 * gst_camerasrc_send_preview:
1557 * @camsrc: #GstCameraSrc object
1559 * Sends HQ image preview image (snapshot) as a GstMessage.
1561 * Returns: TRUE on success.
1564 gst_camerasrc_send_preview (GstCameraSrc * camsrc)
1566 GstCameraSrcClass *bclass;
1567 GstBuffer *buf = NULL;
1568 GstStructure *msg_s = NULL;
1569 GstCaps *prvcaps = NULL;
1570 GstMessage *msg = NULL;
1571 gboolean ret = FALSE;
1573 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
1575 if (bclass->get_preview_image) {
1576 ret = bclass->get_preview_image (camsrc, &buf);
1580 GST_DEBUG_OBJECT (camsrc, "Sending preview image");
1581 prvcaps = gst_caps_new_simple ("video/x-raw-yuv",
1582 "format", GST_TYPE_FOURCC, camsrc->preview_fourcc,
1583 "width", G_TYPE_INT, camsrc->preview_w,
1584 "height", G_TYPE_INT, camsrc->preview_h,
1585 "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
1587 gst_buffer_set_caps (buf, prvcaps);
1589 /* Send custom preview image GstMessage */
1590 msg_s = gst_structure_new (GST_CAMERA_SRC_PREVIEW_IMAGE, "buffer",
1591 GST_TYPE_BUFFER, buf, NULL);
1593 msg = gst_message_new_element (GST_OBJECT (camsrc), msg_s);
1595 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
1596 GST_WARNING ("This element has no bus, therefore no message sent!");
1599 gst_caps_unref (prvcaps);
1601 GST_DEBUG_OBJECT (camsrc, "Retrieving preview image failed");
1604 /* if we still have valid settings for preview, reserve a new buffer */
1605 if (camsrc->preview_resolution_set) {
1606 GST_DEBUG_OBJECT (camsrc, "Reserving a new preview buffer");
1607 bclass->set_capture (camsrc, GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW, FALSE,
1608 &camsrc->preview_fourcc, &camsrc->preview_w, &camsrc->preview_h,
1613 gst_buffer_unref (buf);
1621 * gst_camerasrc_set_capture_caps:
1622 * @camerasrc: #GstCameraSrc object.
1624 * Set the capture caps on element's src pad.
1626 * Returns: TRUE on success.
1629 gst_camerasrc_set_capture_caps (GstCameraSrc * camerasrc)
1631 GstCameraSrcClass *bclass;
1632 GstCaps *newcaps = NULL;
1633 gboolean ret = TRUE;
1635 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1637 GST_DEBUG_OBJECT (camerasrc, "Calling set_capture()");
1639 /* Try what resolution the subclass can capture */
1640 ret = bclass->set_capture (camerasrc,
1641 GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE, TRUE,
1642 &camerasrc->capture_fourcc, &camerasrc->capture_w, &camerasrc->capture_h,
1643 &camerasrc->capture_fps_n, &camerasrc->capture_fps_d);
1649 /* FIXME: FPS definition should be removed from capture caps */
1650 newcaps = gst_camerasrc_get_caps_from_info (camerasrc,
1651 camerasrc->capture_fourcc, camerasrc->capture_w, camerasrc->capture_h,
1652 camerasrc->capture_fps_n, camerasrc->capture_fps_d);
1654 GST_DEBUG_OBJECT (camerasrc, "Set capture caps: %" GST_PTR_FORMAT, newcaps);
1656 /* Notify application that we are ready now. This must be called before */
1657 /* the set_caps() call below, since application needs to know the new caps */
1658 /* so that it can adjust the caps filter to accept new format before */
1659 /* srcpad caps are actually changed */
1660 gst_camerasrc_photo_ready_for_capture (camerasrc, newcaps);
1662 camerasrc->vf_caps =
1663 gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1665 /* This causes caps nego and switches resolution to hi-res mode */
1666 /* FIXME: Do we even need to set this? Application has already set the
1668 if (!gst_caps_is_equal (camerasrc->vf_caps, newcaps)) {
1669 GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps");
1670 ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), newcaps);
1671 GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps FINISHED");
1673 GST_DEBUG_OBJECT (camerasrc, "Forcing the re-initialization");
1674 ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1675 &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1676 &camerasrc->fps_d, newcaps);
1677 gst_caps_unref (camerasrc->vf_caps);
1678 camerasrc->vf_caps = NULL;
1681 gst_caps_unref (newcaps);
1693 gst_camerasrc_apply_timestamp (GstCameraSrc * camerasrc, GstBuffer * buf)
1696 GstClockTime timestamp;
1698 GST_OBJECT_LOCK (camerasrc);
1699 if ((clock = GST_ELEMENT_CLOCK (camerasrc))) {
1700 /* we have a clock, get base time and ref clock */
1701 timestamp = GST_ELEMENT (camerasrc)->base_time;
1702 gst_object_ref (clock);
1704 /* no clock, can't set timestamps */
1705 timestamp = GST_CLOCK_TIME_NONE;
1707 GST_OBJECT_UNLOCK (camerasrc);
1710 /* the time now is the time of the clock minus the base time */
1711 timestamp = gst_clock_get_time (clock) - timestamp;
1712 gst_object_unref (clock);
1714 if (timestamp > camerasrc->duration)
1715 timestamp -= camerasrc->duration;
1720 /* we could also use the timestamp from the buffer itself */
1721 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1722 GST_BUFFER_DURATION (buf) = camerasrc->duration;
1728 static GstFlowReturn
1729 gst_camerasrc_create (GstPushSrc * src, GstBuffer ** buf)
1731 GstCameraSrcClass *bclass;
1732 GstCameraSrc *camerasrc;
1733 GstBaseSrcClass *basesrc_class;
1735 GstBuffer *buf_cap_signal1 = NULL; /*output main buffer for capture signal*/
1737 gboolean still_capture_initialised = FALSE;
1738 GstFlowReturn ret = GST_FLOW_OK;
1741 camerasrc = GST_CAMERA_SRC_CAST (src);
1742 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1743 basesrc_class = GST_BASE_SRC_CLASS (bclass);
1745 if (camerasrc->req_negotiation) {
1746 GST_DEBUG_OBJECT(camerasrc, "negotiation start");
1747 basesrc_class->negotiate(GST_BASE_SRC(camerasrc));
1748 camerasrc->req_negotiation = FALSE;
1749 g_signal_emit(G_OBJECT(camerasrc), gst_camerasrc_signals[CAMERA_IN_SIGNAL_NEGO_COMPLETE], (GQuark)NULL);
1750 GST_DEBUG_OBJECT (camerasrc, "negotiation stop");
1756 g_mutex_lock (camerasrc->state_lock);
1758 if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1759 /* Tell subclass to stop flushing buffers */
1760 if (bclass->unlock_stop) {
1761 GST_DEBUG_OBJECT (camerasrc, "Stop flushing, capture is starting");
1762 bclass->unlock_stop (camerasrc);
1765 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE;
1767 GST_DEBUG_OBJECT (camerasrc,
1768 "Flushing old buffers before starting HQ capture");
1769 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1770 gst_event_new_flush_start ());
1771 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1772 gst_event_new_flush_stop ());
1774 if (!gst_camerasrc_set_capture_caps (camerasrc)) {
1775 goto hq_capture_failed;
1777 still_capture_initialised = TRUE;
1780 else if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) {
1784 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1785 camerasrc->requested_af_mode = AF_OFF_REQUESTED;
1786 camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
1787 GST_DEBUG_OBJECT (camerasrc, "capture done. switching to viewfinder");
1789 /* Set the normal viewfinder resolution back */
1790 if (camerasrc->vf_caps) {
1791 GST_DEBUG_OBJECT (camerasrc, "set VF caps");
1792 ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), camerasrc->vf_caps);
1793 gst_caps_unref (camerasrc->vf_caps);
1794 camerasrc->vf_caps = NULL;
1798 tmp = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1800 /* Reconfigure the device to run viewfinder again */
1801 ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1802 &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1803 &camerasrc->fps_d, tmp);
1805 gst_caps_unref (tmp);
1809 GST_WARNING_OBJECT (camerasrc, "Reinitializing viewfinder failed");
1810 g_mutex_unlock (camerasrc->state_lock);
1811 return GST_FLOW_ERROR;
1814 GST_DEBUG_OBJECT (camerasrc, "viewfinder running");
1817 g_mutex_lock (camerasrc->af_lock);
1819 /* Handle AF requests only in VIEWFINDER and AUTOFOCUS states */
1820 if ((camerasrc->photo_capture_phase == GST_CAMERA_VIEWFINDER ||
1821 camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS ||
1822 camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS_DONE) &&
1823 camerasrc->requested_af_mode != AF_NONE_REQUESTED) {
1824 if (camerasrc->requested_af_mode == AF_ON_REQUESTED) {
1827 ret = bclass->set_autofocus (camerasrc, TRUE);
1829 camerasrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS;
1832 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1835 camerasrc->requested_af_mode = AF_NONE_REQUESTED;
1838 g_mutex_unlock (camerasrc->af_lock);
1839 g_mutex_unlock (camerasrc->state_lock);
1841 ret = bclass->grab_frame (camerasrc, &temp, camerasrc->photo_capture_phase);
1843 g_mutex_lock (camerasrc->state_lock);
1845 if (ret != GST_FLOW_OK) {
1846 /* _prepare_for_capture() may have interrupted frame grabbing. */
1847 if (ret == GST_FLOW_WRONG_STATE &&
1848 camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1849 g_mutex_unlock (camerasrc->state_lock);
1853 g_mutex_unlock (camerasrc->state_lock);
1860 /* Post-capture phase */
1862 if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE) {
1865 src_caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1866 gst_buffer_set_caps (*buf, src_caps);
1867 gst_caps_unref (src_caps);
1869 /* Restore the original number of buffers after capture is done */
1870 /* FIXME: Commented out */
1871 // camerasrc->num_buffers = tmp_num_buffers;
1873 // gst_camerasrc_send_image_tags (camerasrc);
1875 gst_camerasrc_send_preview (camerasrc);
1877 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1880 if(GST_CAMERA_SRC_CAPTURE_MODE_STILL == camerasrc->capture_mode) {
1881 gst_camerasrc_send_image_tags (camerasrc);
1882 if ((camerasrc->signal_still_capture == TRUE) && (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) && (still_capture_initialised == TRUE)) {
1883 still_capture_initialised = FALSE;
1885 /* alloc buffer for capture callback */
1886 buf_cap_signal1 = gst_buffer_new ();
1888 GST_BUFFER_DATA(buf_cap_signal1) = GST_BUFFER_DATA(*buf);
1889 GST_BUFFER_SIZE(buf_cap_signal1) = GST_BUFFER_SIZE(*buf);
1890 GST_BUFFER_CAPS(buf_cap_signal1) = gst_caps_new_simple("video/x-raw-yuv",
1891 "format", GST_TYPE_FOURCC, camerasrc->capture_fourcc,
1892 "width", G_TYPE_INT, camerasrc->capture_w,
1893 "height", G_TYPE_INT,camerasrc->capture_h,
1896 GST_LOG_OBJECT (camerasrc, "CALL: capture callback");
1897 g_mutex_unlock (camerasrc->state_lock);
1898 g_signal_emit( G_OBJECT (camerasrc),
1899 gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_CAPTURE],
1904 GST_LOG_OBJECT (camerasrc, "RETURN: capture callback");
1905 g_mutex_lock (camerasrc->state_lock);
1908 if(--camerasrc->capture_counter > 0) {
1909 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_START;
1910 GST_DEBUG_OBJECT (camerasrc, "do some more captures count %d",camerasrc->capture_counter);
1913 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1915 g_mutex_unlock (camerasrc->state_lock);
1920 if (GST_BUFFER_TIMESTAMP (*buf) == GST_CLOCK_TIME_NONE) {
1921 gst_camerasrc_apply_timestamp (camerasrc, *buf);
1926 g_mutex_unlock (camerasrc->state_lock);
1933 GST_ELEMENT_ERROR (camerasrc, RESOURCE, READ,
1934 ("Error during HQ capture"), (NULL));
1935 ret = GST_FLOW_ERROR;
1940 static GstStateChangeReturn
1941 gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
1943 GstCameraSrcClass *bclass;
1944 GstCameraSrc *camerasrc;
1945 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1947 camerasrc = GST_CAMERA_SRC_CAST (element);
1948 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1950 GST_LOG_OBJECT (camerasrc, "State change: %s -> %s",
1951 gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1952 gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
1954 switch (transition) {
1955 case GST_STATE_CHANGE_NULL_TO_READY:
1956 /* Open the device */
1957 if (!bclass->open (camerasrc))
1958 return GST_STATE_CHANGE_FAILURE;
1964 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1966 switch (transition) {
1967 case GST_STATE_CHANGE_READY_TO_NULL:
1968 if (bclass->is_open (camerasrc)) {
1969 bclass->close (camerasrc);
1971 camerasrc->capture_w = camerasrc->preview_w = camerasrc->current_w = 0;
1972 camerasrc->capture_h = camerasrc->preview_h = camerasrc->current_h = 0;
1973 camerasrc->capture_fourcc = camerasrc->preview_fourcc = 0;
1974 camerasrc->current_fourcc = 0;
1975 camerasrc->fps_d = camerasrc->fps_n = 0;
1976 camerasrc->capture_resolution_set = FALSE;
1977 camerasrc->preview_resolution_set = FALSE;
1979 /* Notify that preview caps have changed (to NULL) */
1980 g_object_notify (G_OBJECT (camerasrc),
1981 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
1993 * gst_camerasrc_add_color_channel:
1994 * @camsrc: #GstCameraSrc object.
1995 * @channel: #GstColorBalanceChannel object.
1997 * Add a new color channel to list.
2000 gst_camerasrc_add_color_channel (GstCameraSrc * camsrc,
2001 GstColorBalanceChannel * channel)
2003 camsrc->colors = g_list_append (camsrc->colors, (gpointer) channel);
2008 * gst_camerasrc_clear_color_channels:
2009 * @camsrc: #GstCameraSrc object.
2011 * Delete all color channels.
2014 gst_camerasrc_clear_color_channels (GstCameraSrc * camsrc)
2016 g_list_foreach (camsrc->colors, (GFunc) g_object_unref, NULL);
2017 g_list_free (camsrc->colors);
2018 camsrc->colors = NULL;
2022 * gst_camerasrc_add_cameracontrol_channel:
2023 * @camsrc: #GstCameraSrc object.
2024 * @channel: #GstColorBalanceChannel object.
2026 * Add a new cameracontrol channel to list.
2029 gst_camerasrc_add_cameracontrol_channel (GstCameraSrc * camsrc,
2030 GstCameraControlChannel * channel)
2032 camsrc->camera_controls = g_list_append (camsrc->camera_controls, (gpointer) channel);
2036 * gst_camerasrc_clear_cameracontrol_channels:
2037 * @camsrc: #GstCameraSrc object.
2039 * Delete all cameracontrol channels.
2043 gst_camerasrc_clear_cameracontrol_channels (GstCameraSrc * camsrc)
2045 g_list_foreach (camsrc->camera_controls, (GFunc) g_object_unref, NULL);
2046 g_list_free (camsrc->camera_controls);
2047 camsrc->camera_controls = NULL;
2051 * gst_camerasrc_send_capture_start_message:
2052 * @camsrc: GstCameraSrc object
2054 * Sends a GstMessage notification to GstBus that capture operation is
2058 gst_camerasrc_send_capture_start_message (GstCameraSrc * camsrc)
2063 GST_DEBUG_OBJECT (camsrc, "Sending capture-start message");
2065 /* Send custom GstMessage "photo-capture-start" */
2066 s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_START, NULL);
2067 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2069 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2070 GST_WARNING ("This element has no bus, therefore no message sent!");
2073 GST_LOG_OBJECT (camsrc, "Capture-start message sent");
2078 * gst_camerasrc_send_capture_stop_message:
2079 * @camsrc: GstCameraSrc object
2081 * Sends a GstMessage notification to GstBus that capture operation has
2085 gst_camerasrc_send_capture_stop_message (GstCameraSrc * camsrc)
2090 GST_DEBUG_OBJECT (camsrc, "Sending capture-stop message");
2092 /* Send custom GstMessage "photo-capture-end" */
2093 s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_END, NULL);
2094 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2096 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2097 GST_WARNING ("This element has no bus, therefore no message sent!");
2100 GST_LOG_OBJECT (camsrc, "Capture-stop message sent");
2105 * gst_camerasrc_af_update:
2106 * @camsrc: #GstCameraSrc object.
2107 * @fs: #GstCameraFocusStatus structure. Owned by caller.
2109 * Tell GstCameraSrc that previously started autofocus operation has finished.
2112 gst_camerasrc_af_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2114 GstCameraSrcClass *bclass;
2116 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
2118 g_mutex_lock (camsrc->state_lock);
2119 g_mutex_lock (camsrc->af_lock);
2121 if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS ||
2122 fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL) {
2126 GST_DEBUG_OBJECT (camsrc, "autofocusing ended");
2128 /* Send custom GstMessage "autofocus-done" */
2129 s = gst_structure_new (GST_PHOTOGRAPHY_AUTOFOCUS_DONE,
2130 "status", G_TYPE_INT, fs->status, NULL);
2132 /* If autofocus succeeded, send the bitmask that defines focused
2134 if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS) {
2138 windows = g_array_new (FALSE, FALSE, sizeof (gint));
2139 for (i = 0; i < fs->num_windows; i++) {
2140 GST_DEBUG_OBJECT (camsrc, "focus window: %d", fs->windows[i]);
2141 g_array_append_val (windows, fs->windows[i]);
2144 gst_structure_set (s,
2145 //"focus-windows", G_TYPE_ARRAY, windows,
2146 "focus-window-rows", G_TYPE_INT, fs->focus_rows,
2147 "focus-window-columns", G_TYPE_INT, fs->focus_columns,
2148 "focus-window-coverage", G_TYPE_INT, fs->coverage, NULL);
2150 GST_DEBUG_OBJECT (camsrc, "focus rows: %d", fs->focus_rows);
2151 GST_DEBUG_OBJECT (camsrc, "focus columns: %d", fs->focus_columns);
2152 GST_DEBUG_OBJECT (camsrc, "focus coverage: %d", fs->coverage);
2155 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2157 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2158 GST_WARNING ("This element has no bus, therefore no message sent!");
2161 camsrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS_DONE;
2164 g_mutex_unlock (camsrc->af_lock);
2165 g_mutex_unlock (camsrc->state_lock);
2170 * gst_camerasrc_caf_update:
2171 * @camsrc: GstCameraSrc object.
2172 * @fs: #GstCameraFocusStatus structure. Owned by caller.
2174 * Tell GstCameraSrc that continuous autofocus algorithm has changed its state.
2175 * Sends a GstMessage notification to GstBus indicating a change in
2176 * continuous autofocus status.
2179 gst_camerasrc_caf_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2184 GST_DEBUG_OBJECT (camsrc, "Sending CAF status: %d", fs->status);
2186 /* Send custom GstMessage "caf-update" */
2187 s = gst_structure_new (GST_CAMERA_SRC_CAF_STATUS, NULL);
2188 gst_structure_set (s, "status", G_TYPE_INT, fs->status, NULL);
2189 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2191 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2192 GST_WARNING ("This element has no bus, therefore no message sent!");
2195 GST_LOG_OBJECT (camsrc, "CAF update message sent");
2200 * gst_camerasrc_shake_update:
2201 * @camsrc: GstCameraSrc object.
2202 * @risk: GstPhotoShakeRisk value.
2204 * Tell GstCameraSrc that shake risk has changed. Sends a GstMessage
2205 * notification to GstBus indicating a change in shake risk status.
2208 gst_camerasrc_shake_update (GstCameraSrc * camsrc, GstPhotoShakeRisk risk)
2213 GST_DEBUG_OBJECT (camsrc, "Sending shake risk update: %d", risk);
2215 /* Send custom GstMessage telling the changed shake risk level */
2216 s = gst_structure_new (GST_PHOTOGRAPHY_SHAKE_RISK, NULL);
2217 gst_structure_set (s, "shake_risk", G_TYPE_INT, risk, NULL);
2218 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2220 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2221 GST_WARNING ("This element has no bus, therefore no message sent!");
2224 GST_LOG_OBJECT (camsrc, "Shake indicator message sent");
2228 /* Tag helper functions */
2231 * gst_camerasrc_exposure_mode_from_exif_value:
2232 * @value: exposure mode in EXIF format.
2234 * Convert exposure mode to string.
2236 * Returns: String representation of the scene capture type, or NULL if invalid
2237 * value was given. Possible values: "auto-exposure", "manual-exposure" and
2241 gst_camerasrc_exposure_mode_from_exif_value (gint value)
2245 return "auto-exposure";
2247 return "manual-exposure";
2249 return "auto-bracket";
2251 GST_WARNING ("Invalid exif exposure mode: %d", value);
2257 * gst_camerasrc_scene_capture_type_from_exif_value:
2258 * @value: scene capture type in EXIF format.
2260 * Convert scene capture type to string.
2262 * Returns: String representation of the scene capture type, or NULL if invalid
2263 * value was given. Possible values: "standard", "landscape", "portrait" and
2267 gst_camerasrc_scene_capture_type_from_exif_value (gint value)
2277 return "night-scene";
2279 GST_WARNING ("Invalid exif scene capture type: %d", value);
2286 * gst_camerasrc_gain_adjustment_from_exif_value:
2287 * @value: gain adjustment type in EXIF format.
2289 * Convert gain adjustment type to string.
2291 * Returns: String representation of the gain adjustment type, or NULL if
2292 * invalid value was given. Possible values: "none", "low-gain-up",
2293 * "high-gain-up", "low-gain-down" and "high-gain-down".
2296 gst_camerasrc_gain_adjustment_from_exif_value (gint value)
2302 return "low-gain-up";
2304 return "high-gain-up";
2306 return "low-gain-down";
2308 return "high-gain-down";
2310 GST_WARNING ("Invalid exif gain control type: %d", value);
2317 * gst_camerasrc_contrast_from_exif_value:
2318 * @value: contrast type in EXIF format.
2320 * Convert contrast type to string.
2322 * Returns: String representation of the contrast type, or NULL if invalid
2323 * value was given. Possible values: "normal", "soft" and "hard".
2326 gst_camerasrc_contrast_from_exif_value (gint value)
2336 GST_WARNING ("Invalid contrast type: %d", value);
2343 * gst_camerasrc_saturation_from_exif_value:
2344 * @value: saturation type in EXIF format.
2346 * Convert saturation type to string.
2348 * Returns: String representation of the saturation type, or NULL if invalid
2349 * value was given. Possible values: "normal", "low-saturation" and
2350 * "high-saturation".
2353 gst_camerasrc_saturation_from_exif_value (gint value)
2359 return "low-saturation";
2361 return "high-saturation";
2363 GST_WARNING ("Invalid saturation type: %d", value);
2370 * gst_camerasrc_flash_mode_from_exif_value:
2371 * @value: flash EXIF field
2373 * Convert "flash" EXIF field into text string.
2375 * Returns: String representation of the flash mode, or NULL if invalid
2376 * value was given. Possible values: "always", "never" and "auto".
2379 gst_camerasrc_flash_mode_from_exif_value (gint value)
2383 // bits 3 and 4 indicate the flash mode,
2385 // Values for bits 3 and 4 indicating the camera's flash mode.
2387 // 01b = Compulsory flash firing
2388 // 10b = Compulsory flash suppression
2392 /* Bit numbering in EXIF spec starts from 0 */
2395 switch (value & 0x3) {
2403 GST_WARNING ("Invalid flash mode type: %d", value);
2410 * gst_camerasrc_sharpness_from_exif_value:
2411 * @value: sharpness type in EXIF format.
2413 * Convert sharpness type to string.
2415 * Returns: String representation of the sharpness type, or NULL if invalid
2416 * value was given. Possible values: "normal", "soft" and "hard".
2419 gst_camerasrc_sharpness_from_exif_value (gint value)
2429 GST_WARNING ("Invalid sharpness type: %d", value);
2436 * gst_camerasrc_metering_mode_from_exif_value:
2437 * @value: metering mode type in EXIF format.
2439 * Convert metering mode type to string.
2441 * Returns: String representation of the metering mode type, or NULL if invalid
2442 * value was given. Possible values: "unknown", "average",
2443 * "center-weighted-average", "spot", "multi-spot", "pattern", "partial" and
2447 gst_camerasrc_metering_mode_from_exif_value (gint value)
2455 return "center-weighted-average";
2459 return "multi-spot";
2467 GST_WARNING ("Invalid metering mode type: %d", value);
2474 * gst_camerasrc_file_source_from_exif_value:
2475 * @value: FileSource type in EXIF format.
2477 * Convert FileSource type to string.
2479 * Returns: String representation of the FileSource type, or NULL if invalid
2480 * value was given. Possible values: "dsc", "transparent-scanner",
2481 * "reflex-scanner" and "other".
2484 gst_camerasrc_file_source_from_exif_value (gint value)
2490 return "transparent-scanner";
2492 return "reflex-scanner";
2496 GST_WARNING ("Invalid file source type: %d", value);
2502 /* Default implementations for vmethods */
2505 gst_camerasrc_default_capabilities (GstCameraSrc * camsrc)
2507 return GST_PHOTOGRAPHY_CAPS_NONE;
2511 gst_camerasrc_default_ret_true_with_settings (GstCameraSrc * camsrc,
2512 GstPhotoSettings * photoconf)
2518 gst_camerasrc_default_write_settings (GstCameraSrc * camsrc,
2519 GstPhotoSettings * photoconf, gboolean scene_mode_override)
2525 gst_camerasrc_default_set_onoff (GstCameraSrc * camsrc, gboolean on_off)
2531 gst_camerasrc_default_get_caps (GstCameraSrc * camsrc, GstOperationMode mode)
2533 GST_DEBUG_OBJECT (camsrc, "Returning NULL caps for mode %d", mode);
2538 gst_camerasrc_default_read_exif (GstCameraSrc *camsrc,
2539 GstCameraControlExifInfo *exif_info)
2541 GST_DEBUG_OBJECT (camsrc, "default implementation of exif read called return defaults %d");
2542 // TODO: fill with default values
2547 gst_camerasrc_default_set_flash_mode (GstCameraSrc *camsrc, int value)
2553 gst_camerasrc_default_functions_init (GstCameraSrcClass * camera_class)
2555 camera_class->get_capabilities = gst_camerasrc_default_capabilities;
2556 camera_class->set_autofocus = gst_camerasrc_default_set_onoff;
2557 camera_class->read_settings = gst_camerasrc_default_ret_true_with_settings;
2558 camera_class->write_settings = gst_camerasrc_default_write_settings;
2559 camera_class->get_supported_caps = gst_camerasrc_default_get_caps;
2560 camera_class->set_flash_mode = gst_camerasrc_default_set_flash_mode;
2561 camera_class->read_exif = gst_camerasrc_default_read_exif;
2563 GST_DEBUG ("Default functions set");
2568 gst_camerasrc_handle_event (GstCameraSrc * camerasrc, GstEvent * event)
2570 GstCameraSrcClass *bclass;
2571 gboolean ret = FALSE;
2573 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2574 GST_LOG_OBJECT (camerasrc, "handling %s event", GST_EVENT_TYPE_NAME (event));
2576 if (bclass->event) {
2577 ret = bclass->event (camerasrc, event);
2585 * gst_camerasrc_send_event:
2586 * @element: GstElement object.
2587 * @event: GstEvent to be handled.
2589 * Returns: TRUE if the event was handled.
2592 gst_camerasrc_send_event (GstElement * element, GstEvent * event)
2594 GstCameraSrc *camerasrc;
2595 gboolean ret = FALSE;
2597 camerasrc = GST_CAMERA_SRC_CAST (element);
2599 GST_LOG_OBJECT (camerasrc, "got %s event", GST_EVENT_TYPE_NAME (event));
2601 switch (GST_EVENT_TYPE (event)) {
2602 case GST_EVENT_CUSTOM_UPSTREAM:
2603 ret = gst_camerasrc_handle_event (camerasrc, event);
2610 ret = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
2618 * gst_camerasrc_event:
2619 * @src: #GstBaseSrc object.
2620 * @event: #GetEvent object.
2622 * Returns: TRUE of the event was handled.
2625 gst_camerasrc_event (GstBaseSrc * src, GstEvent * event)
2627 GstCameraSrc *camerasrc;
2630 camerasrc = GST_CAMERA_SRC_CAST (src);
2631 ret = gst_camerasrc_handle_event (camerasrc, event);
2634 ret = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
2642 * gst_camerasrc_update_max_zoom:
2643 * @camerasrc: #GstCameraSrc object.
2645 * Check and update zoom property maximum value.
2648 gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc)
2650 GstCameraSrcClass *bclass;
2651 GObjectClass *oclass;
2653 GParamSpecFloat *pspec_f;
2654 gfloat maxzoom = 10.0;
2656 oclass = G_OBJECT_GET_CLASS (camerasrc);
2657 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2658 pspec = g_object_class_find_property (oclass, "zoom");
2660 if (bclass->get_max_zoom) {
2661 if (!bclass->get_max_zoom (camerasrc, &maxzoom)) {
2666 /* Update gobject property */
2667 if (pspec && (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_FLOAT)) {
2668 pspec_f = G_PARAM_SPEC_FLOAT (pspec);
2669 pspec_f->maximum = maxzoom;
2670 GST_DEBUG_OBJECT (camerasrc, "set maximum zoom as %f", pspec_f->maximum);
2671 /* Check if new maximum zoom is lower than current zoom level */
2672 if (pspec_f->maximum < camerasrc->photoconf.zoom) {
2673 GST_DEBUG_OBJECT (camerasrc, "current zoom level too high: %f",
2674 camerasrc->photoconf.zoom);
2675 g_object_set (G_OBJECT (camerasrc), "zoom", pspec_f->maximum, NULL);
2678 GST_WARNING_OBJECT (camerasrc, "updating maximum zoom failed");