From 40c68e49c5d1a987a4f2725a655244ca47cd34fb Mon Sep 17 00:00:00 2001 From: Mateusz Krawczuk Date: Fri, 17 Apr 2015 16:16:35 +0200 Subject: Add automatic detection of drm, fimc and mfc. Update dates Signed-off-by: Mateusz Krawczuk Signed-off-by: Kamil Debski --- v4l2-mfc-example/args.c | 80 +++++++++++++++++- v4l2-mfc-example/common.h | 3 +- v4l2-mfc-example/drm.c | 204 +++++++++++++++++++++++++++++++++++++++++++++- v4l2-mfc-example/drm.h | 16 +++- v4l2-mfc-example/main.c | 6 +- v4l2-mfc-example/parser.c | 3 +- 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 #include #include +#include +#include +#include #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 - FIMC device (e.g. /dev/video4)\n"); printf("\t-i - Input file name\n"); printf("\t-m - MFC device (e.g. /dev/video8)\n"); + printf("\t-A Autodetect mode \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"); @@ -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 +#include + +#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 #include -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 \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; } -- cgit v1.2.3