示例#1
0
/* Is conversion necessary ? */
int v4lconvert_needs_conversion(struct v4lconvert_data *data,
		const struct v4l2_format *src_fmt,  /* in */
		const struct v4l2_format *dest_fmt) /* in */
{
	if (src_fmt->fmt.pix.width != dest_fmt->fmt.pix.width ||
			src_fmt->fmt.pix.height != dest_fmt->fmt.pix.height ||
			src_fmt->fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat ||
			(v4lcontrol_needs_conversion(data->control) &&
			 v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)))
		return 1;

	return 0;
}
示例#2
0
struct v4lcontrol_data *v4lcontrol_create(int fd, void *dev_ops_priv,
	const struct libv4l_dev_ops *dev_ops, int always_needs_conversion)
{
	int shm_fd;
	int i, rc, got_usb_info, speed, init = 0;
	char *s, shm_name[256], pwd_buf[1024];
	struct v4l2_capability cap;
	struct v4l2_queryctrl ctrl;
	struct passwd pwd, *pwd_p;
	unsigned short vendor_id = 0;
	unsigned short product_id = 0;
	struct v4l2_input input;

	struct v4lcontrol_data *data = calloc(1, sizeof(struct v4lcontrol_data));

	if (!data) {
		fprintf(stderr, "libv4lcontrol: error: out of memory!\n");
		return NULL;
	}

	data->fd = fd;
	data->dev_ops = dev_ops;
	data->dev_ops_priv = dev_ops_priv;

	/* Check if the driver has indicated some form of flipping is needed */
	if ((data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
				  VIDIOC_G_INPUT, &input.index) == 0) &&
	    (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
	    			VIDIOC_ENUMINPUT, &input) == 0)) {
		if (input.status & V4L2_IN_ST_HFLIP)
			data->flags |= V4LCONTROL_HFLIPPED;
		if (input.status & V4L2_IN_ST_VFLIP)
			data->flags |= V4LCONTROL_VFLIPPED;
	}

	s = getenv("LIBV4LCONTROL_SYSFS_PREFIX");
	if (!s)
		s = "";

	got_usb_info = v4lcontrol_get_usb_info(data, s, &vendor_id, &product_id,
					       &speed);
	if (got_usb_info) {
		v4lcontrol_get_flags_from_db(data, s, vendor_id, product_id);
		switch (speed) {
		case 12:
			data->bandwidth = 1023 * 1000;
			break;
		case 480:
			data->bandwidth = 3 * 1024 * 8000;
			break;
		case 5000:
			data->bandwidth = 48 * 1024 * 8000;
			break;
		default:
			/* heuh, low speed device, or ... ? */
			data->bandwidth = speed / 20;
		}
	} else
		data->bandwidth = 0;

	/* Allow overriding through environment */
	s = getenv("LIBV4LCONTROL_FLAGS");
	if (s)
		data->flags = strtol(s, NULL, 0);

	ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
	if (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
			VIDIOC_QUERYCTRL, &ctrl) == 0)
		data->priv_flags |= V4LCONTROL_SUPPORTS_NEXT_CTRL;

	/* If the device always needs conversion, we can add fake controls at no cost
	   (no cost when not activated by the user that is) */
	if (always_needs_conversion || v4lcontrol_needs_conversion(data)) {
		for (i = 0; i < V4LCONTROL_AUTO_ENABLE_COUNT; i++) {
			ctrl.id = fake_controls[i].id;
			rc = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
					VIDIOC_QUERYCTRL, &ctrl);
			if (rc == -1 ||
			    (rc == 0 &&
			     (ctrl.flags & V4L2_CTRL_FLAG_DISABLED)))
				data->controls |= 1 << i;
		}
	}

	/* Check if a camera does not have hardware autogain and has the necessary
	   controls, before enabling sw autogain, even if this is requested by flags.
	   This is necessary because some cameras share a USB-ID, but can have
	   different sensors with / without autogain or the necessary controls. */
	while (data->flags & V4LCONTROL_WANTS_AUTOGAIN) {
		ctrl.id = V4L2_CID_AUTOGAIN;
		rc = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
				VIDIOC_QUERYCTRL, &ctrl);
		if (rc == 0 && !(ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
			break;

		ctrl.id = V4L2_CID_EXPOSURE;
		rc = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
				VIDIOC_QUERYCTRL, &ctrl);
		if (rc != 0 || (ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
			break;

		ctrl.id = V4L2_CID_GAIN;
		rc = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
				VIDIOC_QUERYCTRL, &ctrl);
		if (rc != 0 || (ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
			break;

		data->controls |= 1 << V4LCONTROL_AUTOGAIN |
			1 << V4LCONTROL_AUTOGAIN_TARGET;
		break;
	}

	/* Allow overriding through environment */
	s = getenv("LIBV4LCONTROL_CONTROLS");
	if (s)
		data->controls = strtol(s, NULL, 0);

	if (data->controls == 0)
		return data; /* No need to create a shared memory segment */

	if (data->dev_ops->ioctl(data->dev_ops_priv, fd,
			VIDIOC_QUERYCAP, &cap)) {
		perror("libv4lcontrol: error querying device capabilities");
		goto error;
	}

	if (getpwuid_r(geteuid(), &pwd, pwd_buf, sizeof(pwd_buf), &pwd_p) == 0) {
		if (got_usb_info)
			snprintf(shm_name, 256, "/libv4l-%s:%s:%04x:%04x:%s", pwd.pw_name,
					cap.bus_info, (int)vendor_id, (int)product_id, cap.card);
		else
			snprintf(shm_name, 256, "/libv4l-%s:%s:%s", pwd.pw_name,
					cap.bus_info, cap.card);
	} else {
		perror("libv4lcontrol: error getting username using uid instead");
		if (got_usb_info)
			snprintf(shm_name, 256, "/libv4l-%lu:%s:%04x:%04x:%s",
					(unsigned long)geteuid(), cap.bus_info,
					(int)vendor_id, (int)product_id, cap.card);
		else
			snprintf(shm_name, 256, "/libv4l-%lu:%s:%s", (unsigned long)geteuid(),
					cap.bus_info, cap.card);
	}

	/* / is not allowed inside shm names */
	for (i = 1; shm_name[i]; i++)
		if (shm_name[i] == '/')
			shm_name[i] = '-';

#ifndef ANDROID
	/* Open the shared memory object identified by shm_name */
	shm_fd = shm_open(shm_name, (O_CREAT | O_EXCL | O_RDWR), (S_IREAD | S_IWRITE));
	if (shm_fd >= 0)
		init = 1;
	else
		shm_fd = shm_open(shm_name, O_RDWR, (S_IREAD | S_IWRITE));

	if (shm_fd >= 0) {
		/* Set the shared memory size */
		ftruncate(shm_fd, V4LCONTROL_SHM_SIZE);

		/* Retreive a pointer to the shm object */
		data->shm_values = mmap(NULL, V4LCONTROL_SHM_SIZE, (PROT_READ | PROT_WRITE),
				MAP_SHARED, shm_fd, 0);
		close(shm_fd);

		if (data->shm_values == MAP_FAILED) {
			perror("libv4lcontrol: error shm mmap failed");
			data->shm_values = NULL;
		}
	} else
		perror("libv4lcontrol: error creating shm segment failed");
#endif

	/* Fall back to malloc */
	if (data->shm_values == NULL) {
		fprintf(stderr,
				"libv4lcontrol: falling back to malloc-ed memory for controls\n");
		data->shm_values = malloc(V4LCONTROL_SHM_SIZE);
		if (!data->shm_values) {
			fprintf(stderr, "libv4lcontrol: error: out of memory!\n");
			goto error;
		}
		init = 1;
		data->priv_flags |= V4LCONTROL_MEMORY_IS_MALLOCED;
	}

	if (init) {
		/* Initialize the new shm object we created */
		memset(data->shm_values, 0, V4LCONTROL_SHM_SIZE);

		for (i = 0; i < V4LCONTROL_COUNT; i++)
			data->shm_values[i] = fake_controls[i].default_value;

		if (data->flags & V4LCONTROL_WANTS_WB)
			data->shm_values[V4LCONTROL_WHITEBALANCE] = 1;

		if (data->flags_info && data->flags_info->default_gamma)
			data->shm_values[V4LCONTROL_GAMMA] = data->flags_info->default_gamma;
	}

	return data;

error:
	free(data);
	return NULL;
}
示例#3
0
int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data)
{
	return v4lcontrol_needs_conversion(data->control) &&
		data->supported_src_formats;
}