summaryrefslogtreecommitdiff
path: root/v4l2-mfc-example
diff options
context:
space:
mode:
authorKamil Debski <k.debski@samsung.com>2014-06-30 10:45:25 +0200
committerKamil Debski <k.debski@samsung.com>2014-08-07 16:01:31 +0200
commitc655913a3bdd7ef6413814482983c3beff00bdc0 (patch)
tree02add96cbc81c5b68b6a75eca234222047ea9eb8 /v4l2-mfc-example
parent0edbb0f97b0b5136d16313e48ff5a79714abc0a7 (diff)
v4l2-mfc-example: Add DRM support
Patch adding support for DRM video rendering. Signed-off-by: Kamil Debski <k.debski@samsung.com>
Diffstat (limited to 'v4l2-mfc-example')
-rw-r--r--v4l2-mfc-example/Makefile13
-rw-r--r--v4l2-mfc-example/args.c63
-rw-r--r--v4l2-mfc-example/common.h49
-rw-r--r--v4l2-mfc-example/drm.c164
-rw-r--r--v4l2-mfc-example/drm.h36
-rw-r--r--v4l2-mfc-example/fb.c18
-rw-r--r--v4l2-mfc-example/fimc.c22
-rw-r--r--v4l2-mfc-example/fimc.h4
-rw-r--r--v4l2-mfc-example/main.c81
9 files changed, 398 insertions, 52 deletions
diff --git a/v4l2-mfc-example/Makefile b/v4l2-mfc-example/Makefile
index 2117e1e..2594f9b 100644
--- a/v4l2-mfc-example/Makefile
+++ b/v4l2-mfc-example/Makefile
@@ -19,20 +19,25 @@
# Toolchain path
TCPATH = arm-linux-gnueabi-
#TCPATH =
-KERNELHEADERS = /home/kamil/praca/w1-party/kernel/headers/include
+KERNELHEADERS = -I/home/kamil/praca/w1-party/kernel/headers/include
+DRMHEADERS = -I/home/kamil/praca/drm/dst/include/libdrm \
+ -I/home/kamil/praca/drm/dst/include/exynos \
+ -I/home/kamil/praca/drm/dst/include
+LIBRARIES = -L/home/kamil/praca/drm/dst/lib/
+LIBS = -ldrm
CC = ${TCPATH}gcc
AR = "${TCPATH}ar rc"
AR2 = ${TCPATH}ranlib make -j4
-INCLUDES = -I$(KERNELHEADERS)
+INCLUDES = $(KERNELHEADERS) $(DRMHEADERS)
#INCLUDES = -I$(KERNELHEADERS)/include
#-I$(TARGETROOT)/usr/include/linux
-SOURCES = main.c fileops.c args.c parser.c fb.c fimc.c mfc.c queue.c
+SOURCES = main.c fileops.c args.c parser.c fb.c fimc.c mfc.c queue.c drm.c
OBJECTS := $(SOURCES:.c=.o)
EXEC = v4l2_decode
CFLAGS = -Wall -g -DS5PC1XX_FIMC -lm
@@ -44,7 +49,7 @@ all: $(EXEC)
$(CC) -c $(CFLAGS) $(INCLUDES) $<
$(EXEC): $(OBJECTS)
- $(CC) $(CFLAGS) -o $(EXEC) $(OBJECTS) -pthread
+ $(CC) $(CFLAGS) -o $(EXEC) $(OBJECTS) $(LIBRARIES) $(LIBS) -pthread
clean:
rm -f *.o $(EXEC)
diff --git a/v4l2-mfc-example/args.c b/v4l2-mfc-example/args.c
index 0e9e89c..e0298c0 100644
--- a/v4l2-mfc-example/args.c
+++ b/v4l2-mfc-example/args.c
@@ -20,6 +20,7 @@
*
*/
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -40,9 +41,11 @@ void print_usage(char *name)
printf("\t-f <device> - FIMC device (e.g. /dev/video4)\n");
printf("\t-i <file> - Input file name\n");
printf("\t-m <device> - MFC device (e.g. /dev/video8)\n");
+ printf("\t-D <module>:<crtc>:<conn> - DRM module (e.g. exynos:4:17)\n");
printf("\t-V - synchronise to vsync\n");
- //printf("\t- <device> - \n");
- printf("\tp2\n");
+ printf("\t\n");
+ printf("\tIf DRM or Frame buffer is used then FIMC should be suppplied.\n");
+ printf("\tOnly one of the following Frame Buffer, DRM can be used at a time.\n");
printf("\n");
}
@@ -71,17 +74,19 @@ int get_codec(char *str)
int parse_args(struct instance *i, int argc, char **argv)
{
+ char *tmp;
int c;
init_to_defaults(i);
- while ((c = getopt(argc, argv, "c:d:f:i:m:V")) != -1) {
+ while ((c = getopt(argc, argv, "c:d:f:i:m:VD:")) != -1) {
switch (c) {
case 'c':
i->parser.codec = get_codec(optarg);
break;
case 'd':
i->fb.name = optarg;
+ i->fb.enabled = 1;
break;
case 'f':
i->fimc.name = optarg;
@@ -94,7 +99,38 @@ int parse_args(struct instance *i, int argc, char **argv)
i->mfc.name = optarg;
break;
case 'V':
- i->fb.double_buf = 1;
+ i->fimc.double_buf = 1;
+ break;
+ case 'D':
+ /* Name */
+ tmp = optarg;
+ while (*tmp && *tmp != ':')
+ tmp++;
+ if (*tmp) {
+ i->drm.name = optarg;
+ *tmp = 0;
+ dbg("DRM module name: %s", optarg);
+ optarg = ++tmp;
+ } else {
+ break;
+ }
+ /* Crtc */
+ while (*tmp && *tmp != ':')
+ tmp++;
+ if (*tmp) {
+ *tmp = 0;
+ i->drm.crtc_id = atoi(optarg);
+ dbg("crtc: %d (%s)", i->drm.crtc_id, optarg);
+ optarg = ++tmp;
+ } else {
+ break;
+ }
+ /* Crtc */
+ while (*tmp && *tmp != ':')
+ tmp++;
+ i->drm.conn_id = atoi(optarg);
+ dbg("conn: %d (%s)", i->drm.conn_id, optarg);
+ i->drm.enabled = 1;
break;
default:
err("Bad argument");
@@ -102,15 +138,24 @@ int parse_args(struct instance *i, int argc, char **argv)
}
}
- if (!i->in.name || !i->fb.name || !i->mfc.name) {
- err("The following arguments are required: -d -i -m -c");
- return -1;
- }
-
if (!i->parser.codec) {
err("Unknown or not set codec (-c)");
return -1;
}
+ if (!i->in.name || !i->mfc.name) {
+ err("The following arguments are required: -i -m -c");
+ return -1;
+ }
+ if (i->fimc.enabled) {
+ if (i->drm.enabled) {
+ dbg("Using DRM for display");
+ } else if (i->fb.enabled) {
+ dbg("Using FrameBuffer for display\n");
+ } else {
+ err("When using FIMC a framewbuffer or DRM has to be used\n");
+ return -1;
+ }
+ }
switch (i->parser.codec) {
case V4L2_PIX_FMT_XVID:
diff --git a/v4l2-mfc-example/common.h b/v4l2-mfc-example/common.h
index 3f55283..aff8972 100644
--- a/v4l2-mfc-example/common.h
+++ b/v4l2-mfc-example/common.h
@@ -36,6 +36,14 @@
/* When DEBUG is defined debug messages are printed on the screen.
* Otherwise only error messages are displayed. */
#define DEBUG
+/* Remove #define DRM will disable DRM support */
+#define DRM
+
+#ifdef DRM
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <exynos_drm.h>
+#endif
#ifdef ADD_DETAILS
#define err(msg, ...) \
@@ -76,7 +84,7 @@
#define FIMC_CAP_PLANES 1
/* Maximum number of frame buffers - used for double buffering and
* vsyns synchronisation */
-#define FB_MAX_BUFS 2
+#define MAX_BUFS 2
/* The buffer is free to use by MFC */
#define BUF_FREE 0
@@ -96,12 +104,35 @@ struct instance {
int offs;
} in;
+ /* DRM related parameters */
+ struct {
+ char *name;
+ int fd;
+
+ int fb[MAX_BUFS];
+ int crtc[MAX_BUFS];
+
+ int width;
+ int height;
+
+ char *p[MAX_BUFS];
+
+ unsigned int conn_id;
+ unsigned int crtc_id;
+#ifdef DRM
+ struct drm_exynos_gem_create gem[MAX_BUFS];
+ struct drm_exynos_gem_mmap mmap[MAX_BUFS];
+ drmModeRes *resources;
+#endif
+ char enabled;
+
+ } drm;
+
/* Frame buffer related parameters */
struct {
char *name;
int fd;
- char *p[FB_MAX_BUFS];
- int cur_buf;
+ char *p[MAX_BUFS];
int buffers;
int width;
int height;
@@ -111,7 +142,7 @@ struct instance {
int stride;
int size;
int full_size;
- int double_buf;
+ char enabled;
} fb;
/* FIMC related parameter */
@@ -124,6 +155,16 @@ struct instance {
* the MFC thread */
sem_t done;
char enabled;
+
+ int cur_buf;
+ int double_buf;
+ int size;
+ int buffers;
+ int bpp;
+ int width;
+ int stride;
+ int height;
+ char *p[MAX_BUFS];
} fimc;
/* MFC related parameters */
diff --git a/v4l2-mfc-example/drm.c b/v4l2-mfc-example/drm.c
new file mode 100644
index 0000000..188d394
--- /dev/null
+++ b/v4l2-mfc-example/drm.c
@@ -0,0 +1,164 @@
+/*
+ * V4L2 Codec decoding example application
+ * Kamil Debski <k.debski@samsung.com>
+ *
+ * DRM operations
+ *
+ * Copyright 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "drm.h"
+#include <string.h>
+
+#ifdef DRM
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <exynos_drm.h>
+
+int drm_open(struct instance *i, char *name)
+{
+ char mode[32];
+ drmModeCrtc *crtc;
+ struct drm_gem_close args;
+ drmModeConnector *connector;
+ drmModeModeInfo *mode_drm;
+ unsigned int fb_id;
+ int ret;
+ int n;
+
+ i->drm.fd =drmOpen(name, NULL);
+ if (i->drm.fd < 0) {
+ err("Failed to open drm module \"%s\"", name);
+ return -1;
+ }
+
+ i->drm.resources = drmModeGetResources(i->drm.fd);
+
+ crtc = drmModeGetCrtc(i->drm.fd, i->drm.crtc_id);
+ if (!crtc) {
+ err("Failed to get crtc: %d", i->drm.crtc_id);
+ return -1;
+ }
+
+ i->drm.width = crtc->width;
+ i->drm.height = crtc->height;
+
+ dbg("DRM crtc (%d) resolution: %dx%d @", i->drm.crtc_id, i->drm.width,
+ i->drm.height);
+ drmModeFreeCrtc(crtc);
+
+ for (n = 0; n < (i->fimc.double_buf?2:1); n++) {
+ i->drm.gem[n].size = i->drm.width * i->drm.height * 4;
+ ret = ioctl(i->drm.fd, DRM_IOCTL_EXYNOS_GEM_CREATE,
+ &i->drm.gem[n]);
+ if (ret < 0) {
+ err("Failed to create gem");
+ 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;
+ }
+ ret = drmModeAddFB(i->drm.fd, i->drm.width, i->drm.height, 32,
+ 32, 4 * i->drm.width, i->drm.gem[n].handle, &fb_id);
+ if (ret) {
+ munmap((void *)(unsigned long)i->drm.mmap[n].mapped,
+ i->drm.gem[n].size);
+ ioctl(i->drm.fd, DRM_IOCTL_GEM_CLOSE, &args);
+ err("Failed to add fb");
+ 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);
+
+ connector = drmModeGetConnector(i->drm.fd, i->drm.conn_id);
+ if (!connector || connector->connector_id != i->drm.conn_id) {
+ err("Couldn't find the connector");
+ drmModeFreeConnector(connector);
+ return -1;
+ }
+
+ mode_drm = 0;
+
+ for (n = 0; n < connector->count_modes; n++) {
+ if (!strncmp(connector->modes[n].name, mode, 32)) {
+ mode_drm = &connector->modes[n];
+ break;
+ }
+ }
+
+ if (!mode_drm) {
+ err("Failed to find mode\n");
+ drmModeFreeConnector(connector);
+ return -1;
+ }
+
+ ret = drmModeSetCrtc(i->drm.fd, i->drm.crtc_id, i->drm.fb[0], 0, 0,
+ &i->drm.conn_id, 1, mode_drm);
+ if (ret) {
+ err("Failed to set crtc");
+ drmModeFreeConnector(connector);
+ return -1;
+ }
+
+ i->fimc.width = i->drm.width;
+ i->fimc.height = i->drm.height;
+ i->fimc.stride = i->drm.width * 4;
+ i->fimc.bpp = 32;
+ i->fimc.buffers = (i->fimc.double_buf?2:1);
+ i->fimc.size = i->drm.width * i->drm.height * 4;
+
+ i->drm.crtc[0] = i->drm.crtc_id;
+ i->drm.crtc[1] = i->drm.crtc_id;
+
+ return 0;
+}
+
+void drm_close(struct instance *i)
+{
+ drmClose(i->drm.fd);
+}
+
+#else /* DRM */
+
+int drm_open(struct instance *i, char *name)
+{
+ return 0;
+};
+
+void drm_close(struct instance *i) {
+ return;
+}
+
+#endif /* DRM */
diff --git a/v4l2-mfc-example/drm.h b/v4l2-mfc-example/drm.h
new file mode 100644
index 0000000..1cd31e4
--- /dev/null
+++ b/v4l2-mfc-example/drm.h
@@ -0,0 +1,36 @@
+/*
+ * V4L2 Codec decoding example application
+ * Kamil Debski <k.debski@samsung.com>
+ *
+ * DRM operations header file
+ *
+ * Copyright 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef INCLUDE_DRM_H
+#define INCLUDE_DRM_H
+
+#ifdef DRM
+
+/* Open and mmap DRM buffer. Also read its properties */
+int drm_open(struct instance *i, char *name);
+/* Unmap and close the buffer */
+void drm_close(struct instance *i);
+
+#endif /* DRM */
+
+#endif /* INCLUDE_DRM_H */
+
diff --git a/v4l2-mfc-example/fb.c b/v4l2-mfc-example/fb.c
index a2d0bcb..162b511 100644
--- a/v4l2-mfc-example/fb.c
+++ b/v4l2-mfc-example/fb.c
@@ -52,25 +52,29 @@ int fb_open(struct instance *i, char *name)
dbg("Virtual resolution: vxres=%d vyres=%d",
fbinfo.xres_virtual, fbinfo.yres_virtual);
- i->fb.width = fbinfo.xres;
- i->fb.height = fbinfo.yres;
+ i->fimc.width = i->fb.width = fbinfo.xres;
+ i->fimc.height = i->fb.height = fbinfo.yres;
i->fb.virt_width = fbinfo.xres_virtual;
i->fb.virt_height = fbinfo.yres_virtual;
- i->fb.bpp = fbinfo.bits_per_pixel;
- i->fb.stride = i->fb.virt_width * i->fb.bpp / 8;
- i->fb.full_size = i->fb.stride * i->fb.virt_height;
- i->fb.size = i->fb.stride * fbinfo.yres;
+ i->fimc.bpp = i->fb.bpp = fbinfo.bits_per_pixel;
+ i->fimc.stride = i->fb.stride = i->fb.virt_width * i->fb.bpp / 8;
+ i->fb.full_size = i->fb.stride * i->fb.virt_height;
+ i->fimc.size = i->fb.size = i->fb.stride * fbinfo.yres;
i->fb.p[0] = mmap(0, i->fb.full_size, PROT_WRITE | PROT_READ,
MAP_SHARED, i->fb.fd, 0);
i->fb.buffers = 1;
- if (i->fb.double_buf) {
+ if (i->fimc.double_buf) {
i->fb.p[1] = i->fb.p[0] + i->fb.size;
i->fb.buffers = 2;
}
+ i->fimc.buffers = i->fb.buffers;
+ i->fimc.p[0] = i->fb.p[0];
+ i->fimc.p[1] = i->fb.p[1];
+
return fb_set_virt_y_offset(i, 0);
}
diff --git a/v4l2-mfc-example/fimc.c b/v4l2-mfc-example/fimc.c
index 4af3aa3..61476ba 100644
--- a/v4l2-mfc-example/fimc.c
+++ b/v4l2-mfc-example/fimc.c
@@ -152,7 +152,7 @@ int fimc_setup_output_from_mfc(struct instance *i)
return 0;
}
-int fimc_setup_capture_from_fb(struct instance *i)
+int fimc_setup_capture(struct instance *i)
{
struct v4l2_plane_pix_format planes[MFC_OUT_PLANES];
struct v4l2_requestbuffers reqbuf;
@@ -160,10 +160,10 @@ int fimc_setup_capture_from_fb(struct instance *i)
int ret;
memzero(planes);
- planes[0].sizeimage = i->fb.stride * i->fb.height;
- planes[0].bytesperline = i->fb.stride;
+ planes[0].sizeimage = i->fimc.stride * i->fimc.height;
+ planes[0].bytesperline = i->fimc.stride;
- switch (i->fb.bpp) {
+ switch (i->fimc.bpp) {
case 16:
fmt = V4L2_PIX_FMT_RGB565;
break;
@@ -171,18 +171,18 @@ int fimc_setup_capture_from_fb(struct instance *i)
fmt = V4L2_PIX_FMT_RGB32;
break;
default:
- err("Framebuffer format in not recognized. Bpp=%d", i->fb.bpp);
+ err("Framebuffer format in not recognized. Bpp=%d", i->fimc.bpp);
return -1;
}
- ret = fimc_sfmt(i, i->fb.width, i->fb.height,
+ ret = fimc_sfmt(i, i->fimc.width, i->fimc.height,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, fmt, 1, planes);
if (ret)
return -1;
memzero(reqbuf);
- reqbuf.count = i->fb.buffers;
+ reqbuf.count = i->fimc.buffers;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
reqbuf.memory = V4L2_MEMORY_USERPTR;
@@ -249,7 +249,7 @@ int fimc_dec_queue_buf_out_from_mfc(struct instance *i, int n)
return 0;
}
-int fimc_dec_queue_buf_cap_from_fb(struct instance *i, int n)
+int fimc_dec_queue_buf_cap(struct instance *i, int n)
{
struct v4l2_buffer buf;
struct v4l2_plane planes[FIMC_CAP_PLANES];
@@ -263,9 +263,9 @@ int fimc_dec_queue_buf_cap_from_fb(struct instance *i, int n)
buf.m.planes = planes;
buf.length = FIMC_CAP_PLANES;
- buf.m.planes[0].bytesused = i->fb.size;
- buf.m.planes[0].length = i->fb.size;
- buf.m.planes[0].m.userptr = (unsigned long)i->fb.p[n];
+ 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];
ret = ioctl(i->fimc.fd, VIDIOC_QBUF, &buf);
diff --git a/v4l2-mfc-example/fimc.h b/v4l2-mfc-example/fimc.h
index 7a3f08b..5102547 100644
--- a/v4l2-mfc-example/fimc.h
+++ b/v4l2-mfc-example/fimc.h
@@ -36,13 +36,13 @@ int fimc_sfmt(struct instance *i, int width, int height,
/* Setup OUTPUT queue of FIMC basing on the configuration of MFC */
int fimc_setup_output_from_mfc(struct instance *i);
/* Setup CAPTURE queue of FIMC basing on the configuration of the frame buffer */
-int fimc_setup_capture_from_fb(struct instance *i);
+int fimc_setup_capture(struct instance *i);
/* Control streaming status */
int fimc_stream(struct instance *i, enum v4l2_buf_type type, int status);
/* Convenience function for queueing buffers from MFC */
int fimc_dec_queue_buf_out_from_mfc(struct instance *i, int n);
/* Convenience function for queueing buffers from frame buffer*/
-int fimc_dec_queue_buf_cap_from_fb(struct instance *i, int n);
+int fimc_dec_queue_buf_cap(struct instance *i, int n);
/* Dequeue buffer */
int fimc_dec_dequeue_buf(struct instance *i, int *n, int nplanes, int type);
/* Dequeue buffer from the CAPTURE queue. The argument *n is set to the index of
diff --git a/v4l2-mfc-example/main.c b/v4l2-mfc-example/main.c
index fef0c8d..6453c07 100644
--- a/v4l2-mfc-example/main.c
+++ b/v4l2-mfc-example/main.c
@@ -33,6 +33,7 @@
#include "fileops.h"
#include "mfc.h"
#include "parser.h"
+#include "drm.h"
/* This is the size of the buffer for the compressed stream.
* It limits the maximum compressed frame size. */
@@ -55,7 +56,10 @@ void cleanup(struct instance *i)
fb_close(i);
if (i->in.fd)
input_close(i);
- queue_free(&i->fimc.queue);
+ if (i->drm.fd)
+ drm_close(i);
+ if (i->fimc.enabled)
+ queue_free(&i->fimc.queue);
}
int extract_and_process_header(struct instance *i)
@@ -287,6 +291,14 @@ void *mfc_thread_func(void *args)
return 0;
}
+void
+page_flip_handler(int fd, unsigned int frame,
+ unsigned int sec, unsigned int usec, void *data)
+{
+ printf("Handled %d %d %d\n", frame, sec, usec);
+
+}
+
/* This thread handles FIMC processing and optionally frame buffer
* switching and synchronisation to the vsync of frame buffer. */
void *fimc_thread_func(void *args)
@@ -296,6 +308,8 @@ void *fimc_thread_func(void *args)
struct instance *i = (struct instance *)args;
int n, tmp;
+ i->fimc.cur_buf = 0;
+
while (!i->error && (!i->finish ||
(i->finish && !queue_empty(&i->fimc.queue))
)) {
@@ -324,18 +338,12 @@ void *fimc_thread_func(void *args)
break;
}
- i->fb.cur_buf = 0;
-
- if (i->fb.double_buf) {
- i->fb.cur_buf++;
- i->fb.cur_buf %= i->fb.buffers;
- }
-
- if (fimc_dec_queue_buf_cap_from_fb(i, i->fb.cur_buf)) {
+ if (fimc_dec_queue_buf_cap(i, i->fimc.cur_buf)) {
i->error = 1;
break;
}
+
if (first_run) {
/* Since our fabulous V4L2 framework enforces that at
* least one buffer is queued before switching streaming
@@ -369,11 +377,49 @@ void *fimc_thread_func(void *args)
break;
}
- if (i->fb.double_buf) {
- fb_set_virt_y_offset(i, i->fb.height);
+ if (i->fimc.double_buf && i->fb.enabled) {
+ fb_set_virt_y_offset(i, i->fimc.cur_buf * i->fb.height);
fb_wait_for_vsync(i);
}
+ if (i->fimc.double_buf && i->drm.enabled) {
+ drmModePageFlip(i->drm.fd, i->drm.crtc[i->fimc.cur_buf],
+ i->drm.fb[i->fimc.cur_buf],
+ DRM_MODE_PAGE_FLIP_EVENT, 0);
+
+ while (1) {
+ struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+ fd_set fds;
+ int ret;
+ drmEventContext evctx;
+
+ memset(&evctx, 0, sizeof evctx);
+ evctx.version = DRM_EVENT_CONTEXT_VERSION;
+ evctx.vblank_handler = NULL;
+ evctx.page_flip_handler = page_flip_handler;
+
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ FD_SET(i->drm.fd, &fds);
+ ret = select(i->drm.fd + 1, &fds, NULL, NULL, &timeout);
+
+ if (ret <= 0)
+ continue;
+ else if (FD_ISSET(0, &fds))
+ break;
+
+ drmHandleEvent(i->drm.fd, &evctx);
+ break;
+
+ }
+
+ }
+
+ if (i->fimc.double_buf) {
+ i->fimc.cur_buf++;
+ i->fimc.cur_buf %= i->fimc.buffers;
+ }
+
i->mfc.cap_buf_flag[n] = BUF_FREE;
sem_post(&i->fimc.done);
@@ -393,7 +439,7 @@ int main(int argc, char **argv)
printf("V4L2 Codec decoding example application\n");
printf("Kamil Debski <k.debski@samsung.com>\n");
- printf("Copyright 2012 Samsung Electronics Co., Ltd.\n\n");
+ printf("Copyright 2012-2014 Samsung Electronics Co., Ltd.\n\n");
if (parse_args(&inst, argc, argv)) {
print_usage(argv[0]);
@@ -408,12 +454,17 @@ int main(int argc, char **argv)
return 1;
}
- if (fb_open(&inst, inst.fb.name)) {
+ if (inst.fb.enabled && fb_open(&inst, inst.fb.name)) {
+ cleanup(&inst);
+ return 1;
+ }
+
+ if (inst.drm.enabled && drm_open(&inst, inst.drm.name)) {
cleanup(&inst);
return 1;
}
- if (inst.fimc.name && fimc_open(&inst, inst.fimc.name)) {
+ if (inst.fimc.enabled && fimc_open(&inst, inst.fimc.name)) {
cleanup(&inst);
return 1;
}
@@ -453,7 +504,7 @@ int main(int argc, char **argv)
return 1;
}
- if (inst.fimc.enabled && fimc_setup_capture_from_fb(&inst)) {
+ if (inst.fimc.enabled && fimc_setup_capture(&inst)) {
cleanup(&inst);
return 1;
}