if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
goto get_fmt_failed;
- if (format.type == v4l2object->type &&
- format.fmt.pix.width == width &&
- format.fmt.pix.height == height &&
- format.fmt.pix.pixelformat == pixelformat &&
- format.fmt.pix.field == field) {
- /* Nothing to do. We want to succeed immediately
- * here because setting the same format back
- * can still fail due to EBUSY. By short-circuiting
- * here, we allow pausing and re-playing pipelines
- * with changed caps, as long as the changed caps
- * do not change the webcam's format. Otherwise,
- * any caps change would require us to go to NULL
- * state to close the device and set format.
- */
- return TRUE;
+ GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
+ "%" GST_FOURCC_FORMAT " bytesperline %d, colorspace %d",
+ format.fmt.pix.width, format.fmt.pix.height,
+ GST_FOURCC_ARGS (format.fmt.pix.pixelformat), format.fmt.pix.bytesperline,
+ format.fmt.pix.colorspace);
+
+ if (format.type != v4l2object->type ||
+ format.fmt.pix.width != width ||
+ format.fmt.pix.height != height ||
+ format.fmt.pix.pixelformat != pixelformat ||
+ format.fmt.pix.field != field || format.fmt.pix.bytesperline != stride) {
+ /* something different, set the format */
+ GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
+ "%" GST_FOURCC_FORMAT " bytesperline %d", width, height,
+ GST_FOURCC_ARGS (pixelformat), stride);
+
+ format.type = v4l2object->type;
+ format.fmt.pix.width = width;
+ format.fmt.pix.height = height;
+ format.fmt.pix.pixelformat = pixelformat;
+ format.fmt.pix.field = field;
+ /* try to ask our prefered stride */
+ format.fmt.pix.bytesperline = stride;
+
+ if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
+ goto set_fmt_failed;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
+ "%" GST_FOURCC_FORMAT " stride %d", format.fmt.pix.width,
+ format.fmt.pix.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
+ format.fmt.pix.bytesperline);
+
+ if (format.fmt.pix.width != width || format.fmt.pix.height != height)
+ goto invalid_dimensions;
+
+ if (format.fmt.pix.pixelformat != pixelformat)
+ goto invalid_pixelformat;
}
- format.type = v4l2object->type;
- format.fmt.pix.width = width;
- format.fmt.pix.height = height;
- format.fmt.pix.pixelformat = pixelformat;
- format.fmt.pix.field = field;
+ /* figure out the frame layout */
+ v4l2object->bytesperline = format.fmt.pix.bytesperline;
+ v4l2object->sizeimage = format.fmt.pix.sizeimage;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "Got sizeimage %u",
+ v4l2object->sizeimage);
+
+ /* Is there a reason we require the caller to always specify a framerate? */
+ GST_DEBUG_OBJECT (v4l2object->element, "Desired framerate: %u/%u", fps_n,
+ fps_d);
+
+ memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm));
+ streamparm.type = v4l2object->type;
+
+ if (v4l2_ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0)
+ goto get_parm_failed;
+
+ GST_VIDEO_INFO_FPS_N (&info) =
+ streamparm.parm.capture.timeperframe.denominator;
+ GST_VIDEO_INFO_FPS_D (&info) = streamparm.parm.capture.timeperframe.numerator;
+
+ if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ GST_DEBUG_OBJECT (v4l2object->element, "Got framerate: %u/%u",
+ streamparm.parm.capture.timeperframe.denominator,
+ streamparm.parm.capture.timeperframe.numerator);
+
- /* Note: V4L2 provides the frame interval, we have the frame rate */
- if (!fractions_are_equal (streamparm.parm.capture.timeperframe.numerator,
- streamparm.parm.capture.timeperframe.denominator, fps_d, fps_n)) {
- GST_LOG_OBJECT (v4l2object->element, "Setting framerate to %u/%u", fps_n,
- fps_d);
- /* We want to change the frame rate, so check whether we can. Some cheap USB
- * cameras don't have the capability */
- if ((streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
- GST_DEBUG_OBJECT (v4l2object->element,
- "Not setting framerate (not supported)");
- goto done;
- }
++ /* We used to skip frame rate setup if the camera was already setup
++ * with the requested frame rate. This breaks some cameras though,
++ * causing them to not output data (several models of Thinkpad cameras
++ * have this problem at least).
++ * So, don't skip. */
++ GST_LOG_OBJECT (v4l2object->element, "Setting framerate to %u/%u", fps_n,
++ fps_d);
++ /* We want to change the frame rate, so check whether we can. Some cheap USB
++ * cameras don't have the capability */
++ if ((streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
++ GST_DEBUG_OBJECT (v4l2object->element,
++ "Not setting framerate (not supported)");
++ goto done;
++ }
+
- /* Note: V4L2 wants the frame interval, we have the frame rate */
- streamparm.parm.capture.timeperframe.numerator = fps_d;
- streamparm.parm.capture.timeperframe.denominator = fps_n;
++ /* Note: V4L2 wants the frame interval, we have the frame rate */
++ streamparm.parm.capture.timeperframe.numerator = fps_d;
++ streamparm.parm.capture.timeperframe.denominator = fps_n;
- /* some cheap USB cam's won't accept any change */
- if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
- goto set_parm_failed;
- if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
- goto set_fmt_failed;
++ /* some cheap USB cam's won't accept any change */
++ if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
++ goto set_parm_failed;
+
- /* get new values */
- fps_d = streamparm.parm.capture.timeperframe.numerator;
- fps_n = streamparm.parm.capture.timeperframe.denominator;
++ /* get new values */
++ fps_d = streamparm.parm.capture.timeperframe.numerator;
++ fps_n = streamparm.parm.capture.timeperframe.denominator;
+
- GST_INFO_OBJECT (v4l2object->element, "Set framerate to %u/%u", fps_n,
- fps_d);
++ GST_INFO_OBJECT (v4l2object->element, "Set framerate to %u/%u", fps_n,
++ fps_d);
+
- GST_VIDEO_INFO_FPS_N (&info) = fps_n;
- GST_VIDEO_INFO_FPS_D (&info) = fps_d;
- }
++ GST_VIDEO_INFO_FPS_N (&info) = fps_n;
++ GST_VIDEO_INFO_FPS_D (&info) = fps_d;
}
- if (format.fmt.pix.width != width || format.fmt.pix.height != height)
- goto invalid_dimensions;
+done:
+ /* if we have a framerate pre-calculate duration */
+ if (fps_n > 0 && fps_d > 0) {
+ v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
+ } else {
+ v4l2object->duration = GST_CLOCK_TIME_NONE;
+ }
+ v4l2object->info = info;
+ v4l2object->fmtdesc = fmtdesc;
- if (format.fmt.pix.pixelformat != pixelformat)
- goto invalid_pixelformat;
+ /* now configure ther pools */
+ if (!gst_v4l2_object_setup_pool (v4l2object, caps))
+ goto pool_failed;
return TRUE;