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 "videodev.h"
155 #include <linux/videodev2.h>
158 GST_DEBUG_CATEGORY (gst_camerasrc_debug);
159 #define GST_CAT_DEFAULT gst_camerasrc_debug
162 #define DEFAULT_PROP_ALWAYS_COPY FALSE
165 #define MAX_ZOOM 1000.0
166 #define ZOOM_1X 100.0
168 GST_IMPLEMENT_CAMERA_SRC_COLOR_BALANCE_METHODS (GstCameraSrc, gst_camsrc);
169 GST_IMPLEMENT_CAMERA_SRC_PHOTO_METHODS (GstCameraSrc, gst_camsrc);
170 GST_IMPLEMENT_CAMERA_SRC_CAMERA_CONTROL_METHODS (GstCameraSrc, gst_camsrc);
176 SIGNAL_STILL_CAPTURE,
177 SIGNAL_NEGO_COMPLETE,
181 static guint gst_camerasrc_signals[LAST_SIGNAL] = { 0 };
184 gst_camerasrc_iface_supported (GstImplementsInterface * iface, GType iface_type)
186 GstCameraSrc *camsrc;
187 GstCameraSrcClass *bclass;
189 camsrc = GST_CAMERA_SRC (iface);
190 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
192 g_assert (iface_type == GST_TYPE_PHOTOGRAPHY ||
193 iface_type == GST_TYPE_COLOR_BALANCE || iface_type == GST_TYPE_CAMERA_CONTROL );
195 /* We implement GstPhotography in NULL state as well */
196 if (iface_type == GST_TYPE_PHOTOGRAPHY)
199 else if (!bclass->is_open (camsrc))
206 gst_camerasrc_interface_init (GstImplementsInterfaceClass * klass)
209 * default virtual functions
211 klass->supported = gst_camerasrc_iface_supported;
215 gst_camerasrc_init_interfaces (GType type)
217 static const GInterfaceInfo camsrc_iface_info = {
218 (GInterfaceInitFunc) gst_camerasrc_interface_init,
222 static const GInterfaceInfo camsrc_photo_info = {
223 (GInterfaceInitFunc) gst_camsrc_photo_interface_init,
227 static const GInterfaceInfo camsrc_colorbalance_info = {
228 (GInterfaceInitFunc) gst_camsrc_color_balance_interface_init,
233 static const GInterfaceInfo camsrc_cameracontrol_info = {
234 (GInterfaceInitFunc) gst_camsrc_camera_control_interface_init,
239 g_type_add_interface_static (type,
240 GST_TYPE_IMPLEMENTS_INTERFACE, &camsrc_iface_info);
241 g_type_add_interface_static (type, GST_TYPE_PHOTOGRAPHY, &camsrc_photo_info);
242 g_type_add_interface_static (type,
243 GST_TYPE_COLOR_BALANCE, &camsrc_colorbalance_info);
244 g_type_add_interface_static (type,
245 GST_TYPE_CAMERA_CONTROL, &camsrc_cameracontrol_info);
250 gst_camerasrc_capture_mode_get_type (void)
252 static GType gst_camerasrc_capture_mode_type = 0;
253 static GEnumValue gst_camerasrc_capture_modes[] = {
254 {GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER, "Viewfinder mode", "viewfinder"},
255 {GST_CAMERA_SRC_CAPTURE_MODE_STILL, "Still image capture mode", "still"},
256 {GST_CAMERA_SRC_CAPTURE_MODE_VIDEO, "Video capturing mode", "video"},
260 if (G_UNLIKELY (!gst_camerasrc_capture_mode_type)) {
261 gst_camerasrc_capture_mode_type =
262 g_enum_register_static ("GstCameraCaptureMode",
263 gst_camerasrc_capture_modes);
265 return gst_camerasrc_capture_mode_type;
269 gst_camerasrc_viewfinder_mode_get_type (void)
271 static GType gst_camerasrc_viewfinder_mode_type = 0;
272 static GEnumValue gst_camerasrc_viewfinder_modes[] = {
273 {GST_CAMERA_SRC_VIEWFINDER_MODE_STILL, "Still image capture mode", "still"},
274 {GST_CAMERA_SRC_VIEWFINDER_MODE_VIDEO, "Video capturing mode", "video"},
278 if (G_UNLIKELY (!gst_camerasrc_viewfinder_mode_type)) {
279 gst_camerasrc_viewfinder_mode_type =
280 g_enum_register_static ("GstCameraViewfinderMode",
281 gst_camerasrc_viewfinder_modes);
283 return gst_camerasrc_viewfinder_mode_type;
286 GST_BOILERPLATE_FULL (GstCameraSrc, gst_camerasrc, GstPushSrc,
287 GST_TYPE_PUSH_SRC, gst_camerasrc_init_interfaces);
289 static void gst_camerasrc_dispose (GObject * object);
291 /* element methods */
292 static GstStateChangeReturn
293 gst_camerasrc_change_state (GstElement * element, GstStateChange transition);
295 /* basesrc methods */
296 static gboolean gst_camerasrc_start (GstBaseSrc * src);
298 static gboolean gst_camerasrc_unlock (GstBaseSrc * src);
300 static gboolean gst_camerasrc_unlock_stop (GstBaseSrc * src);
302 static gboolean gst_camerasrc_stop (GstBaseSrc * src);
304 static gboolean gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps);
306 static GstCaps *gst_camerasrc_get_caps (GstBaseSrc * src);
308 static gboolean gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query);
310 static GstFlowReturn gst_camerasrc_create (GstPushSrc * src, GstBuffer ** out);
312 static void gst_camerasrc_fixate (GstBaseSrc * basesrc, GstCaps * caps);
314 static gboolean gst_camerasrc_negotiate (GstBaseSrc * basesrc);
316 static void gst_camerasrc_set_property (GObject * object, guint prop_id,
317 const GValue * value, GParamSpec * pspec);
319 static void gst_camerasrc_get_property (GObject * object, guint prop_id,
320 GValue * value, GParamSpec * pspec);
322 static void gst_camerasrc_override_photo_properties (GObjectClass *
325 static void gst_camerasrc_default_functions_init (GstCameraSrcClass *
328 static gboolean gst_camerasrc_event (GstBaseSrc * src, GstEvent * event);
330 static gboolean gst_camerasrc_send_event (GstElement * element,
333 static void gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc);
338 gst_camerasrc_base_init (gpointer g_class)
340 // GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
341 gst_tag_register_musicbrainz_tags ();
343 GST_DEBUG_CATEGORY_INIT (gst_camerasrc_debug, "camerasrc", 0,
344 "camerasrc element");
348 /* VOID:OBJECT,OBJECT (generated by 'glib-genmarshal') */
349 #define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
350 void gst_camerasrc_VOID__OBJECT_OBJECT(GClosure *closure,
351 GValue *return_value,
352 guint n_param_values,
353 const GValue *param_values,
354 gpointer invocation_hint,
355 gpointer marshal_data)
357 typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT)(gpointer data1,
362 register GMarshalFunc_VOID__OBJECT_OBJECT callback;
363 register GCClosure *cc = (GCClosure*) closure;
364 register gpointer data1, data2;
366 g_return_if_fail (n_param_values == 4);
368 if (G_CCLOSURE_SWAP_DATA(closure)) {
369 data1 = closure->data;
370 data2 = g_value_peek_pointer(param_values + 0);
372 data1 = g_value_peek_pointer(param_values + 0);
373 data2 = closure->data;
376 callback = (GMarshalFunc_VOID__OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback);
379 g_marshal_value_peek_object(param_values + 1),
380 g_marshal_value_peek_object(param_values + 2),
381 g_marshal_value_peek_object(param_values + 3),
385 int gst_camerasrc_send_af_status(GstCameraSrc *camsrc , int state)
387 GstMessage *m = NULL;
388 GstStructure *s = NULL;
390 GST_INFO_OBJECT(camsrc, "autofocus callback: state [%d]", state);
392 s = gst_structure_new("camerasrc-AF",
393 "focus-state", G_TYPE_INT, state,
396 m = gst_message_new_element(GST_OBJECT(camsrc), s);
397 gst_element_post_message(GST_ELEMENT(camsrc), m);
404 gst_camerasrc_class_init (GstCameraSrcClass * klass)
406 GObjectClass *gobject_class;
407 GstElementClass *element_class;
408 GstBaseSrcClass *basesrc_class;
409 GstPushSrcClass *pushsrc_class;
411 gobject_class = G_OBJECT_CLASS (klass);
412 element_class = GST_ELEMENT_CLASS (klass);
413 basesrc_class = GST_BASE_SRC_CLASS (klass);
414 pushsrc_class = GST_PUSH_SRC_CLASS (klass);
416 gobject_class->dispose = gst_camerasrc_dispose;
417 gobject_class->set_property = gst_camerasrc_set_property;
418 gobject_class->get_property = gst_camerasrc_get_property;
420 element_class->change_state = gst_camerasrc_change_state;
421 element_class->send_event = gst_camerasrc_send_event;
423 g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
424 g_param_spec_boolean ("always-copy", "Always Copy",
425 "If the buffer will or not be used directly from mmap",
426 DEFAULT_PROP_ALWAYS_COPY,
427 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
429 g_object_class_install_property (gobject_class, PROP_MAKER_NOTE,
430 g_param_spec_boolean ("maker-note", "Maker Note",
431 "Whether send the maker note with image during the capture",
432 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
433 GST_PARAM_CONTROLLABLE));
435 g_object_class_install_property (gobject_class, PROP_CAPTURE_WIDTH,
436 g_param_spec_int ("capture-width", "Capture Widht",
437 "Image width used in capture mode.In case capture is done when pipeline is already running in viewfinder mode", 0,
439 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
441 g_object_class_install_property (gobject_class, PROP_CAPTURE_HEIGHT,
442 g_param_spec_int ("capture-height", "Capture Height",
443 "Image height used in capture mode. In case capture is done when pipeline is already running in viewfinder mode", 0,
445 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
447 g_object_class_install_property(gobject_class, PROP_CAPTURE_FOURCC,
448 g_param_spec_uint("capture-fourcc", "Capture format",
449 "Fourcc value for capture format",0,
451 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
453 g_object_class_install_property(gobject_class, PROP_CAPTURE_COUNT,
454 g_param_spec_uint("capture-count", "Capture count",
455 "image count taken in capture",0,
457 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
459 g_object_class_install_property(gobject_class, PROP_REQ_NEGOTIATION,
460 g_param_spec_boolean("req-negotiation", "Request re-negotiation",
461 "Request to negotiate while on playing",
463 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ));
465 g_object_class_install_property(gobject_class, PROP_SIGNAL_STILL_CAPTURE,
466 g_param_spec_boolean("signal-still-capture", "Signal Still Capture",
467 "Send a signal before pushing the buffer",
469 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ));
472 * GstCameraSrc:capture-mode:
474 * Defines capturing mode to be used. This information is needed by extension
475 * modules, which control hardware-specific functionality.
477 g_object_class_install_property (gobject_class, PROP_CAPTURE_MODE,
478 g_param_spec_enum ("capture-mode", "Capturing mode",
479 "Defines what kind of capturing mode to be used",
480 GST_TYPE_CAMERA_SRC_CAPTURE_MODE,
481 GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER,
482 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
485 * GstCameraSrc:viewfinder-mode:
487 * Defines which mode viewfinder should run in. This information is needed
488 * by extension modules, which control hardware-specific functionality.
490 g_object_class_install_property (gobject_class, PROP_VIEWFINDER_MODE,
491 g_param_spec_enum ("viewfinder-mode", "Viewfinder mode",
492 "Defines in what mode viewfinder should be run",
493 GST_TYPE_CAMERA_SRC_VIEWFINDER_MODE,
494 GST_CAMERA_SRC_VIEWFINDER_MODE_STILL,
495 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
499 * GstCameraSrc::nego-complete:
500 * @camerasrc: the camerasrc instance
501 * @start: when re-negotiation is finished.
504 gst_camerasrc_signals[SIGNAL_NEGO_COMPLETE] =
505 g_signal_new("nego-complete",
506 G_TYPE_FROM_CLASS (klass),
508 G_STRUCT_OFFSET(GstCameraSrcClass, nego_complete),
511 gst_marshal_VOID__VOID,
515 * GstCameraSrc::still-capture:
516 * @camerasrc: the camerasrc instance
517 * @buffer: the buffer that will be pushed - Main
518 * @buffer: the buffer that will be pushed - Thumbnail
519 * @buffer: the buffer that will be pushed - Screennail
521 * This signal gets emitted before sending the buffer.
523 gst_camerasrc_signals[SIGNAL_STILL_CAPTURE] =
524 g_signal_new("still-capture",
525 G_TYPE_FROM_CLASS(klass),
527 G_STRUCT_OFFSET(GstCameraSrcClass, still_capture),
530 gst_camerasrc_VOID__OBJECT_OBJECT,
532 3, /* Number of parameter */
533 GST_TYPE_BUFFER, /* Main image buffer */
534 GST_TYPE_BUFFER, /* Thumbnail image buffer */
535 GST_TYPE_BUFFER); /* Screennail image buffer */
539 gst_camerasrc_override_photo_properties (gobject_class);
541 basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_camerasrc_get_caps);
542 basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_camerasrc_set_caps);
543 basesrc_class->start = GST_DEBUG_FUNCPTR (gst_camerasrc_start);
544 basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_camerasrc_unlock);
545 basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_camerasrc_unlock_stop);
546 basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_camerasrc_stop);
547 basesrc_class->query = GST_DEBUG_FUNCPTR (gst_camerasrc_query);
548 basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_camerasrc_fixate);
549 basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_camerasrc_negotiate);
550 basesrc_class->event = GST_DEBUG_FUNCPTR (gst_camerasrc_event);
552 pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_camerasrc_create);
554 /* Initialize vmethods with default implementations */
555 gst_camerasrc_default_functions_init (klass);
561 gst_camerasrc_init (GstCameraSrc * camerasrc, GstCameraSrcClass * klass)
563 /* number of buffers requested */
564 camerasrc->always_copy = DEFAULT_PROP_ALWAYS_COPY;
566 camerasrc->state_lock = g_mutex_new ();
567 camerasrc->af_lock = g_mutex_new ();
569 gst_base_src_set_format (GST_BASE_SRC (camerasrc), GST_FORMAT_TIME);
570 gst_base_src_set_live (GST_BASE_SRC (camerasrc), TRUE);
572 /* Photo interface */
573 camerasrc->photoconf.zoom = 1.0;
574 camerasrc->photoconf.ev_compensation = 0.0;
575 camerasrc->photoconf.exposure = 0; /* 0 = auto */
576 camerasrc->photoconf.aperture = 0; /* 0 = auto */
577 camerasrc->photoconf.iso_speed = 0; /* 0 = auto */
578 camerasrc->photoconf.wb_mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
579 camerasrc->photoconf.scene_mode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL;
580 camerasrc->photoconf.flash_mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
581 camerasrc->photoconf.tone_mode = GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NORMAL;
582 camerasrc->photoconf.flicker_mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ;
583 camerasrc->photoconf.focus_mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
584 camerasrc->photoconf.noise_reduction = GST_PHOTOGRAPHY_NOISE_REDUCTION_YCC |
585 GST_PHOTOGRAPHY_NOISE_REDUCTION_BAYER;
587 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
588 camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
589 camerasrc->viewfinder_mode = GST_CAMERA_SRC_VIEWFINDER_MODE_STILL;
590 camerasrc->capture_resolution_set = FALSE;
591 camerasrc->preview_resolution_set = FALSE;
592 camerasrc->req_negotiation = FALSE;
593 camerasrc->signal_still_capture = FALSE;
595 camerasrc->capture_w = 0;
596 camerasrc->capture_h = 0;
597 camerasrc->capture_fps_n = 0;
598 camerasrc->capture_fps_d = 0;
599 camerasrc->capture_fourcc = 0;
600 camerasrc->capture_count = 1;
601 camerasrc->capture_counter = 1;
603 camerasrc->preview_w = 0;
604 camerasrc->preview_h = 0;
605 camerasrc->preview_fourcc = 0;
607 camerasrc->requested_af_mode = AF_NONE_REQUESTED;
608 camerasrc->maker_note = FALSE;
614 gst_camerasrc_dispose (GObject * object)
616 GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (object);
618 if (camerasrc->vf_caps) {
619 gst_caps_unref (camerasrc->vf_caps);
620 camerasrc->vf_caps = NULL;
622 if (camerasrc->state_lock) {
623 g_mutex_free (camerasrc->state_lock);
624 camerasrc->state_lock = NULL;
626 if (camerasrc->af_lock) {
627 g_mutex_free (camerasrc->af_lock);
628 camerasrc->af_lock = NULL;
630 gst_camerasrc_clear_color_channels (camerasrc);
632 gst_camerasrc_clear_cameracontrol_channels (camerasrc);
634 G_OBJECT_CLASS (parent_class)->dispose (object);
638 gst_camerasrc_override_photo_properties (GObjectClass * gobject_class)
640 g_object_class_override_property (gobject_class, PROP_WB_MODE,
641 GST_PHOTOGRAPHY_PROP_WB_MODE);
643 g_object_class_override_property (gobject_class, PROP_COLOUR_TONE,
644 GST_PHOTOGRAPHY_PROP_COLOUR_TONE);
646 g_object_class_override_property (gobject_class, PROP_SCENE_MODE,
647 GST_PHOTOGRAPHY_PROP_SCENE_MODE);
649 g_object_class_override_property (gobject_class, PROP_FLASH_MODE,
650 GST_PHOTOGRAPHY_PROP_FLASH_MODE);
652 g_object_class_override_property (gobject_class, PROP_CAPABILITIES,
653 GST_PHOTOGRAPHY_PROP_CAPABILITIES);
655 g_object_class_override_property (gobject_class, PROP_EV_COMP,
656 GST_PHOTOGRAPHY_PROP_EV_COMP);
658 g_object_class_override_property (gobject_class, PROP_ISO_SPEED,
659 GST_PHOTOGRAPHY_PROP_ISO_SPEED);
661 g_object_class_override_property (gobject_class, PROP_APERTURE,
662 GST_PHOTOGRAPHY_PROP_APERTURE);
664 g_object_class_override_property (gobject_class, PROP_EXPOSURE,
665 GST_PHOTOGRAPHY_PROP_EXPOSURE);
667 g_object_class_override_property (gobject_class, PROP_ZOOM,
668 GST_PHOTOGRAPHY_PROP_ZOOM);
670 g_object_class_override_property (gobject_class, PROP_FLICKER_MODE,
671 GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
673 g_object_class_override_property (gobject_class, PROP_FOCUS_MODE,
674 GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
676 g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION,
677 GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
679 g_object_class_override_property (gobject_class, PROP_IMAGE_CAPTURE_CAPS,
680 GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
682 g_object_class_override_property (gobject_class, PROP_IMAGE_PREVIEW_CAPS,
683 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
685 g_object_class_override_property (gobject_class, PROP_AUTOFOCUS,
686 GST_PHOTOGRAPHY_PROP_AUTOFOCUS);
693 gst_camerasrc_set_property (GObject * object,
694 guint prop_id, const GValue * value, GParamSpec * pspec)
696 GstCameraSrc *camerasrc;
697 GstCameraSrcClass *bclass;
699 camerasrc = GST_CAMERA_SRC_CAST (object);
700 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
702 if (gst_camerasrc_photo_set_property (camerasrc, prop_id, value))
706 case PROP_ALWAYS_COPY:
707 camerasrc->always_copy = g_value_get_boolean (value);
709 case PROP_MAKER_NOTE:
710 camerasrc->maker_note = g_value_get_boolean (value);
712 case PROP_CAPTURE_MODE:
713 camerasrc->capture_mode = g_value_get_enum (value);
714 GST_INFO_OBJECT (camerasrc, "Setting capture mode: %d",
715 camerasrc->capture_mode);
717 if (camerasrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_VIDEO &&
718 bclass->is_active (camerasrc)) {
719 /* Stop autofocus in video mode */
720 bclass->set_autofocus (camerasrc, FALSE);
721 /* AutoExposure must be run always in video mode */
722 bclass->set_autoexposure (camerasrc, TRUE);
724 if (bclass->set_capture_mode) {
725 bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
729 case PROP_VIEWFINDER_MODE:
730 camerasrc->viewfinder_mode = g_value_get_enum (value);
731 GST_INFO_OBJECT (camerasrc, "Setting viewfinder mode: %d",
732 camerasrc->viewfinder_mode);
734 if (bclass->set_vfinder_mode) {
735 bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
738 case PROP_CAPTURE_WIDTH:
739 camerasrc->capture_w = g_value_get_int (value);
740 GST_DEBUG_OBJECT (camerasrc, "Capture width %d",
741 camerasrc->capture_w);
742 /* both width & height should be set before setting flag to TRUE */
743 if(camerasrc->capture_h != 0)
744 camerasrc->capture_resolution_set = TRUE;
746 case PROP_CAPTURE_HEIGHT:
747 camerasrc->capture_h = g_value_get_int (value);
748 GST_DEBUG_OBJECT (camerasrc, "Capture Height: %d",
749 camerasrc->capture_h);
750 /* both width & height should be set before setting flag to TRUE */
751 if(camerasrc->capture_w != 0)
752 camerasrc->capture_resolution_set = TRUE;
754 case PROP_CAPTURE_FOURCC:
755 camerasrc->capture_fourcc = g_value_get_uint (value);
756 GST_DEBUG_OBJECT (camerasrc, "Capture fourcc: %d",
757 camerasrc->capture_fourcc);
759 case PROP_CAPTURE_COUNT:
760 camerasrc->capture_count = g_value_get_uint (value);
761 GST_DEBUG_OBJECT (camerasrc, "Capture count: %d",
762 camerasrc->capture_count);
764 case PROP_REQ_NEGOTIATION:
765 camerasrc->req_negotiation = g_value_get_boolean(value);
766 GST_DEBUG_OBJECT (camerasrc, "negotaion request %d",
767 camerasrc->req_negotiation);
769 case PROP_SIGNAL_STILL_CAPTURE:
770 camerasrc->signal_still_capture = g_value_get_boolean(value);
773 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
781 gst_camerasrc_get_property (GObject * object,
782 guint prop_id, GValue * value, GParamSpec * pspec)
784 GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (object);
786 if (gst_camerasrc_photo_get_property (camerasrc, prop_id, value))
790 case PROP_ALWAYS_COPY:
791 g_value_set_boolean (value, camerasrc->always_copy);
793 case PROP_MAKER_NOTE:
794 g_value_set_boolean (value, camerasrc->maker_note);
796 case PROP_CAPTURE_MODE:
797 g_value_set_enum (value, camerasrc->capture_mode);
799 case PROP_VIEWFINDER_MODE:
800 g_value_set_enum (value, camerasrc->viewfinder_mode);
802 case PROP_CAPTURE_WIDTH:
803 g_value_set_int (value, camerasrc->capture_w);
805 case PROP_CAPTURE_HEIGHT:
806 g_value_set_int (value, camerasrc->capture_h);
808 case PROP_CAPTURE_FOURCC:
809 g_value_set_uint (value, camerasrc->capture_fourcc);
811 case PROP_CAPTURE_COUNT:
812 g_value_set_uint (value, camerasrc->capture_count);
814 case PROP_REQ_NEGOTIATION:
815 g_value_set_boolean(value, camerasrc->req_negotiation);
817 case PROP_SIGNAL_STILL_CAPTURE:
818 g_value_set_boolean (value, camerasrc->signal_still_capture);
821 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
826 /* this function is a bit of a last resort */
828 gst_camerasrc_fixate (GstBaseSrc * basesrc, GstCaps * caps)
830 GstStructure *structure;
834 GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
836 for (i = 0; i < gst_caps_get_size (caps); ++i) {
839 structure = gst_caps_get_structure (caps, i);
841 /* FIXME such sizes? we usually fixate to something in the 320x200
843 /* We are fixating to greatest possble size (limited to GST_CAMERA_SRC_MAX_SIZE)
844 and the maximum framerate resolution for that size */
845 gst_structure_fixate_field_nearest_int (structure, "width",
846 GST_CAMERA_SRC_MAX_SIZE);
847 gst_structure_fixate_field_nearest_int (structure, "height",
848 GST_CAMERA_SRC_MAX_SIZE);
849 gst_structure_fixate_field_nearest_fraction (structure, "framerate",
852 v = gst_structure_get_value (structure, "format");
853 if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
856 g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
858 fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
859 gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
863 GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
869 gst_camerasrc_negotiate (GstBaseSrc * basesrc)
873 GstCaps *caps = NULL;
875 GstCaps *peercaps = NULL;
877 gboolean result = FALSE;
879 /* first see what is possible on our source pad */
880 thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
881 GST_DEBUG_OBJECT (basesrc, "caps of src suppressed on DEBUG (>= 5 to see)");
882 GST_LOG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
883 /* nothing or anything is allowed, we're done */
884 if (thiscaps == NULL || gst_caps_is_any (thiscaps))
887 /* get the peer caps */
888 peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
889 GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
890 if (peercaps && !gst_caps_is_any (peercaps)) {
891 GstCaps *icaps = NULL;
894 /* Prefer the first caps we are compatible with that the peer proposed */
895 for (i = 0; i < gst_caps_get_size (peercaps); i++) {
896 /* get intersection */
897 GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
899 GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
901 icaps = gst_caps_intersect (thiscaps, ipcaps);
902 gst_caps_unref (ipcaps);
904 if (!gst_caps_is_empty (icaps))
907 gst_caps_unref (icaps);
911 GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
913 /* If there are multiple intersections pick the one with the smallest
914 * resolution strictly bigger then the first peer caps */
915 if (gst_caps_get_size (icaps) > 1) {
916 GstStructure *s = gst_caps_get_structure (peercaps, 0);
922 int width = G_MAXINT, height = G_MAXINT;
924 if (gst_structure_get_int (s, "width", &twidth)
925 && gst_structure_get_int (s, "height", &theight)) {
927 /* Walk the structure backwards to get the first entry of the
928 * smallest resolution bigger (or equal to) the preferred resolution)
930 for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
931 GstStructure *is = gst_caps_get_structure (icaps, i);
935 if (gst_structure_get_int (is, "width", &w)
936 && gst_structure_get_int (is, "height", &h)) {
937 if (w >= twidth && w <= width && h >= theight && h <= height) {
946 caps = gst_caps_copy_nth (icaps, best);
947 gst_caps_unref (icaps);
952 gst_caps_unref (thiscaps);
953 gst_caps_unref (peercaps);
955 /* no peer or peer have ANY caps, work with our own caps then */
959 caps = gst_caps_make_writable (caps);
960 gst_caps_truncate (caps);
963 if (!gst_caps_is_empty (caps)) {
964 gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
965 GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
967 if (gst_caps_is_any (caps)) {
968 /* hmm, still anything, so element can do anything and
969 * nego is not needed */
971 } else if (gst_caps_is_fixed (caps)) {
972 /* yay, fixed caps, use those then */
973 result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
974 GST_DEBUG_OBJECT (basesrc, "Set caps returned: %d", result);
977 gst_caps_unref (caps);
983 GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
985 gst_caps_unref (thiscaps);
994 gst_camerasrc_get_caps (GstBaseSrc * src)
996 GstCameraSrc *camerasrc;
997 GstCameraSrcClass *bclass;
999 camerasrc = GST_CAMERA_SRC_CAST (src);
1000 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1002 if (!bclass->is_open (camerasrc) || !bclass->get_caps) {
1003 return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
1007 return bclass->get_caps (camerasrc);
1012 * gst_camerasrc_get_caps_info:
1013 * @caps: given input caps
1014 * @four_cc: location for the fourcc
1015 * @w/@h: location for width and height
1016 * @fps_n/@fps_d: location for framerate
1018 * Collect data for the given caps.
1021 gst_camerasrc_get_caps_info (GstCameraSrc * camerasrc, GstCaps * caps,
1022 guint32 * four_cc, guint * w, guint * h, guint * fps_n, guint * fps_d,
1025 GstCameraSrcClass *bclass;
1026 GstStructure *structure;
1027 const GValue *framerate;
1028 const gchar *mimetype;
1032 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1034 /* default unknown values */
1038 structure = gst_caps_get_structure (caps, 0);
1040 mimetype = gst_structure_get_name (structure);
1042 if (!gst_structure_get_int (structure, "width", (gint *) w))
1045 if (!gst_structure_get_int (structure, "height", (gint *) h))
1048 framerate = gst_structure_get_value (structure, "framerate");
1052 *fps_n = gst_value_get_fraction_numerator (framerate);
1053 *fps_d = gst_value_get_fraction_denominator (framerate);
1055 if (!strcmp (mimetype, "video/x-raw-yuv")) {
1056 gst_structure_get_fourcc (structure, "format", &fourcc);
1059 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1060 case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
1061 fourcc = V4L2_PIX_FMT_YUV420;
1062 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1063 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1065 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1066 fourcc = V4L2_PIX_FMT_YUYV;
1067 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1069 case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
1070 fourcc = V4L2_PIX_FMT_Y41P;
1071 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1073 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1074 fourcc = V4L2_PIX_FMT_UYVY;
1075 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1077 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1078 fourcc = V4L2_PIX_FMT_YVU420;
1079 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1080 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1082 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
1083 fourcc = V4L2_PIX_FMT_YUV411P;
1084 outsize = GST_ROUND_UP_4 (*w) * *h;
1085 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1087 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
1088 fourcc = V4L2_PIX_FMT_YUV422P;
1089 outsize = GST_ROUND_UP_4 (*w) * *h;
1090 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1092 case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1093 fourcc = V4L2_PIX_FMT_NV12;
1094 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1095 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1097 case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1098 fourcc = V4L2_PIX_FMT_NV21;
1099 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1100 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1102 #ifdef V4L2_PIX_FMT_YVYU
1103 case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
1104 fourcc = V4L2_PIX_FMT_YVYU;
1105 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1109 } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
1110 gint depth, endianness, r_mask;
1112 gst_structure_get_int (structure, "depth", &depth);
1113 gst_structure_get_int (structure, "endianness", &endianness);
1114 gst_structure_get_int (structure, "red_mask", &r_mask);
1118 fourcc = V4L2_PIX_FMT_RGB332;
1121 fourcc = (endianness == G_LITTLE_ENDIAN) ?
1122 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
1125 fourcc = (endianness == G_LITTLE_ENDIAN) ?
1126 V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
1129 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
1132 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
1135 } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
1136 gst_structure_get_fourcc (structure, "format", &fourcc);
1138 case GST_MAKE_FOURCC ('B', 'A', '8', '1'):
1139 fourcc = V4L2_PIX_FMT_SBGGR8;
1141 case GST_MAKE_FOURCC ('G', 'B', 'R', 'G'):
1142 fourcc = V4L2_PIX_FMT_SGBRG8;
1144 case GST_MAKE_FOURCC ('G', 'R', 'B', 'G'):
1145 fourcc = V4L2_PIX_FMT_SGRBG8;
1147 case GST_MAKE_FOURCC ('R', 'G', 'G', 'B'):
1148 fourcc = V4L2_PIX_FMT_SRGGB8;
1150 case GST_MAKE_FOURCC ('B', 'G', '1', '0'):
1151 fourcc = V4L2_PIX_FMT_SBGGR10;
1153 case GST_MAKE_FOURCC ('G', 'B', '1', '0'):
1154 fourcc = V4L2_PIX_FMT_SGBRG10;
1156 case GST_MAKE_FOURCC ('B', 'A', '1', '0'):
1157 fourcc = V4L2_PIX_FMT_SGRBG10;
1159 case GST_MAKE_FOURCC ('R', 'G', '1', '0'):
1160 fourcc = V4L2_PIX_FMT_SRGGB10;
1162 case GST_MAKE_FOURCC ('B', 'Y', 'R', '2'):
1163 fourcc = V4L2_PIX_FMT_SBGGR16;
1166 } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
1167 fourcc = V4L2_PIX_FMT_GREY;
1180 * gst_camerasrc_get_caps_from_info:
1181 * @camsrc: #GstCameraSrc object
1182 * @fourcc: fourcc code
1183 * @width: width to be set
1184 * @height: height to be set
1185 * @fps_n: FPS numerator to be set or 0
1186 * @fps_d: FPS denominator to be set or 0
1188 * Converts given parameters into GstCaps structure.
1190 * Returns: GstCaps representing the given values.
1193 gst_camerasrc_get_caps_from_info (GstCameraSrc * camsrc, guint32 fourcc,
1194 guint width, guint height, guint fps_n, guint fps_d)
1199 s = gst_structure_new ("video/x-raw-yuv",
1200 "format", GST_TYPE_FOURCC, fourcc,
1201 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
1203 if (fps_n != 0 && fps_d != 0) {
1204 gst_structure_set (s, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
1207 newcaps = gst_caps_new_empty ();
1208 gst_caps_append_structure (newcaps, s);
1217 gst_camerasrc_configure_device (GstCameraSrc * camerasrc, guint * w, guint * h,
1218 guint32 * fourcc, guint * fps_n, guint * fps_d, GstCaps * buffer_caps)
1220 GstCameraSrcClass *bclass;
1221 GstOperationMode opmode;
1223 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1225 /* Stop the capturing */
1226 if (!bclass->stop (camerasrc))
1229 GST_DEBUG_OBJECT (camerasrc, "trying to set_capture %dx%d at %d/%d fps",
1230 *w, *h, *fps_n, *fps_d);
1232 if (bclass->set_vfinder_mode) {
1233 bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
1235 if (bclass->set_capture_mode) {
1236 bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
1239 opmode = camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE ?
1240 GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE :
1241 GST_PHOTOGRAPHY_OPERATION_MODE_VIEWFINDER;
1243 if (!bclass->set_capture (camerasrc, opmode, FALSE, fourcc, w, h,
1245 GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1246 ("Failed configuring device for capturing"), (NULL));
1250 gst_camerasrc_update_max_zoom (camerasrc);
1252 /* Only start the driver when not in HQ capture mode, since in HQ mode */
1253 /* we have already called start_capture() above */
1255 if (!bclass->start (camerasrc, buffer_caps))
1258 if (camerasrc->photo_capture_phase != GST_CAMERA_CAPTURE) {
1260 if (!bclass->write_settings (camerasrc, &camerasrc->photoconf, FALSE)) {
1261 GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1262 ("Failed to configure driver module"), (NULL));
1275 gst_camerasrc_init_from_caps (GstCameraSrc * camerasrc, GstCaps * caps)
1283 /* we want our own type of fourcc codes */
1284 if (!gst_camerasrc_get_caps_info (camerasrc, caps, &fourcc, &w, &h, &fps_n,
1286 GST_DEBUG_OBJECT (camerasrc,
1287 "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1291 ret = gst_camerasrc_configure_device (camerasrc, &w, &h, &fourcc,
1292 &fps_n, &fps_d, caps);
1295 camerasrc->current_w = w;
1296 camerasrc->current_h = h;
1297 camerasrc->fps_n = fps_n;
1298 camerasrc->fps_d = fps_d;
1299 camerasrc->current_fourcc = fourcc;
1301 camerasrc->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
1302 GST_DEBUG_OBJECT (camerasrc, "Buffer duration: %" GST_TIME_FORMAT,
1303 GST_TIME_ARGS (camerasrc->duration));
1305 // camerasrc->frame_byte_size = size;
1314 gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps)
1316 GstCameraSrc *camerasrc;
1317 GstCameraSrcClass *bclass;
1319 camerasrc = GST_CAMERA_SRC_CAST (src);
1320 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1322 GST_DEBUG_OBJECT (camerasrc, "set_caps called: %" GST_PTR_FORMAT, caps);
1324 /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1325 if (!bclass->is_open (camerasrc))
1328 return gst_camerasrc_init_from_caps (camerasrc, caps);
1334 gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query)
1337 GstCameraSrcClass *bclass;
1338 gboolean res = FALSE;
1341 src = GST_CAMERA_SRC_CAST (bsrc);
1342 bclass = GST_CAMERA_SRC_GET_CLASS (src);
1344 switch (GST_QUERY_TYPE (query)) {
1345 case GST_QUERY_LATENCY:{
1346 GstClockTime max_latency;
1348 /* device must be open */
1349 if (!bclass->is_open (src)) {
1350 GST_WARNING_OBJECT (src,
1351 "Can't give latency since device isn't open !");
1355 /* we must have a framerate */
1356 if (src->fps_n <= 0 || src->fps_d <= 0) {
1357 GST_WARNING_OBJECT (src,
1358 "Can't give latency since framerate isn't fixated !");
1362 num_buffers = bclass->get_num_buffers (src);
1363 /* max latency is total duration of the frame buffer */
1364 max_latency = num_buffers * src->duration;
1366 GST_DEBUG_OBJECT (bsrc,
1367 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1368 GST_TIME_ARGS (src->duration), GST_TIME_ARGS (max_latency));
1370 /* we are always live, the min latency is 1 frame and the max latency is
1371 * the complete buffer of frames. */
1372 gst_query_set_latency (query, TRUE, src->duration, max_latency);
1378 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1388 gst_camerasrc_start (GstBaseSrc * src)
1390 // GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (src);
1398 gst_camerasrc_stop (GstBaseSrc * src)
1400 GstCameraSrc *camerasrc;
1401 GstCameraSrcClass *bclass;
1403 camerasrc = GST_CAMERA_SRC_CAST (src);
1404 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1406 GST_DEBUG_OBJECT (camerasrc, "Stopping");
1408 bclass->stop (camerasrc);
1410 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1416 gst_camerasrc_unlock (GstBaseSrc * src)
1418 GstCameraSrcClass *pclass;
1419 GstCameraSrc *camerasrc;
1420 gboolean ret = TRUE;
1422 camerasrc = GST_CAMERA_SRC_CAST (src);
1423 pclass = GST_CAMERA_SRC_GET_CLASS (src);
1425 GST_DEBUG_OBJECT (camerasrc, "Unlock");
1428 ret = pclass->unlock (camerasrc);
1434 gst_camerasrc_unlock_stop (GstBaseSrc * src)
1436 GstCameraSrcClass *pclass;
1437 GstCameraSrc *camerasrc;
1438 gboolean ret = TRUE;
1440 camerasrc = GST_CAMERA_SRC_CAST (src);
1441 pclass = GST_CAMERA_SRC_GET_CLASS (src);
1443 GST_DEBUG_OBJECT (camerasrc, "Unlock stop");
1445 if (pclass->unlock_stop)
1446 ret = pclass->unlock_stop (camerasrc);
1453 * gst_camerasrc_send_image_tags:
1454 * @camerasrc: #GstCameraSrc object.
1458 gst_camerasrc_send_image_tags (GstCameraSrc * camerasrc)
1460 GstTagMergeMode mode;
1461 GstCameraSrcClass *bclass;
1462 guint iso, wbalance;
1467 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1469 tlist = gst_tag_list_new ();
1470 zoom = camerasrc->photoconf.zoom;
1471 iso = camerasrc->photoconf.iso_speed;
1473 (camerasrc->photoconf.wb_mode == GST_PHOTOGRAPHY_WB_MODE_AUTO) ? 0 : 1;
1475 gst_tag_register_musicbrainz_tags();
1477 mode = GST_TAG_MERGE_REPLACE;
1478 gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, (gdouble)zoom, NULL);
1479 gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_ISO_SPEED, iso, NULL);
1481 if(camerasrc->maker_note)
1485 GstBuffer *pmakerbuf = NULL;
1487 unsigned num_afwindows, num_awbgrid;
1491 ret = bclass->makernote_init(camerasrc, &buf_size, num_afwindows, 0, 0, num_awbgrid, &handle);
1494 pmakerbuf = gst_buffer_new_and_alloc(buf_size);
1496 ret = bclass->makernote_deal(camerasrc, pmakerbuf, num_afwindows, num_awbgrid, handle);
1499 gst_tag_list_add(tlist, mode, GST_TAG_APPLICATION_DATA, pmakerbuf, NULL);
1502 bclass->makernote_uninit(camerasrc, handle);
1503 gst_buffer_unref(pmakerbuf);
1507 if (bclass->fill_image_tags)
1508 bclass->fill_image_tags (camerasrc, tlist);
1510 tagevent = gst_event_new_tag (gst_tag_list_copy (tlist));
1511 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc), tagevent);
1512 GST_DEBUG_OBJECT (camerasrc, "image tags sent: %" GST_PTR_FORMAT, tlist);
1513 gst_tag_list_free (tlist);
1520 * gst_camerasrc_send_preview:
1521 * @camsrc: #GstCameraSrc object
1523 * Sends HQ image preview image (snapshot) as a GstMessage.
1525 * Returns: TRUE on success.
1528 gst_camerasrc_send_preview (GstCameraSrc * camsrc)
1530 GstCameraSrcClass *bclass;
1531 GstBuffer *buf = NULL;
1532 GstStructure *msg_s = NULL;
1533 GstCaps *prvcaps = NULL;
1534 GstMessage *msg = NULL;
1535 gboolean ret = FALSE;
1537 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
1539 if (bclass->get_preview_image) {
1540 ret = bclass->get_preview_image (camsrc, &buf);
1544 GST_DEBUG_OBJECT (camsrc, "Sending preview image");
1545 prvcaps = gst_caps_new_simple ("video/x-raw-yuv",
1546 "format", GST_TYPE_FOURCC, camsrc->preview_fourcc,
1547 "width", G_TYPE_INT, camsrc->preview_w,
1548 "height", G_TYPE_INT, camsrc->preview_h,
1549 "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
1551 gst_buffer_set_caps (buf, prvcaps);
1553 /* Send custom preview image GstMessage */
1554 msg_s = gst_structure_new (GST_CAMERA_SRC_PREVIEW_IMAGE, "buffer",
1555 GST_TYPE_BUFFER, buf, NULL);
1557 msg = gst_message_new_element (GST_OBJECT (camsrc), msg_s);
1559 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
1560 GST_WARNING ("This element has no bus, therefore no message sent!");
1563 gst_caps_unref (prvcaps);
1565 GST_DEBUG_OBJECT (camsrc, "Retrieving preview image failed");
1568 /* if we still have valid settings for preview, reserve a new buffer */
1569 if (camsrc->preview_resolution_set) {
1570 GST_DEBUG_OBJECT (camsrc, "Reserving a new preview buffer");
1571 bclass->set_capture (camsrc, GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW, FALSE,
1572 &camsrc->preview_fourcc, &camsrc->preview_w, &camsrc->preview_h,
1577 gst_buffer_unref (buf);
1585 * gst_camerasrc_set_capture_caps:
1586 * @camerasrc: #GstCameraSrc object.
1588 * Set the capture caps on element's src pad.
1590 * Returns: TRUE on success.
1593 gst_camerasrc_set_capture_caps (GstCameraSrc * camerasrc)
1595 GstCameraSrcClass *bclass;
1596 GstCaps *newcaps = NULL;
1597 gboolean ret = TRUE;
1599 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1601 GST_DEBUG_OBJECT (camerasrc, "Calling set_capture()");
1603 /* Try what resolution the subclass can capture */
1604 ret = bclass->set_capture (camerasrc,
1605 GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE, TRUE,
1606 &camerasrc->capture_fourcc, &camerasrc->capture_w, &camerasrc->capture_h,
1607 &camerasrc->capture_fps_n, &camerasrc->capture_fps_d);
1613 /* FIXME: FPS definition should be removed from capture caps */
1614 newcaps = gst_camerasrc_get_caps_from_info (camerasrc,
1615 camerasrc->capture_fourcc, camerasrc->capture_w, camerasrc->capture_h,
1616 camerasrc->capture_fps_n, camerasrc->capture_fps_d);
1618 GST_DEBUG_OBJECT (camerasrc, "Set capture caps: %" GST_PTR_FORMAT, newcaps);
1620 /* Notify application that we are ready now. This must be called before */
1621 /* the set_caps() call below, since application needs to know the new caps */
1622 /* so that it can adjust the caps filter to accept new format before */
1623 /* srcpad caps are actually changed */
1624 gst_camerasrc_photo_ready_for_capture (camerasrc, newcaps);
1626 camerasrc->vf_caps =
1627 gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1629 /* This causes caps nego and switches resolution to hi-res mode */
1630 /* FIXME: Do we even need to set this? Application has already set the
1632 if (!gst_caps_is_equal (camerasrc->vf_caps, newcaps)) {
1633 GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps");
1634 ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), newcaps);
1635 GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps FINISHED");
1637 GST_DEBUG_OBJECT (camerasrc, "Forcing the re-initialization");
1638 ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1639 &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1640 &camerasrc->fps_d, newcaps);
1641 gst_caps_unref (camerasrc->vf_caps);
1642 camerasrc->vf_caps = NULL;
1645 gst_caps_unref (newcaps);
1657 gst_camerasrc_apply_timestamp (GstCameraSrc * camerasrc, GstBuffer * buf)
1660 GstClockTime timestamp;
1662 GST_OBJECT_LOCK (camerasrc);
1663 if ((clock = GST_ELEMENT_CLOCK (camerasrc))) {
1664 /* we have a clock, get base time and ref clock */
1665 timestamp = GST_ELEMENT (camerasrc)->base_time;
1666 gst_object_ref (clock);
1668 /* no clock, can't set timestamps */
1669 timestamp = GST_CLOCK_TIME_NONE;
1671 GST_OBJECT_UNLOCK (camerasrc);
1674 /* the time now is the time of the clock minus the base time */
1675 timestamp = gst_clock_get_time (clock) - timestamp;
1676 gst_object_unref (clock);
1678 if (timestamp > camerasrc->duration)
1679 timestamp -= camerasrc->duration;
1684 /* we could also use the timestamp from the buffer itself */
1685 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1686 GST_BUFFER_DURATION (buf) = camerasrc->duration;
1692 static GstFlowReturn
1693 gst_camerasrc_create (GstPushSrc * src, GstBuffer ** buf)
1695 GstCameraSrcClass *bclass;
1696 GstCameraSrc *camerasrc;
1697 GstBaseSrcClass *basesrc_class;
1699 GstBuffer *buf_cap_signal1 = NULL; /*output main buffer for capture signal*/
1701 gboolean still_capture_initialised = FALSE;
1702 GstFlowReturn ret = GST_FLOW_OK;
1705 camerasrc = GST_CAMERA_SRC_CAST (src);
1706 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1707 basesrc_class = GST_BASE_SRC_CLASS (bclass);
1709 if (camerasrc->req_negotiation) {
1710 GST_DEBUG_OBJECT(camerasrc, "negotiation start");
1711 basesrc_class->negotiate(GST_BASE_SRC(camerasrc));
1712 camerasrc->req_negotiation = FALSE;
1713 g_signal_emit(G_OBJECT(camerasrc), gst_camerasrc_signals[SIGNAL_NEGO_COMPLETE], (GQuark)NULL);
1714 GST_DEBUG_OBJECT (camerasrc, "negotiation stop");
1720 g_mutex_lock (camerasrc->state_lock);
1722 if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1723 /* Tell subclass to stop flushing buffers */
1724 if (bclass->unlock_stop) {
1725 GST_DEBUG_OBJECT (camerasrc, "Stop flushing, capture is starting");
1726 bclass->unlock_stop (camerasrc);
1729 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE;
1731 GST_DEBUG_OBJECT (camerasrc,
1732 "Flushing old buffers before starting HQ capture");
1733 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1734 gst_event_new_flush_start ());
1735 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1736 gst_event_new_flush_stop ());
1738 if (!gst_camerasrc_set_capture_caps (camerasrc)) {
1739 goto hq_capture_failed;
1741 still_capture_initialised = TRUE;
1744 else if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) {
1748 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1749 camerasrc->requested_af_mode = AF_OFF_REQUESTED;
1750 camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
1751 GST_DEBUG_OBJECT (camerasrc, "capture done. switching to viewfinder");
1753 /* Set the normal viewfinder resolution back */
1754 if (camerasrc->vf_caps) {
1755 GST_DEBUG_OBJECT (camerasrc, "set VF caps");
1756 ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), camerasrc->vf_caps);
1757 gst_caps_unref (camerasrc->vf_caps);
1758 camerasrc->vf_caps = NULL;
1762 tmp = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1764 /* Reconfigure the device to run viewfinder again */
1765 ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1766 &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1767 &camerasrc->fps_d, tmp);
1769 gst_caps_unref (tmp);
1773 GST_WARNING_OBJECT (camerasrc, "Reinitializing viewfinder failed");
1774 g_mutex_unlock (camerasrc->state_lock);
1775 return GST_FLOW_ERROR;
1778 GST_DEBUG_OBJECT (camerasrc, "viewfinder running");
1781 g_mutex_lock (camerasrc->af_lock);
1783 /* Handle AF requests only in VIEWFINDER and AUTOFOCUS states */
1784 if ((camerasrc->photo_capture_phase == GST_CAMERA_VIEWFINDER ||
1785 camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS ||
1786 camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS_DONE) &&
1787 camerasrc->requested_af_mode != AF_NONE_REQUESTED) {
1788 if (camerasrc->requested_af_mode == AF_ON_REQUESTED) {
1791 /* In still capture mode AE will be locked during AF operation */
1792 if (camerasrc->viewfinder_mode == GST_CAMERA_SRC_VIEWFINDER_MODE_STILL) {
1793 bclass->set_autoexposure (camerasrc, FALSE);
1795 ret = bclass->set_autofocus (camerasrc, TRUE);
1798 camerasrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS;
1800 /* Starting AF failed, so start AE again */
1801 bclass->set_autoexposure (camerasrc, TRUE);
1804 bclass->set_autofocus (camerasrc, FALSE);
1805 bclass->set_autoexposure (camerasrc, TRUE);
1806 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1809 camerasrc->requested_af_mode = AF_NONE_REQUESTED;
1812 g_mutex_unlock (camerasrc->af_lock);
1813 g_mutex_unlock (camerasrc->state_lock);
1815 ret = bclass->grab_frame (camerasrc, &temp, camerasrc->photo_capture_phase);
1817 g_mutex_lock (camerasrc->state_lock);
1819 if (ret != GST_FLOW_OK) {
1820 /* _prepare_for_capture() may have interrupted frame grabbing. */
1821 if (ret == GST_FLOW_WRONG_STATE &&
1822 camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1823 g_mutex_unlock (camerasrc->state_lock);
1827 g_mutex_unlock (camerasrc->state_lock);
1834 /* Post-capture phase */
1836 if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE) {
1839 src_caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1840 gst_buffer_set_caps (*buf, src_caps);
1841 gst_caps_unref (src_caps);
1843 /* Restore the original number of buffers after capture is done */
1844 /* FIXME: Commented out */
1845 // camerasrc->num_buffers = tmp_num_buffers;
1847 // gst_camerasrc_send_image_tags (camerasrc);
1849 gst_camerasrc_send_preview (camerasrc);
1851 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1854 if(GST_CAMERA_SRC_CAPTURE_MODE_STILL == camerasrc->capture_mode) {
1855 gst_camerasrc_send_image_tags (camerasrc);
1856 if ((camerasrc->signal_still_capture == TRUE) && (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) && (still_capture_initialised == TRUE)) {
1857 still_capture_initialised = FALSE;
1859 /* alloc buffer for capture callback */
1860 buf_cap_signal1 = gst_buffer_new ();
1862 GST_BUFFER_DATA(buf_cap_signal1) = GST_BUFFER_DATA(*buf);
1863 GST_BUFFER_SIZE(buf_cap_signal1) = GST_BUFFER_SIZE(*buf);
1864 GST_BUFFER_CAPS(buf_cap_signal1) = gst_caps_new_simple("video/x-raw-yuv",
1865 "format", GST_TYPE_FOURCC, camerasrc->capture_fourcc,
1866 "width", G_TYPE_INT, camerasrc->capture_w,
1867 "height", G_TYPE_INT,camerasrc->capture_h,
1870 GST_LOG_OBJECT (camerasrc, "CALL: capture callback");
1871 g_mutex_unlock (camerasrc->state_lock);
1872 g_signal_emit( G_OBJECT (camerasrc),
1873 gst_camerasrc_signals[SIGNAL_STILL_CAPTURE],
1878 GST_LOG_OBJECT (camerasrc, "RETURN: capture callback");
1879 g_mutex_lock (camerasrc->state_lock);
1882 if(--camerasrc->capture_counter > 0) {
1883 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_START;
1884 GST_DEBUG_OBJECT (camerasrc, "do some more captures count %d",camerasrc->capture_counter);
1887 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1889 g_mutex_unlock (camerasrc->state_lock);
1894 if (GST_BUFFER_TIMESTAMP (*buf) == GST_CLOCK_TIME_NONE) {
1895 gst_camerasrc_apply_timestamp (camerasrc, *buf);
1900 g_mutex_unlock (camerasrc->state_lock);
1907 GST_ELEMENT_ERROR (camerasrc, RESOURCE, READ,
1908 ("Error during HQ capture"), (NULL));
1909 ret = GST_FLOW_ERROR;
1914 static GstStateChangeReturn
1915 gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
1917 GstCameraSrcClass *bclass;
1918 GstCameraSrc *camerasrc;
1919 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1921 camerasrc = GST_CAMERA_SRC_CAST (element);
1922 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1924 GST_LOG_OBJECT (camerasrc, "State change: %s -> %s",
1925 gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1926 gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
1928 switch (transition) {
1929 case GST_STATE_CHANGE_NULL_TO_READY:
1930 /* Open the device */
1931 if (!bclass->open (camerasrc))
1932 return GST_STATE_CHANGE_FAILURE;
1938 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1940 switch (transition) {
1941 case GST_STATE_CHANGE_READY_TO_NULL:
1942 if (bclass->is_open (camerasrc)) {
1943 bclass->close (camerasrc);
1945 camerasrc->capture_w = camerasrc->preview_w = camerasrc->current_w = 0;
1946 camerasrc->capture_h = camerasrc->preview_h = camerasrc->current_h = 0;
1947 camerasrc->capture_fourcc = camerasrc->preview_fourcc = 0;
1948 camerasrc->current_fourcc = 0;
1949 camerasrc->fps_d = camerasrc->fps_n = 0;
1950 camerasrc->capture_resolution_set = FALSE;
1951 camerasrc->preview_resolution_set = FALSE;
1953 /* Notify that preview caps have changed (to NULL) */
1954 g_object_notify (G_OBJECT (camerasrc),
1955 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
1967 * gst_camerasrc_add_color_channel:
1968 * @camsrc: #GstCameraSrc object.
1969 * @channel: #GstColorBalanceChannel object.
1971 * Add a new color channel to list.
1974 gst_camerasrc_add_color_channel (GstCameraSrc * camsrc,
1975 GstColorBalanceChannel * channel)
1977 camsrc->colors = g_list_append (camsrc->colors, (gpointer) channel);
1982 * gst_camerasrc_clear_color_channels:
1983 * @camsrc: #GstCameraSrc object.
1985 * Delete all color channels.
1988 gst_camerasrc_clear_color_channels (GstCameraSrc * camsrc)
1990 g_list_foreach (camsrc->colors, (GFunc) g_object_unref, NULL);
1991 g_list_free (camsrc->colors);
1992 camsrc->colors = NULL;
1996 * gst_camerasrc_add_cameracontrol_channel:
1997 * @camsrc: #GstCameraSrc object.
1998 * @channel: #GstColorBalanceChannel object.
2000 * Add a new cameracontrol channel to list.
2003 gst_camerasrc_add_cameracontrol_channel (GstCameraSrc * camsrc,
2004 GstCameraControlChannel * channel)
2006 camsrc->camera_controls = g_list_append (camsrc->camera_controls, (gpointer) channel);
2010 * gst_camerasrc_clear_cameracontrol_channels:
2011 * @camsrc: #GstCameraSrc object.
2013 * Delete all cameracontrol channels.
2017 gst_camerasrc_clear_cameracontrol_channels (GstCameraSrc * camsrc)
2019 g_list_foreach (camsrc->camera_controls, (GFunc) g_object_unref, NULL);
2020 g_list_free (camsrc->camera_controls);
2021 camsrc->camera_controls = NULL;
2025 * gst_camerasrc_send_capture_start_message:
2026 * @camsrc: GstCameraSrc object
2028 * Sends a GstMessage notification to GstBus that capture operation is
2032 gst_camerasrc_send_capture_start_message (GstCameraSrc * camsrc)
2037 GST_DEBUG_OBJECT (camsrc, "Sending capture-start message");
2039 /* Send custom GstMessage "photo-capture-start" */
2040 s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_START, NULL);
2041 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2043 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2044 GST_WARNING ("This element has no bus, therefore no message sent!");
2047 GST_LOG_OBJECT (camsrc, "Capture-start message sent");
2052 * gst_camerasrc_send_capture_stop_message:
2053 * @camsrc: GstCameraSrc object
2055 * Sends a GstMessage notification to GstBus that capture operation has
2059 gst_camerasrc_send_capture_stop_message (GstCameraSrc * camsrc)
2064 GST_DEBUG_OBJECT (camsrc, "Sending capture-stop message");
2066 /* Send custom GstMessage "photo-capture-end" */
2067 s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_END, NULL);
2068 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2070 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2071 GST_WARNING ("This element has no bus, therefore no message sent!");
2074 GST_LOG_OBJECT (camsrc, "Capture-stop message sent");
2079 * gst_camerasrc_af_update:
2080 * @camsrc: #GstCameraSrc object.
2081 * @fs: #GstCameraFocusStatus structure. Owned by caller.
2083 * Tell GstCameraSrc that previously started autofocus operation has finished.
2086 gst_camerasrc_af_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2088 GstCameraSrcClass *bclass;
2090 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
2092 g_mutex_lock (camsrc->state_lock);
2093 g_mutex_lock (camsrc->af_lock);
2095 if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS ||
2096 fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL) {
2100 GST_DEBUG_OBJECT (camsrc, "autofocusing ended");
2102 /* Send custom GstMessage "autofocus-done" */
2103 s = gst_structure_new (GST_PHOTOGRAPHY_AUTOFOCUS_DONE,
2104 "status", G_TYPE_INT, fs->status, NULL);
2106 /* If autofocus succeeded, send the bitmask that defines focused
2108 if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS) {
2112 windows = g_array_new (FALSE, FALSE, sizeof (gint));
2113 for (i = 0; i < fs->num_windows; i++) {
2114 GST_DEBUG_OBJECT (camsrc, "focus window: %d", fs->windows[i]);
2115 g_array_append_val (windows, fs->windows[i]);
2118 gst_structure_set (s,
2119 //"focus-windows", G_TYPE_ARRAY, windows,
2120 "focus-window-rows", G_TYPE_INT, fs->focus_rows,
2121 "focus-window-columns", G_TYPE_INT, fs->focus_columns,
2122 "focus-window-coverage", G_TYPE_INT, fs->coverage, NULL);
2124 GST_DEBUG_OBJECT (camsrc, "focus rows: %d", fs->focus_rows);
2125 GST_DEBUG_OBJECT (camsrc, "focus columns: %d", fs->focus_columns);
2126 GST_DEBUG_OBJECT (camsrc, "focus coverage: %d", fs->coverage);
2129 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2131 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2132 GST_WARNING ("This element has no bus, therefore no message sent!");
2135 /* In still capture mode we don't turn off AF algorithm yet, since it */
2136 /* would enable CAF. Instead, it is turned off when application */
2137 /* explicitly calls set_autofocus (FALSE), which in turn raises */
2138 /* af_requested = OFF flag and AF is finally stopped. */
2140 /* In video capture mode AF will be stopped immediately to enable AE */
2141 if (camsrc->viewfinder_mode == GST_CAMERA_SRC_VIEWFINDER_MODE_VIDEO) {
2142 bclass->set_autofocus (camsrc, FALSE);
2145 /* We don't turn on autoexposure here either. This way AE stays */
2146 /* "locked" until application explicitly calls set_autofocus (FALSE). */
2148 camsrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS_DONE;
2151 g_mutex_unlock (camsrc->af_lock);
2152 g_mutex_unlock (camsrc->state_lock);
2157 * gst_camerasrc_caf_update:
2158 * @camsrc: GstCameraSrc object.
2159 * @fs: #GstCameraFocusStatus structure. Owned by caller.
2161 * Tell GstCameraSrc that continuous autofocus algorithm has changed its state.
2162 * Sends a GstMessage notification to GstBus indicating a change in
2163 * continuous autofocus status.
2166 gst_camerasrc_caf_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2171 GST_DEBUG_OBJECT (camsrc, "Sending CAF status: %d", fs->status);
2173 /* Send custom GstMessage "caf-update" */
2174 s = gst_structure_new (GST_CAMERA_SRC_CAF_STATUS, NULL);
2175 gst_structure_set (s, "status", G_TYPE_INT, fs->status, NULL);
2176 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2178 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2179 GST_WARNING ("This element has no bus, therefore no message sent!");
2182 GST_LOG_OBJECT (camsrc, "CAF update message sent");
2187 * gst_camerasrc_shake_update:
2188 * @camsrc: GstCameraSrc object.
2189 * @risk: GstPhotoShakeRisk value.
2191 * Tell GstCameraSrc that shake risk has changed. Sends a GstMessage
2192 * notification to GstBus indicating a change in shake risk status.
2195 gst_camerasrc_shake_update (GstCameraSrc * camsrc, GstPhotoShakeRisk risk)
2200 GST_DEBUG_OBJECT (camsrc, "Sending shake risk update: %d", risk);
2202 /* Send custom GstMessage telling the changed shake risk level */
2203 s = gst_structure_new (GST_PHOTOGRAPHY_SHAKE_RISK, NULL);
2204 gst_structure_set (s, "shake_risk", G_TYPE_INT, risk, NULL);
2205 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2207 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2208 GST_WARNING ("This element has no bus, therefore no message sent!");
2211 GST_LOG_OBJECT (camsrc, "Shake indicator message sent");
2215 /* Tag helper functions */
2218 * gst_camerasrc_exposure_mode_from_exif_value:
2219 * @value: exposure mode in EXIF format.
2221 * Convert exposure mode to string.
2223 * Returns: String representation of the scene capture type, or NULL if invalid
2224 * value was given. Possible values: "auto-exposure", "manual-exposure" and
2228 gst_camerasrc_exposure_mode_from_exif_value (gint value)
2232 return "auto-exposure";
2234 return "manual-exposure";
2236 return "auto-bracket";
2238 GST_WARNING ("Invalid exif exposure mode: %d", value);
2244 * gst_camerasrc_scene_capture_type_from_exif_value:
2245 * @value: scene capture type in EXIF format.
2247 * Convert scene capture type to string.
2249 * Returns: String representation of the scene capture type, or NULL if invalid
2250 * value was given. Possible values: "standard", "landscape", "portrait" and
2254 gst_camerasrc_scene_capture_type_from_exif_value (gint value)
2264 return "night-scene";
2266 GST_WARNING ("Invalid exif scene capture type: %d", value);
2273 * gst_camerasrc_gain_adjustment_from_exif_value:
2274 * @value: gain adjustment type in EXIF format.
2276 * Convert gain adjustment type to string.
2278 * Returns: String representation of the gain adjustment type, or NULL if
2279 * invalid value was given. Possible values: "none", "low-gain-up",
2280 * "high-gain-up", "low-gain-down" and "high-gain-down".
2283 gst_camerasrc_gain_adjustment_from_exif_value (gint value)
2289 return "low-gain-up";
2291 return "high-gain-up";
2293 return "low-gain-down";
2295 return "high-gain-down";
2297 GST_WARNING ("Invalid exif gain control type: %d", value);
2304 * gst_camerasrc_contrast_from_exif_value:
2305 * @value: contrast type in EXIF format.
2307 * Convert contrast type to string.
2309 * Returns: String representation of the contrast type, or NULL if invalid
2310 * value was given. Possible values: "normal", "soft" and "hard".
2313 gst_camerasrc_contrast_from_exif_value (gint value)
2323 GST_WARNING ("Invalid contrast type: %d", value);
2330 * gst_camerasrc_saturation_from_exif_value:
2331 * @value: saturation type in EXIF format.
2333 * Convert saturation type to string.
2335 * Returns: String representation of the saturation type, or NULL if invalid
2336 * value was given. Possible values: "normal", "low-saturation" and
2337 * "high-saturation".
2340 gst_camerasrc_saturation_from_exif_value (gint value)
2346 return "low-saturation";
2348 return "high-saturation";
2350 GST_WARNING ("Invalid saturation type: %d", value);
2357 * gst_camerasrc_flash_mode_from_exif_value:
2358 * @value: flash EXIF field
2360 * Convert "flash" EXIF field into text string.
2362 * Returns: String representation of the flash mode, or NULL if invalid
2363 * value was given. Possible values: "always", "never" and "auto".
2366 gst_camerasrc_flash_mode_from_exif_value (gint value)
2370 // bits 3 and 4 indicate the flash mode,
2372 // Values for bits 3 and 4 indicating the camera's flash mode.
2374 // 01b = Compulsory flash firing
2375 // 10b = Compulsory flash suppression
2379 /* Bit numbering in EXIF spec starts from 0 */
2382 switch (value & 0x3) {
2390 GST_WARNING ("Invalid flash mode type: %d", value);
2397 * gst_camerasrc_sharpness_from_exif_value:
2398 * @value: sharpness type in EXIF format.
2400 * Convert sharpness type to string.
2402 * Returns: String representation of the sharpness type, or NULL if invalid
2403 * value was given. Possible values: "normal", "soft" and "hard".
2406 gst_camerasrc_sharpness_from_exif_value (gint value)
2416 GST_WARNING ("Invalid sharpness type: %d", value);
2423 * gst_camerasrc_metering_mode_from_exif_value:
2424 * @value: metering mode type in EXIF format.
2426 * Convert metering mode type to string.
2428 * Returns: String representation of the metering mode type, or NULL if invalid
2429 * value was given. Possible values: "unknown", "average",
2430 * "center-weighted-average", "spot", "multi-spot", "pattern", "partial" and
2434 gst_camerasrc_metering_mode_from_exif_value (gint value)
2442 return "center-weighted-average";
2446 return "multi-spot";
2454 GST_WARNING ("Invalid metering mode type: %d", value);
2461 * gst_camerasrc_file_source_from_exif_value:
2462 * @value: FileSource type in EXIF format.
2464 * Convert FileSource type to string.
2466 * Returns: String representation of the FileSource type, or NULL if invalid
2467 * value was given. Possible values: "dsc", "transparent-scanner",
2468 * "reflex-scanner" and "other".
2471 gst_camerasrc_file_source_from_exif_value (gint value)
2477 return "transparent-scanner";
2479 return "reflex-scanner";
2483 GST_WARNING ("Invalid file source type: %d", value);
2489 /* Default implementations for vmethods */
2492 gst_camerasrc_default_capabilities (GstCameraSrc * camsrc)
2494 return GST_PHOTOGRAPHY_CAPS_NONE;
2498 gst_camerasrc_default_ret_true_with_settings (GstCameraSrc * camsrc,
2499 GstPhotoSettings * photoconf)
2505 gst_camerasrc_default_write_settings (GstCameraSrc * camsrc,
2506 GstPhotoSettings * photoconf, gboolean scene_mode_override)
2512 gst_camerasrc_default_set_onoff (GstCameraSrc * camsrc, gboolean on_off)
2518 gst_camerasrc_default_get_caps (GstCameraSrc * camsrc, GstOperationMode mode)
2520 GST_DEBUG_OBJECT (camsrc, "Returning NULL caps for mode %d", mode);
2525 gst_camerasrc_default_read_exif (GstCameraSrc *camsrc,
2526 GstCameraControlExifInfo *exif_info)
2528 GST_DEBUG_OBJECT (camsrc, "default implementation of exif read called return defaults %d");
2529 // TODO: fill with default values
2534 gst_camerasrc_default_set_flash_mode (GstCameraSrc *camsrc, int value)
2540 gst_camerasrc_default_functions_init (GstCameraSrcClass * camera_class)
2542 camera_class->get_capabilities = gst_camerasrc_default_capabilities;
2543 camera_class->set_autofocus = gst_camerasrc_default_set_onoff;
2544 camera_class->set_autoexposure = gst_camerasrc_default_set_onoff;
2545 camera_class->read_settings = gst_camerasrc_default_ret_true_with_settings;
2546 camera_class->write_settings = gst_camerasrc_default_write_settings;
2547 camera_class->get_supported_caps = gst_camerasrc_default_get_caps;
2548 camera_class->set_flash_mode = gst_camerasrc_default_set_flash_mode;
2549 camera_class->read_exif = gst_camerasrc_default_read_exif;
2551 GST_DEBUG ("Default functions set");
2556 gst_camerasrc_handle_event (GstCameraSrc * camerasrc, GstEvent * event)
2558 GstCameraSrcClass *bclass;
2559 gboolean ret = FALSE;
2561 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2562 GST_LOG_OBJECT (camerasrc, "handling %s event", GST_EVENT_TYPE_NAME (event));
2564 if (bclass->event) {
2565 ret = bclass->event (camerasrc, event);
2573 * gst_camerasrc_send_event:
2574 * @element: GstElement object.
2575 * @event: GstEvent to be handled.
2577 * Returns: TRUE if the event was handled.
2580 gst_camerasrc_send_event (GstElement * element, GstEvent * event)
2582 GstCameraSrc *camerasrc;
2583 gboolean ret = FALSE;
2585 camerasrc = GST_CAMERA_SRC_CAST (element);
2587 GST_LOG_OBJECT (camerasrc, "got %s event", GST_EVENT_TYPE_NAME (event));
2589 switch (GST_EVENT_TYPE (event)) {
2590 case GST_EVENT_CUSTOM_UPSTREAM:
2591 ret = gst_camerasrc_handle_event (camerasrc, event);
2598 ret = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
2606 * gst_camerasrc_event:
2607 * @src: #GstBaseSrc object.
2608 * @event: #GetEvent object.
2610 * Returns: TRUE of the event was handled.
2613 gst_camerasrc_event (GstBaseSrc * src, GstEvent * event)
2615 GstCameraSrc *camerasrc;
2618 camerasrc = GST_CAMERA_SRC_CAST (src);
2619 ret = gst_camerasrc_handle_event (camerasrc, event);
2622 ret = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
2630 * gst_camerasrc_update_max_zoom:
2631 * @camerasrc: #GstCameraSrc object.
2633 * Check and update zoom property maximum value.
2636 gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc)
2638 GstCameraSrcClass *bclass;
2639 GObjectClass *oclass;
2641 GParamSpecFloat *pspec_f;
2642 gfloat maxzoom = 10.0;
2644 oclass = G_OBJECT_GET_CLASS (camerasrc);
2645 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2646 pspec = g_object_class_find_property (oclass, "zoom");
2648 if (bclass->get_max_zoom) {
2649 if (!bclass->get_max_zoom (camerasrc, &maxzoom)) {
2654 /* Update gobject property */
2655 if (pspec && (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_FLOAT)) {
2656 pspec_f = G_PARAM_SPEC_FLOAT (pspec);
2657 pspec_f->maximum = maxzoom;
2658 GST_DEBUG_OBJECT (camerasrc, "set maximum zoom as %f", pspec_f->maximum);
2659 /* Check if new maximum zoom is lower than current zoom level */
2660 if (pspec_f->maximum < camerasrc->photoconf.zoom) {
2661 GST_DEBUG_OBJECT (camerasrc, "current zoom level too high: %f",
2662 camerasrc->photoconf.zoom);
2663 g_object_set (G_OBJECT (camerasrc), "zoom", pspec_f->maximum, NULL);
2666 GST_WARNING_OBJECT (camerasrc, "updating maximum zoom failed");