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-0.10 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/raw) Source",
62 "Reads raw frames from a video4linux2 (BT8x8) device",
63 "Ronald Bultje <rbultje@ronald.bitfreak.net>,"
64 " Edgard Lima <edgard.lima@indt.org.br>");
66 GST_DEBUG_CATEGORY (v4l2src_debug);
67 #define GST_CAT_DEFAULT v4l2src_debug
69 #define DEFAULT_PROP_ALWAYS_COPY TRUE
74 V4L2_STD_OBJECT_PROPS,
79 static const guint32 gst_v4l2_formats[] = {
80 /* from Linux 2.6.15 videodev2.h */
99 /* two planes -- one Y, one Cr + Cb interleaved */
103 /* The following formats are not defined in the V4L2 specification */
109 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
110 #ifdef V4L2_PIX_FMT_SBGGR8
114 /* compressed formats */
120 /* Vendor-specific formats */
123 #ifdef V4L2_PIX_FMT_SN9C10X
124 V4L2_PIX_FMT_SN9C10X,
126 #ifdef V4L2_PIX_FMT_PWC1
129 #ifdef V4L2_PIX_FMT_PWC2
134 #define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
136 GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SrcClass, gst_v4l2src);
137 GST_IMPLEMENT_V4L2_COLOR_BALANCE_METHODS (GstV4l2Src, gst_v4l2src);
138 GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Src, gst_v4l2src);
139 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
140 GST_IMPLEMENT_V4L2_XOVERLAY_METHODS (GstV4l2Src, gst_v4l2src);
142 GST_IMPLEMENT_V4L2_VIDORIENT_METHODS (GstV4l2Src, gst_v4l2src);
145 gst_v4l2src_iface_supported (GstImplementsInterface * iface, GType iface_type)
147 GstV4l2Object *v4l2object = GST_V4L2SRC (iface)->v4l2object;
149 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
150 g_assert (iface_type == GST_TYPE_TUNER ||
151 iface_type == GST_TYPE_X_OVERLAY ||
152 iface_type == GST_TYPE_COLOR_BALANCE ||
153 iface_type == GST_TYPE_VIDEO_ORIENTATION);
155 g_assert (iface_type == GST_TYPE_TUNER ||
156 iface_type == GST_TYPE_COLOR_BALANCE ||
157 iface_type == GST_TYPE_VIDEO_ORIENTATION);
160 if (v4l2object->video_fd == -1)
163 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
164 if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L2_IS_OVERLAY (v4l2object))
172 gst_v4l2src_interface_init (GstImplementsInterfaceClass * klass)
175 * default virtual functions
177 klass->supported = gst_v4l2src_iface_supported;
181 gst_v4l2src_init_interfaces (GType type)
183 static const GInterfaceInfo v4l2iface_info = {
184 (GInterfaceInitFunc) gst_v4l2src_interface_init,
188 static const GInterfaceInfo v4l2_tuner_info = {
189 (GInterfaceInitFunc) gst_v4l2src_tuner_interface_init,
193 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
194 static const GInterfaceInfo v4l2_xoverlay_info = {
195 (GInterfaceInitFunc) gst_v4l2src_xoverlay_interface_init,
200 static const GInterfaceInfo v4l2_colorbalance_info = {
201 (GInterfaceInitFunc) gst_v4l2src_color_balance_interface_init,
205 static const GInterfaceInfo v4l2_videoorientation_info = {
206 (GInterfaceInitFunc) gst_v4l2src_video_orientation_interface_init,
210 static const GInterfaceInfo v4l2_propertyprobe_info = {
211 (GInterfaceInitFunc) gst_v4l2src_property_probe_interface_init,
216 g_type_add_interface_static (type,
217 GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
218 g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l2_tuner_info);
219 #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
220 g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
222 g_type_add_interface_static (type,
223 GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
224 g_type_add_interface_static (type,
225 GST_TYPE_VIDEO_ORIENTATION, &v4l2_videoorientation_info);
226 g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
227 &v4l2_propertyprobe_info);
230 GST_BOILERPLATE_FULL (GstV4l2Src, gst_v4l2src, GstPushSrc, GST_TYPE_PUSH_SRC,
231 gst_v4l2src_init_interfaces);
233 static void gst_v4l2src_dispose (GObject * object);
235 static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
237 /* basesrc methods */
238 static gboolean gst_v4l2src_start (GstBaseSrc * src);
240 static gboolean gst_v4l2src_stop (GstBaseSrc * src);
242 static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
244 static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src);
246 static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
248 static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
250 static void gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
252 static gboolean gst_v4l2src_negotiate (GstBaseSrc * basesrc);
254 static void gst_v4l2src_set_property (GObject * object, guint prop_id,
255 const GValue * value, GParamSpec * pspec);
256 static void gst_v4l2src_get_property (GObject * object, guint prop_id,
257 GValue * value, GParamSpec * pspec);
259 static GstCaps *gst_v4l2src_get_all_caps (void);
262 gst_v4l2src_base_init (gpointer g_class)
264 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
266 GstV4l2SrcClass *gstv4l2src_class = GST_V4L2SRC_CLASS (g_class);
268 gstv4l2src_class->v4l2_class_devices = NULL;
270 GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "V4L2 source element");
272 gst_element_class_set_details (gstelement_class, &gst_v4l2src_details);
274 gst_element_class_add_pad_template
276 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
277 gst_v4l2src_get_all_caps ()));
281 gst_v4l2src_class_init (GstV4l2SrcClass * klass)
283 GObjectClass *gobject_class;
285 GstBaseSrcClass *basesrc_class;
287 GstPushSrcClass *pushsrc_class;
289 gobject_class = G_OBJECT_CLASS (klass);
290 basesrc_class = GST_BASE_SRC_CLASS (klass);
291 pushsrc_class = GST_PUSH_SRC_CLASS (klass);
293 gobject_class->dispose = gst_v4l2src_dispose;
294 gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2src_finalize;
295 gobject_class->set_property = gst_v4l2src_set_property;
296 gobject_class->get_property = gst_v4l2src_get_property;
298 gst_v4l2_object_install_properties_helper (gobject_class);
299 g_object_class_install_property (gobject_class, PROP_QUEUE_SIZE,
300 g_param_spec_uint ("queue-size", "Queue size",
301 "Number of buffers to be enqueud in the driver",
302 GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS,
304 g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
305 g_param_spec_boolean ("always-copy", "Always Copy",
306 "If the buffer will or not be used directly from mmap",
307 DEFAULT_PROP_ALWAYS_COPY, G_PARAM_READWRITE));
309 basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
310 basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps);
311 basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start);
312 basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2src_stop);
313 basesrc_class->query = GST_DEBUG_FUNCPTR (gst_v4l2src_query);
314 basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_v4l2src_fixate);
315 basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
317 pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
321 gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
323 /* fixme: give an update_fps_function */
324 v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
325 gst_v4l2_get_input, gst_v4l2_set_input, NULL);
327 /* number of buffers requested */
328 v4l2src->num_buffers = GST_V4L2_MIN_BUFFERS;
330 v4l2src->always_copy = DEFAULT_PROP_ALWAYS_COPY;
332 v4l2src->formats = NULL;
334 v4l2src->is_capturing = FALSE;
336 gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
337 gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
345 gst_v4l2src_dispose (GObject * object)
347 GstV4l2Src *v4l2src = GST_V4L2SRC (object);
349 if (v4l2src->formats) {
350 gst_v4l2src_clear_format_list (v4l2src);
353 if (v4l2src->probed_caps) {
354 gst_caps_unref (v4l2src->probed_caps);
358 G_OBJECT_CLASS (parent_class)->dispose (object);
363 gst_v4l2src_finalize (GstV4l2Src * v4l2src)
365 gst_v4l2_object_destroy (v4l2src->v4l2object);
367 G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (v4l2src));
372 gst_v4l2src_set_property (GObject * object,
373 guint prop_id, const GValue * value, GParamSpec * pspec)
375 GstV4l2Src *v4l2src = GST_V4L2SRC (object);
377 if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
378 prop_id, value, pspec)) {
380 case PROP_QUEUE_SIZE:
381 v4l2src->num_buffers = g_value_get_uint (value);
383 case PROP_ALWAYS_COPY:
384 v4l2src->always_copy = g_value_get_boolean (value);
387 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
395 gst_v4l2src_get_property (GObject * object,
396 guint prop_id, GValue * value, GParamSpec * pspec)
398 GstV4l2Src *v4l2src = GST_V4L2SRC (object);
400 if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
401 prop_id, value, pspec)) {
403 case PROP_QUEUE_SIZE:
404 g_value_set_uint (value, v4l2src->num_buffers);
406 case PROP_ALWAYS_COPY:
407 g_value_set_boolean (value, v4l2src->always_copy);
410 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
417 /* this function is a bit of a last resort */
419 gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
421 GstStructure *structure;
425 GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
427 for (i = 0; i < gst_caps_get_size (caps); ++i) {
430 structure = gst_caps_get_structure (caps, i);
432 /* FIXME such sizes? we usually fixate to something in the 320x200
434 /* We are fixating to greater possble size (limited to GST_V4L2_MAX_SIZE)
435 and the maximum framerate resolution for that size */
436 gst_structure_fixate_field_nearest_int (structure, "width",
438 gst_structure_fixate_field_nearest_int (structure, "height",
440 gst_structure_fixate_field_nearest_fraction (structure, "framerate",
443 v = gst_structure_get_value (structure, "format");
444 if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
447 g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
449 fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
450 gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
454 GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
459 gst_v4l2src_negotiate (GstBaseSrc * basesrc)
463 GstCaps *caps = NULL;
465 GstCaps *peercaps = NULL;
467 gboolean result = FALSE;
469 /* first see what is possible on our source pad */
470 thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
471 GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
472 /* nothing or anything is allowed, we're done */
473 if (thiscaps == NULL || gst_caps_is_any (thiscaps))
476 /* get the peer caps */
477 peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
478 GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
479 if (peercaps && !gst_caps_is_any (peercaps)) {
480 GstCaps *icaps = NULL;
483 /* Prefer the first caps we are compatible with that the peer proposed */
484 for (i = 0; i < gst_caps_get_size (peercaps); i++) {
485 /* get intersection */
486 GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
488 GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
490 icaps = gst_caps_intersect (thiscaps, ipcaps);
491 gst_caps_unref (ipcaps);
493 if (!gst_caps_is_empty (icaps))
496 gst_caps_unref (icaps);
500 GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
502 /* If there are multiple intersections pick the one with the smallest
503 * resolution strictly bigger then the first peer caps */
504 if (gst_caps_get_size (icaps) > 1) {
505 GstStructure *s = gst_caps_get_structure (peercaps, 0);
511 int width = G_MAXINT, height = G_MAXINT;
513 if (gst_structure_get_int (s, "width", &twidth)
514 && gst_structure_get_int (s, "height", &theight)) {
516 /* Walk the structure backwards to get the first entry of the
517 * smallest resolution bigger (or equal to) the preferred resolution)
519 for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
520 GstStructure *is = gst_caps_get_structure (icaps, i);
524 if (gst_structure_get_int (is, "width", &w)
525 && gst_structure_get_int (is, "height", &h)) {
526 if (w >= twidth && w <= width && h >= theight && h <= height) {
535 caps = gst_caps_copy_nth (icaps, best);
536 gst_caps_unref (icaps);
541 gst_caps_unref (thiscaps);
542 gst_caps_unref (peercaps);
544 /* no peer or peer have ANY caps, work with our own caps then */
548 caps = gst_caps_make_writable (caps);
549 gst_caps_truncate (caps);
552 if (!gst_caps_is_empty (caps)) {
553 gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
554 GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
556 if (gst_caps_is_any (caps)) {
557 /* hmm, still anything, so element can do anything and
558 * nego is not needed */
560 } else if (gst_caps_is_fixed (caps)) {
561 /* yay, fixed caps, use those then */
562 gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
566 gst_caps_unref (caps);
572 GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
574 gst_caps_unref (thiscaps);
580 static GstStructure *
581 gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc)
583 GstStructure *structure = NULL;
586 case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */
587 case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */
588 structure = gst_structure_new ("image/jpeg", NULL);
590 case V4L2_PIX_FMT_RGB332:
591 case V4L2_PIX_FMT_RGB555:
592 case V4L2_PIX_FMT_RGB555X:
593 case V4L2_PIX_FMT_RGB565:
594 case V4L2_PIX_FMT_RGB565X:
595 case V4L2_PIX_FMT_RGB24:
596 case V4L2_PIX_FMT_BGR24:
597 case V4L2_PIX_FMT_RGB32:
598 case V4L2_PIX_FMT_BGR32:{
599 guint depth = 0, bpp = 0;
603 guint32 r_mask = 0, b_mask = 0, g_mask = 0;
606 case V4L2_PIX_FMT_RGB332:
608 endianness = G_BYTE_ORDER; /* 'like, whatever' */
613 case V4L2_PIX_FMT_RGB555:
614 case V4L2_PIX_FMT_RGB555X:
618 fourcc == V4L2_PIX_FMT_RGB555X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
623 case V4L2_PIX_FMT_RGB565:
624 case V4L2_PIX_FMT_RGB565X:
627 fourcc == V4L2_PIX_FMT_RGB565X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
632 case V4L2_PIX_FMT_RGB24:
634 endianness = G_BIG_ENDIAN;
639 case V4L2_PIX_FMT_BGR24:
641 endianness = G_BIG_ENDIAN;
646 case V4L2_PIX_FMT_RGB32:
648 endianness = G_BIG_ENDIAN;
653 case V4L2_PIX_FMT_BGR32:
655 endianness = G_BIG_ENDIAN;
661 g_assert_not_reached ();
664 structure = gst_structure_new ("video/x-raw-rgb",
665 "bpp", G_TYPE_INT, bpp,
666 "depth", G_TYPE_INT, depth,
667 "red_mask", G_TYPE_INT, r_mask,
668 "green_mask", G_TYPE_INT, g_mask,
669 "blue_mask", G_TYPE_INT, b_mask,
670 "endianness", G_TYPE_INT, endianness, NULL);
673 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
674 structure = gst_structure_new ("video/x-raw-gray",
675 "bpp", G_TYPE_INT, 8, NULL);
677 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
678 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
679 /* FIXME: get correct fourccs here */
681 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
682 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
683 case V4L2_PIX_FMT_YVU410:
684 case V4L2_PIX_FMT_YUV410:
685 case V4L2_PIX_FMT_YUV420: /* I420/IYUV */
686 case V4L2_PIX_FMT_YUYV:
687 case V4L2_PIX_FMT_YVU420:
688 case V4L2_PIX_FMT_UYVY:
689 case V4L2_PIX_FMT_Y41P:
690 case V4L2_PIX_FMT_YUV422P:
691 case V4L2_PIX_FMT_YUV411P:{
695 case V4L2_PIX_FMT_NV12:
696 fcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
698 case V4L2_PIX_FMT_NV21:
699 fcc = GST_MAKE_FOURCC ('N', 'V', '2', '1');
701 case V4L2_PIX_FMT_YVU410:
702 fcc = GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
704 case V4L2_PIX_FMT_YUV410:
705 fcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
707 case V4L2_PIX_FMT_YUV420:
708 fcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
710 case V4L2_PIX_FMT_YUYV:
711 fcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
713 case V4L2_PIX_FMT_YVU420:
714 fcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
716 case V4L2_PIX_FMT_UYVY:
717 fcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
719 case V4L2_PIX_FMT_Y41P:
720 fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P');
722 case V4L2_PIX_FMT_YUV411P:
723 fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
725 case V4L2_PIX_FMT_YUV422P:
726 fcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
729 g_assert_not_reached ();
732 structure = gst_structure_new ("video/x-raw-yuv",
733 "format", GST_TYPE_FOURCC, fcc, NULL);
736 case V4L2_PIX_FMT_DV:
738 gst_structure_new ("video/x-dv", "systemstream", G_TYPE_BOOLEAN, TRUE,
741 case V4L2_PIX_FMT_MPEG: /* MPEG */
742 /* someone figure out the MPEG format used... */
744 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
746 #ifdef V4L2_PIX_FMT_SBGGR8
747 case V4L2_PIX_FMT_SBGGR8:
748 structure = gst_structure_new ("video/x-raw-bayer", NULL);
751 #ifdef V4L2_PIX_FMT_SN9C10X
752 case V4L2_PIX_FMT_SN9C10X:
753 structure = gst_structure_new ("video/x-sonix", NULL);
756 #ifdef V4L2_PIX_FMT_PWC1
757 case V4L2_PIX_FMT_PWC1:
758 structure = gst_structure_new ("video/x-pwc1", NULL);
761 #ifdef V4L2_PIX_FMT_PWC2
762 case V4L2_PIX_FMT_PWC2:
763 structure = gst_structure_new ("video/x-pwc2", NULL);
767 GST_DEBUG ("Unknown fourcc 0x%08x %" GST_FOURCC_FORMAT,
768 fourcc, GST_FOURCC_ARGS (fourcc));
775 static struct v4l2_fmtdesc *
776 gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
778 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);
837 if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
840 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
844 if (v4l2src->probed_caps)
845 return gst_caps_ref (v4l2src->probed_caps);
847 if (!v4l2src->formats)
848 gst_v4l2src_fill_format_list (v4l2src);
850 ret = gst_caps_new_empty ();
852 for (walk = v4l2src->formats; walk; walk = walk->next) {
853 struct v4l2_fmtdesc *format;
855 GstStructure *template;
857 format = (struct v4l2_fmtdesc *) walk->data;
859 template = gst_v4l2src_v4l2fourcc_to_structure (format->pixelformat);
864 tmp = gst_v4l2src_probe_caps_for_format (v4l2src, format->pixelformat,
867 gst_caps_append (ret, tmp);
869 gst_structure_free (template);
871 GST_DEBUG_OBJECT (v4l2src, "unknown format %u", format->pixelformat);
875 v4l2src->probed_caps = gst_caps_ref (ret);
877 GST_INFO_OBJECT (v4l2src, "probed caps: %" GST_PTR_FORMAT, ret);
882 /* collect data for the given caps
883 * @caps: given input caps
884 * @format: location for the v4l format
885 * @w/@h: location for width and height
886 * @fps_n/@fps_d: location for framerate
887 * @size: location for expected size of the frame or 0 if unknown
890 gst_v4l2_get_caps_info (GstV4l2Src * v4l2src, GstCaps * caps,
891 struct v4l2_fmtdesc **format, gint * w, gint * h, guint * fps_n,
892 guint * fps_d, guint * size)
894 GstStructure *structure;
896 const GValue *framerate;
900 const gchar *mimetype;
904 /* default unknown values */
908 structure = gst_caps_get_structure (caps, 0);
910 if (!gst_structure_get_int (structure, "width", w))
913 if (!gst_structure_get_int (structure, "height", h))
916 framerate = gst_structure_get_value (structure, "framerate");
920 *fps_n = gst_value_get_fraction_numerator (framerate);
921 *fps_d = gst_value_get_fraction_denominator (framerate);
923 mimetype = gst_structure_get_name (structure);
925 if (!strcmp (mimetype, "video/x-raw-yuv")) {
926 gst_structure_get_fourcc (structure, "format", &fourcc);
929 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
930 case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
931 fourcc = V4L2_PIX_FMT_YUV420;
932 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
933 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
935 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
936 fourcc = V4L2_PIX_FMT_YUYV;
937 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
939 case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
940 fourcc = V4L2_PIX_FMT_Y41P;
941 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
943 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
944 fourcc = V4L2_PIX_FMT_UYVY;
945 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
947 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
948 fourcc = V4L2_PIX_FMT_YVU420;
949 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
950 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
952 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
953 fourcc = V4L2_PIX_FMT_YUV411P;
954 outsize = GST_ROUND_UP_4 (*w) * *h;
955 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
957 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
958 fourcc = V4L2_PIX_FMT_YUV422P;
959 outsize = GST_ROUND_UP_4 (*w) * *h;
960 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
962 case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
963 fourcc = V4L2_PIX_FMT_NV12;
964 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
965 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
967 case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
968 fourcc = V4L2_PIX_FMT_NV21;
969 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
970 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
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;
1039 struct v4l2_fmtdesc *format;
1045 v4l2src = GST_V4L2SRC (src);
1047 /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1048 if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object))
1051 /* make sure we stop capturing and dealloc buffers */
1052 if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
1053 /* both will throw an element-error on failure */
1054 if (!gst_v4l2src_capture_stop (v4l2src))
1056 if (!gst_v4l2src_capture_deinit (v4l2src))
1060 /* we want our own v4l2 type of fourcc codes */
1061 if (!gst_v4l2_get_caps_info (v4l2src, caps, &format, &w, &h, &fps_n, &fps_d,
1063 GST_DEBUG_OBJECT (v4l2src,
1064 "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1068 GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
1069 "format %s", w, h, fps_n, fps_d, format->description);
1071 if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, fps_n,
1073 /* error already posted */
1076 if (!gst_v4l2src_capture_init (v4l2src, caps))
1079 if (!gst_v4l2src_capture_start (v4l2src))
1082 /* now store the expected output size */
1083 v4l2src->frame_byte_size = size;
1089 gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
1093 gboolean res = FALSE;
1095 src = GST_V4L2SRC (bsrc);
1097 switch (GST_QUERY_TYPE (query)) {
1098 case GST_QUERY_LATENCY:{
1099 GstClockTime min_latency, max_latency;
1101 /* device must be open */
1102 if (!GST_V4L2_IS_OPEN (src->v4l2object)) {
1103 GST_WARNING_OBJECT (src,
1104 "Can't give latency since device isn't open !");
1108 /* we must have a framerate */
1109 if (src->fps_n <= 0 || src->fps_d <= 0) {
1110 GST_WARNING_OBJECT (src,
1111 "Can't give latency since framerate isn't fixated !");
1115 /* min latency is the time to capture one frame */
1117 gst_util_uint64_scale_int (GST_SECOND, src->fps_d, src->fps_n);
1119 /* max latency is total duration of the frame buffer */
1120 max_latency = src->num_buffers * min_latency;
1122 GST_DEBUG_OBJECT (bsrc,
1123 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1124 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
1126 /* we are always live, the min latency is 1 frame and the max latency is
1127 * the complete buffer of frames. */
1128 gst_query_set_latency (query, TRUE, min_latency, max_latency);
1134 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1143 /* start and stop are not symmetric -- start will open the device, but not start
1144 * capture. it's setcaps that will start capture, which is called via basesrc's
1145 * negotiate method. stop will both stop capture and close the device.
1148 gst_v4l2src_start (GstBaseSrc * src)
1150 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1152 /* open the device */
1153 if (!gst_v4l2_object_start (v4l2src->v4l2object))
1156 v4l2src->offset = 0;
1162 gst_v4l2src_stop (GstBaseSrc * src)
1164 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1166 if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)
1167 && !gst_v4l2src_capture_stop (v4l2src))
1170 if (v4l2src->v4l2object->buffer != NULL) {
1171 if (!gst_v4l2src_capture_deinit (v4l2src))
1175 /* close the device */
1176 if (!gst_v4l2_object_stop (v4l2src->v4l2object))
1185 static GstFlowReturn
1186 gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
1192 buffersize = v4l2src->frame_byte_size;
1194 *buf = gst_buffer_new_and_alloc (buffersize);
1198 v4l2_read (v4l2src->v4l2object->video_fd, GST_BUFFER_DATA (*buf),
1200 if (amount == buffersize) {
1202 } else if (amount == -1) {
1203 if (errno == EAGAIN || errno == EINTR) {
1208 /* short reads can happen if a signal interrupts the read */
1213 GST_BUFFER_OFFSET (*buf) = v4l2src->offset++;
1214 GST_BUFFER_OFFSET_END (*buf) = v4l2src->offset;
1215 /* timestamps, LOCK to get clock and base time. */
1219 GstClockTime timestamp;
1221 GST_OBJECT_LOCK (v4l2src);
1222 if ((clock = GST_ELEMENT_CLOCK (v4l2src))) {
1223 /* we have a clock, get base time and ref clock */
1224 timestamp = GST_ELEMENT (v4l2src)->base_time;
1225 gst_object_ref (clock);
1227 /* no clock, can't set timestamps */
1228 timestamp = GST_CLOCK_TIME_NONE;
1230 GST_OBJECT_UNLOCK (v4l2src);
1233 GstClockTime latency;
1235 /* the time now is the time of the clock minus the base time */
1236 timestamp = gst_clock_get_time (clock) - timestamp;
1237 gst_object_unref (clock);
1240 gst_util_uint64_scale_int (GST_SECOND, v4l2src->fps_d,
1243 if (timestamp > latency)
1244 timestamp -= latency;
1249 /* FIXME: use the timestamp from the buffer itself! */
1250 GST_BUFFER_TIMESTAMP (*buf) = timestamp;
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)
1280 ret = gst_v4l2src_grab_frame (v4l2src, &temp);
1281 if (ret != GST_FLOW_OK)
1284 if (v4l2src->frame_byte_size > 0) {
1285 size = GST_BUFFER_SIZE (temp);
1287 /* if size does not match what we expected, try again */
1288 if (size != v4l2src->frame_byte_size) {
1289 GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ,
1290 (_("Got unexpected frame size of %u instead of %u."),
1291 size, v4l2src->frame_byte_size), (NULL));
1292 gst_buffer_unref (temp);
1307 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
1308 (_("Error reading %d bytes on device '%s'."),
1309 v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL));
1310 return GST_FLOW_ERROR;
1314 static GstFlowReturn
1315 gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
1317 GstV4l2Src *v4l2src = GST_V4L2SRC (src);
1321 if (v4l2src->use_mmap) {
1322 ret = gst_v4l2src_get_mmap (v4l2src, buf);
1324 ret = gst_v4l2src_get_read (v4l2src, buf);