Пример #1
0
int v4l2_close(int fd)
{
	int index, result;

	index = v4l2_get_index(fd);
	if (index == -1)
		return SYS_CLOSE(fd);

	/* Abuse stream_lock to stop 2 closes from racing and trying to free the
	   resources twice */
	pthread_mutex_lock(&devices[index].stream_lock);
	devices[index].open_count--;
	result = devices[index].open_count != 0;
	pthread_mutex_unlock(&devices[index].stream_lock);

	if (result)
		return 0;

	/* Free resources */
	v4l2_unmap_buffers(index);
	if (devices[index].convert_mmap_buf != MAP_FAILED) {
		if (v4l2_buffers_mapped(index))
			V4L2_LOG_WARN("v4l2 mmap buffers still mapped on close()\n");
		else
			SYS_MUNMAP(devices[index].convert_mmap_buf,
					devices[index].no_frames * V4L2_FRAME_BUF_SIZE);
		devices[index].convert_mmap_buf = MAP_FAILED;
	}
	v4lconvert_destroy(devices[index].convert);
	free(devices[index].readbuf);
	devices[index].readbuf = NULL;
	devices[index].readbuf_size = 0;

	/* Remove the fd from our list of managed fds before closing it, because as
	   soon as we've done the actual close the fd maybe returned by an open in
	   another thread and we don't want to intercept calls to this new fd. */
	devices[index].fd = -1;

	/* Since we've marked the fd as no longer used, and freed the resources,
	   redo the close in case it was interrupted */
	do {
		result = SYS_CLOSE(fd);
	} while (result == -1 && errno == EINTR);

	V4L2_LOG("close: %d\n", fd);

	return result;
}
Пример #2
0
int v4l2_open(const char *file, int oflag, ...)
{
	int fd;

	/* original open code */
	if (oflag & O_CREAT) {
		va_list ap;
		mode_t mode;

		va_start(ap, oflag);
		mode = va_arg(ap, mode_t);

		fd = SYS_OPEN(file, oflag, mode);

		va_end(ap);
	} else {
		fd = SYS_OPEN(file, oflag, 0);
	}
	/* end of original open code */

	if (fd == -1)
		return fd;

	if (v4l2_fd_open(fd, 0) == -1) {
		int saved_err = errno;

		SYS_CLOSE(fd);
		errno = saved_err;
		return -1;
	}

	return fd;
}
Пример #3
0
int v4l1_close(int fd)
{
	int index, result;

	index = v4l1_get_index(fd);
	if (index == -1)
		return SYS_CLOSE(fd);

	/* Abuse stream_lock to stop 2 closes from racing and trying to free the
	   resources twice */
	pthread_mutex_lock(&devices[index].stream_lock);
	devices[index].open_count--;
	result = devices[index].open_count != 0;
	pthread_mutex_unlock(&devices[index].stream_lock);

	if (result)
		return v4l2_close(fd);

	/* Free resources */
	if (devices[index].v4l1_frame_pointer != MAP_FAILED) {
		if (devices[index].v4l1_frame_buf_map_count)
			V4L1_LOG("v4l1 capture buffer still mapped: %d times on close()\n",
					devices[index].v4l1_frame_buf_map_count);
		else
			SYS_MUNMAP(devices[index].v4l1_frame_pointer,
					V4L1_NO_FRAMES * V4L1_FRAME_BUF_SIZE);
		devices[index].v4l1_frame_pointer = MAP_FAILED;
	}

	/* Remove the fd from our list of managed fds before closing it, because as
	   soon as we've done the actual close the fd maybe returned by an open in
	   another thread and we don't want to intercept calls to this new fd. */
	devices[index].fd = -1;

	result = v4l2_close(fd);

	V4L1_LOG("close: %d\n", fd);

	return result;
}
Пример #4
0
int v4l1_open(const char *file, int oflag, ...)
{
	int index, fd;
	char *lfname;
	struct v4l2_capability cap2;
	struct v4l2_format fmt2;
	struct v4l2_input input2;
	struct v4l2_standard standard2;
	int v4l_device = 0;

	/* check if we're opening a video4linux2 device */
	if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) {
		/* Some apps open the device read only, but we need rw rights as the
		   buffers *MUST* be mapped rw */
		oflag = (oflag & ~O_ACCMODE) | O_RDWR;
		v4l_device = 1;
	}

	/* original open code */
	if (oflag & O_CREAT) {
		va_list ap;
		mode_t mode;

		va_start(ap, oflag);
		mode = va_arg(ap, PROMOTED_MODE_T);

		fd = SYS_OPEN(file, oflag, mode);

		va_end(ap);
	} else {
		fd = SYS_OPEN(file, oflag, 0);
	}

	/* end of original open code */

	if (fd == -1 || !v4l_device)
		return fd;

	/* check that this is an v4l2 device, no need to emulate v4l1 on
	   a v4l1 device */
	if (SYS_IOCTL(fd, VIDIOC_QUERYCAP, &cap2))
		return fd;

	/* If no log file was set by the app, see if one was specified through the
	   environment */
	if (!v4l1_log_file) {
		lfname = getenv("LIBV4L1_LOG_FILENAME");
		if (lfname)
			v4l1_log_file = fopen(lfname, "w");
	}

	/* redirect libv4l2 log messages to our logfile if no libv4l2 logfile is
	   specified */
	if (!v4l2_log_file)
		v4l2_log_file = v4l1_log_file;

	/* Register with libv4l2, as we use that todo format conversion and read()
	   emulation for us */
	if (v4l2_fd_open(fd, 0) == -1) {
		int saved_err = errno;

		SYS_CLOSE(fd);
		errno = saved_err;
		return -1;
	}

	/* Get initial width, height and pixelformat */
	fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt2)) {
		int saved_err = errno;

		SYS_CLOSE(fd);
		errno = saved_err;
		return -1;
	}

	/* So we have a device on which we can (and want to) emulate v4l1, register
	   it in our devices array */
	pthread_mutex_lock(&v4l1_open_mutex);
	for (index = 0; index < V4L1_MAX_DEVICES; index++)
		if (devices[index].fd == -1) {
			devices[index].fd = fd;
			break;
		}
	pthread_mutex_unlock(&v4l1_open_mutex);

	if (index == V4L1_MAX_DEVICES) {
		V4L1_LOG_ERR("attempting to open more then %d video devices\n",
				V4L1_MAX_DEVICES);
		v4l2_close(fd);
		errno = EBUSY;
		return -1;
	}

	if (index >= devices_used)
		devices_used = index + 1;

	devices[index].flags = 0;
	devices[index].open_count = 1;
	devices[index].v4l1_frame_buf_map_count = 0;
	devices[index].v4l1_frame_pointer = MAP_FAILED;
	devices[index].width  = fmt2.fmt.pix.width;
	devices[index].height = fmt2.fmt.pix.height;
	devices[index].v4l2_pixfmt = fmt2.fmt.pix.pixelformat;
	devices[index].v4l1_pal = pixelformat_to_palette(fmt2.fmt.pix.pixelformat);
	devices[index].depth = ((fmt2.fmt.pix.bytesperline << 3) +
			(fmt2.fmt.pix.width - 1)) / fmt2.fmt.pix.width;

	v4l1_find_min_and_max_size(index, &fmt2);

	/* Check ENUM_INPUT and ENUM_STD support */
	input2.index = 0;
	if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input2) == 0)
		devices[index].flags |= V4L1_SUPPORTS_ENUMINPUT;

	standard2.index = 0;
	if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &standard2) == 0)
		devices[index].flags |= V4L1_SUPPORTS_ENUMSTD;

	V4L1_LOG("open: %d\n", fd);

	return fd;
}