All of lore.kernel.org
 help / color / mirror / Atom feed
* [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2
@ 2011-05-19 12:36 Yordan Kamenov
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 1/3] Add files for media controller pipelines Yordan Kamenov
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Yordan Kamenov @ 2011-05-19 12:36 UTC (permalink / raw)
  To: linux-media; +Cc: sakari.ailus, Yordan Kamenov

Hi,

This is the Media Controller plugin for libv4l. It uses libv4l2 plugin support
which is accepted by Hans De Goede, but not yet included in mainline libv4l2:
http://www.spinics.net/lists/linux-media/msg32017.html

The plugin allows a traditional v4l2 applications to work with Media Controller
framework. The plugin is loaded when application opens /dev/video0 and it
configures the media controller and then all ioctl's by the applicatin are
handled by the plugin.

The plugin implements init, close and ioctl callbacks. The init callback
checks it's input file descriptor and if it coresponds to /dev/video0, then
the media controller is initialized and appropriate pipeline is created.
The close callback deinitializes the pipeline, and closes the media device.
The ioctl callback is responsible to handle ioctl calls from application by
using the media controller pipeline.

The plugin uses media-ctl library for media controller operations:
http://git.ideasonboard.org/?p=media-ctl.git;a=summary

The plugin is divided in three separate patches:
 * Media Controller pipelines initialization, configuration and destruction
 * v4l operations - uses some functionality from the first one
 * Plugin interface operations (init, close and ioctl) - uses functionality
   from first two



Yordan Kamenov (3):
  Add files for media controller pipelines
  Add files for v4l operations
  Add libv4l2 media controller plugin interface files


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [libv4l-mcplugin PATCH 1/3] Add files for media controller pipelines
  2011-05-19 12:36 [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Yordan Kamenov
@ 2011-05-19 12:36 ` Yordan Kamenov
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 2/3] Add files for v4l operations Yordan Kamenov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Yordan Kamenov @ 2011-05-19 12:36 UTC (permalink / raw)
  To: linux-media; +Cc: sakari.ailus, Yordan Kamenov

Add Makefile.
Add files for Media Controller pipelines initialization, configuration and
destruction.
Add file for list operations.
Add config file.

Signed-off-by: Yordan Kamenov <ykamenov@mm-sol.com>
---
 Makefile      |   30 ++
 omap3-mc.conf |   82 +++++
 paths.c       |  959 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 paths.h       |   64 ++++
 sl_list.h     |   65 ++++
 5 files changed, 1200 insertions(+), 0 deletions(-)
 create mode 100644 Makefile
 create mode 100644 omap3-mc.conf
 create mode 100644 paths.c
 create mode 100644 paths.h
 create mode 100644 sl_list.h

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2b3b375
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+ARCH ?= arm
+KDIR ?= /usr/src/linux
+LIBV4LINCDIR ?= ../../v4l-utils/lib/include/
+LIBMEDIACTLDIR ?= /usr/local/lib
+CONF_INST_DIR := $(DESTDIR)/etc/libv4l2plugins
+PLUGIN_INST_DIR := $(DESTDIR)/usr/lib/libv4l/plugins
+
+KINC := -I$(KDIR)/include -I$(KDIR)/arch/$(ARCH)/include
+INC := -I$(LIBV4LINCDIR) $(KINC)
+CC   := $(CROSS_COMPILE)gcc
+
+LDFLAGS += -L$(LIBMEDIACTLDIR) -lmediactl
+
+CFLAGS += -O2 -Wall -fpic -I. $(INC)
+OBJS = libv4l2plugin-omap3mc.o paths.o operations.o
+
+all: libv4l2plugin-omap3mc.so
+
+libv4l2plugin-omap3mc.so: $(OBJS)
+	$(CC) $(CFLAGS) -shared $(LDFLAGS) -o libv4l2plugin-omap3mc.so $(OBJS)
+clean:
+	rm -f $(OBJS) libv4l2plugin-omap3mc.so
+
+install: libv4l2plugin-omap3mc.so
+	test -z "$(CONF_INST_DIR)" || mkdir -p "$(CONF_INST_DIR)"
+	install -m 666 omap3-mc.conf "$(CONF_INST_DIR)"
+	test -z "$(PLUGIN_INST_DIR)" || mkdir -p "$(PLUGIN_INST_DIR)"
+	install -m 755 libv4l2plugin-omap3mc.so "$(PLUGIN_INST_DIR)"
+
+.PHONY: clean all
diff --git a/omap3-mc.conf b/omap3-mc.conf
new file mode 100644
index 0000000..3b7947c
--- /dev/null
+++ b/omap3-mc.conf
@@ -0,0 +1,82 @@
+# Configuration file for media controller plugin for libv4l
+#
+#
+# Format:
+#
+# [primary|secondary]_path
+#     list of subdevice names
+# end
+#
+# [primary|secondary]_in_pixfmt
+#     list of formats supported by input device
+# end
+#
+# [primary|secondary]_out_pixfmt
+#     list of formats supported by output device
+# end
+#
+#
+#
+# Sensors:
+#      jt8ev1, smiapp-001, smiapp-002, smiapp-003, smiapp-004, tcm8500md, vw6558
+#
+# Subdevices:
+#      OMAP3 ISP CSI2a
+#      OMAP3 ISP CSI2a output
+#      OMAP3 ISP CCP2
+#      OMAP3 ISP CCP2 input
+#      OMAP3 ISP CCDC
+#      OMAP3 ISP preview
+#      OMAP3 ISP preview output
+#      OMAP3 ISP resizer input
+#      OMAP3 ISP resizer
+#      OMAP3 ISP resizer output
+#
+#
+# Formats:
+#      BAYER8_SBGGR, BAYER8_SGBRG, BAYER8_SGRBG, BAYER10_SGRBG, BAYER10_SRGGB,
+#      BAYER10_SBGGR, BAYER10_SGBRG, BAYER10DPCM8_SGRBG, YUYV, UYVY
+#
+#
+
+
+
+primary_path
+    jt8ev1
+    OMAP3 ISP CSI2a
+    OMAP3 ISP CCDC
+    OMAP3 ISP preview
+    OMAP3 ISP resizer
+    OMAP3 ISP resizer output
+end
+
+primary_in_pixfmt
+    BAYER10DPCM8_SGRBG
+    BAYER10_SGRBG
+end
+
+primary_out_pixfmt
+    UYVY
+end
+
+
+
+secondary_path
+    vw6558
+    OMAP3 ISP CCP2
+    OMAP3 ISP CCDC
+    OMAP3 ISP preview
+    OMAP3 ISP resizer
+    OMAP3 ISP resizer output
+end
+
+secondary_in_pixfmt
+    BAYER10DPCM8_SGRBG
+    BAYER10_SGRBG
+end
+
+secondary_out_pixfmt
+    UYVY
+end
+
+
diff --git a/paths.c b/paths.c
new file mode 100644
index 0000000..bbc6cfd
--- /dev/null
+++ b/paths.c
@@ -0,0 +1,959 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <linux/v4l2-subdev.h>
+
+#include "sl_list.h"
+#include "paths.h"
+
+#define CONFIG_FILE "/etc/libv4l2plugins/omap3-mc.conf"
+
+#define LINESIZE        (256)
+#define CHOMP(x)                        \
+    do {                                \
+        char *p;                        \
+        int  sz;                        \
+        p = (x);                        \
+        sz = strlen(p);            \
+        p += sz - 1;                    \
+        if (sz) \
+            while (isspace(*p)) *p-- = 0;	\
+    } while (0)
+
+/* Sections in configuration file */
+enum mc_plugin_config_sections {
+	CONFIG_SECTION_NONE,
+	CONFIG_SECTION_PRIMARY_PATH,
+	CONFIG_SECTION_PRIMARY_IN_PIXFMT,
+	CONFIG_SECTION_PRIMARY_OUT_PIXFMT,
+	CONFIG_SECTION_SECONDARY_PATH,
+	CONFIG_SECTION_SECONDARY_IN_PIXFMT,
+	CONFIG_SECTION_SECONDARY_OUT_PIXFMT
+};
+
+struct capture_pipeline pipe_sensor_yuv_path;
+
+int pixel_mc_plugin_to_subdev(enum mc_plugin_pixelformat pixfmt)
+{
+	switch (pixfmt) {
+		case MC_PLUGIN_PIX_FMT_BAYER10_SGRBG:
+			return V4L2_MBUS_FMT_SGRBG10_1X10;
+
+		case MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG:
+			return V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8;
+
+		case MC_PLUGIN_PIX_FMT_YUYV:
+			return V4L2_MBUS_FMT_YUYV8_1X16;
+
+		case MC_PLUGIN_PIX_FMT_UYVY:
+			return V4L2_MBUS_FMT_UYVY8_1X16;
+
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+enum mc_plugin_pixelformat pixel_subdev_to_mc_plugin(int pixfmt)
+{
+	switch (pixfmt) {
+		case V4L2_MBUS_FMT_SGRBG10_1X10:
+			return MC_PLUGIN_PIX_FMT_BAYER10_SGRBG;
+
+		case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+			return MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG;
+
+		case V4L2_MBUS_FMT_YUYV8_1X16:
+			return MC_PLUGIN_PIX_FMT_YUYV;
+
+		case V4L2_MBUS_FMT_UYVY8_1X16:
+			return MC_PLUGIN_PIX_FMT_UYVY;
+
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+int pixel_mc_plugin_to_v4l(enum mc_plugin_pixelformat pixfmt)
+{
+	switch (pixfmt) {
+		case MC_PLUGIN_PIX_FMT_BAYER10_SGRBG:
+			return V4L2_PIX_FMT_SGRBG10;
+
+#ifdef V4L2_PIX_FMT_SGRBG10DPCM8
+		case MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG:
+			return V4L2_PIX_FMT_SGRBG10DPCM8;
+#endif
+
+		case MC_PLUGIN_PIX_FMT_YUYV:
+			return V4L2_PIX_FMT_YUYV;
+
+		case MC_PLUGIN_PIX_FMT_UYVY:
+			return V4L2_PIX_FMT_UYVY;
+
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+enum mc_plugin_pixelformat pixel_v4l_to_mc_plugin(int pixfmt)
+{
+	switch (pixfmt) {
+		case V4L2_PIX_FMT_SGRBG10:
+			return MC_PLUGIN_PIX_FMT_BAYER10_SGRBG;
+
+#ifdef V4L2_PIX_FMT_SGRBG10DPCM8
+		case V4L2_PIX_FMT_SGRBG10DPCM8:
+			return MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG;
+#endif
+
+		case V4L2_PIX_FMT_YUYV:
+			return MC_PLUGIN_PIX_FMT_YUYV;
+
+		case V4L2_PIX_FMT_UYVY:
+			return MC_PLUGIN_PIX_FMT_UYVY;
+
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+enum mc_plugin_pixelformat pixel_str_to_mc_plugin(char *strpix)
+{
+	if (strcmp(strpix, "BAYER8_SBGGR") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER8_SBGGR;
+	if (strcmp(strpix, "BAYER8_SGBRG") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER8_SGBRG;
+	if (strcmp(strpix, "BAYER8_SGRBG") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER8_SGRBG;
+	if (strcmp(strpix, "BAYER10_SGRBG") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER10_SGRBG;
+	if (strcmp(strpix, "BAYER10_SRGGB") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER10_SRGGB;
+	if (strcmp(strpix, "BAYER10_SBGGR") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER10_SBGGR;
+	if (strcmp(strpix, "BAYER10_SGBRG") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER10_SGBRG;
+	if (strcmp(strpix, "BAYER10DPCM8_SGRBG") == 0)
+		return MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG;
+	if (strcmp(strpix, "YUYV") == 0)
+		return MC_PLUGIN_PIX_FMT_YUYV;
+	if (strcmp(strpix, "UYVY") == 0)
+		return MC_PLUGIN_PIX_FMT_UYVY;
+
+	return MC_PLUGIN_PIX_FMT_INVALID;
+}
+
+const struct capture_pipeline *pipe_sensor_yuv(int primary)
+{
+	FILE *fp = NULL;
+	char buffer[LINESIZE], *begin;
+	int i = 0;
+	enum mc_plugin_config_sections conf_section = CONFIG_SECTION_NONE;
+
+	fp = fopen(CONFIG_FILE, "r");
+	if (!fp) {
+		MC_PLUGIN_PRINTF ("Opening file %s failed", CONFIG_FILE);
+		return NULL;
+	}
+
+	while (fgets(buffer, LINESIZE, fp)) {
+		/* skip initial whitespace */
+		begin = buffer + strspn(buffer, "\r\t ");
+
+		/* skip comments and empty lines */
+		if (*begin == '#')
+			continue;
+		if (*begin == '\n')
+			continue;
+
+		/* Remove LF */
+		CHOMP(begin);
+
+		/* Check if we enter a config section */
+		if (conf_section == CONFIG_SECTION_NONE) {
+			if (strcmp(begin, "primary_path") == 0)
+				conf_section = CONFIG_SECTION_PRIMARY_PATH;
+			else if (strcmp(begin, "primary_in_pixfmt") == 0)
+				conf_section = CONFIG_SECTION_PRIMARY_IN_PIXFMT;
+			else if (strcmp(begin, "primary_out_pixfmt") == 0)
+				conf_section = CONFIG_SECTION_PRIMARY_OUT_PIXFMT;
+			else if (strcmp(begin, "secondary_path") == 0)
+				conf_section = CONFIG_SECTION_SECONDARY_PATH;
+			else if (strcmp(begin, "secondary_in_pixfmt") == 0)
+				conf_section = CONFIG_SECTION_SECONDARY_IN_PIXFMT;
+			else if (strcmp(begin, "secondary_out_pixfmt") == 0)
+				conf_section = CONFIG_SECTION_SECONDARY_OUT_PIXFMT;
+
+			i = 0;
+			continue;
+		}
+
+		/* Check if we exit a config section */
+		if (strcmp(begin, "end") == 0) {
+			conf_section = CONFIG_SECTION_NONE;
+			continue;
+		}
+
+		if ((i + 1) > PIPELINE_MAX_ELEMENTS ||
+			strlen(begin) >= SUBDEVICE_MAX_NAME_LEN) {
+
+			fclose(fp);
+			return NULL;
+		}
+
+		switch (conf_section) {
+		case CONFIG_SECTION_PRIMARY_PATH:
+			if (!primary)
+				break;
+			strcpy(pipe_sensor_yuv_path.path[i], begin);
+			strcpy(pipe_sensor_yuv_path.path[i+1], "");
+			i++;
+			break;
+		case CONFIG_SECTION_PRIMARY_IN_PIXFMT:
+			if (!primary)
+				break;
+			pipe_sensor_yuv_path.in_pixfmt[i] = pixel_str_to_mc_plugin(begin);
+			pipe_sensor_yuv_path.in_pixfmt[i+1] = MC_PLUGIN_PIX_FMT_INVALID;
+			i++;
+			break;
+		case CONFIG_SECTION_PRIMARY_OUT_PIXFMT:
+			if (!primary)
+				break;
+			pipe_sensor_yuv_path.out_pixfmt[i] = pixel_str_to_mc_plugin(begin);
+			pipe_sensor_yuv_path.out_pixfmt[i+1] = MC_PLUGIN_PIX_FMT_INVALID;
+			i++;
+			break;
+		case CONFIG_SECTION_SECONDARY_PATH:
+			if (primary)
+				break;
+			strcpy(pipe_sensor_yuv_path.path[i], begin);
+			strcpy(pipe_sensor_yuv_path.path[i+1], "");
+			i++;
+			break;
+		case CONFIG_SECTION_SECONDARY_IN_PIXFMT:
+			if (primary)
+				break;
+			pipe_sensor_yuv_path.in_pixfmt[i] = pixel_str_to_mc_plugin(begin);
+			pipe_sensor_yuv_path.in_pixfmt[i+1] = MC_PLUGIN_PIX_FMT_INVALID;
+			i++;
+			break;
+		case CONFIG_SECTION_SECONDARY_OUT_PIXFMT:
+			if (primary)
+				break;
+			pipe_sensor_yuv_path.out_pixfmt[i] = pixel_str_to_mc_plugin(begin);
+			pipe_sensor_yuv_path.out_pixfmt[i+1] = MC_PLUGIN_PIX_FMT_INVALID;
+			i++;
+			break;
+		case CONFIG_SECTION_NONE:
+			break;
+		}
+
+	}
+
+	fclose(fp);
+
+	return &pipe_sensor_yuv_path;
+}
+
+struct media_link *media_find_link(struct media_device *media,
+                                         struct media_entity *source,
+                                         struct media_entity *sink)
+{
+	unsigned int l;
+
+	for (l = 0; l < source->num_links; l++) {
+		struct media_link *link = &source->links[l];
+
+		if (link->source->entity == source &&
+			link->sink->entity == sink)
+				return link;
+	}
+
+	return NULL;
+}
+
+struct ipipe_descriptor *path_allocate(struct media_device *media,
+										const struct capture_pipeline *pipe)
+{
+	struct ipipe_descriptor *image_path;
+	struct sub_module *sub;
+	struct media_entity *entity;
+	const char *entity_name;
+	int i;
+
+	if (!media || !pipe) {
+		MC_PLUGIN_PRINTF("NULL pointer\n");
+		return NULL;
+	}
+
+	image_path = malloc(sizeof(*image_path));
+	if (!image_path) {
+		perror("image path");
+		return NULL;
+	}
+
+	image_path->pipe = pipe;
+	INIT_LIST_HEAD(&image_path->container);
+
+	for (i = 0; ; i++) {
+		entity_name = (char *)pipe->path[i];
+		if (strlen(entity_name) == 0)
+			break;
+
+		entity = media_get_entity_by_name(media, entity_name, strlen(entity_name));
+		if (!entity) {
+			MC_PLUGIN_PRINTF("Can't find entity [%s]\n", entity_name);
+			continue;
+		}
+
+		sub = submodule_alloc();
+		if (sub) {
+			sub->entity = entity;
+			list_add_tail(&sub->list, &image_path->container);
+		}
+	}
+
+	return image_path;
+}
+
+struct sub_module *submodule_alloc()
+{
+	struct sub_module *sb = NULL;
+
+	sb = malloc(sizeof (*sb));
+	if (!sb) {
+		MC_PLUGIN_PRINTF("Can not allocate module\n");
+		return sb;
+	}
+
+	sb->entity = NULL;
+	INIT_LIST_HEAD(&sb->list);
+
+	return sb;
+}
+
+void submodule_free(struct sub_module *sb)
+{
+	free(sb);
+	sb = NULL;
+}
+
+struct sub_module *path_destination_submodule(struct ipipe_descriptor *path)
+{
+	struct sub_module *next, *last;
+
+	if (NULL == path) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return NULL;
+	}
+
+	last = NULL;
+	list_for_each_entry(next, &path->container, list)
+		last = next;
+
+	return last;
+}
+
+int path_power_on(struct ipipe_descriptor *path, int fd)
+{
+	struct sub_module *sub_mod, *next_sub_mod;
+	int last_sm, err = 0;
+
+	if (NULL == path) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return -1;
+	}
+
+	list_for_each_entry(sub_mod, &path->container, list) {
+		next_sub_mod = list_entry(sub_mod->list.next, typeof(*sub_mod), list);
+		last_sm = &next_sub_mod->list == &path->container;
+		err += submodule_open(sub_mod, fd, last_sm);
+	}
+
+	return err;
+}
+
+int submodule_open(struct sub_module *sb, int fd, int last_sm)
+{
+	int err = 0;
+
+	if (!sb) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return -1;
+	}
+
+	if (sb->entity->fd < 0)
+		sb->entity->fd = SYS_OPEN(sb->entity->devname, O_RDWR, 0);
+
+	if (sb->entity->fd < 0)
+		err = -1;
+
+	if (last_sm && err != -1) {
+		int dr;
+		dr = dup2(sb->entity->fd, fd);
+		close(sb->entity->fd);
+		sb->entity->fd = fd;
+	}
+
+	return err;
+}
+
+int path_connect_entities(struct media_device *media,
+							struct ipipe_descriptor *path)
+{
+	struct media_entity *source, *sink;
+	struct media_link *link;
+	const char *sink_name, *source_name;
+	int i, err = 0;
+
+	if (!media || !path) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return -1;
+	}
+
+	source_name = (char *)path->pipe->path[0];
+	sink_name = (char *)path->pipe->path[1];
+	i = 1;
+
+	while (strlen(source_name) != 0) {
+
+		sink_name = (char *)path->pipe->path[i];
+		if (strlen(sink_name) == 0)
+			break;
+
+		source = media_get_entity_by_name(media, source_name, strlen(source_name));
+		sink = media_get_entity_by_name(media, sink_name, strlen(sink_name));
+
+		if ((NULL == sink) || (NULL == source)) {
+			MC_PLUGIN_PRINTF("Error finding entities\n");
+			err = -1;
+			break;
+		}
+
+		link = media_find_link(media, source, sink);
+
+		/* Do not explicitly setup immutable links */
+		if (!(link->flags & MEDIA_LINK_FLAG_IMMUTABLE)) {
+			err = media_setup_link(media, link->source, link->sink,
+								MEDIA_LINK_FLAG_ACTIVE);
+		} else {
+			if (!(link->flags & MEDIA_LINK_FLAG_ACTIVE)) {
+				MC_PLUGIN_PRINTF("Immutable link is not activated\n");
+				err = -1;
+			}
+		}
+
+		if (err < 0) {
+			MC_PLUGIN_PRINTF("Fail to connect %s->%s\n", source_name, sink_name);
+			break;
+		}
+
+		source_name = sink_name;
+		i++;
+	}
+
+	return err;
+}
+
+void path_power_off(struct ipipe_descriptor *path)
+{
+	struct sub_module *sub_mod, *next_sub_mod;
+	int last_sm;
+
+	if (NULL == path) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return;
+	}
+
+	list_for_each_entry(sub_mod, &path->container, list) {
+		next_sub_mod = list_entry(sub_mod->list.next, typeof(*sub_mod), list);
+		last_sm = &next_sub_mod->list == &path->container;
+		submodule_power_off(sub_mod, last_sm);
+	}
+
+}
+
+int submodule_power_off(struct sub_module *sb, int last_sm)
+{
+	if (!sb) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return -1;
+	}
+
+	if (sb->entity->fd > 0 && !last_sm)
+		SYS_CLOSE(sb->entity->fd);
+
+	sb->entity->fd = -1;
+
+	return 0;
+}
+
+int path_disconnect_entities(struct media_device *media,
+								struct ipipe_descriptor *path)
+{
+	struct media_entity *source, *sink;
+	struct media_link *link;
+	const char *sink_name, *source_name;
+	int i, err = 0;
+
+	if (!media || !path) {
+		MC_PLUGIN_PRINTF("Wrong argument: NULL pointer\n");
+		return -1;
+	}
+
+	source_name = (char *)path->pipe->path[0];
+	sink_name = (char *)path->pipe->path[1];
+	i = 1;
+
+	while (strlen(source_name) != 0) {
+
+		sink_name = (char *)path->pipe->path[i];
+		if (strlen(sink_name) == 0)
+			break;
+
+		source = media_get_entity_by_name(media, source_name, strlen(source_name));
+		sink = media_get_entity_by_name(media, sink_name, strlen(sink_name));
+
+		if ((NULL == sink) || (NULL == source)) {
+			MC_PLUGIN_PRINTF("Error finding entities\n");
+			err = -1;
+			break;
+		}
+
+		link = media_find_link(media, source, sink);
+
+		/* Do not explicitly setup immutable links */
+		if (!(link->flags & MEDIA_LINK_FLAG_IMMUTABLE))
+			err = media_setup_link(media, link->source, link->sink,
+									(link->flags & ~MEDIA_LINK_FLAG_ACTIVE));
+
+		source_name = sink_name;
+		i++;
+	}
+
+	return err;
+}
+
+int path_enum_src_framesizes(struct omap3mcplugin *plugin,
+								enum mc_plugin_pixelformat *pixfmt,
+								struct v4l2_rect *res, int max_rect)
+{
+	struct media_entity *source, *sink;
+	const char *sink_name, *source_name;
+	struct media_link *link;
+	int ret = -1;
+	struct v4l2_subdev_frame_size_enum size;
+
+	if (!plugin || !pixfmt || !res) {
+		MC_PLUGIN_PRINTF("NULL pointer");
+		return -1;
+	}
+
+	source_name = (char *)plugin->path->pipe->path[0];
+	sink_name = (char *)plugin->path->pipe->path[1];
+
+	source = media_get_entity_by_name(plugin->media, source_name, strlen(source_name));
+	sink = media_get_entity_by_name(plugin->media, sink_name, strlen(sink_name));
+
+	if ((NULL == sink) || (NULL == source)) {
+		MC_PLUGIN_PRINTF("Error finding entities\n");
+		errno = EBADF;
+		return -1;
+	}
+
+	link = media_find_link(plugin->media, source, sink);
+
+	if (NULL == link) {
+		MC_PLUGIN_PRINTF("No link present between source and sink\n");
+		errno = EBADF;
+		return -1;
+	}
+
+	memset(&size, 0, sizeof(size));
+
+	size.index = 0;
+	size.code = pixel_mc_plugin_to_subdev(*pixfmt);
+	size.pad = link->source->index;
+
+	while (0 == SYS_IOCTL(source->fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &size)) {
+		/* NOTE : min_width min_height and max_width max_height */
+		/* are equal for now so take just one of them */
+		ret = 0;
+		res[size.index].width = size.max_width;
+		res[size.index].height = size.max_height;
+
+		++size.index;
+		if (size.index >= max_rect)
+			break;
+
+	}
+
+	return ret;
+}
+
+int path_set_resolution(struct omap3mcplugin *plugin,
+							struct v4l2_rect *src_res,
+							enum mc_plugin_pixelformat *src_pix,
+							struct v4l2_rect *dst_res,
+							enum mc_plugin_pixelformat *dst_pix)
+{
+	struct media_link *link = NULL;
+	struct sub_module *pos, *source = NULL, *sink = NULL;
+	struct v4l2_rect res;
+	struct v4l2_format format;
+	struct v4l2_subdev_format subdev_fmt;
+	enum mc_plugin_pixelformat source_pix, sink_pix;
+	int first_submodule, err = -1;
+
+	if (!plugin || !src_res || !src_pix ||
+		!dst_res || !dst_pix) {
+
+		MC_PLUGIN_PRINTF("NULL pointer\n");
+		return -1;
+	}
+
+	if (!src_res->width || !src_res->height || MC_PLUGIN_PIX_FMT_INVALID == *src_pix ||
+		!dst_res->width || !dst_res->height || MC_PLUGIN_PIX_FMT_INVALID == *dst_pix) {
+
+		MC_PLUGIN_PRINTF("Wrong input argumets\n");
+		return -1;
+	}
+
+	source_pix = *src_pix;
+	sink_pix = *src_pix;
+	res = *src_res;
+
+	first_submodule = 1;
+	list_for_each_entry(pos, &plugin->path->container, list) {
+
+		/* If first submodule just set source pixel format and resolution */
+		if (NULL == source) {
+			source = pos;
+			continue;
+		}
+
+		/* If we reach last submodule apply destination resolution */
+		if (media_entity_type(pos->entity) == MEDIA_ENTITY_TYPE_NODE && sink) {
+			res = *dst_res;
+
+			memset (&format, 0x0, sizeof (struct v4l2_format));
+			format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			err = SYS_IOCTL(pos->entity->fd, VIDIOC_G_FMT, &format);
+			if (err < 0) {
+				perror("VIDIOC_G_FMT:");
+				break;
+			}
+
+			format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			format.fmt.pix.width = dst_res->width;
+			format.fmt.pix.height = dst_res->height;
+			format.fmt.pix.pixelformat = pixel_mc_plugin_to_v4l(*dst_pix);
+			format.fmt.pix.field = V4L2_FIELD_ANY;
+
+			err = SYS_IOCTL(pos->entity->fd, VIDIOC_S_FMT, &format);
+			if (err < 0) {
+				perror("VIDIOC_S_FMT:");
+				break;
+			}
+		}
+
+		sink = pos;
+
+		link = media_find_link(plugin->media, source->entity, sink->entity);
+
+		if (link == NULL) {
+			MC_PLUGIN_PRINTF("No link present between source and sink\n");
+			err = -1;
+			break;
+		}
+
+		if (!(link->flags & MEDIA_LINK_FLAG_ACTIVE)) {
+			MC_PLUGIN_PRINTF("This link is not active\n");
+			err = -1;
+			break;
+		}
+
+		/* Set source format */
+		memset(&subdev_fmt, 0, sizeof(subdev_fmt));
+		subdev_fmt.format.code = pixel_mc_plugin_to_subdev(source_pix);
+		subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		subdev_fmt.format.width = res.width;
+		subdev_fmt.format.height = res.height;
+		subdev_fmt.pad = link->source->index;
+
+		err = SYS_IOCTL(source->entity->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
+		if (err < 0) {
+			perror("Error set source format:");
+			break;
+		} else {
+			res.width = subdev_fmt.format.width;
+			res.height = subdev_fmt.format.height;
+			source_pix = pixel_subdev_to_mc_plugin(subdev_fmt.format.code);
+		}
+
+		if (media_entity_type(pos->entity) == MEDIA_ENTITY_TYPE_NODE && sink)
+			break;
+
+		/* Set sink format */
+		memset(&subdev_fmt, 0, sizeof(subdev_fmt));
+		subdev_fmt.format.code = pixel_mc_plugin_to_subdev(sink_pix);
+		subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		subdev_fmt.format.width = res.width;
+		subdev_fmt.format.height = res.height;
+		subdev_fmt.pad = link->sink->index;
+
+		err = SYS_IOCTL(sink->entity->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
+		if (err < 0) {
+			perror("Error set sink format:");
+			break;
+		} else {
+			res.width = subdev_fmt.format.width;
+			res.height = subdev_fmt.format.height;
+			sink_pix = pixel_subdev_to_mc_plugin(subdev_fmt.format.code);
+		}
+
+		/* Sink pix is not supported modify source pixelformat also */
+		if (source_pix != sink_pix) {
+			source_pix = sink_pix;
+
+			memset(&subdev_fmt, 0, sizeof(subdev_fmt));
+			subdev_fmt.format.code = pixel_mc_plugin_to_subdev(source_pix);
+			subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+			subdev_fmt.format.width = res.width;
+			subdev_fmt.format.height = res.height;
+			subdev_fmt.pad = link->source->index;
+
+			err = SYS_IOCTL(source->entity->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
+			if (err < 0) {
+				perror("Error set source format:");
+				break;
+			} else {
+				res.width = subdev_fmt.format.width;
+				res.height = subdev_fmt.format.height;
+				source_pix = pixel_subdev_to_mc_plugin(subdev_fmt.format.code);
+			}
+
+			err += (source_pix == sink_pix) ? 0 : -1;
+		}
+
+		if (err < 0) {
+			fprintf(stderr, "Error set source format for second time %s\n", source->entity->info.name);
+			break;
+		}
+
+		/* Store correct source pixel format and resolution */
+		if (first_submodule) {
+			*src_pix = source_pix;
+			*src_res = res;
+			first_submodule = 0;
+		}
+
+		/* Try to set destination pixel fmt */
+		source_pix = sink_pix = *dst_pix;
+		/* Continue with next element */
+		source = sink;
+	}
+
+	/* Set Destination resolution and pixel format */
+	if (0 == err) {
+		*dst_pix = sink_pix;
+		*dst_res = res;
+	}
+
+	return err;
+}
+
+int path_try_resolution(struct omap3mcplugin *plugin,
+							struct v4l2_rect *src_res,
+							enum mc_plugin_pixelformat *src_pix,
+							struct v4l2_rect *dst_res,
+							enum mc_plugin_pixelformat *dst_pix)
+{
+	struct media_link *link = NULL;
+	struct sub_module *pos, *source = NULL, *sink = NULL;
+	struct v4l2_rect res;
+	struct v4l2_subdev_format subdev_fmt;
+	enum mc_plugin_pixelformat source_pix, sink_pix;
+	int first_submodule, err = -1;
+
+	if (!plugin || !src_res || !src_pix ||
+		!dst_res || !dst_pix) {
+
+		MC_PLUGIN_PRINTF("NULL pointer\n"
+						"  plugin=%p\n"
+						"  src_res=%p, src_pix=%p\n"
+						"  dst_res=%p, dst_pix=%p\n",
+						plugin,
+						src_res, src_pix,
+						dst_res, dst_pix);
+
+		return -1;
+	}
+
+	if (!src_res->width || !src_res->height || MC_PLUGIN_PIX_FMT_INVALID == *src_pix ||
+		!dst_res->width || !dst_res->height || MC_PLUGIN_PIX_FMT_INVALID == *dst_pix) {
+
+		MC_PLUGIN_PRINTF("Wrong input argumets\n"
+						"  Source format: Width = %d, Height = %d, Format = %d\n"
+						"  Destination format: Width = %d, Height = %d, Format = %d\n",
+						src_res->width, src_res->height, *src_pix,
+						dst_res->width, dst_res->height, *dst_pix);
+		return -1;
+	}
+
+	source_pix = *src_pix;
+	sink_pix = *src_pix;
+	res = *src_res;
+
+	first_submodule = 1;
+	list_for_each_entry(pos, &plugin->path->container, list) {
+
+		/* If first submodule just set source pixel format and resolution */
+		if (NULL == source) {
+			source = pos;
+			continue;
+		}
+
+		/* If we reach last submodule apply destination resolution */
+		if (media_entity_type(pos->entity) == MEDIA_ENTITY_TYPE_NODE && sink)
+			res = *dst_res;
+
+		sink = pos;
+
+		link = media_find_link(plugin->media, source->entity, sink->entity);
+
+		if (NULL == link) {
+			MC_PLUGIN_PRINTF("No link present between source and sink\n");
+			err = -1;
+			break;
+		}
+
+		if (!(link->flags & MEDIA_LINK_FLAG_ACTIVE)) {
+			MC_PLUGIN_PRINTF("This link is not active\n");
+			err = -1;
+			break;
+		}
+
+		/* Set source format */
+		memset(&subdev_fmt, 0, sizeof(subdev_fmt));
+		subdev_fmt.format.code = pixel_mc_plugin_to_subdev(source_pix);
+		subdev_fmt.which = V4L2_SUBDEV_FORMAT_TRY;
+		subdev_fmt.format.width = res.width;
+		subdev_fmt.format.height = res.height;
+		subdev_fmt.pad = link->source->index;
+
+		err = SYS_IOCTL(source->entity->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
+		if (err < 0) {
+			perror("Error try source format:");
+			break;
+		} else {
+			res.width = subdev_fmt.format.width;
+			res.height = subdev_fmt.format.height;
+			source_pix = pixel_subdev_to_mc_plugin(subdev_fmt.format.code);
+		}
+
+		if (media_entity_type(pos->entity) == MEDIA_ENTITY_TYPE_NODE && sink)
+			break;
+
+		/* Set sink format */
+		memset(&subdev_fmt, 0, sizeof(subdev_fmt));
+		subdev_fmt.format.code = pixel_mc_plugin_to_subdev(sink_pix);
+		subdev_fmt.which = V4L2_SUBDEV_FORMAT_TRY;
+		subdev_fmt.format.width = res.width;
+		subdev_fmt.format.height = res.height;
+		subdev_fmt.pad = link->sink->index;
+
+		err = SYS_IOCTL(sink->entity->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
+		if (err < 0) {
+			MC_PLUGIN_PRINTF("Error try sink format\n");
+			break;
+		} else {
+			res.width = subdev_fmt.format.width;
+			res.height = subdev_fmt.format.height;
+			sink_pix = pixel_subdev_to_mc_plugin(subdev_fmt.format.code);
+		}
+
+		/* Sink pix is not supported modify source pixelformat also */
+		if (source_pix != sink_pix) {
+			source_pix = sink_pix;
+
+			memset(&subdev_fmt, 0, sizeof(subdev_fmt));
+			subdev_fmt.format.code = pixel_mc_plugin_to_subdev(source_pix);
+			subdev_fmt.which = V4L2_SUBDEV_FORMAT_TRY;
+			subdev_fmt.format.width = res.width;
+			subdev_fmt.format.height = res.height;
+			subdev_fmt.pad = link->source->index;
+
+			err = SYS_IOCTL(source->entity->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
+			if (err < 0) {
+				perror("Error try source format:");
+				break;
+			} else {
+				res.width = subdev_fmt.format.width;
+				res.height = subdev_fmt.format.height;
+				source_pix = pixel_subdev_to_mc_plugin(subdev_fmt.format.code);
+			}
+
+			err += (source_pix == sink_pix) ? 0 : -1;
+		}
+
+		if (err < 0) {
+			fprintf(stderr, "Error try source format for second time %s\n", source->entity->info.name);
+			break;
+		}
+
+		/* Store correct source pixel format and resolution */
+		if (first_submodule) {
+			*src_pix = source_pix;
+			*src_res = res;
+			first_submodule = 0;
+		}
+
+		/* Try to set destination pixel fmt */
+		source_pix = sink_pix = *dst_pix;
+		/* Continue with next element */
+		source = sink;
+	}
+
+	/* Set Destination resolution and pixel format */
+	if (0 == err) {
+		*dst_pix = sink_pix;
+		*dst_res = res;
+	}
+
+	return err;
+}
diff --git a/paths.h b/paths.h
new file mode 100644
index 0000000..58d2409
--- /dev/null
+++ b/paths.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __PATHS_H__
+#define __PATHS_H__
+
+#include <linux/videodev2.h>
+#include <mediactl/media.h>
+
+#include "libv4l2plugin-omap3mc.h"
+
+struct media_link *media_find_link(struct media_device *media,
+	struct media_entity *source,
+	struct media_entity *sink);
+int pixel_mc_plugin_to_subdev(enum mc_plugin_pixelformat pixfmt);
+enum mc_plugin_pixelformat pixel_subdev_to_mc_plugin(int pixfmt);
+int pixel_mc_plugin_to_v4l(enum mc_plugin_pixelformat pixfmt);
+enum mc_plugin_pixelformat pixel_v4l_to_mc_plugin(int pixfmt);
+const struct capture_pipeline *pipe_sensor_yuv(int primary);
+struct ipipe_descriptor *path_allocate(struct media_device *media,
+	const struct capture_pipeline *pipe);
+struct sub_module *submodule_alloc();
+void submodule_free(struct sub_module *sb);
+struct sub_module *path_destination_submodule(struct ipipe_descriptor *path);
+int path_power_on(struct ipipe_descriptor *path, int fd);
+int submodule_open(struct sub_module *sb, int fd, int last_sb);
+int path_connect_entities(struct media_device *media,
+	struct ipipe_descriptor *path);
+void path_power_off(struct ipipe_descriptor *path);
+int submodule_power_off(struct sub_module *sb, int last_sb);
+int path_disconnect_entities(struct media_device *media,
+	struct ipipe_descriptor *path);
+int path_enum_src_framesizes(struct omap3mcplugin *plugin,
+	enum mc_plugin_pixelformat *pixfmt,
+	struct v4l2_rect *res, int max_rect);
+int path_set_resolution(struct omap3mcplugin *plugin,
+	struct v4l2_rect *src_res,
+	enum mc_plugin_pixelformat *src_pix,
+	struct v4l2_rect *dst_res,
+	enum mc_plugin_pixelformat *dst_pix);
+int path_try_resolution(struct omap3mcplugin *plugin,
+	struct v4l2_rect *src_res,
+	enum mc_plugin_pixelformat *src_pix,
+	struct v4l2_rect *dst_res,
+	enum mc_plugin_pixelformat *dst_pix);
+
+
+#endif /* __PATHS_H__ */
diff --git a/sl_list.h b/sl_list.h
new file mode 100644
index 0000000..e48b984
--- /dev/null
+++ b/sl_list.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __SINGLE_LINKED_LIST_H__
+#define __SINGLE_LINKED_LIST_H__
+
+/* Simple single linked list implementation. */
+
+struct list_head {
+	struct list_head *next;
+};
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+	list->next = list;
+}
+
+/* Insert new node after known node */
+static inline void list_add_after(struct list_head *new,
+					struct list_head *prev)
+{
+	new->next = prev->next;
+	prev->next = new;
+}
+
+/* Insert new node at the end of the list */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	struct list_head *element = head;
+
+	while (element->next != head)
+		element = element->next;
+
+	list_add_after(new, element);
+}
+
+ /* Get the struct for this entry */
+#define list_entry(ptr, type, member)({          \
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+	((type *)(void *)( (char *)__mptr - offsetof(type,member) ));})
+
+
+/* Iterate over the list */
+#define list_for_each_entry(pos, head, member)              \
+	for (pos = list_entry((head)->next, typeof(*pos), member);  \
+		&pos->member != (head);    \
+		pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#endif
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [libv4l-mcplugin PATCH 2/3] Add files for v4l operations
  2011-05-19 12:36 [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Yordan Kamenov
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 1/3] Add files for media controller pipelines Yordan Kamenov
@ 2011-05-19 12:36 ` Yordan Kamenov
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 3/3] Add libv4l2 media controller plugin interface files Yordan Kamenov
  2011-05-20  7:11 ` [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Hans de Goede
  3 siblings, 0 replies; 6+ messages in thread
From: Yordan Kamenov @ 2011-05-19 12:36 UTC (permalink / raw)
  To: linux-media; +Cc: sakari.ailus, Yordan Kamenov

Add files with implementation of v4l ioctls.

Signed-off-by: Yordan Kamenov <ykamenov@mm-sol.com>
---
 operations.c |  611 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 operations.h |   44 +++++
 2 files changed, 655 insertions(+), 0 deletions(-)
 create mode 100644 operations.c
 create mode 100644 operations.h

diff --git a/operations.c b/operations.c
new file mode 100644
index 0000000..307785f
--- /dev/null
+++ b/operations.c
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stddef.h>
+
+#include <linux/v4l2-subdev.h>
+
+#include "sl_list.h"
+#include "operations.h"
+#include "paths.h"
+
+#define CHECK_DST_SUBMODULE(dst_sm, error_msg) {\
+	if ((dst_sm) == NULL) {\
+		MC_PLUGIN_PRINTF(error_msg);\
+		errno = EBADF;\
+		return -1;\
+	}\
+}
+
+int mc_vidioc_streamon(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	struct sub_module *dst_sub_module = NULL;
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "streamon failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_STREAMON, &type);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("streamon: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_streamoff(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	struct sub_module *dst_sub_module = NULL;
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "streamoff failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_STREAMOFF, &type);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("streamoff: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_s_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int pix_count, res_count, found = 0, ret = -1;
+	enum mc_plugin_pixelformat src_pixfmt, dst_pixfmt, temp_pixfmt;
+	struct v4l2_rect src_res, dst_res;
+	const int max_rect = 10;
+	struct v4l2_rect res[max_rect];
+	struct v4l2_format *arg;
+	va_list ap;
+	enum mc_plugin_pixelformat pixfmt;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_format *);
+	va_end(ap);
+
+	pixfmt = pixel_v4l_to_mc_plugin(arg->fmt.pix.pixelformat);
+
+	/* Check if destionation format is supported from pipeline */
+	for (pix_count = 0;
+		 MC_PLUGIN_PIX_FMT_INVALID != plugin->path->pipe->out_pixfmt[pix_count];
+		 pix_count++)
+		if (pixfmt == plugin->path->pipe->out_pixfmt[pix_count]) {
+			dst_pixfmt = pixfmt;
+			ret = 0;
+			break;
+		}
+
+	if (ret < 0) {
+		MC_PLUGIN_PRINTF("Destination format not supported\n");
+		errno = EINVAL;
+		return ret;
+	}
+
+	for (pix_count = 0;
+		 MC_PLUGIN_PIX_FMT_INVALID != plugin->path->pipe->in_pixfmt[pix_count];
+		 pix_count++) {
+
+		memset(res, 0x0, sizeof(res));
+		src_pixfmt = plugin->path->pipe->in_pixfmt[pix_count];
+		temp_pixfmt = src_pixfmt;
+
+		ret = path_enum_src_framesizes(plugin, &src_pixfmt, res, max_rect);
+
+		/* Find Best capture resolution */
+		for (res_count = 0; res_count < max_rect; res_count++) {
+
+			src_res = res[res_count];
+			dst_res.width = arg->fmt.pix.width;
+			dst_res.height = arg->fmt.pix.height;
+
+			/* If width and height are not valid we reach end of resolutions */
+			if (0 == res[res_count].width && 0 == res[res_count].height)
+				break;
+
+			ret = path_set_resolution(plugin, &src_res, &src_pixfmt,
+										&dst_res, &dst_pixfmt);
+			if (ret < 0) {
+				MC_PLUGIN_PRINTF("Set Resolution fail!\n");
+				break;
+			}
+
+			if (dst_res.width == arg->fmt.pix.width &&
+				dst_res.height == arg->fmt.pix.height &&
+				temp_pixfmt == src_pixfmt) {
+				/* Capture resolution found */
+				found = 1;
+				break;
+			}
+		}
+
+		if (1 == found)
+			break;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_g_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_format *arg;
+	va_list ap;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_format *);
+	va_end(ap);
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "get format failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_G_FMT, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("get format: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_try_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int pix_count, res_count, found = 0, ret = -1;
+	enum mc_plugin_pixelformat src_pixfmt, dst_pixfmt, temp_pixfmt;
+	struct v4l2_rect src_res, dst_res;
+	const int max_rect = 10;
+	struct v4l2_rect res[max_rect];
+	struct v4l2_format *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_format *);
+	va_end(ap);
+
+	enum mc_plugin_pixelformat pixfmt = pixel_v4l_to_mc_plugin(arg->fmt.pix.pixelformat);
+
+	/* Check if destionation format is supported from pipeline */
+	for (pix_count = 0;
+		 MC_PLUGIN_PIX_FMT_INVALID != plugin->path->pipe->out_pixfmt[pix_count];
+		 pix_count++)
+		if (pixfmt == plugin->path->pipe->out_pixfmt[pix_count]) {
+			dst_pixfmt = pixfmt;
+			ret = 0;
+			break;
+		}
+
+	if (ret < 0) {
+		MC_PLUGIN_PRINTF("Destination format not supported\n");
+		errno = EINVAL;
+		return ret;
+	}
+
+	for (pix_count = 0;
+		 MC_PLUGIN_PIX_FMT_INVALID != plugin->path->pipe->in_pixfmt[pix_count];
+		 pix_count++) {
+
+		memset(res, 0x0, sizeof(res));
+		src_pixfmt = plugin->path->pipe->in_pixfmt[pix_count];
+		temp_pixfmt = src_pixfmt;
+
+		ret = path_enum_src_framesizes(plugin, &src_pixfmt, res, max_rect);
+
+		/* Find Best capture resolution */
+		for (res_count = 0; res_count < max_rect; res_count++) {
+
+			src_res = res[res_count];
+			dst_res.width = arg->fmt.pix.width;
+			dst_res.height = arg->fmt.pix.height;
+
+			/* If width and height are not valid we reach end of resolutions */
+			if (0 == res[res_count].width && 0 == res[res_count].height)
+				break;
+
+			ret = path_try_resolution(plugin, &src_res, &src_pixfmt,
+										&dst_res, &dst_pixfmt);
+			if (ret < 0) {
+				MC_PLUGIN_PRINTF("Set Resolution fail!\n");
+				break;
+			}
+
+			if (dst_res.width == arg->fmt.pix.width &&
+				dst_res.height == arg->fmt.pix.height &&
+				temp_pixfmt == src_pixfmt) {
+				/* Capture resolution found */
+				found = 1;
+				break;
+			}
+		}
+
+		if (1 == found)
+			break;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_s_crop(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_subdev_crop s_crop;
+	struct v4l2_crop *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_crop *);
+	va_end(ap);
+
+	memset (&s_crop, 0, sizeof (s_crop));
+	s_crop.pad = 0;    /* It has only one sink pad */
+	s_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	s_crop.rect.top = arg->c.top;
+	s_crop.rect.left = arg->c.left;
+	s_crop.rect.width = arg->c.width;
+	s_crop.rect.height = arg->c.height;
+
+	ret = SYS_IOCTL(plugin->fd, VIDIOC_SUBDEV_S_CROP, &s_crop);
+	if (ret < 0) {
+		MC_PLUGIN_PRINTF("set crop: %s\n", strerror(errno));
+	} else {
+		arg->c.top = s_crop.rect.top;
+		arg->c.left = s_crop.rect.left;
+		arg->c.width = s_crop.rect.width;
+		arg->c.height = s_crop.rect.height;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_g_crop(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_subdev_crop g_crop;
+	struct v4l2_crop *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_crop *);
+	va_end(ap);
+
+	memset (&g_crop, 0, sizeof (g_crop));
+	g_crop.pad = 0;    /* It has only one sink pad */
+	g_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+	ret = SYS_IOCTL(plugin->fd, VIDIOC_SUBDEV_G_CROP, &g_crop);
+	if (ret < 0) {
+		MC_PLUGIN_PRINTF("get crop: %s\n", strerror(errno));
+	} else {
+		arg->c.top = g_crop.rect.top;
+		arg->c.left = g_crop.rect.left;
+		arg->c.width = g_crop.rect.width;
+		arg->c.height = g_crop.rect.height;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_queryctrl(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct sub_module *sub_mod;
+	struct v4l2_queryctrl *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_queryctrl *);
+	va_end(ap);
+
+	list_for_each_entry(sub_mod, &plugin->path->container, list) {
+		ret = SYS_IOCTL(sub_mod->entity->fd, VIDIOC_QUERYCTRL, arg);
+		if (ret == 0)
+			break;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_g_ctrl(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct sub_module *sub_mod;
+	struct v4l2_control *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_control *);
+	va_end(ap);
+
+	list_for_each_entry(sub_mod, &plugin->path->container, list) {
+		ret = SYS_IOCTL(sub_mod->entity->fd, VIDIOC_G_CTRL, arg);
+		if (ret == 0)
+			break;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_s_ctrl(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct sub_module *sub_mod;
+	struct v4l2_control *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_control *);
+	va_end(ap);
+
+	list_for_each_entry(sub_mod, &plugin->path->container, list) {
+		ret = SYS_IOCTL(sub_mod->entity->fd, VIDIOC_S_CTRL, arg);
+		if (ret == 0)
+			break;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_querycap(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_capability *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_capability *);
+	va_end(ap);
+
+	ret = SYS_IOCTL(plugin->fd, VIDIOC_QUERYCAP, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("query capabilities: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_enum_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_fmtdesc *arg;
+	va_list ap;
+	struct v4l2_subdev_mbus_code_enum mbus_format;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_fmtdesc *);
+	va_end(ap);
+
+	mbus_format.pad = 0;
+	mbus_format.index = arg->index;
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "enum fmt failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbus_format);
+	if (ret == 0) {
+		arg->flags = 0;
+		arg->pixelformat = pixel_mc_plugin_to_v4l(mbus_format.code);
+	}
+
+	return ret;
+}
+
+int mc_vidioc_enum_framesizes(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_frmsizeenum *arg;
+	va_list ap;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_frmsizeenum *);
+	va_end(ap);
+
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "enum framesizes\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_ENUM_FRAMESIZES, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("enum framesizes: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_enum_frameintervals(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct media_entity *source, *sink;
+	struct media_link *link;
+	struct v4l2_subdev_frame_interval_enum e_interval;
+	const char *sink_name, *source_name;
+	struct v4l2_frmivalenum *arg;
+	va_list ap;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_frmivalenum *);
+	va_end(ap);
+
+	source_name = plugin->path->pipe->path[0];
+	sink_name = plugin->path->pipe->path[1];
+
+	source = media_get_entity_by_name(plugin->media, source_name, strlen(source_name));
+	sink = media_get_entity_by_name(plugin->media, sink_name, strlen(sink_name));
+
+	if ((NULL == sink) || (NULL == source)) {
+		MC_PLUGIN_PRINTF("Error finding entities\n");
+		errno = EBADF;
+		return -1;
+	}
+
+	link = media_find_link(plugin->media, source, sink);
+
+	if (NULL == link) {
+		MC_PLUGIN_PRINTF("No link present between source and sink\n");
+		errno = EBADF;
+		return -1;
+	}
+
+	e_interval.index = arg->index;
+	e_interval.code = arg->pixel_format;
+	e_interval.width = arg->width;
+	e_interval.height = arg->height;
+	e_interval.pad = link->source->index;
+
+	ret = SYS_IOCTL(source->fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &e_interval);
+	if (ret == 0) {
+		arg->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+		arg->discrete.numerator = e_interval.interval.numerator;
+		arg->discrete.denominator = e_interval.interval.denominator;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_reqbufs(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_requestbuffers *arg;
+	va_list ap;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_requestbuffers *);
+	va_end(ap);
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "request buffer failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_REQBUFS, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("request buffer: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_querybuf(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_buffer *arg;
+	va_list ap;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_buffer *);
+	va_end(ap);
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "query failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_QUERYBUF, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("query buffer: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_qbuf(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_buffer *arg;
+	va_list ap;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_buffer *);
+	va_end(ap);
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "queue buffer failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_QBUF, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("queue buffer: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
+
+int mc_vidioc_dqbuf(struct omap3mcplugin *plugin, unsigned long int request, ...)
+{
+	int ret = -1;
+	struct v4l2_buffer *arg;
+	va_list ap;
+	struct sub_module *dst_sub_module = NULL;
+
+	va_start(ap, request);
+	arg = va_arg(ap, struct v4l2_buffer *);
+	va_end(ap);
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	CHECK_DST_SUBMODULE(dst_sub_module, "dequeue failed\n");
+
+	ret = SYS_IOCTL(dst_sub_module->entity->fd, VIDIOC_DQBUF, arg);
+	if (ret) {
+		int saved_err = errno;
+		MC_PLUGIN_PRINTF("dequeue buffer: %s\n", strerror(errno));
+		errno = saved_err;
+	}
+
+	return ret;
+}
diff --git a/operations.h b/operations.h
new file mode 100644
index 0000000..62129c0
--- /dev/null
+++ b/operations.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __OPERATIONS_H__
+#define __OPERATIONS_H__
+
+#include "libv4l2plugin-omap3mc.h"
+
+int mc_vidioc_streamon(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_streamoff(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_s_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_g_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_try_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_s_crop(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_g_crop(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_queryctrl(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_g_ctrl(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_s_ctrl(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_querycap(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_enum_fmt(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_enum_framesizes(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_enum_frameintervals(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_reqbufs(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_querybuf(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_qbuf(struct omap3mcplugin *plugin, unsigned long int request, ...);
+int mc_vidioc_dqbuf(struct omap3mcplugin *plugin, unsigned long int request, ...);
+
+#endif /* __OPERATIONS_H__ */
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [libv4l-mcplugin PATCH 3/3] Add libv4l2 media controller plugin interface files
  2011-05-19 12:36 [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Yordan Kamenov
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 1/3] Add files for media controller pipelines Yordan Kamenov
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 2/3] Add files for v4l operations Yordan Kamenov
@ 2011-05-19 12:36 ` Yordan Kamenov
  2011-05-20  7:11 ` [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Hans de Goede
  3 siblings, 0 replies; 6+ messages in thread
From: Yordan Kamenov @ 2011-05-19 12:36 UTC (permalink / raw)
  To: linux-media; +Cc: sakari.ailus, Yordan Kamenov

Add interface functions init(), close() and ioctl(), called by libv4l2.

Signed-off-by: Yordan Kamenov <ykamenov@mm-sol.com>
---
 libv4l2plugin-omap3mc.c |  241 +++++++++++++++++++++++++++++++++++++++++++++++
 libv4l2plugin-omap3mc.h |   91 ++++++++++++++++++
 2 files changed, 332 insertions(+), 0 deletions(-)
 create mode 100644 libv4l2plugin-omap3mc.c
 create mode 100644 libv4l2plugin-omap3mc.h

diff --git a/libv4l2plugin-omap3mc.c b/libv4l2plugin-omap3mc.c
new file mode 100644
index 0000000..e5b5ef0
--- /dev/null
+++ b/libv4l2plugin-omap3mc.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <glob.h>
+#include <linux/videodev2.h>
+#include <mediactl/media.h>
+
+#include "libv4l2-plugin.h"
+#include "libv4l2plugin-omap3mc.h"
+#include "paths.h"
+#include "operations.h"
+
+#if __GNUC__ >= 4
+#define PLUGIN_PUBLIC __attribute__ ((visibility("default")))
+#define PLUGIN_HIDDEN __attribute__ ((visibility("hidden")))
+#else
+#define PLUGIN_PUBLIC
+#define PLUGIN_HIDDEN
+#endif
+
+/* Check if /dev/media0 is already open*/
+int media_in_use()
+{
+	int glob_ret, file, ret = 0;
+	glob_t globbuf;
+	ssize_t link_len;
+	char file_name[16];
+
+	glob_ret = glob("/proc/self/fd/*", 0, NULL, &globbuf);
+
+	if (glob_ret == GLOB_NOSPACE)
+		return ret;
+
+	if (glob_ret == GLOB_ABORTED || glob_ret == GLOB_NOMATCH)
+		goto leave;
+
+	for (file = 0; file < globbuf.gl_pathc; file++) {
+		link_len = readlink(globbuf.gl_pathv[file],
+					file_name, strlen(MEDIA_DEVICE));
+		if (link_len == strlen(MEDIA_DEVICE))
+			file_name[link_len] = '\0';
+		else
+			continue;
+
+		if (!strncmp(file_name, MEDIA_DEVICE, strlen(MEDIA_DEVICE))) {
+			ret = 1;
+			break;
+		}
+	}
+
+leave:
+	globfree(&globbuf);
+
+	return ret;
+}
+
+PLUGIN_HIDDEN void * omap3mc_init(int fd)
+{
+	int ret = -1, primary;
+	struct omap3mcplugin *plugin;
+	const struct capture_pipeline *pipe = NULL;
+	struct sub_module *dst_sub_module = NULL;
+	char link_path[20];
+	ssize_t link_len;
+	char file[VIDEO_NODE_LENGTH + 1];
+
+	/* Get filename from fd */
+	sprintf(link_path, "/proc/self/fd/%d", fd);
+	link_len = readlink(link_path, file, VIDEO_NODE_LENGTH);
+	if (link_len == VIDEO_NODE_LENGTH)
+		link_path[link_len] = '\0';
+	else
+		return NULL;
+
+	/* FIXME: What we do if the application is aware of video nodes
+	   and tries to open() real /dev/video0 (CSI2 capture) */
+	if (strncmp(file, VIDEO_PRIMARY, strlen(VIDEO_PRIMARY)) == 0)
+		primary = 1;
+	else if (strncmp(file, VIDEO_SECONDARY, strlen(VIDEO_SECONDARY)) == 0)
+		primary = 0;
+	else
+		return NULL;
+
+	if (media_in_use())
+		return NULL;
+
+	plugin = calloc(1, sizeof(*plugin));
+	if (plugin == NULL)
+		return NULL;
+
+	plugin->media = media_open(MEDIA_DEVICE, 1);
+	if (plugin->media == NULL) {
+		free(plugin);
+		return NULL;
+	}
+
+	pipe = pipe_sensor_yuv(primary);
+
+	if (pipe)
+		plugin->path = path_allocate(plugin->media, pipe);
+
+	if (plugin->path)
+		dst_sub_module = path_destination_submodule(plugin->path);
+
+	if (dst_sub_module)
+		ret = path_power_on(plugin->path, fd);
+
+	if (ret == 0)
+		ret = path_connect_entities(plugin->media, plugin->path);
+
+	plugin->fd = dst_sub_module->entity->fd;
+
+	if (ret != 0) {
+		path_disconnect_entities(plugin->media, plugin->path);
+		path_power_off(plugin->path);
+
+		media_close(plugin->media);
+		free(plugin);
+		plugin = NULL;
+	}
+
+	return plugin;
+}
+
+PLUGIN_HIDDEN void omap3mc_close(void *dev_ops_priv)
+{
+	struct omap3mcplugin *plugin;
+
+	if (dev_ops_priv == NULL)
+		return;
+
+	plugin = (struct omap3mcplugin *)dev_ops_priv;
+
+	path_disconnect_entities(plugin->media, plugin->path);
+	path_power_off(plugin->path);
+
+	media_close(plugin->media);
+
+	free(plugin);
+}
+
+PLUGIN_HIDDEN int omap3mc_ioctl(void *dev_ops_priv, int fd,
+						unsigned long int request, void *arg)
+{
+	int ret = -1;
+	struct omap3mcplugin *plugin;
+
+	plugin = (struct omap3mcplugin *)dev_ops_priv;
+
+	switch (request) {
+	case VIDIOC_STREAMON:
+		ret = mc_vidioc_streamon(plugin, request, arg);
+		break;
+	case VIDIOC_STREAMOFF:
+		ret = mc_vidioc_streamoff(plugin, request, arg);
+		break;
+	case VIDIOC_S_FMT:
+		ret = mc_vidioc_s_fmt(plugin, request, arg);
+		break;
+	case VIDIOC_G_FMT:
+		ret = mc_vidioc_g_fmt(plugin, request, arg);
+		break;
+	case VIDIOC_TRY_FMT:
+		ret = mc_vidioc_try_fmt(plugin, request, arg);
+		break;
+	case VIDIOC_S_CROP:
+		ret = mc_vidioc_s_crop(plugin, request, arg);
+		break;
+	case VIDIOC_G_CROP:
+		ret = mc_vidioc_g_crop(plugin, request, arg);
+		break;
+	case VIDIOC_QUERYCTRL:
+		ret = mc_vidioc_queryctrl(plugin, request, arg);
+		break;
+	case VIDIOC_G_CTRL:
+		ret = mc_vidioc_g_ctrl(plugin, request, arg);
+		break;
+	case VIDIOC_S_CTRL:
+		ret = mc_vidioc_s_ctrl(plugin, request, arg);
+		break;
+	case VIDIOC_QUERYCAP:
+		ret = mc_vidioc_querycap(plugin, request, arg);
+		break;
+	case VIDIOC_ENUM_FMT:
+		ret = mc_vidioc_enum_fmt(plugin, request, arg);
+		break;
+	case VIDIOC_ENUM_FRAMESIZES:
+		ret = mc_vidioc_enum_framesizes(plugin, request, arg);
+		break;
+	case VIDIOC_ENUM_FRAMEINTERVALS:
+		ret = mc_vidioc_enum_frameintervals(plugin, request, arg);
+		break;
+	case VIDIOC_REQBUFS:
+		ret = mc_vidioc_reqbufs(plugin, request, arg);
+		break;
+	case VIDIOC_QUERYBUF:
+		ret = mc_vidioc_querybuf(plugin, request, arg);
+		break;
+	case VIDIOC_QBUF:
+		ret = mc_vidioc_qbuf(plugin, request, arg);
+		break;
+	case VIDIOC_DQBUF:
+		ret = mc_vidioc_dqbuf(plugin, request, arg);
+		break;
+	default:
+		errno = EINVAL;
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+PLUGIN_PUBLIC const struct libv4l2_dev_ops libv4l2_plugin = {
+	.init = &omap3mc_init,
+	.close = &omap3mc_close,
+	.ioctl = &omap3mc_ioctl,
+	.read = NULL
+};
diff --git a/libv4l2plugin-omap3mc.h b/libv4l2plugin-omap3mc.h
new file mode 100644
index 0000000..430df96
--- /dev/null
+++ b/libv4l2plugin-omap3mc.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __LIBV4L2PLUGIN_OMAP3MC_H__
+#define __LIBV4L2PLUGIN_OMAP3MC_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mediactl/media.h>
+
+#include "sl_list.h"
+
+#define SYS_OPEN(file, oflag, mode) \
+	syscall(SYS_open, (const char *)(file), (int)(oflag), (mode_t)(mode))
+#define SYS_CLOSE(fd) \
+	syscall(SYS_close, (int)(fd))
+#define SYS_IOCTL(fd, cmd, arg) \
+	syscall(SYS_ioctl, (int)(fd), (unsigned long)(cmd), (void *)(arg))
+
+
+#define VIDEO_PRIMARY "/dev/video0"
+#define VIDEO_SECONDARY "/dev/video1"
+#define VIDEO_NODE_LENGTH 11
+#define MEDIA_DEVICE "/dev/media0"
+
+#define PIPELINE_MAX_ELEMENTS 32
+#define SUBDEVICE_MAX_NAME_LEN 32
+#define PIXELFMT_MAX_ELEMENTS 10
+
+#define MC_PLUGIN_VERBOSE
+#ifdef MC_PLUGIN_VERBOSE
+#define MC_PLUGIN_PRINTF(str,args...) \
+			printf("%s():%d: " str, __FUNCTION__,__LINE__,##args)
+#endif
+
+
+
+/* pixel formats */
+enum mc_plugin_pixelformat {
+	MC_PLUGIN_PIX_FMT_INVALID = 0,
+	MC_PLUGIN_PIX_FMT_BAYER8_SBGGR,
+	MC_PLUGIN_PIX_FMT_BAYER8_SGBRG,
+	MC_PLUGIN_PIX_FMT_BAYER8_SGRBG,
+	MC_PLUGIN_PIX_FMT_BAYER10_SGRBG,
+	MC_PLUGIN_PIX_FMT_BAYER10_SRGGB,
+	MC_PLUGIN_PIX_FMT_BAYER10_SBGGR,
+	MC_PLUGIN_PIX_FMT_BAYER10_SGBRG,
+	MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG,
+	MC_PLUGIN_PIX_FMT_YUYV,
+	MC_PLUGIN_PIX_FMT_UYVY
+};
+
+struct capture_pipeline {
+	char path[PIPELINE_MAX_ELEMENTS][SUBDEVICE_MAX_NAME_LEN];
+	enum mc_plugin_pixelformat in_pixfmt[PIXELFMT_MAX_ELEMENTS];
+	enum mc_plugin_pixelformat out_pixfmt[PIXELFMT_MAX_ELEMENTS];
+};
+
+struct ipipe_descriptor {
+	const struct capture_pipeline *pipe;
+	struct list_head container;
+};
+struct sub_module {
+	struct media_entity *entity;
+	struct list_head list;
+};
+
+
+struct omap3mcplugin {
+	struct media_device *media;
+	struct ipipe_descriptor *path;
+	int fd;
+};
+
+#endif /* __LIBV4L2PLUGIN_OMAP3MC_H__ */
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2
  2011-05-19 12:36 [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Yordan Kamenov
                   ` (2 preceding siblings ...)
  2011-05-19 12:36 ` [libv4l-mcplugin PATCH 3/3] Add libv4l2 media controller plugin interface files Yordan Kamenov
@ 2011-05-20  7:11 ` Hans de Goede
  2011-05-20  8:42   ` Yordan Kamenov
  3 siblings, 1 reply; 6+ messages in thread
From: Hans de Goede @ 2011-05-20  7:11 UTC (permalink / raw)
  To: Yordan Kamenov; +Cc: linux-media, sakari.ailus

Hi,

So judging from the directory layout, this is supposed to be a separate
project, and not part of v4l-utils / libv4l, right?

WRT my merging plans for libv4l. I've recently done some much needed
work to better support high-res usb cameras. I plan to do a 0.8.4 release
with that work included real soon. Once that is done I'll change the version
in the Make.rules to 0.9.0-test and merge the plugin. Then we'll have
some 0.9.x releases followed by some 0.9.9x release (all testing releases)
followed by a 0.10.0 which should be the first stable release with plugin
support.

Regards,

Hans


On 05/19/2011 02:36 PM, Yordan Kamenov wrote:
> Hi,
>
> This is the Media Controller plugin for libv4l. It uses libv4l2 plugin support
> which is accepted by Hans De Goede, but not yet included in mainline libv4l2:
> http://www.spinics.net/lists/linux-media/msg32017.html
>
> The plugin allows a traditional v4l2 applications to work with Media Controller
> framework. The plugin is loaded when application opens /dev/video0 and it
> configures the media controller and then all ioctl's by the applicatin are
> handled by the plugin.
>
> The plugin implements init, close and ioctl callbacks. The init callback
> checks it's input file descriptor and if it coresponds to /dev/video0, then
> the media controller is initialized and appropriate pipeline is created.
> The close callback deinitializes the pipeline, and closes the media device.
> The ioctl callback is responsible to handle ioctl calls from application by
> using the media controller pipeline.
>
> The plugin uses media-ctl library for media controller operations:
> http://git.ideasonboard.org/?p=media-ctl.git;a=summary
>
> The plugin is divided in three separate patches:
>   * Media Controller pipelines initialization, configuration and destruction
>   * v4l operations - uses some functionality from the first one
>   * Plugin interface operations (init, close and ioctl) - uses functionality
>     from first two
>
>
>
> Yordan Kamenov (3):
>    Add files for media controller pipelines
>    Add files for v4l operations
>    Add libv4l2 media controller plugin interface files
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2
  2011-05-20  7:11 ` [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Hans de Goede
@ 2011-05-20  8:42   ` Yordan Kamenov
  0 siblings, 0 replies; 6+ messages in thread
From: Yordan Kamenov @ 2011-05-20  8:42 UTC (permalink / raw)
  To: Hans de Goede; +Cc: linux-media, sakari.ailus

Hans de Goede wrote:
> Hi,
Hi Hans,
>
> So judging from the directory layout, this is supposed to be a separate
> project, and not part of v4l-utils / libv4l, right?
>
It is separate now, but I guess that at some point it would be good to have
'plugins' directory containing some generic plugins as part of libv4l.

Regards
Yordan
> WRT my merging plans for libv4l. I've recently done some much needed
> work to better support high-res usb cameras. I plan to do a 0.8.4 release
> with that work included real soon. Once that is done I'll change the 
> version
> in the Make.rules to 0.9.0-test and merge the plugin. Then we'll have
> some 0.9.x releases followed by some 0.9.9x release (all testing 
> releases)
> followed by a 0.10.0 which should be the first stable release with plugin
> support.
>
> Regards,
>
> Hans
>
>
> On 05/19/2011 02:36 PM, Yordan Kamenov wrote:
>> Hi,
>>
>> This is the Media Controller plugin for libv4l. It uses libv4l2 
>> plugin support
>> which is accepted by Hans De Goede, but not yet included in mainline 
>> libv4l2:
>> http://www.spinics.net/lists/linux-media/msg32017.html
>>
>> The plugin allows a traditional v4l2 applications to work with Media 
>> Controller
>> framework. The plugin is loaded when application opens /dev/video0 
>> and it
>> configures the media controller and then all ioctl's by the 
>> applicatin are
>> handled by the plugin.
>>
>> The plugin implements init, close and ioctl callbacks. The init callback
>> checks it's input file descriptor and if it coresponds to 
>> /dev/video0, then
>> the media controller is initialized and appropriate pipeline is created.
>> The close callback deinitializes the pipeline, and closes the media 
>> device.
>> The ioctl callback is responsible to handle ioctl calls from 
>> application by
>> using the media controller pipeline.
>>
>> The plugin uses media-ctl library for media controller operations:
>> http://git.ideasonboard.org/?p=media-ctl.git;a=summary
>>
>> The plugin is divided in three separate patches:
>>   * Media Controller pipelines initialization, configuration and 
>> destruction
>>   * v4l operations - uses some functionality from the first one
>>   * Plugin interface operations (init, close and ioctl) - uses 
>> functionality
>>     from first two
>>
>>
>>
>> Yordan Kamenov (3):
>>    Add files for media controller pipelines
>>    Add files for v4l operations
>>    Add libv4l2 media controller plugin interface files
>>
>> -- 
>> To unsubscribe from this list: send the line "unsubscribe 
>> linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-05-20  8:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-19 12:36 [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Yordan Kamenov
2011-05-19 12:36 ` [libv4l-mcplugin PATCH 1/3] Add files for media controller pipelines Yordan Kamenov
2011-05-19 12:36 ` [libv4l-mcplugin PATCH 2/3] Add files for v4l operations Yordan Kamenov
2011-05-19 12:36 ` [libv4l-mcplugin PATCH 3/3] Add libv4l2 media controller plugin interface files Yordan Kamenov
2011-05-20  7:11 ` [libv4l-mcplugin PATCH 0/3] Media controller plugin for libv4l2 Hans de Goede
2011-05-20  8:42   ` Yordan Kamenov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.