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;
  }
}
Example #2
0
/******************************************************
 * 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;
  }
}