3 * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * 2006 Edgard Lima <edgard.lima@indt.org.br>
6 * gstv4l2src.c: Video4Linux2 source element
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * SECTION:element-v4l2src
27 * v4l2src can be used to capture video from v4l2 devices, like webcams and tv
31 * <title>Example launch lines</title>
33 * gst-launch v4l2src ! xvimagesink
34 * ]| This pipeline shows the video captured from /dev/video0 tv card and for
37 * gst-launch v4l2src ! jpegdec ! xvimagesink
38 * ]| This pipeline shows the video captured from a webcam that delivers jpeg
49 #include "v4l2src_calls.h"
52 #include "gstv4l2colorbalance.h"
53 #include "gstv4l2tuner.h"
54 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
55 #include "gstv4l2xoverlay.h"
57 #include "gstv4l2vidorient.h"
59 static const GstElementDetails gst_v4l2src_details =
60 GST_ELEMENT_DETAILS ("Video (video4linux2) Source",
62 "Reads frames from a video4linux2 (BT8x8) device",
63 "Ronald Bultje <rbultje@ronald.bitfreak.net>,"
64 " Edgard Lima <edgard.lima@indt.org.br>,"
65 " Stefan Kost <ensonic@users.sf.net>");
67 GST_DEBUG_CATEGORY (v4l2src_debug);
68 #define GST_CAT_DEFAULT v4l2src_debug
70 #define PROP_DEF_QUEUE_SIZE 2
71 #define PROP_DEF_ALWAYS_COPY TRUE
76 V4L2_STD_OBJECT_PROPS,
81 static const guint32 gst_v4l2_formats[] = {
82 /* from Linux 2.6.15 videodev2.h */
101 /* two planes -- one Y, one Cr + Cb interleaved */
105 /* The following formats are not defined in the V4L2 specification */
111 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
112 #ifdef V4L2_PIX_FMT_SBGGR8
116 /* compressed formats */
122 /* Vendor-specific formats */
125 #ifdef V4L2_PIX_FMT_SN9C10X
126 V4L2_PIX_FMT_SN9C10X,
128 #ifdef V4L2_PIX_FMT_PWC1
131 #ifdef V4L2_PIX_FMT_PWC2
134 #ifdef V4L2_PIX_FMT_YVYU
139 #define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
141 GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SrcClass, gst_v4l2src);
142 GST_IMPLEMENT_V4L2_COLOR_BALANCE_METHODS (GstV4l2Src, gst_v4l2src);
143 GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Src, gst_v4l2src);
144 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
145 GST_IMPLEMENT_V4L2_XOVERLAY_METHODS (GstV4l2Src, gst_v4l2src);
147 GST_IMPLEMENT_V4L2_VIDORIENT_METHODS (GstV4l2Src, gst_v4l2src);
150 gst_v4l2src_iface_supported (GstImplementsInterface * iface, GType iface_type)
152 GstV4l2Object *v4l2object = GST_V4L2SRC (iface)->v4l2object;
154 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
155 g_assert (iface_type == GST_TYPE_TUNER ||
156 iface_type == GST_TYPE_X_OVERLAY ||
157 iface_type == GST_TYPE_COLOR_BALANCE ||
158 iface_type == GST_TYPE_VIDEO_ORIENTATION);
160 g_assert (iface_type == GST_TYPE_TUNER ||
161 iface_type == GST_TYPE_COLOR_BALANCE ||
162 iface_type == GST_TYPE_VIDEO_ORIENTATION);
165 if (v4l2object->video_fd == -1)
168 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
169 if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L2_IS_OVERLAY (v4l2object))
177 gst_v4l2src_interface_init (GstImplementsInterfaceClass * klass)
180 * default virtual functions
182 klass->supported = gst_v4l2src_iface_supported;
186 gst_v4l2src_init_interfaces (GType type)
188 static const GInterfaceInfo v4l2iface_info = {
189 (GInterfaceInitFunc) gst_v4l2src_interface_init,
193 static const GInterfaceInfo v4l2_tuner_info = {
194 (GInterfaceInitFunc) gst_v4l2src_tuner_interface_init,
198 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
199 static const GInterfaceInfo v4l2_xoverlay_info = {
200 (GInterfaceInitFunc) gst_v4l2src_xoverlay_interface_init,
205 static const GInterfaceInfo v4l2_colorbalance_info = {
206 (GInterfaceInitFunc) gst_v4l2src_color_balance_interface_init,
210 static const GInterfaceInfo v4l2_videoorientation_info = {
211 (GInterfaceInitFunc) gst_v4l2src_video_orientation_interface_init,
215 static const GInterfaceInfo v4l2_propertyprobe_info = {
216 (GInterfaceInitFunc) gst_v4l2src_property_probe_interface_init,
221 g_type_add_interface_static (type,
222 GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
223 g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l2_tuner_info);
224 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
225 g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
227 g_type_add_interface_static (type,
228 GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
229 g_type_add_interface_static (type,
230 GST_TYPE_VIDEO_ORIENTATION, &v4l2_videoorientation_info);
231 g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
232 &v4l2_propertyprobe_info);
235 GST_BOILERPLATE_FULL (GstV4l2Src, gst_v4l2src, GstPushSrc, GST_TYPE_PUSH_SRC,
236 gst_v4l2src_init_interfaces);
238 static void gst_v4l2src_dispose (GObject * object);
239 static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
241 /* basesrc methods */
242 static gboolean gst_v4l2src_start (GstBaseSrc * src);
243 static gboolean gst_v4l2src_unlock (GstBaseSrc * src);
244 static gboolean gst_v4l2src_unlock_stop (GstBaseSrc * src);
245 static gboolean gst_v4l2src_stop (GstBaseSrc * src);
246 static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
247 static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src);
248 static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
249 static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
250 static void gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
251 static gboolean gst_v4l2src_negotiate (GstBaseSrc * basesrc);
253 static void gst_v4l2src_set_property (GObject * object, guint prop_id,
254 const GValue * value, GParamSpec * pspec);
255 static void gst_v4l2src_get_property (GObject * object, guint prop_id,
256 GValue * value, GParamSpec * pspec);
258 static GstCaps *gst_v4l2src_get_all_caps (void);
261 gst_v4l2src_base_init (gpointer g_class)
263 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
264 GstV4l2SrcClass *gstv4l2src_class = GST_V4L2SRC_CLASS (g_class);
266 gstv4l2src_class->v4l2_class_devices = NULL;
268 GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "V4L2 source element");
270 gst_element_class_set_details (gstelement_class, &gst_v4l2src_details);
272 gst_element_class_add_pad_template
274 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
275 gst_v4l2src_get_all_caps ()));
279 gst_v4l2src_class_init (GstV4l2SrcClass * klass)
281 GObjectClass *gobject_class;
282 GstBaseSrcClass *basesrc_class;
283 GstPushSrcClass *pushsrc_class;
285 gobject_class = G_OBJECT_CLASS (klass);
286 basesrc_class = GST_BASE_SRC_CLASS (klass);
287 pushsrc_class = GST_PUSH_SRC_CLASS (klass);
289 gobject_class->dispose = gst_v4l2src_dispose;
290 gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2src_finalize;
291 gobject_class->set_property = gst_v4l2src_set_property;
292 gobject_class->get_property = gst_v4l2src_get_property;
294 gst_v4l2_object_install_properties_helper (gobject_class);
295 g_object_class_install_property (gobject_class, PROP_QUEUE_SIZE,
296 g_param_spec_uint ("queue-size", "Queue size",
297 "Number of buffers to be enqueud in the driver in streaming mode",
298 GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, PROP_DEF_QUEUE_SIZE,
300 g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
301 g_param_spec_boolean ("always-copy", "Always Copy",
302 "If the buffer will or not be used directly from mmap",
303 PROP_DEF_ALWAYS_COPY, G_PARAM_READWRITE));
305 basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
306 basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps);
307 basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start);
308 basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_v4l2src_unlock);
309 basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_v4l2src_unlock_stop);
310 basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2src_stop);
311 basesrc_class->query = GST_DEBUG_FUNCPTR (gst_v4l2src_query);
312 basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_v4l2src_fixate);
313 basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
315 pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
319 gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
321 /* fixme: give an update_fps_function */
322 v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
323 gst_v4l2_get_input, gst_v4l2_set_input, NULL);
325 /* number of buffers requested */
326 v4l2src->num_buffers = PROP_DEF_QUEUE_SIZE;
328 v4l2src->always_copy = PROP_DEF_ALWAYS_COPY;
330 v4l2src->formats = NULL;
332 v4l2src->is_capturing = FALSE;
334 gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
335 gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
343 gst_v4l2src_dispose (GObject * object)
345 GstV4l2Src *v4l2src = GST_V4L2SRC (object);
347 if (v4l2src->formats) {
348 gst_v4l2src_clear_format_list (v4l2src);
351 if (v4l2src->probed_caps) {
352 gst_caps_unref (v4l2src->probed_caps);
355 G_OBJECT_CLASS (parent_class)->dispose (object);
360 gst_v4l2src_finalize (GstV4l2Src * v4l2src)
362 gst_v4l2_object_destroy (v4l2src->v4l2object);
364 G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (v4l2src));
369 gst_v4l2src_set_property (GObject * object,
370 guint prop_id, const GValue * value, GParamSpec * pspec)
372 GstV4l2Src *v4l2src = GST_V4L2SRC (object);
374 if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
375 prop_id, value, pspec)) {
377 case PROP_QUEUE_SIZE:
378 v4l2src->num_buffers = g_value_get_uint (value);
380 case PROP_ALWAYS_COPY:
381 v4l2src->always_copy = g_value_get_boolean (value);
384 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
392 gst_v4l2src_get_property (GObject * object,
393 guint prop_id, GValue * value, GParamSpec * pspec)
395 GstV4l2Src *v4l2src = GST_V4L2SRC (object);
397 if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
398 prop_id, value, pspec)) {
400 case PROP_QUEUE_SIZE:
401 g_value_set_uint (value, v4l2src->num_buffers);
403 case PROP_ALWAYS_COPY:
404 g_value_set_boolean (value, v4l2src->always_copy);
407 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
414 /* this function is a bit of a last resort */
416 gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
418 GstStructure *structure;
421 GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
423 for (i = 0; i < gst_caps_get_size (caps); ++i) {
426 structure = gst_caps_get_structure (caps, i);
428 /* FIXME such sizes? we usually fixate to something in the 320x200
430 /* We are fixating to greater possble size (limited to GST_V4L2_MAX_SIZE)
431 and the maximum framerate resolution for that size */
432 gst_structure_fixate_field_nearest_int (structure, "width",
434 gst_structure_fixate_field_nearest_int (structure, "height",
436 gst_structure_fixate_field_nearest_fraction (structure, "framerate",
439 v = gst_structure_get_value (structure, "format");
440 if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
443 g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
445 fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
446 gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
450 GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
455 gst_v4l2src_negotiate (GstBaseSrc * basesrc)
458 GstCaps *caps = NULL;
459 GstCaps *peercaps = NULL;
460 gboolean result = FALSE;
462 /* first see what is possible on our source pad */
463 thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
464 GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
465 /* nothing or anything is allowed, we're done */
466 if (thiscaps == NULL || gst_caps_is_any (thiscaps))
469 /* get the peer caps */
470 peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
471 GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
472 if (peercaps && !gst_caps_is_any (peercaps)) {
473 GstCaps *icaps = NULL;
476 /* Prefer the first caps we are compatible with that the peer proposed */
477 for (i = 0; i < gst_caps_get_size (peercaps); i++) {
478 /* get intersection */
479 GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
481 GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
483 icaps = gst_caps_intersect (thiscaps, ipcaps);
484 gst_caps_unref (ipcaps);
486 if (!gst_caps_is_empty (icaps))
489 gst_caps_unref (icaps);
493 GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
495 /* If there are multiple intersections pick the one with the smallest
496 * resolution strictly bigger then the first peer caps */
497 if (gst_caps_get_size (icaps) > 1) {
498 GstStructure *s = gst_caps_get_structure (peercaps, 0);
504 int width = G_MAXINT, height = G_MAXINT;
506 if (gst_structure_get_int (s, "width", &twidth)
507 && gst_structure_get_int (s, "height", &theight)) {
509 /* Walk the structure backwards to get the first entry of the
510 * smallest resolution bigger (or equal to) the preferred resolution)
512 for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
513 GstStructure *is = gst_caps_get_structure (icaps, i);
517 if (gst_structure_get_int (is, "width", &w)
518 && gst_structure_get_int (is, "height", &h)) {
519 if (w >= twidth && w <= width && h >= theight && h <= height) {
528 caps = gst_caps_copy_nth (icaps, best);
529 gst_caps_unref (icaps);
534 gst_caps_unref (thiscaps);
535 gst_caps_unref (peercaps);
537 /* no peer or peer have ANY caps, work with our own caps then */
541 caps = gst_caps_make_writable (caps);
542 gst_caps_truncate (caps);
545 if (!gst_caps_is_empty (caps)) {
546 gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
547 GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
549 if (gst_caps_is_any (caps)) {
550 /* hmm, still anything, so element can do anything and
551 * nego is not needed */
553 } else if (gst_caps_is_fixed (caps)) {
554 /* yay, fixed caps, use those then */
555 gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
559 gst_caps_unref (caps);
565 GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
567 gst_caps_unref (thiscaps);
573 static GstStructure *
574 gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc)
576 GstStructure *structure = NULL;
579 case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */
580 case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */
581 structure = gst_structure_new ("image/jpeg", NULL);
583 case V4L2_PIX_FMT_RGB332:
584 case V4L2_PIX_FMT_RGB555:
585 case V4L2_PIX_FMT_RGB555X:
586 case V4L2_PIX_FMT_RGB565:
587 case V4L2_PIX_FMT_RGB565X:
588 case V4L2_PIX_FMT_RGB24:
589 case V4L2_PIX_FMT_BGR24:
590 case V4L2_PIX_FMT_RGB32:
591 case V4L2_PIX_FMT_BGR32:{
592 guint depth = 0, bpp = 0;
596 guint32 r_mask = 0, b_mask = 0, g_mask = 0;
599 case V4L2_PIX_FMT_RGB332:
601 endianness = G_BYTE_ORDER; /* 'like, whatever' */
606 case V4L2_PIX_FMT_RGB555:
607 case V4L2_PIX_FMT_RGB555X:
611 fourcc == V4L2_PIX_FMT_RGB555X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
616 case V4L2_PIX_FMT_RGB565:
617 case V4L2_PIX_FMT_RGB565X:
620 fourcc == V4L2_PIX_FMT_RGB565X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
625 case V4L2_PIX_FMT_RGB24:
627 endianness = G_BIG_ENDIAN;
632 case V4L2_PIX_FMT_BGR24:
634 endianness = G_BIG_ENDIAN;
639 case V4L2_PIX_FMT_RGB32:
641 endianness = G_BIG_ENDIAN;
646 case V4L2_PIX_FMT_BGR32:
648 endianness = G_BIG_ENDIAN;
654 g_assert_not_reached ();
657 structure = gst_structure_new ("video/x-raw-rgb",
658 "bpp", G_TYPE_INT, bpp,
659 "depth", G_TYPE_INT, depth,
660 "red_mask", G_TYPE_INT, r_mask,
661 "green_mask", G_TYPE_INT, g_mask,
662 "blue_mask", G_TYPE_INT, b_mask,
663 "endianness", G_TYPE_INT, endianness, NULL);
666 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
667 structure = gst_structure_new ("video/x-raw-gray",
668 "bpp", G_TYPE_INT, 8, NULL);
670 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
671 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
672 /* FIXME: get correct fourccs here */
674 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
675 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
676 case V4L2_PIX_FMT_YVU410:
677 case V4L2_PIX_FMT_YUV410:
678 case V4L2_PIX_FMT_YUV420: /* I420/IYUV */
679 case V4L2_PIX_FMT_YUYV:
680 case V4L2_PIX_FMT_YVU420:
681 case V4L2_PIX_FMT_UYVY:
682 case V4L2_PIX_FMT_Y41P:
683 case V4L2_PIX_FMT_YUV422P:
684 #ifdef V4L2_PIX_FMT_YVYU
685 case V4L2_PIX_FMT_YVYU:
687 case V4L2_PIX_FMT_YUV411P:{
691 case V4L2_PIX_FMT_NV12:
692 fcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
694 case V4L2_PIX_FMT_NV21:
695 fcc = GST_MAKE_FOURCC ('N', 'V', '2', '1');
697 case V4L2_PIX_FMT_YVU410:
698 fcc = GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
700 case V4L2_PIX_FMT_YUV410:
701 fcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
703 case V4L2_PIX_FMT_YUV420:
704 fcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
706 case V4L2_PIX_FMT_YUYV:
707 fcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
709 case V4L2_PIX_FMT_YVU420:
710 fcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
712 case V4L2_PIX_FMT_UYVY:
713 fcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
715 case V4L2_PIX_FMT_Y41P:
716 fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P');
718 case V4L2_PIX_FMT_YUV411P:
719 fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
721 case V4L2_PIX_FMT_YUV422P:
722 fcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
724 #ifdef V4L2_PIX_FMT_YVYU
725 case V4L2_PIX_FMT_YVYU:
726 fcc = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
730 g_assert_not_reached ();
733 structure = gst_structure_new ("video/x-raw-yuv",
734 "format", GST_TYPE_FOURCC, fcc, NULL);
737 case V4L2_PIX_FMT_DV:
739 gst_structure_new ("video/x-dv", "systemstream", G_TYPE_BOOLEAN, TRUE,
742 case V4L2_PIX_FMT_MPEG: /* MPEG */
743 /* someone figure out the MPEG format used... */
745 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
747 #ifdef V4L2_PIX_FMT_SBGGR8
748 case V4L2_PIX_FMT_SBGGR8:
749 structure = gst_structure_new ("video/x-raw-bayer", NULL);
752 #ifdef V4L2_PIX_FMT_SN9C10X
753 case V4L2_PIX_FMT_SN9C10X:
754 structure = gst_structure_new ("video/x-sonix", NULL);
757 #ifdef V4L2_PIX_FMT_PWC1
758 case V4L2_PIX_FMT_PWC1:
759 structure = gst_structure_new ("video/x-pwc1", NULL);
762 #ifdef V4L2_PIX_FMT_PWC2
763 case V4L2_PIX_FMT_PWC2:
764 structure = gst_structure_new ("video/x-pwc2", NULL);
768 GST_DEBUG ("Unknown fourcc 0x%08x %" GST_FOURCC_FORMAT,
769 fourcc, GST_FOURCC_ARGS (fourcc));
776 static struct v4l2_fmtdesc *
777 gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
779 struct v4l2_fmtdesc *fmt;
785 walk = v4l2src->formats;
787 fmt = (struct v4l2_fmtdesc *) walk->data;
788 if (fmt->pixelformat == fourcc)
790 /* special case for jpeg */
791 if ((fmt->pixelformat == V4L2_PIX_FMT_MJPEG && fourcc == V4L2_PIX_FMT_JPEG)
792 || (fmt->pixelformat == V4L2_PIX_FMT_JPEG
793 && fourcc == V4L2_PIX_FMT_MJPEG)) {
796 walk = g_slist_next (walk);
803 gst_v4l2src_get_all_caps (void)
805 static GstCaps *caps = NULL;
808 GstStructure *structure;
812 caps = gst_caps_new_empty ();
813 for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
814 structure = gst_v4l2src_v4l2fourcc_to_structure (gst_v4l2_formats[i]);
816 gst_structure_set (structure,
817 "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
818 "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
819 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL);
820 gst_caps_append_structure (caps, structure);
829 gst_v4l2src_get_caps (GstBaseSrc * src)
831 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
835 if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
838 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
842 if (v4l2src->probed_caps)
843 return gst_caps_ref (v4l2src->probed_caps);
845 if (!v4l2src->formats)
846 gst_v4l2src_fill_format_list (v4l2src);
848 ret = gst_caps_new_empty ();
850 for (walk = v4l2src->formats; walk; walk = walk->next) {
851 struct v4l2_fmtdesc *format;
853 GstStructure *template;
855 format = (struct v4l2_fmtdesc *) walk->data;
857 template = gst_v4l2src_v4l2fourcc_to_structure (format->pixelformat);
862 tmp = gst_v4l2src_probe_caps_for_format (v4l2src, format->pixelformat,
865 gst_caps_append (ret, tmp);
867 gst_structure_free (template);
869 GST_DEBUG_OBJECT (v4l2src, "unknown format %u", format->pixelformat);
873 v4l2src->probed_caps = gst_caps_ref (ret);
875 GST_INFO_OBJECT (v4l2src, "probed caps: %" GST_PTR_FORMAT, ret);
880 /* collect data for the given caps
881 * @caps: given input caps
882 * @format: location for the v4l format
883 * @w/@h: location for width and height
884 * @fps_n/@fps_d: location for framerate
885 * @size: location for expected size of the frame or 0 if unknown
888 gst_v4l2_get_caps_info (GstV4l2Src * v4l2src, GstCaps * caps,
889 struct v4l2_fmtdesc **format, gint * w, gint * h, guint * fps_n,
890 guint * fps_d, guint * size)
892 GstStructure *structure;
893 const GValue *framerate;
895 const gchar *mimetype;
898 /* default unknown values */
902 structure = gst_caps_get_structure (caps, 0);
904 if (!gst_structure_get_int (structure, "width", w))
907 if (!gst_structure_get_int (structure, "height", h))
910 framerate = gst_structure_get_value (structure, "framerate");
914 *fps_n = gst_value_get_fraction_numerator (framerate);
915 *fps_d = gst_value_get_fraction_denominator (framerate);
917 mimetype = gst_structure_get_name (structure);
919 if (!strcmp (mimetype, "video/x-raw-yuv")) {
920 gst_structure_get_fourcc (structure, "format", &fourcc);
923 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
924 case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
925 fourcc = V4L2_PIX_FMT_YUV420;
926 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
927 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
929 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
930 fourcc = V4L2_PIX_FMT_YUYV;
931 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
933 case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
934 fourcc = V4L2_PIX_FMT_Y41P;
935 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
937 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
938 fourcc = V4L2_PIX_FMT_UYVY;
939 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
941 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
942 fourcc = V4L2_PIX_FMT_YVU420;
943 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
944 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
946 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
947 fourcc = V4L2_PIX_FMT_YUV411P;
948 outsize = GST_ROUND_UP_4 (*w) * *h;
949 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
951 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
952 fourcc = V4L2_PIX_FMT_YUV422P;
953 outsize = GST_ROUND_UP_4 (*w) * *h;
954 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
956 case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
957 fourcc = V4L2_PIX_FMT_NV12;
958 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
959 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
961 case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
962 fourcc = V4L2_PIX_FMT_NV21;
963 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
964 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
966 #ifdef V4L2_PIX_FMT_YVYU
967 case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
968 fourcc = V4L2_PIX_FMT_YVYU;
969 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
973 } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
974 gint depth, endianness, r_mask;
976 gst_structure_get_int (structure, "depth", &depth);
977 gst_structure_get_int (structure, "endianness", &endianness);
978 gst_structure_get_int (structure, "red_mask", &r_mask);
982 fourcc = V4L2_PIX_FMT_RGB332;
985 fourcc = (endianness == G_LITTLE_ENDIAN) ?
986 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
989 fourcc = (endianness == G_LITTLE_ENDIAN) ?
990 V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
993 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
996 fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
999 } else if (strcmp (mimetype, "video/x-dv") == 0) {
1000 fourcc = V4L2_PIX_FMT_DV;
1001 } else if (strcmp (mimetype, "image/jpeg") == 0) {
1002 fourcc = V4L2_PIX_FMT_JPEG;
1003 #ifdef V4L2_PIX_FMT_SBGGR8
1004 } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
1005 fourcc = V4L2_PIX_FMT_SBGGR8;
1007 #ifdef V4L2_PIX_FMT_SN9C10X
1008 } else if (strcmp (mimetype, "video/x-sonix") == 0) {
1009 fourcc = V4L2_PIX_FMT_SN9C10X;
1011 #ifdef V4L2_PIX_FMT_PWC1
1012 } else if (strcmp (mimetype, "video/x-pwc1") == 0) {
1013 fourcc = V4L2_PIX_FMT_PWC1;
1015 #ifdef V4L2_PIX_FMT_PWC2
1016 } else if (strcmp (mimetype, "video/x-pwc2") == 0) {
1017 fourcc = V4L2_PIX_FMT_PWC2;
1019 } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
1020 fourcc = V4L2_PIX_FMT_GREY;
1026 *format = gst_v4l2src_get_format_from_fourcc (v4l2src, fourcc);
1033 gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
1035 GstV4l2Src *v4l2src;
1037 struct v4l2_fmtdesc *format;
1041 v4l2src = GST_V4L2SRC (src);
1043 /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1044 if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object))
1047 /* make sure we stop capturing and dealloc buffers */
1048 if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
1049 /* both will throw an element-error on failure */
1050 if (!gst_v4l2src_capture_stop (v4l2src))
1052 if (!gst_v4l2src_capture_deinit (v4l2src))
1056 /* we want our own v4l2 type of fourcc codes */
1057 if (!gst_v4l2_get_caps_info (v4l2src, caps, &format, &w, &h, &fps_n, &fps_d,
1059 GST_DEBUG_OBJECT (v4l2src,
1060 "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1064 GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
1065 "format %s", w, h, fps_n, fps_d, format->description);
1067 if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, fps_n,
1069 /* error already posted */
1072 if (!gst_v4l2src_capture_init (v4l2src, caps))
1075 if (!gst_v4l2src_capture_start (v4l2src))
1078 /* now store the expected output size */
1079 v4l2src->frame_byte_size = size;
1085 gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
1089 gboolean res = FALSE;
1091 src = GST_V4L2SRC (bsrc);
1093 switch (GST_QUERY_TYPE (query)) {
1094 case GST_QUERY_LATENCY:{
1095 GstClockTime min_latency, max_latency;
1097 /* device must be open */
1098 if (!GST_V4L2_IS_OPEN (src->v4l2object)) {
1099 GST_WARNING_OBJECT (src,
1100 "Can't give latency since device isn't open !");
1104 /* we must have a framerate */
1105 if (src->fps_n <= 0 || src->fps_d <= 0) {
1106 GST_WARNING_OBJECT (src,
1107 "Can't give latency since framerate isn't fixated !");
1111 /* min latency is the time to capture one frame */
1113 gst_util_uint64_scale_int (GST_SECOND, src->fps_d, src->fps_n);
1115 /* max latency is total duration of the frame buffer */
1116 max_latency = src->num_buffers * min_latency;
1118 GST_DEBUG_OBJECT (bsrc,
1119 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1120 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
1122 /* we are always live, the min latency is 1 frame and the max latency is
1123 * the complete buffer of frames. */
1124 gst_query_set_latency (query, TRUE, min_latency, max_latency);
1130 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1139 /* start and stop are not symmetric -- start will open the device, but not start
1140 * capture. it's setcaps that will start capture, which is called via basesrc's
1141 * negotiate method. stop will both stop capture and close the device.
1144 gst_v4l2src_start (GstBaseSrc * src)
1146 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1148 /* open the device */
1149 if (!gst_v4l2_object_start (v4l2src->v4l2object))
1152 v4l2src->offset = 0;
1158 gst_v4l2src_unlock (GstBaseSrc * src)
1160 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1162 GST_LOG_OBJECT (src, "Flushing");
1163 gst_poll_set_flushing (v4l2src->v4l2object->poll, TRUE);
1169 gst_v4l2src_unlock_stop (GstBaseSrc * src)
1171 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1173 GST_LOG_OBJECT (src, "No longer flushing");
1174 gst_poll_set_flushing (v4l2src->v4l2object->poll, FALSE);
1181 gst_v4l2src_stop (GstBaseSrc * src)
1183 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1185 if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)
1186 && !gst_v4l2src_capture_stop (v4l2src))
1189 if (v4l2src->v4l2object->buffer != NULL) {
1190 if (!gst_v4l2src_capture_deinit (v4l2src))
1194 /* close the device */
1195 if (!gst_v4l2_object_stop (v4l2src->v4l2object))
1204 static GstFlowReturn
1205 gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
1212 buffersize = v4l2src->frame_byte_size;
1214 *buf = gst_buffer_new_and_alloc (buffersize);
1217 ret = gst_poll_wait (v4l2src->v4l2object->poll, GST_CLOCK_TIME_NONE);
1218 if (G_UNLIKELY (ret < 0)) {
1221 if (errno != EAGAIN && errno != EINTR)
1225 v4l2_read (v4l2src->v4l2object->video_fd, GST_BUFFER_DATA (*buf),
1227 if (amount == buffersize) {
1229 } else if (amount == -1) {
1230 if (errno == EAGAIN || errno == EINTR) {
1235 /* short reads can happen if a signal interrupts the read */
1240 /* we set the buffer metadata in gst_v4l2src_create() */
1247 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
1248 ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
1249 return GST_FLOW_ERROR;
1253 GST_DEBUG ("stop called");
1254 return GST_FLOW_WRONG_STATE;
1258 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
1259 (_("Error reading %d bytes from device '%s'."),
1260 buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
1261 gst_buffer_unref (*buf);
1262 return GST_FLOW_ERROR;
1266 static GstFlowReturn
1267 gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
1275 ret = gst_v4l2src_grab_frame (v4l2src, &temp);
1276 if (ret != GST_FLOW_OK)
1279 if (v4l2src->frame_byte_size > 0) {
1280 size = GST_BUFFER_SIZE (temp);
1282 /* if size does not match what we expected, try again */
1283 if (size != v4l2src->frame_byte_size) {
1284 GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ,
1285 (_("Got unexpected frame size of %u instead of %u."),
1286 size, v4l2src->frame_byte_size), (NULL));
1287 gst_buffer_unref (temp);
1302 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
1303 (_("Error reading %d bytes on device '%s'."),
1304 v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL));
1305 return GST_FLOW_ERROR;
1309 static GstFlowReturn
1310 gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
1312 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1316 if (v4l2src->use_mmap) {
1317 ret = gst_v4l2src_get_mmap (v4l2src, buf);
1319 ret = gst_v4l2src_get_read (v4l2src, buf);
1321 /* set buffer metadata */
1322 if (ret == GST_FLOW_OK && *buf) {
1324 GstClockTime timestamp;
1326 GST_BUFFER_OFFSET (*buf) = v4l2src->offset++;
1327 GST_BUFFER_OFFSET_END (*buf) = v4l2src->offset;
1329 /* timestamps, LOCK to get clock and base time. */
1330 GST_OBJECT_LOCK (v4l2src);
1331 if ((clock = GST_ELEMENT_CLOCK (v4l2src))) {
1332 /* we have a clock, get base time and ref clock */
1333 timestamp = GST_ELEMENT (v4l2src)->base_time;
1334 gst_object_ref (clock);
1336 /* no clock, can't set timestamps */
1337 timestamp = GST_CLOCK_TIME_NONE;
1339 GST_OBJECT_UNLOCK (v4l2src);
1342 GstClockTime latency;
1344 /* the time now is the time of the clock minus the base time */
1345 timestamp = gst_clock_get_time (clock) - timestamp;
1346 gst_object_unref (clock);
1349 gst_util_uint64_scale_int (GST_SECOND, v4l2src->fps_d,
1352 if (timestamp > latency)
1353 timestamp -= latency;
1358 /* FIXME: use the timestamp from the buffer itself! */
1359 GST_BUFFER_TIMESTAMP (*buf) = timestamp;