gboolean gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other) { GST_DEBUG_OBJECT (v4l2object->element, "Trying to dup device %s", other->videodev); GST_V4L2_CHECK_OPEN (other); GST_V4L2_CHECK_NOT_OPEN (v4l2object); GST_V4L2_CHECK_NOT_ACTIVE (other); GST_V4L2_CHECK_NOT_ACTIVE (v4l2object); v4l2object->vcap = other->vcap; gst_v4l2_adjust_buf_type (v4l2object); v4l2object->video_fd = v4l2_dup (other->video_fd); if (!GST_V4L2_IS_OPEN (v4l2object)) goto not_open; g_free (v4l2object->videodev); v4l2object->videodev = g_strdup (other->videodev); GST_INFO_OBJECT (v4l2object->element, "Cloned device '%s' (%s) successfully", v4l2object->vcap.card, v4l2object->videodev); v4l2object->never_interlaced = other->never_interlaced; return TRUE; not_open: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE, (_("Could not dup device '%s' for reading and writing."), v4l2object->videodev), GST_ERROR_SYSTEM); return FALSE; } }
/****************************************************** * gst_v4l2_open(): * open the video device (v4l2object->videodev) * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_open (GstV4l2Object * v4l2object) { struct stat st; int libv4l2_fd; GstPollFD pollfd = GST_POLL_FD_INIT; GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s", v4l2object->videodev); GST_V4L2_CHECK_NOT_OPEN (v4l2object); GST_V4L2_CHECK_NOT_ACTIVE (v4l2object); /* be sure we have a device */ if (!v4l2object->videodev) v4l2object->videodev = g_strdup ("/dev/video"); /* check if it is a device */ if (stat (v4l2object->videodev, &st) == -1) goto stat_failed; if (!S_ISCHR (st.st_mode)) goto no_device; /* open the device */ v4l2object->video_fd = open (v4l2object->videodev, O_RDWR /* | O_NONBLOCK */ ); if (!GST_V4L2_IS_OPEN (v4l2object)) goto not_open; libv4l2_fd = v4l2_fd_open (v4l2object->video_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); /* Note the v4l2_xxx functions are designed so that if they get passed an unknown fd, the will behave exactly as their regular xxx counterparts, so if v4l2_fd_open fails, we continue as normal (missing the libv4l2 custom cam format to normal formats conversion). Chances are big we will still fail then though, as normally v4l2_fd_open only fails if the device is not a v4l2 device. */ if (libv4l2_fd != -1) v4l2object->video_fd = libv4l2_fd; v4l2object->can_poll_device = TRUE; /* get capabilities, error will be posted */ if (!gst_v4l2_get_capabilities (v4l2object)) goto error; /* do we need to be a capture device? */ if (GST_IS_V4L2SRC (v4l2object->element) && !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) goto not_capture; if (GST_IS_V4L2SINK (v4l2object->element) && !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) goto not_output; /* create enumerations, posts errors. */ if (!gst_v4l2_fill_lists (v4l2object)) goto error; GST_INFO_OBJECT (v4l2object->element, "Opened device '%s' (%s) successfully", v4l2object->vcap.card, v4l2object->videodev); pollfd.fd = v4l2object->video_fd; gst_poll_add_fd (v4l2object->poll, &pollfd); gst_poll_fd_ctl_read (v4l2object->poll, &pollfd, TRUE); return TRUE; /* ERRORS */ stat_failed: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Cannot identify device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } no_device: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("This isn't a device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } not_open: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE, (_("Could not open device '%s' for reading and writing."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } not_capture: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a capture device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } not_output: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a output device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } error: { if (GST_V4L2_IS_OPEN (v4l2object)) { /* close device */ v4l2_close (v4l2object->video_fd); v4l2object->video_fd = -1; } /* empty lists */ gst_v4l2_empty_lists (v4l2object); return FALSE; } }
/****************************************************** * gst_v4l2_open(): * open the video device (v4l2object->videodev) * return value: TRUE on success, FALSE on error ******************************************************/ gboolean gst_v4l2_open (GstV4l2Object * v4l2object) { struct stat st; int libv4l2_fd; GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s", v4l2object->videodev); GST_V4L2_CHECK_NOT_OPEN (v4l2object); GST_V4L2_CHECK_NOT_ACTIVE (v4l2object); /* be sure we have a device */ if (!v4l2object->videodev) v4l2object->videodev = g_strdup ("/dev/video"); /* check if it is a device */ if (stat (v4l2object->videodev, &st) == -1) goto stat_failed; if (!S_ISCHR (st.st_mode)) goto no_device; /* open the device */ v4l2object->video_fd = open (v4l2object->videodev, O_RDWR /* | O_NONBLOCK */ ); if (!GST_V4L2_IS_OPEN (v4l2object)) goto not_open; libv4l2_fd = v4l2_fd_open (v4l2object->video_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); /* Note the v4l2_xxx functions are designed so that if they get passed an unknown fd, the will behave exactly as their regular xxx counterparts, so if v4l2_fd_open fails, we continue as normal (missing the libv4l2 custom cam format to normal formats conversion). Chances are big we will still fail then though, as normally v4l2_fd_open only fails if the device is not a v4l2 device. */ if (libv4l2_fd != -1) v4l2object->video_fd = libv4l2_fd; /* get capabilities, error will be posted */ if (!gst_v4l2_get_capabilities (v4l2object)) goto error; /* do we need to be a capture device? */ if (GST_IS_V4L2SRC (v4l2object->element) && !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE))) goto not_capture; if (GST_IS_V4L2SINK (v4l2object->element) && !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) goto not_output; if (GST_IS_V4L2_VIDEO_DEC (v4l2object->element) && /* Today's M2M device only expose M2M */ !((v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE)) || /* But legacy driver may expose both CAPTURE and OUTPUT */ ((v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) && (v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))))) goto not_m2m; gst_v4l2_adjust_buf_type (v4l2object); /* create enumerations, posts errors. */ if (!gst_v4l2_fill_lists (v4l2object)) goto error; GST_INFO_OBJECT (v4l2object->element, "Opened device '%s' (%s) successfully", v4l2object->vcap.card, v4l2object->videodev); if (v4l2object->extra_controls) gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls); /* UVC devices are never interlaced, and doing VIDIOC_TRY_FMT on them * causes expensive and slow USB IO, so don't probe them for interlaced */ if (!strcmp ((char *) v4l2object->vcap.driver, "uvcusb")) { v4l2object->never_interlaced = TRUE; } return TRUE; /* ERRORS */ stat_failed: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Cannot identify device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } no_device: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("This isn't a device '%s'."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } not_open: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE, (_("Could not open device '%s' for reading and writing."), v4l2object->videodev), GST_ERROR_SYSTEM); goto error; } not_capture: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a capture device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } not_output: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a output device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } not_m2m: { GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND, (_("Device '%s' is not a M2M device."), v4l2object->videodev), ("Capabilities: 0x%x", v4l2object->vcap.capabilities)); goto error; } error: { if (GST_V4L2_IS_OPEN (v4l2object)) { /* close device */ v4l2_close (v4l2object->video_fd); v4l2object->video_fd = -1; } /* empty lists */ gst_v4l2_empty_lists (v4l2object); return FALSE; } }