diff options
| author | Tomasz Stanislawski <t.stanislaws@samsung.com> | 2012-10-09 11:45:16 +0200 | 
|---|---|---|
| committer | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2012-10-09 11:46:23 +0200 | 
| commit | e1dfdd991612931681df969141587365b9d8e4d7 (patch) | |
| tree | 52d0a797e802b0f97be76787826ffe5533e0397d /v4l2-dmabuf-test | |
| parent | 2e7c05969d7923419f2536a92d5e53f4f829ab71 (diff) | |
v4l2-dmabuf-test-01: version 0.1
Simple test with vivi and 2 V4L2 mem-to-mem devices.
The output data is written to a file. Image sizes are
small due to Exynos SYMMU issues in the mainline kernel.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Diffstat (limited to 'v4l2-dmabuf-test')
| -rw-r--r-- | v4l2-dmabuf-test/CHANGELOG | 1 | ||||
| -rw-r--r-- | v4l2-dmabuf-test/v4l2-dmabuf-test-01.c | 670 | 
2 files changed, 671 insertions, 0 deletions
diff --git a/v4l2-dmabuf-test/CHANGELOG b/v4l2-dmabuf-test/CHANGELOG new file mode 100644 index 0000000..673729c --- /dev/null +++ b/v4l2-dmabuf-test/CHANGELOG @@ -0,0 +1 @@ +Version 0.1 diff --git a/v4l2-dmabuf-test/v4l2-dmabuf-test-01.c b/v4l2-dmabuf-test/v4l2-dmabuf-test-01.c new file mode 100644 index 0000000..79894b2 --- /dev/null +++ b/v4l2-dmabuf-test/v4l2-dmabuf-test-01.c @@ -0,0 +1,670 @@ +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +#include <linux/videodev2.h> + +#define ARRAY_SIZE(tab) \ +	(sizeof(tab) / sizeof(*tab)) + +#define CLEAR(s) memset(&s, 0, sizeof(s)) + +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + +static inline int __info(const char *prefix, const char *file, int line, +	const char *fmt, ...) +{ +	int errsv = errno; +	va_list va; + +	va_start(va, fmt); +	fprintf(stderr, "%s(%s:%d): ", prefix, file, line); +	vfprintf(stderr, fmt, va); +	va_end(va); +	errno = errsv; + +	return 1; +} + +#define ERRSTR strerror(errno) + +#define LOG(...) fprintf(stdout, __VA_ARGS__) + +#define ERR(...) __info("Error", __FILE__, __LINE__, __VA_ARGS__) +#define ERR_ON(cond, ...) ((cond) ? ERR(__VA_ARGS__) : 0) + +#define CRIT(...) \ +	do { \ +		__info("Critical", __FILE__, __LINE__, __VA_ARGS__); \ +		exit(EXIT_FAILURE); \ +	} while(0) +#define CRIT_ON(cond, ...) do { if (cond) CRIT(__VA_ARGS__); } while(0) + +struct format { +	unsigned long fourcc; +	unsigned long width; +	unsigned long height; +}; + +struct config { +	char vivi_path[256]; +	char fimc0_path[256]; +	char fimc1_path[256]; +	int rotate; +	bool hflip; +	bool vflip; +	bool help; +}; + +struct state { +	struct config config; +	int vivi_fd; +	int fimc0_fd; +	int fimc1_fd; +}; + +static void usage(void) +{ +#define HELP(...) fprintf(stderr, __VA_ARGS__) +	HELP("Usage:\n"); +	HELP("\t-v path    path to vivi [default /dev/video0]\n"); +	HELP("\t-0 path    path to fimc0 [default /dev/video1]\n"); +	HELP("\t-1 path    path to fimc1 [default /dev/video3]\n"); +	HELP("\t-V         vertical flip\n"); +	HELP("\t-H         horizontal flip\n"); +	HELP("\t-R angle   rotation by angle [default 0]\n"); +	HELP("\t-h         print this help\n"); +	HELP("\n"); +#undef HELP +} + +static int config_create(struct config *config, int argc, char *argv[]) +{ +	int opt, ret = -EINVAL; + +	CLEAR(*config); +	strcpy(config->vivi_path, "/dev/video0"); +	strcpy(config->fimc0_path, "/dev/video1"); +	strcpy(config->fimc1_path, "/dev/video3"); + +	/* parse options */ +	while ((opt = getopt(argc, argv, ":v:0:1:VHR:h")) != -1) { +		switch (opt) { +		case 'v': +			strcpy(config->vivi_path, optarg); +			break; +		case '0': +			strcpy(config->fimc0_path, optarg); +			break; +		case '1': +			strcpy(config->fimc1_path, optarg); +			break; +		case 'V': +			config->vflip = true; +			break; +		case 'H': +			config->hflip = true; +			break; +		case 'R': +			ret = sscanf(optarg, "%d", &config->rotate); +			if (ERR_ON(ret != 1, "invalid rotation\n")) +				return -EILSEQ; +			break; +		case 'h': +			config->help = true; +			break; +		case ':': +			ERR("missing argument\n"); +			return -EINVAL; +		default: /* '?' */ +			ERR("invalid option\n"); +			return -EINVAL; +		} +	} + +	return 0; +} + +void dump_format(char *str, struct v4l2_format *fmt) +{ +	if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { +		struct v4l2_pix_format_mplane *pix = &fmt->fmt.pix_mp; +		LOG("%s: width=%u height=%u format=%.4s\n", str, +			pix->width, pix->height, (char*)&pix->pixelformat); +	} else { +		struct v4l2_pix_format *pix = &fmt->fmt.pix; +		LOG("%s: width=%u height=%u format=%.4s\n", str, +			pix->width, pix->height, (char*)&pix->pixelformat); +	} +} + +int dump_yuyv(int fd, uint8_t *src, int w, int h) +{ +	uint8_t buf[512], *dst = buf; +	for (int wh = w * h; wh; wh--) { +		int y0, y1, u, v; +		int r, g, b; +		y0 = *src++; +		u  = *src++; +		y1 = *src++; +		v  = *src++; +		u -= 128; +		v -= 128; +		g = MAX(y0 - (u + v) / 4, 0); +		r = MIN(u + g, 0xff); +		b = MIN(v + g, 0xff); +		*dst++ = r; +		*dst++ = g; +		*dst++ = b; +		g = MAX(y1 - (u + v) / 4, 0); +		r = MIN(u + g, 0xff); +		b = MIN(v + g, 0xff); +		*dst++ = r; +		*dst++ = g; +		*dst++ = b; +		if (dst - buf < ARRAY_SIZE(buf) - 6) +			continue; +		int ret = write(fd, buf, dst - buf); +		if (ERR_ON(ret < 0, "write: %s\n", ERRSTR)) +			return -errno; +		dst = buf; +	} +	int ret = write(fd, buf, dst - buf); +	if (ERR_ON(ret < 0, "write: %s\n", ERRSTR)) +		return -errno; +	return 0; +} + +int dump_image(char *name, unsigned long fourcc, int w, int h, void *data) +{ +	int fd = open(name, O_WRONLY | O_CREAT, 0644); +	if (ERR_ON(fd < 0, "open: %s\n", ERRSTR)) +		return -errno; +	char buf[64]; +	sprintf(buf, "P6\n%d %d\n255\n", w, h); +	int ret = write(fd, buf, strlen(buf)); +	if (ERR_ON(ret < 0, "write: %s\n", ERRSTR)) +		return -errno; +	ret = 0; +	switch (fourcc) { +	case V4L2_PIX_FMT_YUYV: +		ret = dump_yuyv(fd, data, w, h); +		break; +	default: +		ERR("format %.4s not supported\n", (char*)&fourcc); +		ret = -EINVAL; +	} +	close(fd); +	ERR_ON(ret, "failed to dump %s\n", name); +	return ret; +} + +int setup_formats(struct state *st) +{ +	struct v4l2_format fmt; +	CLEAR(fmt); +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + +	/* get default format from VIVI */ +	int ret = ioctl(st->vivi_fd, VIDIOC_G_FMT, &fmt); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_G_FMT: %s\n", ERRSTR)) +		return -errno; +	dump_format("vivi", &fmt); + +	/* setup format for FIMC 0 */ +	/* keep copy of format for to-mplane conversion */ +	struct v4l2_pix_format pix = fmt.fmt.pix; + +	CLEAR(fmt); +	fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	struct v4l2_pix_format_mplane *pix_mp = &fmt.fmt.pix_mp; + +	pix_mp->width = pix.width; +	pix_mp->height = pix.height; +	pix_mp->pixelformat = pix.pixelformat; +	pix_mp->num_planes = 1; + +	ret = ioctl(st->fimc0_fd, VIDIOC_S_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_S_FMT: %s\n", ERRSTR)) +		return -errno; +	dump_format("fimc0-output", &fmt); + +	/* setup image conversion */ +	struct v4l2_control ctrl; + +	if (st->config.hflip) { +		CLEAR(ctrl); +		ctrl.id = V4L2_CID_HFLIP; +		ctrl.value = 1; +		ret = ioctl(st->fimc0_fd, VIDIOC_S_CTRL, &ctrl); +		if (ERR_ON(ret < 0, "fimc0: VIDIOC_S_CTRL(hflip): %s\n", +		           ERRSTR)) +			return -errno; +	} + +	if (st->config.vflip) { +		CLEAR(ctrl); +		ctrl.id = V4L2_CID_VFLIP; +		ctrl.value = 1; +		ret = ioctl(st->fimc0_fd, VIDIOC_S_CTRL, &ctrl); +		if (ERR_ON(ret < 0, "fimc0: VIDIOC_S_CTRL(vflip): %s\n", +		           ERRSTR)) +			return -errno; +	} + +	if (st->config.rotate) { +		CLEAR(ctrl); +		ctrl.id = V4L2_CID_ROTATE; +		ctrl.value = st->config.rotate; +		ret = ioctl(st->fimc0_fd, VIDIOC_S_CTRL, &ctrl); +		if (ERR_ON(ret < 0, "fimc0: VIDIOC_S_CTRL(rotate): %s\n", +		           ERRSTR)) +			return -errno; +	} + +	/* set the same format on fimc0 capture */ +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_S_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_S_FMT: %s\n", ERRSTR)) +		return -errno; + +	/* copy format from fimc0 capture to fimc1 output */ +	CLEAR(fmt); +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_G_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_G_FMT: %s\n", ERRSTR)) +		return -errno; +	dump_format("fimc0-capture", &fmt); + +	fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_S_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_S_FMT: %s\n", ERRSTR)) +		return -errno; +	ret = ioctl(st->fimc1_fd, VIDIOC_G_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_G_FMT: %s\n", ERRSTR)) +		return -errno; +	dump_format("fimc1-output", &fmt); + +	/* and the same at FIMC1 output */ +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	fmt.fmt.pix_mp.width = 32; +	fmt.fmt.pix_mp.height = 32; +	fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; +	ret = ioctl(st->fimc1_fd, VIDIOC_S_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_S_FMT: %s\n", ERRSTR)) +		return -errno; + +	ret = ioctl(st->fimc1_fd, VIDIOC_G_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_G_FMT: %s\n", ERRSTR)) +		return -errno; +	dump_format("fimc1-capture", &fmt); + +	return 0; +} + +int allocate_buffers(struct state *st) +{ +	int ret; +	struct v4l2_requestbuffers rb; +	CLEAR(rb); + +	/* request buffers for VIVI */ +	rb.count = 1; +	rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	rb.memory = V4L2_MEMORY_DMABUF; +	ret = ioctl(st->vivi_fd, VIDIOC_REQBUFS, &rb); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_REQBUFS: %s\n", ERRSTR)) +		return -errno; + +	/* request buffers for FIMC0 */ +	rb.count = 1; +	rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	rb.memory = V4L2_MEMORY_MMAP; +	ret = ioctl(st->fimc0_fd, VIDIOC_REQBUFS, &rb); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_REQBUFS: %s\n", ERRSTR)) +		return -errno; + +	rb.count = 1; +	rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	rb.memory = V4L2_MEMORY_DMABUF; +	ret = ioctl(st->fimc0_fd, VIDIOC_REQBUFS, &rb); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_REQBUFS: %s\n", ERRSTR)) +		return -errno; + +	/* request buffers for FIMC1 */ +	rb.count = 1; +	rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	rb.memory = V4L2_MEMORY_MMAP; +	ret = ioctl(st->fimc1_fd, VIDIOC_REQBUFS, &rb); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_REQBUFS: %s\n", ERRSTR)) +		return -errno; + +	rb.count = 1; +	rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	rb.memory = V4L2_MEMORY_USERPTR; +	ret = ioctl(st->fimc1_fd, VIDIOC_REQBUFS, &rb); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_REQBUFS: %s\n", ERRSTR)) +		return -errno; + +	return 0; +} + +int process_vivi(struct state *st) +{ +	int ret; +	struct v4l2_exportbuffer eb; +	CLEAR(eb); + +	/* export buffer index=0 from FIMC0 */ +	eb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_EXPBUF, &eb); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_EXPBUF: %s\n", ERRSTR)) +		return -errno; + +	/* enqueue the dmabuf to vivi */ +	struct v4l2_buffer b; +	CLEAR(b); + +	b.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	b.memory = V4L2_MEMORY_DMABUF; +	b.m.fd = eb.fd; +	ret = ioctl(st->vivi_fd, VIDIOC_QBUF, &b); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_QBUF: %s\n", ERRSTR)) +		return -errno; + +	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	ret = ioctl(st->vivi_fd, VIDIOC_STREAMON, &type); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_STREAMON: %s\n", ERRSTR)) +		return -errno; + +	/* dequeue buffer from VIVI */ +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	b.memory = V4L2_MEMORY_DMABUF; +	 +	ret = ioctl(st->vivi_fd, VIDIOC_DQBUF, &b); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_DQBUF: %s\n", ERRSTR)) +		return -errno; + +	/* stop streaming */ +	ret = ioctl(st->vivi_fd, VIDIOC_STREAMOFF, &type); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_STREAMOFF: %s\n", ERRSTR)) +		return -errno; + +	/* TODO: mmap DMABUF and dump result */ +	struct v4l2_format fmt; +	CLEAR(fmt); +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + +	ret = ioctl(st->vivi_fd, VIDIOC_G_FMT, &fmt); +	if (ERR_ON(ret < 0, "vivi: VIDIOC_G_FMT: %s\n", ERRSTR)) +		return -errno; + +	/* mapping DMABUF for dumping */ +	void *ptr = mmap(NULL, fmt.fmt.pix.sizeimage, PROT_READ, +		MAP_SHARED, eb.fd, 0); +	if (ERR_ON(ptr == MAP_FAILED, "mmap: %s\n", ERRSTR)) +		return -errno; + +	/* dump image, ignore errors */ +	dump_image("dmabuf-vivi-fimc0.ppm", fmt.fmt.pix.pixelformat, +		fmt.fmt.pix.width, fmt.fmt.pix.height, ptr); + +	/* small cleanup */ +	munmap(ptr, fmt.fmt.pix.sizeimage); +	close(eb.fd); + +	return 0; +} + +int process_fimc0(struct state *st) +{ +	int ret; +	struct v4l2_buffer b; +	struct v4l2_plane plane; +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	b.memory = V4L2_MEMORY_MMAP; +	b.index = 0; +	b.m.planes = &plane; +	b.length = 1; + +	ret = ioctl(st->fimc0_fd, VIDIOC_QBUF, &b); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_QBUF: %s\n", ERRSTR)) +		return -errno; + +	/* export the first buffer from FIMC1 */ +	struct v4l2_exportbuffer eb; +	CLEAR(eb); +	eb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_EXPBUF, &eb); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_EXPBUF: %s\n", ERRSTR)) +		return -errno; + +	/* enqueue the DMABUF as FIMC0's cature */ +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	b.memory = V4L2_MEMORY_DMABUF; +	b.index = 0; +	b.m.planes = &plane; +	b.length = 1; +	plane.m.fd = eb.fd; + +	ret = ioctl(st->fimc0_fd, VIDIOC_QBUF, &b); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_QBUF: %s\n", ERRSTR)) +		return -errno; + +	/* start processing */ +	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_STREAMON, &type); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_STREAMON: %s\n", ERRSTR)) +		return -errno; + +	type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_STREAMON, &type); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_STREAMON: %s\n", ERRSTR)) +		return -errno; + +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	b.memory = V4L2_MEMORY_DMABUF; +	b.m.planes = &plane; + +	/* grab processed buffers */ +	ret = ioctl(st->fimc0_fd, VIDIOC_DQBUF, &b); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_DQBUF: %s\n", ERRSTR)) +		return -errno; + +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	b.memory = V4L2_MEMORY_MMAP; +	b.m.planes = &plane; + +	ret = ioctl(st->fimc0_fd, VIDIOC_DQBUF, &b); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_DQBUF: %s\n", ERRSTR)) +		return -errno; + +	/* stop processing */ +	type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_STREAMOFF, &type); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_STREAMOFF: %s\n", ERRSTR)) +		return -errno; + +	type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc0_fd, VIDIOC_STREAMOFF, &type); +	if (ERR_ON(ret < 0, "fimc0: VIDIOC_STREAMOFF: %s\n", ERRSTR)) +		return -errno; + +	return 0; +} + +int process_fimc1(struct state *st) +{ +	int ret; +	/* enqueue buffer 0 as FIMC1's output */ +	struct v4l2_buffer b; +	struct v4l2_plane plane; +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	b.memory = V4L2_MEMORY_MMAP; +	b.index = 0; +	b.m.planes = &plane; +	b.length = 1; + +	ret = ioctl(st->fimc1_fd, VIDIOC_QBUF, &b); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_QBUF: %s\n", ERRSTR)) +		return -errno; + +	/* allocate malloc memory suitable for FIMC1 */ +	struct v4l2_format fmt; +	CLEAR(fmt); +	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_G_FMT, &fmt); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_G_FMT: %s\n", ERRSTR)) +		return -errno; + +	long page_size = sysconf(_SC_PAGESIZE); +	if (ERR_ON(page_size == -1, "sysconf: %s\n", ERRSTR)) +		return -errno; + +	/* someone should be shot because of the layout of v4l2_format */ +	size_t size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; +	/* align to page size */ +	size_t size_align = (size + page_size - 1) & ~(page_size - 1); + +	void *ptr; +	ret = posix_memalign(&ptr, page_size, size_align); +	if (ERR_ON(ret, "posix_memalign: %s\n", ERRSTR)) +		return -errno; + +	/* enqueue userptr as FIMC1's capture */ +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	b.memory = V4L2_MEMORY_USERPTR; +	b.index = 0; +	b.m.planes = &plane; +	b.length = 1; +	plane.m.userptr = (unsigned long)ptr; +	plane.length = size_align; + +	ret = ioctl(st->fimc1_fd, VIDIOC_QBUF, &b); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_QBUF: %s\n", ERRSTR)) +		return -errno; + +	/* start processing */ +	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_STREAMON, &type); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_STREAMON: %s\n", ERRSTR)) +		return -errno; + +	type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_STREAMON, &type); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_STREAMON: %s\n", ERRSTR)) +		return -errno; + +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	b.memory = V4L2_MEMORY_USERPTR; +	b.m.planes = &plane; + +	/* grab processed buffers */ +	ret = ioctl(st->fimc1_fd, VIDIOC_DQBUF, &b); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_DQBUF: %s\n", ERRSTR)) +		return -errno; + +	CLEAR(plane); +	CLEAR(b); +	b.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	b.memory = V4L2_MEMORY_MMAP; +	b.m.planes = &plane; + +	ret = ioctl(st->fimc1_fd, VIDIOC_DQBUF, &b); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_DQBUF: %s\n", ERRSTR)) +		return -errno; + +	/* stop processing */ +	type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_STREAMOFF, &type); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_STREAMOFF: %s\n", ERRSTR)) +		return -errno; + +	type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; +	ret = ioctl(st->fimc1_fd, VIDIOC_STREAMOFF, &type); +	if (ERR_ON(ret < 0, "fimc1: VIDIOC_STREAMOFF: %s\n", ERRSTR)) +		return -errno; + +	/* dump image, ignore errors */ +	dump_image("fimc1-cature.ppm", fmt.fmt.pix_mp.pixelformat, +		fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, +		ptr); + +	return 0; +} +int main(int argc, char *argv[]) +{ +	struct state st; +	CLEAR(st); + +	int ret = config_create(&st.config, argc, argv); +	if (ret) { +		usage(); +		CRIT("bad arguments\n"); +	} + +	if (st.config.help) { +		usage(); +		return EXIT_SUCCESS; +	} + +	st.vivi_fd = open(st.config.vivi_path, O_RDWR); +	CRIT_ON(st.vivi_fd < 0, "failed to open VIVI at %s: %s\n", +		st.config.vivi_path, ERRSTR); + +	st.fimc0_fd = open(st.config.fimc0_path, O_RDWR); +	CRIT_ON(st.vivi_fd < 0, "failed to open FIMC0 at %s: %s\n", +		st.config.fimc0_path, ERRSTR); + +	st.fimc1_fd = open(st.config.fimc1_path, O_RDWR); +	CRIT_ON(st.vivi_fd < 0, "failed to open FIMC1 at %s: %s\n", +		st.config.fimc1_path, ERRSTR); + +	ret = setup_formats(&st); +	CRIT_ON(ret, "failed to setup formats\n"); + +	ret = allocate_buffers(&st); +	CRIT_ON(ret, "failed to allocate buffers\n"); + +	ret = process_vivi(&st); +	CRIT_ON(ret, "failed to do vivi processing\n"); + +	ret = process_fimc0(&st); +	CRIT_ON(ret, "failed to do fimc0 processing\n"); + +	ret = process_fimc1(&st); +	CRIT_ON(ret, "failed to do fimc1 processing\n"); + +	return EXIT_SUCCESS; +}  | 
