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);
893 if (gst_structure_has_name(structure, "video/x-vaapi-sharing")) {
895 gst_structure_get_int(structure, "width", &stride);
896 /* row stride need width aligned to 32*/
897 stride = ((stride+31)&(~31));
898 gst_structure_set (structure, "row-stride", G_TYPE_INT, stride, NULL);
902 GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
908 gst_camerasrc_negotiate (GstBaseSrc * basesrc)
912 GstCaps *caps = NULL;
914 GstCaps *peercaps = NULL;
916 gboolean result = FALSE;
918 /* first see what is possible on our source pad */
919 thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
920 GST_DEBUG_OBJECT (basesrc, "caps of src suppressed on DEBUG (>= 5 to see)");
921 GST_LOG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
922 /* nothing or anything is allowed, we're done */
923 if (thiscaps == NULL || gst_caps_is_any (thiscaps))
926 /* get the peer caps */
927 peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
928 GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
929 if (peercaps && !gst_caps_is_any (peercaps)) {
930 GstCaps *icaps = NULL;
933 /* Prefer the first caps we are compatible with that the peer proposed */
934 for (i = 0; i < gst_caps_get_size (peercaps); i++) {
935 /* get intersection */
936 GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
938 GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
940 icaps = gst_caps_intersect (thiscaps, ipcaps);
941 gst_caps_unref (ipcaps);
943 if (!gst_caps_is_empty (icaps))
946 gst_caps_unref (icaps);
950 GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
952 /* If there are multiple intersections pick the one with the smallest
953 * resolution strictly bigger then the first peer caps */
954 if (gst_caps_get_size (icaps) > 1) {
955 GstStructure *s = gst_caps_get_structure (peercaps, 0);
961 int width = G_MAXINT, height = G_MAXINT;
963 if (gst_structure_get_int (s, "width", &twidth)
964 && gst_structure_get_int (s, "height", &theight)) {
966 /* Walk the structure backwards to get the first entry of the
967 * smallest resolution bigger (or equal to) the preferred resolution)
969 for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
970 GstStructure *is = gst_caps_get_structure (icaps, i);
974 if (gst_structure_get_int (is, "width", &w)
975 && gst_structure_get_int (is, "height", &h)) {
976 if (w >= twidth && w <= width && h >= theight && h <= height) {
985 caps = gst_caps_copy_nth (icaps, best);
986 gst_caps_unref (icaps);
991 gst_caps_unref (thiscaps);
992 gst_caps_unref (peercaps);
994 /* no peer or peer have ANY caps, work with our own caps then */
998 caps = gst_caps_make_writable (caps);
999 gst_caps_truncate (caps);
1002 if (!gst_caps_is_empty (caps)) {
1003 GstStructure *s = gst_caps_get_structure (caps, 0);
1004 /* set row-stride for vaapi-sharing */
1005 if (s && gst_structure_has_name(s, "video/x-vaapi-sharing")) {
1006 if (!gst_structure_has_field(s, "row-stride")) {
1007 gst_structure_set (s, "row-stride", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1010 gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
1011 GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
1013 if (gst_caps_is_any (caps)) {
1014 /* hmm, still anything, so element can do anything and
1015 * nego is not needed */
1017 } else if (gst_caps_is_fixed (caps)) {
1018 /* yay, fixed caps, use those then */
1019 result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
1020 GST_DEBUG_OBJECT (basesrc, "Set caps returned: %d", result);
1023 gst_caps_unref (caps);
1029 GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
1031 gst_caps_unref (thiscaps);
1040 gst_camerasrc_get_caps (GstBaseSrc * src)
1042 GstCameraSrc *camerasrc;
1043 GstCameraSrcClass *bclass;
1045 camerasrc = GST_CAMERA_SRC_CAST (src);
1046 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1048 if (!bclass->is_open (camerasrc) || !bclass->get_caps) {
1049 return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
1053 return bclass->get_caps (camerasrc);
1058 * gst_camerasrc_get_caps_info:
1059 * @caps: given input caps
1060 * @four_cc: location for the fourcc
1061 * @w/@h: location for width and height
1062 * @fps_n/@fps_d: location for framerate
1064 * Collect data for the given caps.
1067 gst_camerasrc_get_caps_info (GstCameraSrc * camerasrc, GstCaps * caps,
1068 guint32 * four_cc, guint * w, guint * h, guint * fps_n, guint * fps_d,
1071 GstCameraSrcClass *bclass;
1072 GstStructure *structure;
1073 const GValue *framerate;
1074 const gchar *mimetype;
1078 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1080 /* default unknown values */
1084 structure = gst_caps_get_structure (caps, 0);
1086 mimetype = gst_structure_get_name (structure);
1088 if (!gst_structure_get_int (structure, "width", (gint *) w))
1091 if (!gst_structure_get_int (structure, "height", (gint *) h))
1094 framerate = gst_structure_get_value (structure, "framerate");
1098 *fps_n = gst_value_get_fraction_numerator (framerate);
1099 *fps_d = gst_value_get_fraction_denominator (framerate);
1101 if (!strcmp (mimetype, "video/x-vaapi-sharing")) {
1102 fourcc = V4L2_PIX_FMT_NV12;
1103 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1104 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1105 } else if (!strcmp (mimetype, "video/x-raw-yuv")) {
1106 gst_structure_get_fourcc (structure, "format", &fourcc);
1109 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1110 case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
1111 fourcc = V4L2_PIX_FMT_YUV420;
1112 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1113 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1115 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1116 fourcc = V4L2_PIX_FMT_YUYV;
1117 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1119 case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
1120 fourcc = V4L2_PIX_FMT_Y41P;
1121 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1123 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1124 fourcc = V4L2_PIX_FMT_UYVY;
1125 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1127 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1128 fourcc = V4L2_PIX_FMT_YVU420;
1129 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1130 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1132 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
1133 fourcc = V4L2_PIX_FMT_YUV411P;
1134 outsize = GST_ROUND_UP_4 (*w) * *h;
1135 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1137 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
1138 fourcc = V4L2_PIX_FMT_YUV422P;
1139 outsize = GST_ROUND_UP_4 (*w) * *h;
1140 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1142 case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1143 fourcc = V4L2_PIX_FMT_NV12;
1144 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1145 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1147 case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1148 fourcc = V4L2_PIX_FMT_NV21;
1149 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1150 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1152 #ifdef V4L2_PIX_FMT_YVYU
1153 case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
1154 fourcc = V4L2_PIX_FMT_YVYU;
1155 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1159 } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
1160 gint depth, endianness, r_mask;
1162 gst_structure_get_int (structure, "depth", &depth);
1163 gst_structure_get_int (structure, "endianness", &endianness);
1164 gst_structure_get_int (structure, "red_mask", &r_mask);
1168 fourcc = V4L2_PIX_FMT_RGB332;
1171 fourcc = (endianness == G_LITTLE_ENDIAN) ?
1172 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
1175 fourcc = (endianness == G_LITTLE_ENDIAN) ?
1176 V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
1179 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
1182 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
1185 } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
1186 gst_structure_get_fourcc (structure, "format", &fourcc);
1188 case GST_MAKE_FOURCC ('B', 'A', '8', '1'):
1189 fourcc = V4L2_PIX_FMT_SBGGR8;
1191 case GST_MAKE_FOURCC ('G', 'B', 'R', 'G'):
1192 fourcc = V4L2_PIX_FMT_SGBRG8;
1194 case GST_MAKE_FOURCC ('G', 'R', 'B', 'G'):
1195 fourcc = V4L2_PIX_FMT_SGRBG8;
1197 case GST_MAKE_FOURCC ('R', 'G', 'G', 'B'):
1198 fourcc = V4L2_PIX_FMT_SRGGB8;
1200 case GST_MAKE_FOURCC ('B', 'G', '1', '0'):
1201 fourcc = V4L2_PIX_FMT_SBGGR10;
1203 case GST_MAKE_FOURCC ('G', 'B', '1', '0'):
1204 fourcc = V4L2_PIX_FMT_SGBRG10;
1206 case GST_MAKE_FOURCC ('B', 'A', '1', '0'):
1207 fourcc = V4L2_PIX_FMT_SGRBG10;
1209 case GST_MAKE_FOURCC ('R', 'G', '1', '0'):
1210 fourcc = V4L2_PIX_FMT_SRGGB10;
1212 case GST_MAKE_FOURCC ('B', 'Y', 'R', '2'):
1213 fourcc = V4L2_PIX_FMT_SBGGR16;
1216 } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
1217 fourcc = V4L2_PIX_FMT_GREY;
1230 * gst_camerasrc_get_caps_from_info:
1231 * @camsrc: #GstCameraSrc object
1232 * @fourcc: fourcc code
1233 * @width: width to be set
1234 * @height: height to be set
1235 * @fps_n: FPS numerator to be set or 0
1236 * @fps_d: FPS denominator to be set or 0
1238 * Converts given parameters into GstCaps structure.
1240 * Returns: GstCaps representing the given values.
1243 gst_camerasrc_get_caps_from_info (GstCameraSrc * camsrc, guint32 fourcc,
1244 guint width, guint height, guint fps_n, guint fps_d)
1249 s = gst_structure_new ("video/x-raw-yuv",
1250 "format", GST_TYPE_FOURCC, fourcc,
1251 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
1253 if (fps_n != 0 && fps_d != 0) {
1254 gst_structure_set (s, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
1257 newcaps = gst_caps_new_empty ();
1258 gst_caps_append_structure (newcaps, s);
1267 gst_camerasrc_configure_device (GstCameraSrc * camerasrc, guint * w, guint * h,
1268 guint32 * fourcc, guint * fps_n, guint * fps_d, GstCaps * buffer_caps)
1270 GstCameraSrcClass *bclass;
1271 GstOperationMode opmode;
1273 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1275 /* Stop the capturing */
1276 if (!bclass->stop (camerasrc))
1279 GST_DEBUG_OBJECT (camerasrc, "trying to set_capture %dx%d at %d/%d fps",
1280 *w, *h, *fps_n, *fps_d);
1282 if (bclass->set_vfinder_mode) {
1283 bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
1285 if (bclass->set_capture_mode) {
1286 bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
1289 opmode = camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE ?
1290 GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE :
1291 GST_PHOTOGRAPHY_OPERATION_MODE_VIEWFINDER;
1293 if (!bclass->set_capture (camerasrc, opmode, FALSE, fourcc, w, h,
1295 GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1296 ("Failed configuring device for capturing"), (NULL));
1300 gst_camerasrc_update_max_zoom (camerasrc);
1302 /* Only start the driver when not in HQ capture mode, since in HQ mode */
1303 /* we have already called start_capture() above */
1305 if (!bclass->start (camerasrc, buffer_caps))
1308 if (camerasrc->photo_capture_phase != GST_CAMERA_CAPTURE) {
1310 if (!bclass->write_settings (camerasrc, &camerasrc->photoconf, FALSE)) {
1311 GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1312 ("Failed to configure driver module"), (NULL));
1325 gst_camerasrc_init_from_caps (GstCameraSrc * camerasrc, GstCaps * caps)
1333 /* we want our own type of fourcc codes */
1334 if (!gst_camerasrc_get_caps_info (camerasrc, caps, &fourcc, &w, &h, &fps_n,
1336 GST_DEBUG_OBJECT (camerasrc,
1337 "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1341 ret = gst_camerasrc_configure_device (camerasrc, &w, &h, &fourcc,
1342 &fps_n, &fps_d, caps);
1345 camerasrc->current_w = w;
1346 camerasrc->current_h = h;
1347 camerasrc->fps_n = fps_n;
1348 camerasrc->fps_d = fps_d;
1349 camerasrc->current_fourcc = fourcc;
1351 camerasrc->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
1352 GST_DEBUG_OBJECT (camerasrc, "Buffer duration: %" GST_TIME_FORMAT,
1353 GST_TIME_ARGS (camerasrc->duration));
1355 // camerasrc->frame_byte_size = size;
1364 gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps)
1366 GstCameraSrc *camerasrc;
1367 GstCameraSrcClass *bclass;
1369 camerasrc = GST_CAMERA_SRC_CAST (src);
1370 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1372 GST_DEBUG_OBJECT (camerasrc, "set_caps called: %" GST_PTR_FORMAT, caps);
1374 /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1375 if (!bclass->is_open (camerasrc))
1378 return gst_camerasrc_init_from_caps (camerasrc, caps);
1384 gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query)
1387 GstCameraSrcClass *bclass;
1388 gboolean res = FALSE;
1391 src = GST_CAMERA_SRC_CAST (bsrc);
1392 bclass = GST_CAMERA_SRC_GET_CLASS (src);
1394 switch (GST_QUERY_TYPE (query)) {
1395 case GST_QUERY_LATENCY:{
1396 GstClockTime max_latency;
1398 /* device must be open */
1399 if (!bclass->is_open (src)) {
1400 GST_WARNING_OBJECT (src,
1401 "Can't give latency since device isn't open !");
1405 /* we must have a framerate */
1406 if (src->fps_n <= 0 || src->fps_d <= 0) {
1407 GST_WARNING_OBJECT (src,
1408 "Can't give latency since framerate isn't fixated !");
1412 num_buffers = bclass->get_num_buffers (src);
1413 /* max latency is total duration of the frame buffer */
1414 max_latency = num_buffers * src->duration;
1416 GST_DEBUG_OBJECT (bsrc,
1417 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1418 GST_TIME_ARGS (src->duration), GST_TIME_ARGS (max_latency));
1420 /* we are always live, the min latency is 1 frame and the max latency is
1421 * the complete buffer of frames. */
1422 gst_query_set_latency (query, TRUE, src->duration, max_latency);
1428 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1438 gst_camerasrc_start (GstBaseSrc * src)
1440 // GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (src);
1448 gst_camerasrc_stop (GstBaseSrc * src)
1450 GstCameraSrc *camerasrc;
1451 GstCameraSrcClass *bclass;
1453 camerasrc = GST_CAMERA_SRC_CAST (src);
1454 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1456 GST_DEBUG_OBJECT (camerasrc, "Stopping");
1458 bclass->stop (camerasrc);
1460 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1466 gst_camerasrc_unlock (GstBaseSrc * src)
1468 GstCameraSrcClass *pclass;
1469 GstCameraSrc *camerasrc;
1470 gboolean ret = TRUE;
1472 camerasrc = GST_CAMERA_SRC_CAST (src);
1473 pclass = GST_CAMERA_SRC_GET_CLASS (src);
1475 GST_DEBUG_OBJECT (camerasrc, "Unlock");
1478 ret = pclass->unlock (camerasrc);
1484 gst_camerasrc_unlock_stop (GstBaseSrc * src)
1486 GstCameraSrcClass *pclass;
1487 GstCameraSrc *camerasrc;
1488 gboolean ret = TRUE;
1490 camerasrc = GST_CAMERA_SRC_CAST (src);
1491 pclass = GST_CAMERA_SRC_GET_CLASS (src);
1493 GST_DEBUG_OBJECT (camerasrc, "Unlock stop");
1495 if (pclass->unlock_stop)
1496 ret = pclass->unlock_stop (camerasrc);
1503 * gst_camerasrc_send_image_tags:
1504 * @camerasrc: #GstCameraSrc object.
1508 gst_camerasrc_send_image_tags (GstCameraSrc * camerasrc)
1510 GstTagMergeMode mode;
1511 GstCameraSrcClass *bclass;
1512 guint iso, wbalance;
1517 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1519 tlist = gst_tag_list_new ();
1520 zoom = camerasrc->photoconf.zoom;
1521 iso = camerasrc->photoconf.iso_speed;
1523 (camerasrc->photoconf.wb_mode == GST_PHOTOGRAPHY_WB_MODE_AUTO) ? 0 : 1;
1525 gst_tag_register_musicbrainz_tags();
1527 mode = GST_TAG_MERGE_REPLACE;
1528 gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, (gdouble)zoom, NULL);
1529 gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_ISO_SPEED, iso, NULL);
1531 if(camerasrc->maker_note)
1535 GstBuffer *pmakerbuf = NULL;
1537 unsigned num_afwindows, num_awbgrid;
1541 ret = bclass->makernote_init(camerasrc, &buf_size, num_afwindows, 0, 0, num_awbgrid, &handle);
1544 pmakerbuf = gst_buffer_new_and_alloc(buf_size);
1546 ret = bclass->makernote_deal(camerasrc, pmakerbuf, num_afwindows, num_awbgrid, handle);
1549 gst_tag_list_add(tlist, mode, GST_TAG_APPLICATION_DATA, pmakerbuf, NULL);
1552 bclass->makernote_uninit(camerasrc, handle);
1553 gst_buffer_unref(pmakerbuf);
1557 if (bclass->fill_image_tags)
1558 bclass->fill_image_tags (camerasrc, tlist);
1560 tagevent = gst_event_new_tag (gst_tag_list_copy (tlist));
1561 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc), tagevent);
1562 GST_DEBUG_OBJECT (camerasrc, "image tags sent: %" GST_PTR_FORMAT, tlist);
1563 gst_tag_list_free (tlist);
1570 * gst_camerasrc_send_preview:
1571 * @camsrc: #GstCameraSrc object
1573 * Sends HQ image preview image (snapshot) as a GstMessage.
1575 * Returns: TRUE on success.
1578 gst_camerasrc_send_preview (GstCameraSrc * camsrc)
1580 GstCameraSrcClass *bclass;
1581 GstBuffer *buf = NULL;
1582 GstStructure *msg_s = NULL;
1583 GstCaps *prvcaps = NULL;
1584 GstMessage *msg = NULL;
1585 gboolean ret = FALSE;
1587 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
1589 if (bclass->get_preview_image) {
1590 ret = bclass->get_preview_image (camsrc, &buf);
1594 GST_DEBUG_OBJECT (camsrc, "Sending preview image");
1595 prvcaps = gst_caps_new_simple ("video/x-raw-yuv",
1596 "format", GST_TYPE_FOURCC, camsrc->preview_fourcc,
1597 "width", G_TYPE_INT, camsrc->preview_w,
1598 "height", G_TYPE_INT, camsrc->preview_h,
1599 "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
1601 gst_buffer_set_caps (buf, prvcaps);
1603 /* Send custom preview image GstMessage */
1604 msg_s = gst_structure_new (GST_CAMERA_SRC_PREVIEW_IMAGE, "buffer",
1605 GST_TYPE_BUFFER, buf, NULL);
1607 msg = gst_message_new_element (GST_OBJECT (camsrc), msg_s);
1609 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
1610 GST_WARNING ("This element has no bus, therefore no message sent!");
1613 gst_caps_unref (prvcaps);
1615 GST_DEBUG_OBJECT (camsrc, "Retrieving preview image failed");
1618 /* if we still have valid settings for preview, reserve a new buffer */
1619 if (camsrc->preview_resolution_set) {
1620 GST_DEBUG_OBJECT (camsrc, "Reserving a new preview buffer");
1621 bclass->set_capture (camsrc, GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW, FALSE,
1622 &camsrc->preview_fourcc, &camsrc->preview_w, &camsrc->preview_h,
1627 gst_buffer_unref (buf);
1635 * gst_camerasrc_set_capture_caps:
1636 * @camerasrc: #GstCameraSrc object.
1638 * Set the capture caps on element's src pad.
1640 * Returns: TRUE on success.
1643 gst_camerasrc_set_capture_caps (GstCameraSrc * camerasrc)
1645 GstCameraSrcClass *bclass;
1646 GstCaps *newcaps = NULL;
1647 gboolean ret = TRUE;
1649 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1651 GST_DEBUG_OBJECT (camerasrc, "Calling set_capture()");
1653 /* Try what resolution the subclass can capture */
1654 ret = bclass->set_capture (camerasrc,
1655 GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE, TRUE,
1656 &camerasrc->capture_fourcc, &camerasrc->capture_w, &camerasrc->capture_h,
1657 &camerasrc->capture_fps_n, &camerasrc->capture_fps_d);
1663 /* FIXME: FPS definition should be removed from capture caps */
1664 newcaps = gst_camerasrc_get_caps_from_info (camerasrc,
1665 camerasrc->capture_fourcc, camerasrc->capture_w, camerasrc->capture_h,
1666 camerasrc->capture_fps_n, camerasrc->capture_fps_d);
1668 GST_DEBUG_OBJECT (camerasrc, "Set capture caps: %" GST_PTR_FORMAT, newcaps);
1670 /* Notify application that we are ready now. This must be called before */
1671 /* the set_caps() call below, since application needs to know the new caps */
1672 /* so that it can adjust the caps filter to accept new format before */
1673 /* srcpad caps are actually changed */
1674 gst_camerasrc_photo_ready_for_capture (camerasrc, newcaps);
1676 camerasrc->vf_caps =
1677 gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1679 /* This causes caps nego and switches resolution to hi-res mode */
1680 /* FIXME: Do we even need to set this? Application has already set the
1682 if (!gst_caps_is_equal (camerasrc->vf_caps, newcaps)) {
1683 GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps");
1684 ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), newcaps);
1685 GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps FINISHED");
1687 GST_DEBUG_OBJECT (camerasrc, "Forcing the re-initialization");
1688 ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1689 &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1690 &camerasrc->fps_d, newcaps);
1691 gst_caps_unref (camerasrc->vf_caps);
1692 camerasrc->vf_caps = NULL;
1695 gst_caps_unref (newcaps);
1707 gst_camerasrc_apply_timestamp (GstCameraSrc * camerasrc, GstBuffer * buf)
1710 GstClockTime timestamp;
1712 GST_OBJECT_LOCK (camerasrc);
1713 if ((clock = GST_ELEMENT_CLOCK (camerasrc))) {
1714 /* we have a clock, get base time and ref clock */
1715 timestamp = GST_ELEMENT (camerasrc)->base_time;
1716 gst_object_ref (clock);
1718 /* no clock, can't set timestamps */
1719 timestamp = GST_CLOCK_TIME_NONE;
1721 GST_OBJECT_UNLOCK (camerasrc);
1724 /* the time now is the time of the clock minus the base time */
1725 timestamp = gst_clock_get_time (clock) - timestamp;
1726 gst_object_unref (clock);
1728 if (timestamp > camerasrc->duration)
1729 timestamp -= camerasrc->duration;
1734 /* we could also use the timestamp from the buffer itself */
1735 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1736 GST_BUFFER_DURATION (buf) = camerasrc->duration;
1742 static GstFlowReturn
1743 gst_camerasrc_create (GstPushSrc * src, GstBuffer ** buf)
1745 GstCameraSrcClass *bclass;
1746 GstCameraSrc *camerasrc;
1747 GstBaseSrcClass *basesrc_class;
1749 GstBuffer *buf_cap_signal1 = NULL; /*output main buffer for capture signal*/
1751 gboolean still_capture_initialised = FALSE;
1752 GstFlowReturn ret = GST_FLOW_OK;
1755 camerasrc = GST_CAMERA_SRC_CAST (src);
1756 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1757 basesrc_class = GST_BASE_SRC_CLASS (bclass);
1759 if (camerasrc->req_negotiation) {
1760 GST_DEBUG_OBJECT(camerasrc, "negotiation start");
1761 basesrc_class->negotiate(GST_BASE_SRC(camerasrc));
1762 camerasrc->req_negotiation = FALSE;
1763 g_signal_emit(G_OBJECT(camerasrc), gst_camerasrc_signals[CAMERA_IN_SIGNAL_NEGO_COMPLETE], (GQuark)NULL);
1764 GST_DEBUG_OBJECT (camerasrc, "negotiation stop");
1770 g_mutex_lock (camerasrc->state_lock);
1772 if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1773 /* Tell subclass to stop flushing buffers */
1774 if (bclass->unlock_stop) {
1775 GST_DEBUG_OBJECT (camerasrc, "Stop flushing, capture is starting");
1776 bclass->unlock_stop (camerasrc);
1779 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE;
1781 GST_DEBUG_OBJECT (camerasrc,
1782 "Flushing old buffers before starting HQ capture");
1783 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1784 gst_event_new_flush_start ());
1785 gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1786 gst_event_new_flush_stop ());
1788 if (!gst_camerasrc_set_capture_caps (camerasrc)) {
1789 goto hq_capture_failed;
1791 still_capture_initialised = TRUE;
1794 else if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) {
1798 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1799 camerasrc->requested_af_mode = AF_OFF_REQUESTED;
1800 camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
1801 GST_DEBUG_OBJECT (camerasrc, "capture done. switching to viewfinder");
1803 /* Set the normal viewfinder resolution back */
1804 if (camerasrc->vf_caps) {
1805 GST_DEBUG_OBJECT (camerasrc, "set VF caps");
1806 ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), camerasrc->vf_caps);
1807 gst_caps_unref (camerasrc->vf_caps);
1808 camerasrc->vf_caps = NULL;
1812 tmp = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1814 /* Reconfigure the device to run viewfinder again */
1815 ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1816 &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1817 &camerasrc->fps_d, tmp);
1819 gst_caps_unref (tmp);
1823 GST_WARNING_OBJECT (camerasrc, "Reinitializing viewfinder failed");
1824 g_mutex_unlock (camerasrc->state_lock);
1825 return GST_FLOW_ERROR;
1828 GST_DEBUG_OBJECT (camerasrc, "viewfinder running");
1831 g_mutex_lock (camerasrc->af_lock);
1833 /* Handle AF requests only in VIEWFINDER and AUTOFOCUS states */
1834 if ((camerasrc->photo_capture_phase == GST_CAMERA_VIEWFINDER ||
1835 camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS ||
1836 camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS_DONE) &&
1837 camerasrc->requested_af_mode != AF_NONE_REQUESTED) {
1838 if (camerasrc->requested_af_mode == AF_ON_REQUESTED) {
1841 ret = bclass->set_autofocus (camerasrc, TRUE);
1843 camerasrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS;
1846 camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1849 camerasrc->requested_af_mode = AF_NONE_REQUESTED;
1852 g_mutex_unlock (camerasrc->af_lock);
1853 g_mutex_unlock (camerasrc->state_lock);
1855 ret = bclass->grab_frame (camerasrc, &temp, camerasrc->photo_capture_phase);
1857 g_mutex_lock (camerasrc->state_lock);
1859 if (ret != GST_FLOW_OK) {
1860 /* _prepare_for_capture() may have interrupted frame grabbing. */
1861 if (ret == GST_FLOW_WRONG_STATE &&
1862 camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1863 g_mutex_unlock (camerasrc->state_lock);
1867 g_mutex_unlock (camerasrc->state_lock);
1874 /* Post-capture phase */
1876 if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE) {
1879 src_caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1880 gst_buffer_set_caps (*buf, src_caps);
1881 gst_caps_unref (src_caps);
1883 /* Restore the original number of buffers after capture is done */
1884 /* FIXME: Commented out */
1885 // camerasrc->num_buffers = tmp_num_buffers;
1887 // gst_camerasrc_send_image_tags (camerasrc);
1889 gst_camerasrc_send_preview (camerasrc);
1891 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1894 if(GST_CAMERA_SRC_CAPTURE_MODE_STILL == camerasrc->capture_mode) {
1895 gst_camerasrc_send_image_tags (camerasrc);
1896 if ((camerasrc->signal_still_capture == TRUE) && (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) && (still_capture_initialised == TRUE)) {
1897 still_capture_initialised = FALSE;
1899 /* alloc buffer for capture callback */
1900 buf_cap_signal1 = gst_buffer_new ();
1902 GST_BUFFER_DATA(buf_cap_signal1) = GST_BUFFER_DATA(*buf);
1903 GST_BUFFER_SIZE(buf_cap_signal1) = GST_BUFFER_SIZE(*buf);
1904 GST_BUFFER_CAPS(buf_cap_signal1) = gst_caps_new_simple("video/x-raw-yuv",
1905 "format", GST_TYPE_FOURCC, camerasrc->capture_fourcc,
1906 "width", G_TYPE_INT, camerasrc->capture_w,
1907 "height", G_TYPE_INT,camerasrc->capture_h,
1910 GST_LOG_OBJECT (camerasrc, "CALL: capture callback");
1911 g_mutex_unlock (camerasrc->state_lock);
1912 g_signal_emit( G_OBJECT (camerasrc),
1913 gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_CAPTURE],
1918 GST_LOG_OBJECT (camerasrc, "RETURN: capture callback");
1919 g_mutex_lock (camerasrc->state_lock);
1922 if(--camerasrc->capture_counter > 0) {
1923 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_START;
1924 GST_DEBUG_OBJECT (camerasrc, "do some more captures count %d",camerasrc->capture_counter);
1927 camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1929 g_mutex_unlock (camerasrc->state_lock);
1934 if (GST_BUFFER_TIMESTAMP (*buf) == GST_CLOCK_TIME_NONE) {
1935 gst_camerasrc_apply_timestamp (camerasrc, *buf);
1940 g_mutex_unlock (camerasrc->state_lock);
1947 GST_ELEMENT_ERROR (camerasrc, RESOURCE, READ,
1948 ("Error during HQ capture"), (NULL));
1949 ret = GST_FLOW_ERROR;
1954 static GstStateChangeReturn
1955 gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
1957 GstCameraSrcClass *bclass;
1958 GstCameraSrc *camerasrc;
1959 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1961 camerasrc = GST_CAMERA_SRC_CAST (element);
1962 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1964 GST_LOG_OBJECT (camerasrc, "State change: %s -> %s",
1965 gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1966 gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
1968 switch (transition) {
1969 case GST_STATE_CHANGE_NULL_TO_READY:
1970 /* Open the device */
1971 if (!bclass->open (camerasrc))
1972 return GST_STATE_CHANGE_FAILURE;
1978 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1980 switch (transition) {
1981 case GST_STATE_CHANGE_READY_TO_NULL:
1982 if (bclass->is_open (camerasrc)) {
1983 bclass->close (camerasrc);
1985 camerasrc->capture_w = camerasrc->preview_w = camerasrc->current_w = 0;
1986 camerasrc->capture_h = camerasrc->preview_h = camerasrc->current_h = 0;
1987 camerasrc->capture_fourcc = camerasrc->preview_fourcc = 0;
1988 camerasrc->current_fourcc = 0;
1989 camerasrc->fps_d = camerasrc->fps_n = 0;
1990 camerasrc->capture_resolution_set = FALSE;
1991 camerasrc->preview_resolution_set = FALSE;
1993 /* Notify that preview caps have changed (to NULL) */
1994 g_object_notify (G_OBJECT (camerasrc),
1995 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
2007 * gst_camerasrc_add_color_channel:
2008 * @camsrc: #GstCameraSrc object.
2009 * @channel: #GstColorBalanceChannel object.
2011 * Add a new color channel to list.
2014 gst_camerasrc_add_color_channel (GstCameraSrc * camsrc,
2015 GstColorBalanceChannel * channel)
2017 camsrc->colors = g_list_append (camsrc->colors, (gpointer) channel);
2022 * gst_camerasrc_clear_color_channels:
2023 * @camsrc: #GstCameraSrc object.
2025 * Delete all color channels.
2028 gst_camerasrc_clear_color_channels (GstCameraSrc * camsrc)
2030 g_list_foreach (camsrc->colors, (GFunc) g_object_unref, NULL);
2031 g_list_free (camsrc->colors);
2032 camsrc->colors = NULL;
2036 * gst_camerasrc_add_cameracontrol_channel:
2037 * @camsrc: #GstCameraSrc object.
2038 * @channel: #GstColorBalanceChannel object.
2040 * Add a new cameracontrol channel to list.
2043 gst_camerasrc_add_cameracontrol_channel (GstCameraSrc * camsrc,
2044 GstCameraControlChannel * channel)
2046 camsrc->camera_controls = g_list_append (camsrc->camera_controls, (gpointer) channel);
2050 * gst_camerasrc_clear_cameracontrol_channels:
2051 * @camsrc: #GstCameraSrc object.
2053 * Delete all cameracontrol channels.
2057 gst_camerasrc_clear_cameracontrol_channels (GstCameraSrc * camsrc)
2059 g_list_foreach (camsrc->camera_controls, (GFunc) g_object_unref, NULL);
2060 g_list_free (camsrc->camera_controls);
2061 camsrc->camera_controls = NULL;
2065 * gst_camerasrc_send_capture_start_message:
2066 * @camsrc: GstCameraSrc object
2068 * Sends a GstMessage notification to GstBus that capture operation is
2072 gst_camerasrc_send_capture_start_message (GstCameraSrc * camsrc)
2077 GST_DEBUG_OBJECT (camsrc, "Sending capture-start message");
2079 /* Send custom GstMessage "photo-capture-start" */
2080 s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_START, NULL);
2081 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2083 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2084 GST_WARNING ("This element has no bus, therefore no message sent!");
2087 GST_LOG_OBJECT (camsrc, "Capture-start message sent");
2092 * gst_camerasrc_send_capture_stop_message:
2093 * @camsrc: GstCameraSrc object
2095 * Sends a GstMessage notification to GstBus that capture operation has
2099 gst_camerasrc_send_capture_stop_message (GstCameraSrc * camsrc)
2104 GST_DEBUG_OBJECT (camsrc, "Sending capture-stop message");
2106 /* Send custom GstMessage "photo-capture-end" */
2107 s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_END, NULL);
2108 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2110 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2111 GST_WARNING ("This element has no bus, therefore no message sent!");
2114 GST_LOG_OBJECT (camsrc, "Capture-stop message sent");
2119 * gst_camerasrc_af_update:
2120 * @camsrc: #GstCameraSrc object.
2121 * @fs: #GstCameraFocusStatus structure. Owned by caller.
2123 * Tell GstCameraSrc that previously started autofocus operation has finished.
2126 gst_camerasrc_af_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2128 GstCameraSrcClass *bclass;
2130 bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
2132 g_mutex_lock (camsrc->state_lock);
2133 g_mutex_lock (camsrc->af_lock);
2135 if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS ||
2136 fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL) {
2140 GST_DEBUG_OBJECT (camsrc, "autofocusing ended");
2142 /* Send custom GstMessage "autofocus-done" */
2143 s = gst_structure_new (GST_PHOTOGRAPHY_AUTOFOCUS_DONE,
2144 "status", G_TYPE_INT, fs->status, NULL);
2146 /* If autofocus succeeded, send the bitmask that defines focused
2148 if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS) {
2152 windows = g_array_new (FALSE, FALSE, sizeof (gint));
2153 for (i = 0; i < fs->num_windows; i++) {
2154 GST_DEBUG_OBJECT (camsrc, "focus window: %d", fs->windows[i]);
2155 g_array_append_val (windows, fs->windows[i]);
2158 gst_structure_set (s,
2159 //"focus-windows", G_TYPE_ARRAY, windows,
2160 "focus-window-rows", G_TYPE_INT, fs->focus_rows,
2161 "focus-window-columns", G_TYPE_INT, fs->focus_columns,
2162 "focus-window-coverage", G_TYPE_INT, fs->coverage, NULL);
2164 GST_DEBUG_OBJECT (camsrc, "focus rows: %d", fs->focus_rows);
2165 GST_DEBUG_OBJECT (camsrc, "focus columns: %d", fs->focus_columns);
2166 GST_DEBUG_OBJECT (camsrc, "focus coverage: %d", fs->coverage);
2169 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2171 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2172 GST_WARNING ("This element has no bus, therefore no message sent!");
2175 camsrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS_DONE;
2178 g_mutex_unlock (camsrc->af_lock);
2179 g_mutex_unlock (camsrc->state_lock);
2184 * gst_camerasrc_caf_update:
2185 * @camsrc: GstCameraSrc object.
2186 * @fs: #GstCameraFocusStatus structure. Owned by caller.
2188 * Tell GstCameraSrc that continuous autofocus algorithm has changed its state.
2189 * Sends a GstMessage notification to GstBus indicating a change in
2190 * continuous autofocus status.
2193 gst_camerasrc_caf_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2198 GST_DEBUG_OBJECT (camsrc, "Sending CAF status: %d", fs->status);
2200 /* Send custom GstMessage "caf-update" */
2201 s = gst_structure_new (GST_CAMERA_SRC_CAF_STATUS, NULL);
2202 gst_structure_set (s, "status", G_TYPE_INT, fs->status, NULL);
2203 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2205 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2206 GST_WARNING ("This element has no bus, therefore no message sent!");
2209 GST_LOG_OBJECT (camsrc, "CAF update message sent");
2214 * gst_camerasrc_shake_update:
2215 * @camsrc: GstCameraSrc object.
2216 * @risk: GstPhotoShakeRisk value.
2218 * Tell GstCameraSrc that shake risk has changed. Sends a GstMessage
2219 * notification to GstBus indicating a change in shake risk status.
2222 gst_camerasrc_shake_update (GstCameraSrc * camsrc, GstPhotoShakeRisk risk)
2227 GST_DEBUG_OBJECT (camsrc, "Sending shake risk update: %d", risk);
2229 /* Send custom GstMessage telling the changed shake risk level */
2230 s = gst_structure_new (GST_PHOTOGRAPHY_SHAKE_RISK, NULL);
2231 gst_structure_set (s, "shake_risk", G_TYPE_INT, risk, NULL);
2232 msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2234 if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2235 GST_WARNING ("This element has no bus, therefore no message sent!");
2238 GST_LOG_OBJECT (camsrc, "Shake indicator message sent");
2242 /* Tag helper functions */
2245 * gst_camerasrc_exposure_mode_from_exif_value:
2246 * @value: exposure mode in EXIF format.
2248 * Convert exposure mode to string.
2250 * Returns: String representation of the scene capture type, or NULL if invalid
2251 * value was given. Possible values: "auto-exposure", "manual-exposure" and
2255 gst_camerasrc_exposure_mode_from_exif_value (gint value)
2259 return "auto-exposure";
2261 return "manual-exposure";
2263 return "auto-bracket";
2265 GST_WARNING ("Invalid exif exposure mode: %d", value);
2271 * gst_camerasrc_scene_capture_type_from_exif_value:
2272 * @value: scene capture type in EXIF format.
2274 * Convert scene capture type to string.
2276 * Returns: String representation of the scene capture type, or NULL if invalid
2277 * value was given. Possible values: "standard", "landscape", "portrait" and
2281 gst_camerasrc_scene_capture_type_from_exif_value (gint value)
2291 return "night-scene";
2293 GST_WARNING ("Invalid exif scene capture type: %d", value);
2300 * gst_camerasrc_gain_adjustment_from_exif_value:
2301 * @value: gain adjustment type in EXIF format.
2303 * Convert gain adjustment type to string.
2305 * Returns: String representation of the gain adjustment type, or NULL if
2306 * invalid value was given. Possible values: "none", "low-gain-up",
2307 * "high-gain-up", "low-gain-down" and "high-gain-down".
2310 gst_camerasrc_gain_adjustment_from_exif_value (gint value)
2316 return "low-gain-up";
2318 return "high-gain-up";
2320 return "low-gain-down";
2322 return "high-gain-down";
2324 GST_WARNING ("Invalid exif gain control type: %d", value);
2331 * gst_camerasrc_contrast_from_exif_value:
2332 * @value: contrast type in EXIF format.
2334 * Convert contrast type to string.
2336 * Returns: String representation of the contrast type, or NULL if invalid
2337 * value was given. Possible values: "normal", "soft" and "hard".
2340 gst_camerasrc_contrast_from_exif_value (gint value)
2350 GST_WARNING ("Invalid contrast type: %d", value);
2357 * gst_camerasrc_saturation_from_exif_value:
2358 * @value: saturation type in EXIF format.
2360 * Convert saturation type to string.
2362 * Returns: String representation of the saturation type, or NULL if invalid
2363 * value was given. Possible values: "normal", "low-saturation" and
2364 * "high-saturation".
2367 gst_camerasrc_saturation_from_exif_value (gint value)
2373 return "low-saturation";
2375 return "high-saturation";
2377 GST_WARNING ("Invalid saturation type: %d", value);
2384 * gst_camerasrc_flash_mode_from_exif_value:
2385 * @value: flash EXIF field
2387 * Convert "flash" EXIF field into text string.
2389 * Returns: String representation of the flash mode, or NULL if invalid
2390 * value was given. Possible values: "always", "never" and "auto".
2393 gst_camerasrc_flash_mode_from_exif_value (gint value)
2397 // bits 3 and 4 indicate the flash mode,
2399 // Values for bits 3 and 4 indicating the camera's flash mode.
2401 // 01b = Compulsory flash firing
2402 // 10b = Compulsory flash suppression
2406 /* Bit numbering in EXIF spec starts from 0 */
2409 switch (value & 0x3) {
2417 GST_WARNING ("Invalid flash mode type: %d", value);
2424 * gst_camerasrc_sharpness_from_exif_value:
2425 * @value: sharpness type in EXIF format.
2427 * Convert sharpness type to string.
2429 * Returns: String representation of the sharpness type, or NULL if invalid
2430 * value was given. Possible values: "normal", "soft" and "hard".
2433 gst_camerasrc_sharpness_from_exif_value (gint value)
2443 GST_WARNING ("Invalid sharpness type: %d", value);
2450 * gst_camerasrc_metering_mode_from_exif_value:
2451 * @value: metering mode type in EXIF format.
2453 * Convert metering mode type to string.
2455 * Returns: String representation of the metering mode type, or NULL if invalid
2456 * value was given. Possible values: "unknown", "average",
2457 * "center-weighted-average", "spot", "multi-spot", "pattern", "partial" and
2461 gst_camerasrc_metering_mode_from_exif_value (gint value)
2469 return "center-weighted-average";
2473 return "multi-spot";
2481 GST_WARNING ("Invalid metering mode type: %d", value);
2488 * gst_camerasrc_file_source_from_exif_value:
2489 * @value: FileSource type in EXIF format.
2491 * Convert FileSource type to string.
2493 * Returns: String representation of the FileSource type, or NULL if invalid
2494 * value was given. Possible values: "dsc", "transparent-scanner",
2495 * "reflex-scanner" and "other".
2498 gst_camerasrc_file_source_from_exif_value (gint value)
2504 return "transparent-scanner";
2506 return "reflex-scanner";
2510 GST_WARNING ("Invalid file source type: %d", value);
2516 /* Default implementations for vmethods */
2519 gst_camerasrc_default_capabilities (GstCameraSrc * camsrc)
2521 return GST_PHOTOGRAPHY_CAPS_NONE;
2525 gst_camerasrc_default_ret_true_with_settings (GstCameraSrc * camsrc,
2526 GstPhotoSettings * photoconf)
2532 gst_camerasrc_default_write_settings (GstCameraSrc * camsrc,
2533 GstPhotoSettings * photoconf, gboolean scene_mode_override)
2539 gst_camerasrc_default_set_onoff (GstCameraSrc * camsrc, gboolean on_off)
2545 gst_camerasrc_default_get_caps (GstCameraSrc * camsrc, GstOperationMode mode)
2547 GST_DEBUG_OBJECT (camsrc, "Returning NULL caps for mode %d", mode);
2552 gst_camerasrc_default_read_exif (GstCameraSrc *camsrc,
2553 GstCameraControlExifInfo *exif_info)
2555 GST_DEBUG_OBJECT (camsrc, "default implementation of exif read called return defaults %d");
2556 // TODO: fill with default values
2561 gst_camerasrc_default_set_flash_mode (GstCameraSrc *camsrc, int value)
2567 gst_camerasrc_default_functions_init (GstCameraSrcClass * camera_class)
2569 camera_class->get_capabilities = gst_camerasrc_default_capabilities;
2570 camera_class->set_autofocus = gst_camerasrc_default_set_onoff;
2571 camera_class->read_settings = gst_camerasrc_default_ret_true_with_settings;
2572 camera_class->write_settings = gst_camerasrc_default_write_settings;
2573 camera_class->get_supported_caps = gst_camerasrc_default_get_caps;
2574 camera_class->set_flash_mode = gst_camerasrc_default_set_flash_mode;
2575 camera_class->read_exif = gst_camerasrc_default_read_exif;
2577 GST_DEBUG ("Default functions set");
2582 gst_camerasrc_handle_event (GstCameraSrc * camerasrc, GstEvent * event)
2584 GstCameraSrcClass *bclass;
2585 gboolean ret = FALSE;
2587 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2588 GST_LOG_OBJECT (camerasrc, "handling %s event", GST_EVENT_TYPE_NAME (event));
2590 if (bclass->event) {
2591 ret = bclass->event (camerasrc, event);
2599 * gst_camerasrc_send_event:
2600 * @element: GstElement object.
2601 * @event: GstEvent to be handled.
2603 * Returns: TRUE if the event was handled.
2606 gst_camerasrc_send_event (GstElement * element, GstEvent * event)
2608 GstCameraSrc *camerasrc;
2609 gboolean ret = FALSE;
2611 camerasrc = GST_CAMERA_SRC_CAST (element);
2613 GST_LOG_OBJECT (camerasrc, "got %s event", GST_EVENT_TYPE_NAME (event));
2615 switch (GST_EVENT_TYPE (event)) {
2616 case GST_EVENT_CUSTOM_UPSTREAM:
2617 ret = gst_camerasrc_handle_event (camerasrc, event);
2624 ret = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
2632 * gst_camerasrc_event:
2633 * @src: #GstBaseSrc object.
2634 * @event: #GetEvent object.
2636 * Returns: TRUE of the event was handled.
2639 gst_camerasrc_event (GstBaseSrc * src, GstEvent * event)
2641 GstCameraSrc *camerasrc;
2644 camerasrc = GST_CAMERA_SRC_CAST (src);
2645 ret = gst_camerasrc_handle_event (camerasrc, event);
2648 ret = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
2656 * gst_camerasrc_update_max_zoom:
2657 * @camerasrc: #GstCameraSrc object.
2659 * Check and update zoom property maximum value.
2662 gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc)
2664 GstCameraSrcClass *bclass;
2665 GObjectClass *oclass;
2667 GParamSpecFloat *pspec_f;
2668 gfloat maxzoom = 10.0;
2670 oclass = G_OBJECT_GET_CLASS (camerasrc);
2671 bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2672 pspec = g_object_class_find_property (oclass, "zoom");
2674 if (bclass->get_max_zoom) {
2675 if (!bclass->get_max_zoom (camerasrc, &maxzoom)) {
2680 /* Update gobject property */
2681 if (pspec && (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_FLOAT)) {
2682 pspec_f = G_PARAM_SPEC_FLOAT (pspec);
2683 pspec_f->maximum = maxzoom;
2684 GST_DEBUG_OBJECT (camerasrc, "set maximum zoom as %f", pspec_f->maximum);
2685 /* Check if new maximum zoom is lower than current zoom level */
2686 if (pspec_f->maximum < camerasrc->photoconf.zoom) {
2687 GST_DEBUG_OBJECT (camerasrc, "current zoom level too high: %f",
2688 camerasrc->photoconf.zoom);
2689 g_object_set (G_OBJECT (camerasrc), "zoom", pspec_f->maximum, NULL);
2692 GST_WARNING_OBJECT (camerasrc, "updating maximum zoom failed");