summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Krawczuk <m.krawczuk@samsung.com>2015-04-17 16:16:35 +0200
committerKamil Debski <k.debski@samsung.com>2015-04-30 15:37:07 +0200
commit40c68e49c5d1a987a4f2725a655244ca47cd34fb (patch)
tree949140de416e28bba617406c0319153b5bcf57e1
parent8361c5567d6e51f6771fe9b7cd75e6b41afb2b2d (diff)
Add automatic detection of drm, fimc and mfc. Update dates
Signed-off-by: Mateusz Krawczuk <m.krawczuk@samsung.com> Signed-off-by: Kamil Debski <k.debski@samsung.com>
-rw-r--r--v4l2-mfc-example/args.c80
-rw-r--r--v4l2-mfc-example/common.h3
-rw-r--r--v4l2-mfc-example/drm.c204
-rw-r--r--v4l2-mfc-example/drm.h16
-rw-r--r--v4l2-mfc-example/main.c6
-rw-r--r--v4l2-mfc-example/parser.c3
6 files changed, 298 insertions, 14 deletions
diff --git a/v4l2-mfc-example/args.c b/v4l2-mfc-example/args.c
index 3756001..bfb9f29 100644
--- a/v4l2-mfc-example/args.c
+++ b/v4l2-mfc-example/args.c
@@ -4,7 +4,7 @@
*
* Argument parser
*
- * Copyright 2012 Samsung Electronics Co., Ltd.
+ * Copyright 2012 - 2015 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.
@@ -25,11 +25,13 @@
#include <string.h>
#include <unistd.h>
#include <linux/videodev2.h>
+#include <sys/ioctl.h>
+#include <glob.h>
+#include <fcntl.h>
#include "common.h"
#include "parser.h"
-
void print_usage(char *name)
{
// "d:f:i:m:c:V"
@@ -41,6 +43,7 @@ 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-A Autodetect mode \n");
printf("\t-D <module>:<crtc>:<conn> - 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");
@@ -51,6 +54,70 @@ void print_usage(char *name)
printf("\n");
}
+static int read_file(char const *name, char *buf, int len)
+{
+ int fd;
+ int ret;
+
+ fd = open(name, O_RDONLY);
+ if (fd < 0)
+ return fd;
+ ret = read(fd, buf, len);
+ if (ret > 0 && ret < len)
+ buf[buf[ret - 1] == '\n' ? ret - 1 : ret] = 0;
+ close(fd);
+
+ return ret >= 0 ? 0 : ret;
+}
+
+int detect_video(struct instance *i)
+{
+ char buf[256];
+ glob_t gb;
+ int ret, g, ndigits;
+ static char dev_prefix[] = "/dev/video";
+
+ ret = glob("/sys/class/video4linux/video*/name", 0, NULL, &gb);
+ if (ret != 0)
+ return ret;
+
+ for (g = 0; g < gb.gl_pathc; ++g) {
+ ret = read_file(gb.gl_pathv[g], buf, sizeof buf);
+ if (ret != 0)
+ goto finish;
+ printf("Name:\t\t '%s'\n", buf);
+
+ if (!strcmp("fimc.0.m2m", buf)) {
+ i->fimc.name=(char *) malloc(100);
+ strcpy(i->fimc.name, dev_prefix);
+ ndigits = strlen(gb.gl_pathv[g]) - sizeof "/sys/class/video4linux/video/name" + 1;
+ strncat(i->fimc.name, gb.gl_pathv[g] + sizeof "/sys/class/video4linux/video" - 1, ndigits);
+ printf("Name:\t\t '%s'\n", i->fimc.name);
+ }
+ if (!strcmp("s5p-mfc-dec", buf)) {
+ i->mfc.name=(char *) malloc(100);
+ strcpy(i->mfc.name, dev_prefix);
+ ndigits = strlen(gb.gl_pathv[g]) - sizeof "/sys/class/video4linux/video/name" + 1;
+ strncat(i->mfc.name, gb.gl_pathv[g] + sizeof "/sys/class/video4linux/video" - 1, ndigits);
+ printf("Name:\t\t '%s'\n", i->mfc.name);
+ }
+ }
+
+ if (g == gb.gl_pathc) {
+ ret = -1;
+ goto finish;
+ }
+
+finish:
+ globfree(&gb);
+ return ret;
+
+
+}
+
+
+
+
void init_to_defaults(struct instance *i)
{
memset(i, 0, sizeof(*i));
@@ -81,7 +148,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:VXD:B")) != -1) {
+ while ((c = getopt(argc, argv, "c:d:f:i:m:VXAD:B")) != -1) {
switch (c) {
case 'c':
i->parser.codec = get_codec(optarg);
@@ -109,6 +176,13 @@ int parse_args(struct instance *i, int argc, char **argv)
case 'B':
i->fimc.dmabuf = 1;
break;
+ case 'A':
+ detect_video(i);
+ i->drm.autodetect = 1;
+ i->drm.enabled = 1;
+ i->fimc.dmabuf = 1;
+ i->fimc.enabled = 1;
+ break;
case 'D':
/* Name */
tmp = optarg;
diff --git a/v4l2-mfc-example/common.h b/v4l2-mfc-example/common.h
index 3b3e5a3..5d9cd3d 100644
--- a/v4l2-mfc-example/common.h
+++ b/v4l2-mfc-example/common.h
@@ -4,7 +4,7 @@
*
* Common stuff header file
*
- * Copyright 2012 Samsung Electronics Co., Ltd.
+ * Copyright 2012 - 2015 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.
@@ -117,6 +117,7 @@ struct instance {
char *p[MAX_BUFS];
+ unsigned int autodetect;
unsigned int conn_id;
unsigned int crtc_id;
#ifdef DRM
diff --git a/v4l2-mfc-example/drm.c b/v4l2-mfc-example/drm.c
index b60b439..16d9ee5 100644
--- a/v4l2-mfc-example/drm.c
+++ b/v4l2-mfc-example/drm.c
@@ -4,7 +4,7 @@
*
* DRM operations
*
- * Copyright 2014 Samsung Electronics Co., Ltd.
+ * Copyright 2014 - 2015 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.
@@ -30,6 +30,24 @@
#include "common.h"
#include "drm.h"
#include <string.h>
+#include <errno.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name {
+ int type;
+ char *name;
+};
+
+#define type_name_fn(res) \
+char * res##_str(int type) { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+ if (res##_names[i].type == type) \
+ return res##_names[i].name; \
+ } \
+ return "(invalid)"; \
+}
#ifdef DRM
@@ -37,9 +55,54 @@
#include <xf86drmMode.h>
#include <exynos_drm.h>
-int drm_open(struct instance *i, char *name)
+struct type_name encoder_type_names[] = {
+ { DRM_MODE_ENCODER_NONE, "none" },
+ { DRM_MODE_ENCODER_DAC, "DAC" },
+ { DRM_MODE_ENCODER_TMDS, "TMDS" },
+ { DRM_MODE_ENCODER_LVDS, "LVDS" },
+ { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+type_name_fn(encoder_type)
+
+struct type_name connector_status_names[] = {
+ { DRM_MODE_CONNECTED, "connected" },
+ { DRM_MODE_DISCONNECTED, "disconnected" },
+ { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+type_name_fn(connector_status)
+
+struct type_name connector_type_names[] = {
+ { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+ { DRM_MODE_CONNECTOR_VGA, "VGA" },
+ { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+ { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+ { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+ { DRM_MODE_CONNECTOR_Composite, "composite" },
+ { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+ { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+ { DRM_MODE_CONNECTOR_Component, "component" },
+ { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+ { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
+ { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+ { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+ { DRM_MODE_CONNECTOR_TV, "TV" },
+ { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
+};
+
+type_name_fn(connector_type)
+
+
+int dump_encoders(struct instance *i);
+int dump_connectors(struct instance *i);
+int dump_crtcs(struct instance *i);
+int dump_framebuffers(struct instance *i);
+
+int drm_open(struct instance *i)
{
char mode[32];
+ char *name = "exynos";
drmModeCrtc *crtc;
struct drm_gem_close args;
drmModeConnector *connector;
@@ -58,7 +121,12 @@ int drm_open(struct instance *i, char *name)
}
i->drm.resources = drmModeGetResources(i->drm.fd);
-
+ if(i->drm.autodetect) {
+ i->drm.crtc_id = dump_crtcs(i);
+ i->drm.conn_id=dump_connectors(i);
+ }
+ printf("Conn_id:%i \n",i->drm.conn_id);
+ printf("Crtc_id:%i \n",i->drm.crtc_id);
crtc = drmModeGetCrtc(i->drm.fd, i->drm.crtc_id);
if (!crtc) {
err("Failed to get crtc: %d", i->drm.crtc_id);
@@ -116,6 +184,7 @@ int drm_open(struct instance *i, char *name)
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");
@@ -164,9 +233,136 @@ void drm_close(struct instance *i)
drmClose(i->drm.fd);
}
+int dump_encoders(struct instance *i)
+{
+ drmModeEncoder *encoder;
+ int j;
+
+ printf("Encoders:\n");
+ printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
+ for (j = 0; j < i->drm.resources->count_encoders; j++) {
+ encoder = drmModeGetEncoder(i->drm.fd, i->drm.resources->encoders[j]);
+
+ if (!encoder) {
+ fprintf(stderr, "could not get encoder %i: %s\n",
+ i->drm.resources->encoders[j], strerror(errno));
+ continue;
+ }
+ printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+ encoder->encoder_id,
+ encoder->crtc_id,
+ encoder_type_str(encoder->encoder_type),
+ encoder->possible_crtcs,
+ encoder->possible_clones);
+ drmModeFreeEncoder(encoder);
+ }
+ printf("\n");
+
+ return 0;
+}
+
+int dump_connectors(struct instance *i)
+{
+ drmModeConnector *connector;
+ int g , j;
+
+ printf("Connectors:\n");
+ printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
+ for (g = 0; g < i->drm.resources->count_connectors; g++) {
+ connector = drmModeGetConnector(i->drm.fd, i->drm.resources->connectors[g]);
+
+ if (!connector) {
+ fprintf(stderr, "could not get connector %i: %s\n",
+ i->drm.resources->connectors[g], strerror(errno));
+ continue;
+ }
+
+ printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
+ connector->connector_id,
+ connector->encoder_id,
+ connector_status_str(connector->connection),
+ connector_type_str(connector->connector_type),
+ connector->mmWidth, connector->mmHeight,
+ connector->count_modes);
+
+ for (j = 0; j < connector->count_encoders; j++)
+ printf("%s%d", j > 0 ? ", " : "",
+ connector->encoders[j]);
+ printf("\n");
+
+ if (!connector->count_modes)
+ continue;
+
+ printf(" modes:\n");
+ printf(" name refresh (Hz) hdisp hss hse htot vdisp "
+ "vss vse vtot)\n");
+ printf(" props:\n");
+ return connector->connector_id;
+
+ drmModeFreeConnector(connector);
+ }
+ printf("\n");
+
+ return 0;
+}
+
+int dump_crtcs(struct instance *i)
+{
+ drmModeCrtc *crtc;
+ int j,ret;
+
+ printf("CRTCs:\n");
+ printf("id\tfb\tpos\tsize\n");
+ for (j = 0; j < i->drm.resources->count_crtcs; j++) {
+ crtc = drmModeGetCrtc(i->drm.fd, i->drm.resources->crtcs[j]);
+
+ if (!crtc) {
+ fprintf(stderr, "could not get crtc %i: %s\n",
+ i->drm.resources->crtcs[j], strerror(errno));
+ continue;
+ }
+ ret = crtc->crtc_id;
+ printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+ crtc->crtc_id,
+ crtc->buffer_id,
+ crtc->x, crtc->y,
+ crtc->width, crtc->height);
+ drmModeFreeCrtc(crtc);
+ }
+ printf("%i %i \n",crtc->crtc_id, ret);
+ return ret;
+}
+
+int dump_framebuffers(struct instance *i)
+{
+ drmModeFB *fb;
+ int j;
+
+ printf("Frame buffers:\n");
+ printf("id\tsize\tpitch\n");
+ for (j = 0; j < i->drm.resources->count_fbs; j++) {
+ fb = drmModeGetFB(i->drm.fd, i->drm.resources->fbs[j]);
+
+ if (!fb) {
+ fprintf(stderr, "could not get fb %i: %s\n",
+ i->drm.resources->fbs[j], strerror(errno));
+ continue;
+ }
+ printf("%u\t(%ux%u)\t%u\n",
+ fb->fb_id,
+ fb->width, fb->height,
+ fb->pitch);
+
+ drmModeFreeFB(fb);
+ }
+ printf("\n");
+
+ return 0;
+}
+
#else /* DRM */
-int drm_open(struct instance *i, char *name)
+int drm_open(struct instance *i)
{
return 0;
};
diff --git a/v4l2-mfc-example/drm.h b/v4l2-mfc-example/drm.h
index 1cd31e4..ab2e4f0 100644
--- a/v4l2-mfc-example/drm.h
+++ b/v4l2-mfc-example/drm.h
@@ -4,7 +4,7 @@
*
* DRM operations header file
*
- * Copyright 2014 Samsung Electronics Co., Ltd.
+ * Copyright 2014 - 2015 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.
@@ -26,10 +26,22 @@
#ifdef DRM
/* Open and mmap DRM buffer. Also read its properties */
-int drm_open(struct instance *i, char *name);
+int drm_open(struct instance *i);
/* Unmap and close the buffer */
void drm_close(struct instance *i);
+struct connector {
+ uint32_t id;
+ char mode_str[64];
+ drmModeModeInfo *mode;
+ drmModeEncoder *encoder;
+ int crtc;
+ unsigned int fb_id[2], current_fb_id;
+ struct timeval start;
+
+ int swap_count;
+};
+
#endif /* DRM */
#endif /* INCLUDE_DRM_H */
diff --git a/v4l2-mfc-example/main.c b/v4l2-mfc-example/main.c
index 6453c07..d3c32e3 100644
--- a/v4l2-mfc-example/main.c
+++ b/v4l2-mfc-example/main.c
@@ -4,7 +4,7 @@
*
* Main file of the application
*
- * Copyright 2012 Samsung Electronics Co., Ltd.
+ * Copyright 2012 - 2015 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.
@@ -439,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-2014 Samsung Electronics Co., Ltd.\n\n");
+ printf("Copyright 2012-2015 Samsung Electronics Co., Ltd.\n\n");
if (parse_args(&inst, argc, argv)) {
print_usage(argv[0]);
@@ -459,7 +459,7 @@ int main(int argc, char **argv)
return 1;
}
- if (inst.drm.enabled && drm_open(&inst, inst.drm.name)) {
+ if (inst.drm.enabled && drm_open(&inst)) {
cleanup(&inst);
return 1;
}
diff --git a/v4l2-mfc-example/parser.c b/v4l2-mfc-example/parser.c
index 4fd84db..972cdfc 100644
--- a/v4l2-mfc-example/parser.c
+++ b/v4l2-mfc-example/parser.c
@@ -4,7 +4,7 @@
*
* Really simple stream parser file
*
- * Copyright 2012 Samsung Electronics Co., Ltd.
+ * Copyright 2012 - 2015 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.
@@ -334,6 +334,7 @@ int parse_h264_stream(
if (ctx->got_start) {
if (out_size < frame_length) {
+ printf("out_size: %i frame_length: %i\n", out_size, frame_length);
err("Output buffer too small for current frame");
return 0;
}