2 * Copyright © 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
3 * Copyright © 2007,2008 Jaap Haitsma <jaap@haitsma.org>
4 * Copyright © 2007-2009 daniel g. siegel <dgsiegel@gnome.org>
5 * Copyright © 2008 Ryan Zeigler <zeiglerr@gmail.com>
7 * Licensed under the GNU General Public License Version 2
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <glib/gi18n-lib.h>
31 #include "cheese-camera-device.h"
34 * SECTION:cheese-camera-device
35 * @short_description: Object to represent a video capture device
36 * @stability: Unstable
37 * @include: cheese/cheese-camera-device.h
39 * #CheeseCameraDevice provides an abstraction of a video capture device.
42 static void cheese_camera_device_initable_iface_init (GInitableIface
*iface
);
43 static gboolean
cheese_camera_device_initable_init (GInitable
*initable
,
44 GCancellable
*cancellable
,
47 #define CHEESE_CAMERA_DEVICE_ERROR cheese_camera_device_error_quark ()
50 * CheeseCameraDeviceError:
51 * @CHEESE_CAMERA_DEVICE_ERROR_UNKNOWN: unknown error
52 * @CHEESE_CAMERA_DEVICE_ERROR_NOT_SUPPORTED: cancellation of device
53 * initialisation was requested, but is not supported
54 * @CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS: unsupported GStreamer
56 * @CHEESE_CAMERA_DEVICE_ERROR_FAILED_INITIALIZATION: the device failed to
57 * initialize for capability probing
59 * Errors that can occur during device initialization.
61 enum CheeseCameraDeviceError
63 CHEESE_CAMERA_DEVICE_ERROR_UNKNOWN
,
64 CHEESE_CAMERA_DEVICE_ERROR_NOT_SUPPORTED
,
65 CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS
,
66 CHEESE_CAMERA_DEVICE_ERROR_FAILED_INITIALIZATION
69 GST_DEBUG_CATEGORY (cheese_camera_device_cat
);
70 #define GST_CAT_DEFAULT cheese_camera_device_cat
72 static const gchar
const *supported_formats
[] = {
77 /* FIXME: make this configurable */
79 * CHEESE_MAXIMUM_RATE:
81 * The maximum framerate, in frames per second.
83 static const guint CHEESE_MAXIMUM_RATE
= 30;
93 static GParamSpec
*properties
[PROP_LAST
];
100 GList
*formats
; /* list members are CheeseVideoFormatFull structs. */
102 GError
*construct_error
;
103 } CheeseCameraDevicePrivate
;
105 G_DEFINE_TYPE_WITH_CODE (CheeseCameraDevice
, cheese_camera_device
,
107 G_ADD_PRIVATE (CheeseCameraDevice
)
108 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE
,
109 cheese_camera_device_initable_iface_init
))
112 * This is our private version of CheeseVideoFormat, with extra fields added
113 * at the end. IMPORTANT the first fields *must* be kept in sync with the
114 * public CheeseVideoFormat, since in various places we cast pointers to
115 * CheeseVideoFormatFull to CheeseVideoFormat.
119 /* CheeseVideoFormat members keep synced with cheese-camera-device.h! */
125 } CheeseVideoFormatFull
;
127 GQuark
cheese_camera_device_error_quark (void);
130 cheese_camera_device_error_quark (void)
132 return g_quark_from_static_string ("cheese-camera-device-error-quark");
135 /* CheeseVideoFormat */
137 static CheeseVideoFormat
*
138 cheese_video_format_copy (const CheeseVideoFormat
*format
)
140 return g_slice_dup (CheeseVideoFormat
, format
);
144 cheese_video_format_free (CheeseVideoFormat
*format
)
146 if (G_LIKELY (format
!= NULL
))
147 g_slice_free (CheeseVideoFormat
, format
);
150 G_DEFINE_BOXED_TYPE (CheeseVideoFormat
, cheese_video_format
,
151 cheese_video_format_copy
, cheese_video_format_free
)
156 compare_formats (gconstpointer a
, gconstpointer b
)
158 const CheeseVideoFormatFull
*c
= a
;
159 const CheeseVideoFormatFull
*d
= b
;
161 /* descending sort for rectangle area */
162 return (d
->width
* d
->height
- c
->width
* c
->height
);
166 * cheese_camera_device_filter_caps:
167 * @device: the #CheeseCameraDevice
168 * @caps: the #GstCaps that the device supports
169 * @formats: an array of strings of video formats, in the form axb, where a and
170 * b are in units of pixels
172 * Filter the supplied @caps with %CHEESE_MAXIMUM_RATE to only allow @formats
173 * which can reach the desired framerate.
175 * Returns: the filtered #GstCaps
178 cheese_camera_device_filter_caps (CheeseCameraDevice
*device
,
180 const gchar
const *formats
[])
186 filter
= gst_caps_new_empty ();
188 for (i
= 0; formats
[i
] != NULL
; i
++)
190 gst_caps_append (filter
,
191 gst_caps_new_simple (formats
[i
],
192 "framerate", GST_TYPE_FRACTION_RANGE
,
193 0, 1, CHEESE_MAXIMUM_RATE
, 1,
197 allowed
= gst_caps_intersect (caps
, filter
);
199 GST_DEBUG ("Supported caps %" GST_PTR_FORMAT
, caps
);
200 GST_DEBUG ("Filter caps %" GST_PTR_FORMAT
, filter
);
201 GST_DEBUG ("Filtered caps %" GST_PTR_FORMAT
, allowed
);
203 gst_caps_unref (filter
);
209 * cheese_camera_device_get_highest_framerate:
210 * @framerate: a #GValue holding a framerate cap
211 * @numerator: destination to store the numerator of the highest rate
212 * @denominator: destination to store the denominator of the highest rate
214 * Get the numerator and denominator for the highest framerate stored in
217 * Note this function does not handle framerate ranges, if @framerate
218 * contains a range it will return 0/0 as framerate
221 cheese_camera_device_get_highest_framerate (const GValue
*framerate
,
222 gint
*numerator
, gint
*denominator
)
227 if (GST_VALUE_HOLDS_FRACTION (framerate
))
229 *numerator
= gst_value_get_fraction_numerator (framerate
);
230 *denominator
= gst_value_get_fraction_denominator (framerate
);
232 else if (GST_VALUE_HOLDS_ARRAY (framerate
))
234 float curr
, highest
= 0;
235 guint i
, size
= gst_value_array_get_size (framerate
);
237 for (i
= 0; i
< size
; i
++)
239 const GValue
*val
= gst_value_array_get_value (framerate
, i
);
241 if (!GST_VALUE_HOLDS_FRACTION (val
) ||
242 gst_value_get_fraction_denominator (val
) == 0) {
246 curr
= (float)gst_value_get_fraction_numerator (val
) /
247 (float)gst_value_get_fraction_denominator (val
);
249 if (curr
> highest
&& curr
<= CHEESE_MAXIMUM_RATE
)
252 *numerator
= gst_value_get_fraction_numerator (val
);
253 *denominator
= gst_value_get_fraction_denominator (val
);
257 else if (GST_VALUE_HOLDS_LIST (framerate
))
259 float curr
, highest
= 0;
260 guint i
, size
= gst_value_list_get_size (framerate
);
262 for (i
= 0; i
< size
; i
++)
264 const GValue
*val
= gst_value_list_get_value(framerate
, i
);
266 if (!GST_VALUE_HOLDS_FRACTION (val
) ||
267 gst_value_get_fraction_denominator (val
) == 0)
272 curr
= (float)gst_value_get_fraction_numerator (val
) /
273 (float)gst_value_get_fraction_denominator (val
);
275 if (curr
> highest
&& curr
<= CHEESE_MAXIMUM_RATE
)
278 *numerator
= gst_value_get_fraction_numerator (val
);
279 *denominator
= gst_value_get_fraction_denominator (val
);
283 else if (GST_VALUE_HOLDS_FRACTION_RANGE (framerate
))
285 const GValue
*val
= gst_value_get_fraction_range_max (framerate
);
287 if (GST_VALUE_HOLDS_FRACTION (val
))
289 *numerator
= gst_value_get_fraction_numerator (val
);
290 *denominator
= gst_value_get_fraction_denominator (val
);
296 * cheese_camera_device_format_update_framerate:
297 * @format: the #CheeseVideoFormatFull to update the framerate of
298 * @framerate: a #GValue holding a framerate cap
300 * This function updates the framerate in @format with the highest framerate
301 * from @framerate, if @framerate contains a framerate higher then the
302 * framerate currently stored in @format.
305 cheese_camera_device_format_update_framerate (CheeseVideoFormatFull
*format
,
306 const GValue
*framerate
)
308 float high
, curr
= (float)format
->fr_numerator
/ format
->fr_denominator
;
309 gint high_numerator
, high_denominator
;
311 cheese_camera_device_get_highest_framerate (framerate
, &high_numerator
,
313 if (high_denominator
== 0)
316 high
= (float)high_numerator
/ (float)high_denominator
;
319 format
->fr_numerator
= high_numerator
;
320 format
->fr_denominator
= high_denominator
;
321 GST_INFO ("%dx%d new framerate %d/%d", format
->width
, format
->height
,
322 format
->fr_numerator
, format
->fr_denominator
);
327 * cheese_camera_device_find_full_format:
328 * @device: a #CheeseCameraDevice
329 * @format: #CheeseVideoFormat to find the matching #CheeseVideoFormatFull for
331 * Find a #CheeseVideoFormatFull matching the passed in #CheeseVideoFormat.
333 static CheeseVideoFormatFull
*
334 cheese_camera_device_find_full_format (CheeseCameraDevice
*device
,
335 CheeseVideoFormat
* format
)
337 CheeseCameraDevicePrivate
*priv
;
340 priv
= cheese_camera_device_get_instance_private (device
);
342 for (l
= priv
->formats
; l
!= NULL
; l
= g_list_next (l
))
344 CheeseVideoFormatFull
*item
= l
->data
;
346 if ((item
!= NULL
) &&
347 (item
->width
== format
->width
) && (item
->height
== format
->height
))
357 * cheese_camera_device_add_format:
358 * @device: a #CheeseCameraDevice
359 * @format: the #CheeseVideoFormatFull to add
361 * Add the supplied @format to the list of formats supported by the @device.
364 cheese_camera_device_add_format (CheeseCameraDevice
*device
,
365 CheeseVideoFormatFull
*format
,
366 const GValue
*framerate
)
368 CheeseCameraDevicePrivate
*priv
;
369 CheeseVideoFormatFull
*existing
;
371 priv
= cheese_camera_device_get_instance_private (device
);
372 existing
= cheese_camera_device_find_full_format (device
,
373 (CheeseVideoFormat
*)format
);
377 g_slice_free (CheeseVideoFormatFull
, format
);
378 cheese_camera_device_format_update_framerate (existing
, framerate
);
382 cheese_camera_device_get_highest_framerate (framerate
, &format
->fr_numerator
,
383 &format
->fr_denominator
);
384 GST_INFO ("%dx%d framerate %d/%d", format
->width
, format
->height
,
385 format
->fr_numerator
, format
->fr_denominator
);
387 priv
->formats
= g_list_insert_sorted (priv
->formats
, format
,
392 * free_format_list_foreach:
393 * @data: the #CheeseVideoFormatFull to free
395 * Free the individual #CheeseVideoFormatFull.
398 free_format_list_foreach (gpointer data
)
400 g_slice_free (CheeseVideoFormatFull
, data
);
405 * @device: a #CheeseCameraDevice
407 * Free the list of video formats for the @device.
410 free_format_list (CheeseCameraDevice
*device
)
412 CheeseCameraDevicePrivate
*priv
;
414 priv
= cheese_camera_device_get_instance_private (device
);
416 g_list_free_full (priv
->formats
, free_format_list_foreach
);
417 priv
->formats
= NULL
;
421 * cheese_camera_device_update_format_table:
422 * @device: a #CheeseCameraDevice
424 * Clear the current list of video formats supported by the @device and create
428 cheese_camera_device_update_format_table (CheeseCameraDevice
*device
)
430 CheeseCameraDevicePrivate
*priv
;
433 guint num_structures
;
435 free_format_list (device
);
437 priv
= cheese_camera_device_get_instance_private (device
);
438 num_structures
= gst_caps_get_size (priv
->caps
);
439 for (i
= 0; i
< num_structures
; i
++)
441 GstStructure
*structure
;
442 const GValue
*width
, *height
, *framerate
;
443 structure
= gst_caps_get_structure (priv
->caps
, i
);
445 width
= gst_structure_get_value (structure
, "width");
446 height
= gst_structure_get_value (structure
, "height");
447 framerate
= gst_structure_get_value (structure
, "framerate");
449 if (G_VALUE_HOLDS_INT (width
))
451 CheeseVideoFormatFull
*format
= g_slice_new0 (CheeseVideoFormatFull
);
453 gst_structure_get_int (structure
, "width", &(format
->width
));
454 gst_structure_get_int (structure
, "height", &(format
->height
));
455 cheese_camera_device_add_format (device
, format
, framerate
);
457 else if (GST_VALUE_HOLDS_INT_RANGE (width
))
459 gint min_width
, max_width
, min_height
, max_height
;
460 gint cur_width
, cur_height
;
462 min_width
= gst_value_get_int_range_min (width
);
463 max_width
= gst_value_get_int_range_max (width
);
464 min_height
= gst_value_get_int_range_min (height
);
465 max_height
= gst_value_get_int_range_max (height
);
467 /* Some devices report a very small min_width / height down to reporting
468 * 0x0 as minimum resolution, which causes an infinte loop below, limit
469 * these to something reasonable. */
472 if (min_height
< 120)
475 if (max_width
> 5120)
477 if (max_height
> 3840)
480 cur_width
= min_width
;
481 cur_height
= min_height
;
483 /* Gstreamer will sometimes give us a range with min_xxx == max_xxx,
484 * we use <= here (and not below) to make this work */
485 while (cur_width
<= max_width
&& cur_height
<= max_height
)
487 CheeseVideoFormatFull
*format
= g_slice_new0 (CheeseVideoFormatFull
);
489 /* Gstreamer wants resolutions for YUV formats where the width is
490 * a multiple of 8, and the height is a multiple of 2 */
491 format
->width
= cur_width
& ~7;
492 format
->height
= cur_height
& ~1;
494 cheese_camera_device_add_format (device
, format
, framerate
);
500 cur_width
= max_width
;
501 cur_height
= max_height
;
502 while (cur_width
> min_width
&& cur_height
> min_height
)
504 CheeseVideoFormatFull
*format
= g_slice_new0 (CheeseVideoFormatFull
);
506 /* Gstreamer wants resolutions for YUV formats where the width is
507 * a multiple of 8, and the height is a multiple of 2 */
508 format
->width
= cur_width
& ~7;
509 format
->height
= cur_height
& ~1;
511 cheese_camera_device_add_format (device
, format
, framerate
);
519 g_critical ("GValue type %s, cannot be handled for resolution width", G_VALUE_TYPE_NAME (width
));
525 * cheese_camera_device_get_caps:
526 * @device: a #CheeseCameraDevice
528 * Probe the #GstCaps that the @device supports.
531 cheese_camera_device_get_caps (CheeseCameraDevice
*device
)
533 CheeseCameraDevicePrivate
*priv
;
536 priv
= cheese_camera_device_get_instance_private (device
);
538 caps
= gst_device_get_caps (priv
->device
);
540 caps
= gst_caps_new_empty_simple ("video/x-raw");
542 gst_caps_unref (priv
->caps
);
543 priv
->caps
= cheese_camera_device_filter_caps (device
, caps
, supported_formats
);
545 if (!gst_caps_is_empty (priv
->caps
))
546 cheese_camera_device_update_format_table (device
);
549 g_set_error_literal (&priv
->construct_error
,
550 CHEESE_CAMERA_DEVICE_ERROR
,
551 CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS
,
552 _("Device capabilities not supported"));
554 gst_caps_unref (caps
);
558 cheese_camera_device_constructed (GObject
*object
)
560 CheeseCameraDevice
*device
= CHEESE_CAMERA_DEVICE (object
);
562 cheese_camera_device_get_caps (device
);
564 if (G_OBJECT_CLASS (cheese_camera_device_parent_class
)->constructed
)
565 G_OBJECT_CLASS (cheese_camera_device_parent_class
)->constructed (object
);
569 cheese_camera_device_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
571 CheeseCameraDevice
*device
= CHEESE_CAMERA_DEVICE (object
);
572 CheeseCameraDevicePrivate
*priv
= cheese_camera_device_get_instance_private (device
);
577 g_value_set_string (value
, priv
->name
);
580 g_value_set_object (value
, priv
->device
);
583 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
589 cheese_camera_device_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
591 CheeseCameraDevice
*device
= CHEESE_CAMERA_DEVICE (object
);
592 CheeseCameraDevicePrivate
*priv
= cheese_camera_device_get_instance_private (device
);
598 priv
->name
= g_value_dup_string (value
);
602 g_object_unref (priv
->device
);
603 priv
->device
= g_value_dup_object (value
);
605 priv
->name
= gst_device_get_display_name (priv
->device
);
608 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
614 cheese_camera_device_finalize (GObject
*object
)
616 CheeseCameraDevice
*device
= CHEESE_CAMERA_DEVICE (object
);
617 CheeseCameraDevicePrivate
*priv
= cheese_camera_device_get_instance_private (device
);
619 g_object_unref (priv
->device
);
622 gst_caps_unref (priv
->caps
);
623 free_format_list (device
);
625 G_OBJECT_CLASS (cheese_camera_device_parent_class
)->finalize (object
);
629 cheese_camera_device_class_init (CheeseCameraDeviceClass
*klass
)
631 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
633 if (cheese_camera_device_cat
== NULL
)
634 GST_DEBUG_CATEGORY_INIT (cheese_camera_device_cat
,
635 "cheese-camera-device",
636 0, "Cheese Camera Device");
638 object_class
->finalize
= cheese_camera_device_finalize
;
639 object_class
->get_property
= cheese_camera_device_get_property
;
640 object_class
->set_property
= cheese_camera_device_set_property
;
641 object_class
->constructed
= cheese_camera_device_constructed
;
644 * CheeseCameraDevice:name:
646 * Human-readable name of the video capture device, for display to the user.
648 properties
[PROP_NAME
] = g_param_spec_string ("name",
649 "Name of the device",
650 "Human-readable name of the video capture device",
653 G_PARAM_CONSTRUCT_ONLY
|
654 G_PARAM_STATIC_STRINGS
);
657 * CheeseCameraDevice:device:
659 * GStreamer device object of the video capture device.
661 properties
[PROP_DEVICE
] = g_param_spec_object ("device",
663 "The GStreamer device object of the video capture device",
666 G_PARAM_CONSTRUCT_ONLY
|
667 G_PARAM_STATIC_STRINGS
);
669 g_object_class_install_properties (object_class
, PROP_LAST
, properties
);
673 cheese_camera_device_initable_iface_init (GInitableIface
*iface
)
675 iface
->init
= cheese_camera_device_initable_init
;
679 cheese_camera_device_init (CheeseCameraDevice
*device
)
681 CheeseCameraDevicePrivate
*priv
= cheese_camera_device_get_instance_private (device
);
683 priv
->name
= g_strdup (_("Unknown device"));
684 priv
->caps
= gst_caps_new_empty ();
688 cheese_camera_device_initable_init (GInitable
*initable
,
689 GCancellable
*cancellable
,
692 CheeseCameraDevice
*device
= CHEESE_CAMERA_DEVICE (initable
);
693 CheeseCameraDevicePrivate
*priv
= cheese_camera_device_get_instance_private (device
);
695 g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (initable
), FALSE
);
697 if (cancellable
!= NULL
)
699 g_set_error_literal (error
,
700 CHEESE_CAMERA_DEVICE_ERROR
,
701 CHEESE_CAMERA_DEVICE_ERROR_NOT_SUPPORTED
,
702 _("Cancellable initialization not supported"));
706 if (priv
->construct_error
)
709 *error
= g_error_copy (priv
->construct_error
);
719 * cheese_camera_device_new:
720 * @device: The GStreamer the device, as supplied by GstDeviceMonitor
721 * @error: a location to store errors
723 * Tries to create a new #CheeseCameraDevice with the supplied device. If
724 * construction fails, %NULL is returned, and @error is set.
726 * Returns: a new #CheeseCameraDevice, or %NULL
729 cheese_camera_device_new (GstDevice
*device
,
732 return CHEESE_CAMERA_DEVICE (g_initable_new (CHEESE_TYPE_CAMERA_DEVICE
,
739 * cheese_camera_device_get_format_list:
740 * @device: a #CheeseCameraDevice
742 * Get the sorted list of #CheeseVideoFormat that the @device supports.
744 * Returns: (element-type Cheese.VideoFormat) (transfer container): list of
748 cheese_camera_device_get_format_list (CheeseCameraDevice
*device
)
750 CheeseCameraDevicePrivate
*priv
;
752 g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device
), NULL
);
754 priv
= cheese_camera_device_get_instance_private (device
);
756 return g_list_copy (priv
->formats
);
760 * cheese_camera_device_get_name:
761 * @device: a #CheeseCameraDevice
763 * Get a human-readable name for the device, as reported by udev, which is
764 * suitable for display to a user.
766 * Returns: (transfer none): the human-readable name of the video capture device
769 cheese_camera_device_get_name (CheeseCameraDevice
*device
)
771 CheeseCameraDevicePrivate
*priv
;
773 g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device
), NULL
);
775 priv
= cheese_camera_device_get_instance_private (device
);
781 * cheese_camera_device_get_src:
782 * @device: a #CheeseCameraDevice
784 * Get the source GStreamer element for the @device.
786 * Returns: (transfer full): the source GStreamer element
789 cheese_camera_device_get_src (CheeseCameraDevice
*device
)
791 CheeseCameraDevicePrivate
*priv
;
793 g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device
), NULL
);
795 priv
= cheese_camera_device_get_instance_private (device
);
797 return gst_device_create_element (priv
->device
, NULL
);
801 * cheese_camera_device_get_best_format:
802 * @device: a #CheeseCameraDevice
804 * Get the #CheeseVideoFormat with the highest resolution with a width greater
805 * than 640 pixels and a framerate of greater than 15 FPS for this @device. If
806 * no such format is found, get the highest available resolution instead.
808 * Returns: (transfer full): the highest-resolution supported
812 cheese_camera_device_get_best_format (CheeseCameraDevice
*device
)
814 CheeseCameraDevicePrivate
*priv
;
815 CheeseVideoFormatFull
*format
= NULL
;
818 g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device
), NULL
);
820 priv
= cheese_camera_device_get_instance_private (device
);
822 /* Check for the highest resolution with width >= 640 and FPS >= 15. */
823 for (l
= priv
->formats
; l
!= NULL
; l
= g_list_next (l
))
825 CheeseVideoFormatFull
*item
= l
->data
;
826 float frame_rate
= (float)item
->fr_numerator
827 / (float)item
->fr_denominator
;
829 if (item
->width
>= 640 && frame_rate
>= 15)
836 /* Else simply return the highest resolution. */
839 format
= priv
->formats
->data
;
842 GST_INFO ("%dx%d@%d/%d", format
->width
, format
->height
,
843 format
->fr_numerator
, format
->fr_denominator
);
845 return g_boxed_copy (CHEESE_TYPE_VIDEO_FORMAT
, format
);
849 cheese_camera_device_format_to_caps (const char *media_type
,
850 CheeseVideoFormatFull
*format
)
852 if (format
->fr_numerator
!= 0 && format
->fr_denominator
!= 0)
854 return gst_caps_new_simple (media_type
,
855 "framerate", GST_TYPE_FRACTION
,
856 format
->fr_numerator
, format
->fr_denominator
,
857 "width", G_TYPE_INT
, format
->width
,
858 "height", G_TYPE_INT
, format
->height
, NULL
);
862 return gst_caps_new_simple (media_type
,
863 "width", G_TYPE_INT
, format
->width
,
864 "height", G_TYPE_INT
, format
->height
, NULL
);
869 * cheese_camera_device_get_caps_for_format:
870 * @device: a #CheeseCameraDevice
871 * @format: a #CheeseVideoFormat
873 * Get the #GstCaps for the given @format on the @device.
875 * Returns: (transfer full): the #GstCaps for the given @format
878 cheese_camera_device_get_caps_for_format (CheeseCameraDevice
*device
,
879 CheeseVideoFormat
*format
)
881 CheeseCameraDevicePrivate
*priv
;
882 CheeseVideoFormatFull
*full_format
;
883 GstCaps
*desired_caps
;
884 GstCaps
*subset_caps
;
887 g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device
), NULL
);
889 full_format
= cheese_camera_device_find_full_format (device
, format
);
893 GST_INFO ("Getting caps for %dx%d: no such format!",
894 format
->width
, format
->height
);
895 return gst_caps_new_empty ();
898 GST_INFO ("Getting caps for %dx%d @ %d/%d fps",
899 full_format
->width
, full_format
->height
,
900 full_format
->fr_numerator
, full_format
->fr_denominator
);
902 desired_caps
= gst_caps_new_empty ();
904 for (i
= 0; supported_formats
[i
] != NULL
; i
++)
906 gst_caps_append (desired_caps
,
907 cheese_camera_device_format_to_caps (supported_formats
[i
],
911 priv
= cheese_camera_device_get_instance_private (device
);
912 subset_caps
= gst_caps_intersect (desired_caps
, priv
->caps
);
913 subset_caps
= gst_caps_simplify (subset_caps
);
914 gst_caps_unref (desired_caps
);
916 GST_INFO ("Got %" GST_PTR_FORMAT
, subset_caps
);