From 1aab95de7ce3e60d723a91707e5c7b926cfad4eb Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Wed, 2 Jul 2014 17:54:34 +0200 Subject: v4l2-mfc-example: Add support for DMABUF buffer sharing This patch adds support for buffer sharing with DMABUF. Now FIMC can take DMABUF buffers from MFC and DRM. Signed-off-by: Kamil Debski --- v4l2-mfc-example/args.c | 6 +++++- v4l2-mfc-example/common.h | 3 +++ v4l2-mfc-example/drm.c | 28 +++++++++++++++++-------- v4l2-mfc-example/fimc.c | 36 +++++++++++++++++++++++++------- v4l2-mfc-example/mfc.c | 53 ++++++++++++++++++++++++++++++++++------------- 5 files changed, 94 insertions(+), 32 deletions(-) diff --git a/v4l2-mfc-example/args.c b/v4l2-mfc-example/args.c index e0298c0..1df7a38 100644 --- a/v4l2-mfc-example/args.c +++ b/v4l2-mfc-example/args.c @@ -42,6 +42,7 @@ void print_usage(char *name) printf("\t-i - Input file name\n"); printf("\t-m - MFC device (e.g. /dev/video8)\n"); printf("\t-D :: - DRM module (e.g. exynos:4:17)\n"); + printf("\t-B - use DMABUF instead of userptr for sharing buffers\n"); printf("\t-V - synchronise to vsync\n"); printf("\t\n"); printf("\tIf DRM or Frame buffer is used then FIMC should be suppplied.\n"); @@ -79,7 +80,7 @@ int parse_args(struct instance *i, int argc, char **argv) init_to_defaults(i); - while ((c = getopt(argc, argv, "c:d:f:i:m:VD:")) != -1) { + while ((c = getopt(argc, argv, "c:d:f:i:m:VD:B")) != -1) { switch (c) { case 'c': i->parser.codec = get_codec(optarg); @@ -101,6 +102,9 @@ int parse_args(struct instance *i, int argc, char **argv) case 'V': i->fimc.double_buf = 1; break; + case 'B': + i->fimc.dmabuf = 1; + break; case 'D': /* Name */ tmp = optarg; diff --git a/v4l2-mfc-example/common.h b/v4l2-mfc-example/common.h index aff8972..ea5a9d7 100644 --- a/v4l2-mfc-example/common.h +++ b/v4l2-mfc-example/common.h @@ -165,6 +165,8 @@ struct instance { int stride; int height; char *p[MAX_BUFS]; + int dbuf[MAX_BUFS]; + int dmabuf; } fimc; /* MFC related parameters */ @@ -193,6 +195,7 @@ struct instance { char *cap_buf_addr[MFC_MAX_CAP_BUF][MFC_CAP_PLANES]; int cap_buf_flag[MFC_MAX_CAP_BUF]; int cap_buf_queued; + int dbuf[MFC_MAX_CAP_BUF][MFC_CAP_PLANES]; } mfc; /* Parser related parameters */ diff --git a/v4l2-mfc-example/drm.c b/v4l2-mfc-example/drm.c index 188d394..d53a0b4 100644 --- a/v4l2-mfc-example/drm.c +++ b/v4l2-mfc-example/drm.c @@ -78,13 +78,25 @@ int drm_open(struct instance *i, char *name) return -1; } args.handle = i->drm.gem[n].handle; - i->drm.mmap[n].handle = i->drm.gem[n].handle; - i->drm.mmap[n].size = i->drm.gem[n].size; - ret = ioctl(i->drm.fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &i->drm.mmap[n]); - if (ret < 0) { - ioctl(i->drm.fd, DRM_IOCTL_GEM_CLOSE, &args); - err("Failed to mmap gem"); - return -1; + + if (i->fimc.dmabuf) { + ret = drmPrimeHandleToFD(i->drm.fd, i->drm.gem[n].handle, DRM_CLOEXEC, &i->fimc.dbuf[n]); + if (ret < 0) { + ioctl(i->drm.fd, DRM_IOCTL_GEM_CLOSE, &args); + err("Failed to expbuf a gem object"); + return -1; + } + } else { + i->drm.mmap[n].handle = i->drm.gem[n].handle; + i->drm.mmap[n].size = i->drm.gem[n].size; + ret = ioctl(i->drm.fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &i->drm.mmap[n]); + if (ret < 0) { + ioctl(i->drm.fd, DRM_IOCTL_GEM_CLOSE, &args); + err("Failed to mmap gem"); + return -1; + } + i->drm.p[n] = (char *)(unsigned int)i->drm.mmap[n].mapped; + i->fimc.p[n] = (char *)(unsigned int)i->drm.mmap[n].mapped; } ret = drmModeAddFB(i->drm.fd, i->drm.width, i->drm.height, 32, 32, 4 * i->drm.width, i->drm.gem[n].handle, &fb_id); @@ -96,8 +108,6 @@ int drm_open(struct instance *i, char *name) return -1; } i->drm.fb[n] = fb_id; - i->drm.p[n] = (char *)(unsigned int)i->drm.mmap[n].mapped; - i->fimc.p[n] = (char *)(unsigned int)i->drm.mmap[n].mapped; } snprintf(mode, 32, "%dx%d", crtc->width, crtc->height); diff --git a/v4l2-mfc-example/fimc.c b/v4l2-mfc-example/fimc.c index 61476ba..0459c38 100644 --- a/v4l2-mfc-example/fimc.c +++ b/v4l2-mfc-example/fimc.c @@ -139,7 +139,11 @@ int fimc_setup_output_from_mfc(struct instance *i) memzero(reqbuf); reqbuf.count = i->mfc.cap_buf_cnt; reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - reqbuf.memory = V4L2_MEMORY_USERPTR; + if (i->fimc.dmabuf) { + reqbuf.memory = V4L2_MEMORY_DMABUF; + } else { + reqbuf.memory = V4L2_MEMORY_USERPTR; + } ret = ioctl(i->fimc.fd, VIDIOC_REQBUFS, &reqbuf); if (ret) { @@ -183,8 +187,12 @@ int fimc_setup_capture(struct instance *i) memzero(reqbuf); reqbuf.count = i->fimc.buffers; + dbg("reqbuf.count = %d", reqbuf.count); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - reqbuf.memory = V4L2_MEMORY_USERPTR; + if (i->fimc.dmabuf && i->drm.enabled) + reqbuf.memory = V4L2_MEMORY_DMABUF; + else + reqbuf.memory = V4L2_MEMORY_USERPTR; ret = ioctl(i->fimc.fd, VIDIOC_REQBUFS, &reqbuf); if (ret) { @@ -224,18 +232,25 @@ int fimc_dec_queue_buf_out_from_mfc(struct instance *i, int n) memzero(buf); memzero(planes); buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - buf.memory = V4L2_MEMORY_USERPTR; buf.index = n; buf.m.planes = planes; buf.length = MFC_CAP_PLANES; buf.m.planes[0].bytesused = i->mfc.cap_buf_size[0]; buf.m.planes[0].length = i->mfc.cap_buf_size[0]; - buf.m.planes[0].m.userptr = (unsigned long)i->mfc.cap_buf_addr[n][0]; buf.m.planes[1].bytesused = i->mfc.cap_buf_size[1]; buf.m.planes[1].length = i->mfc.cap_buf_size[1]; - buf.m.planes[1].m.userptr = (unsigned long)i->mfc.cap_buf_addr[n][1]; + + if (i->fimc.dmabuf) { + buf.memory = V4L2_MEMORY_DMABUF; + buf.m.planes[0].m.fd = i->mfc.dbuf[n][0]; + buf.m.planes[1].m.fd = i->mfc.dbuf[n][1]; + } else { + buf.memory = V4L2_MEMORY_USERPTR; + buf.m.planes[0].m.userptr = (unsigned long)i->mfc.cap_buf_addr[n][0]; + buf.m.planes[1].m.userptr = (unsigned long)i->mfc.cap_buf_addr[n][1]; + } ret = ioctl(i->fimc.fd, VIDIOC_QBUF, &buf); @@ -258,19 +273,24 @@ int fimc_dec_queue_buf_cap(struct instance *i, int n) memzero(buf); memzero(planes); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buf.memory = V4L2_MEMORY_USERPTR; buf.index = n; buf.m.planes = planes; buf.length = FIMC_CAP_PLANES; buf.m.planes[0].bytesused = i->fimc.size; buf.m.planes[0].length = i->fimc.size; - buf.m.planes[0].m.userptr = (unsigned long)i->fimc.p[n]; + if (i->fimc.dmabuf && i->drm.enabled) { + buf.memory = V4L2_MEMORY_DMABUF; + buf.m.planes[0].m.fd = i->fimc.dbuf[n]; + } else { + buf.memory = V4L2_MEMORY_USERPTR; + buf.m.planes[0].m.userptr = (unsigned long)i->fimc.p[n]; + } ret = ioctl(i->fimc.fd, VIDIOC_QBUF, &buf); if (ret) { - err("Failed to queue buffer (index=%d) on OUTPUT", n); + err("Failed to queue buffer (index=%d) on CAPTURE", n); return -1; } diff --git a/v4l2-mfc-example/mfc.c b/v4l2-mfc-example/mfc.c index 89aa22d..1f279a1 100644 --- a/v4l2-mfc-example/mfc.c +++ b/v4l2-mfc-example/mfc.c @@ -248,6 +248,7 @@ int mfc_dec_setup_capture(struct instance *i, int extra_buf) struct v4l2_plane planes[MFC_CAP_PLANES]; struct v4l2_control ctrl; struct v4l2_crop crop; + struct v4l2_exportbuffer expbuf; int ret; int n; @@ -325,20 +326,44 @@ int mfc_dec_setup_capture(struct instance *i, int extra_buf) return -1; } - i->mfc.cap_buf_off[n][0] = buf.m.planes[0].m.mem_offset; - i->mfc.cap_buf_off[n][1] = buf.m.planes[1].m.mem_offset; - - i->mfc.cap_buf_addr[n][0] = mmap(NULL, buf.m.planes[0].length, - PROT_READ | PROT_WRITE, MAP_SHARED, - i->mfc.fd, buf.m.planes[0].m.mem_offset); - i->mfc.cap_buf_addr[n][1] = mmap(NULL, buf.m.planes[1].length, - PROT_READ | PROT_WRITE, MAP_SHARED, - i->mfc.fd, buf.m.planes[1].m.mem_offset); - - if (i->mfc.cap_buf_addr[n][0] == MAP_FAILED || - i->mfc.cap_buf_addr[n][1] == MAP_FAILED) { - err("Failed to MMAP MFC CAPTURE buffer"); - return -1; + if (i->fimc.dmabuf) { + memset(&expbuf, 0, sizeof(expbuf)); + expbuf.index = n; + expbuf.plane = 0; + expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ret = ioctl(i->mfc.fd, VIDIOC_EXPBUF, &expbuf); + if (ret != 0) { + err("Failed to export buffer\n"); + return -1; + } + i->mfc.dbuf[n][0] = expbuf.fd; + + memset(&expbuf, 0, sizeof(expbuf)); + expbuf.index = n; + expbuf.plane = 1; + expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ret = ioctl(i->mfc.fd, VIDIOC_EXPBUF, &expbuf); + if (ret != 0) { + err("Failed to export buffer\n"); + return -1; + } + i->mfc.dbuf[n][1] = expbuf.fd; + } else { + i->mfc.cap_buf_off[n][0] = buf.m.planes[0].m.mem_offset; + i->mfc.cap_buf_off[n][1] = buf.m.planes[1].m.mem_offset; + + i->mfc.cap_buf_addr[n][0] = mmap(NULL, buf.m.planes[0].length, + PROT_READ | PROT_WRITE, MAP_SHARED, + i->mfc.fd, buf.m.planes[0].m.mem_offset); + i->mfc.cap_buf_addr[n][1] = mmap(NULL, buf.m.planes[1].length, + PROT_READ | PROT_WRITE, MAP_SHARED, + i->mfc.fd, buf.m.planes[1].m.mem_offset); + + if (i->mfc.cap_buf_addr[n][0] == MAP_FAILED || + i->mfc.cap_buf_addr[n][1] == MAP_FAILED) { + err("Failed to MMAP MFC CAPTURE buffer"); + return -1; + } } } -- cgit v1.2.3