diff options
| -rw-r--r-- | v4l2-mfc-example/args.c | 80 | ||||
| -rw-r--r-- | v4l2-mfc-example/common.h | 3 | ||||
| -rw-r--r-- | v4l2-mfc-example/drm.c | 204 | ||||
| -rw-r--r-- | v4l2-mfc-example/drm.h | 16 | ||||
| -rw-r--r-- | v4l2-mfc-example/main.c | 6 | ||||
| -rw-r--r-- | 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 <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;  		} | 
