[FFmpeg-devel] [RFC/PATCH 2/8] tidsp: add to build

Felipe Contreras felipe.contreras
Mon Sep 6 00:15:29 CEST 2010


Signed-off-by: Felipe Contreras <felipe.contreras at gmail.com>
---
 configure                     |    4 +-
 libavcodec/Makefile           |    1 +
 libavcodec/tidsp/dmm_buffer.h |  159 ++++++
 libavcodec/tidsp/dsp_bridge.c | 1169 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/tidsp/dsp_bridge.h |  428 +++++++++++++++
 libavcodec/tidsp/log.c        |   76 +++
 libavcodec/tidsp/log.h        |   38 ++
 libavcodec/tidsp/tidsp.c      |  555 +++++++++++++++++++
 libavcodec/tidsp/tidsp.h      |   77 +++
 9 files changed, 2506 insertions(+), 1 deletions(-)
 create mode 100644 libavcodec/tidsp/dmm_buffer.h
 create mode 100644 libavcodec/tidsp/dsp_bridge.c
 create mode 100644 libavcodec/tidsp/dsp_bridge.h
 create mode 100644 libavcodec/tidsp/log.c
 create mode 100644 libavcodec/tidsp/log.h
 create mode 100644 libavcodec/tidsp/tidsp.c
 create mode 100644 libavcodec/tidsp/tidsp.h

diff --git a/configure b/configure
index d86c1d3..42dc84d 100755
--- a/configure
+++ b/configure
@@ -111,6 +111,7 @@ Configuration options:
   --disable-vaapi          disable VAAPI code
   --disable-vdpau          disable VDPAU code
   --disable-dxva2          disable DXVA2 code
+  --disable-tidsp          disable TIDSP code
   --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
   --enable-hardcoded-tables use hardcoded tables instead of runtime generation
   --enable-memalign-hack   emulate memalign, interferes with memory debuggers
@@ -915,6 +916,7 @@ CONFIG_LIST="
     static
     swscale
     swscale_alpha
+    tidsp
     vaapi
     vdpau
     version3
@@ -1237,7 +1239,7 @@ mpeg2_dxva2_hwaccel_deps="dxva2api_h"
 mpeg2_dxva2_hwaccel_select="dxva2 mpeg2video_decoder"
 mpeg2_vaapi_hwaccel_select="vaapi mpeg2video_decoder"
 mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
-mpeg4_tidsp_hwaccel_select="mpeg4_decoder"
+mpeg4_tidsp_hwaccel_select="tidsp mpeg4_decoder"
 mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
 mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h"
 mpeg_xvmc_decoder_select="mpegvideo_decoder"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 8dc0f6c..501747e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -40,6 +40,7 @@ OBJS-$(CONFIG_LSP)                     += lsp.o
 OBJS-$(CONFIG_MDCT)                    += mdct.o
 RDFT-OBJS-$(CONFIG_HARDCODED_TABLES)   += sin_tables.o
 OBJS-$(CONFIG_RDFT)                    += rdft.o $(RDFT-OBJS-yes)
+OBJS-$(CONFIG_TIDSP)                   += tidsp/tidsp.o tidsp/dsp_bridge.o tidsp/log.o
 OBJS-$(CONFIG_VAAPI)                   += vaapi.o
 OBJS-$(CONFIG_VDPAU)                   += vdpau.o
 
diff --git a/libavcodec/tidsp/dmm_buffer.h b/libavcodec/tidsp/dmm_buffer.h
new file mode 100644
index 0000000..5ccc856
--- /dev/null
+++ b/libavcodec/tidsp/dmm_buffer.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Felipe Contreras
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Authors:
+ * Felipe Contreras <felipe.contreras at nokia.com>
+ * Marco Ballesio <marco.ballesio at nokia.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#ifndef DMM_BUFFER_H
+#define DMM_BUFFER_H
+
+#include <stdlib.h> /* for calloc, free */
+#include <string.h> /* for memset */
+
+#include "dsp_bridge.h"
+#include "log.h"
+
+#define ROUND_UP(num, scale) (((num) + ((scale) - 1)) & ~((scale) - 1))
+#define PAGE_SIZE 0x1000
+
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL,
+	DMA_TO_DEVICE,
+	DMA_FROM_DEVICE,
+};
+
+struct dmm_buffer {
+	int handle;
+	void *proc;
+	void *data;
+	void *allocated_data;
+	size_t size;
+	size_t len;
+	void *reserve;
+	void *map;
+	size_t alignment;
+	int dir;
+};
+
+static inline struct dmm_buffer *
+dmm_buffer_new(int handle,
+		void *proc,
+		int dir)
+{
+	struct dmm_buffer *b;
+	b = calloc(1, sizeof(*b));
+
+	b->handle = handle;
+	b->proc = proc;
+	b->alignment = 128;
+	b->dir = dir;
+
+	return b;
+}
+
+static inline void
+dmm_buffer_free(struct dmm_buffer *b)
+{
+	if (!b)
+		return;
+	if (b->map)
+		dsp_unmap(b->handle, b->proc, b->map);
+	if (b->reserve)
+		dsp_unreserve(b->handle, b->proc, b->reserve);
+	free(b->allocated_data);
+	free(b);
+}
+
+static inline void
+dmm_buffer_begin(struct dmm_buffer *b,
+		size_t len)
+{
+	if (b->dir == DMA_FROM_DEVICE)
+		dsp_invalidate(b->handle, b->proc, b->data, len);
+	else
+		dsp_flush(b->handle, b->proc, b->data, len, 1);
+}
+
+static inline void
+dmm_buffer_end(struct dmm_buffer *b,
+		size_t len)
+{
+	if (b->dir != DMA_TO_DEVICE)
+		dsp_invalidate(b->handle, b->proc, b->data, len);
+}
+
+static inline void
+dmm_buffer_map(struct dmm_buffer *b)
+{
+	size_t to_reserve;
+	if (b->map)
+		dsp_unmap(b->handle, b->proc, b->map);
+	if (b->reserve)
+		dsp_unreserve(b->handle, b->proc, b->reserve);
+	/**
+	 * @todo What exactly do we want to do here? Shouldn't the driver
+	 * calculate this?
+	 */
+	to_reserve = ROUND_UP(b->size, PAGE_SIZE) + PAGE_SIZE;
+	dsp_reserve(b->handle, b->proc, to_reserve, &b->reserve);
+	dsp_map(b->handle, b->proc, b->data, b->size, b->reserve, &b->map, 0);
+}
+
+static inline void
+dmm_buffer_unmap(struct dmm_buffer *b)
+{
+	if (b->map) {
+		dsp_unmap(b->handle, b->proc, b->map);
+		b->map = NULL;
+	}
+	if (b->reserve) {
+		dsp_unreserve(b->handle, b->proc, b->reserve);
+		b->reserve = NULL;
+	}
+}
+
+static inline void
+dmm_buffer_allocate(struct dmm_buffer *b,
+		size_t size)
+{
+	free(b->allocated_data);
+	if (b->alignment != 0) {
+		if (posix_memalign(&b->allocated_data, b->alignment, ROUND_UP(size, b->alignment)) != 0)
+			b->allocated_data = NULL;
+		b->data = b->allocated_data;
+	}
+	else
+		b->data = b->allocated_data = malloc(size);
+	b->size = size;
+}
+
+static inline void
+dmm_buffer_use(struct dmm_buffer *b,
+		void *data,
+		size_t size)
+{
+	b->data = data;
+	b->size = size;
+}
+
+static inline struct dmm_buffer *
+dmm_buffer_calloc(int handle,
+		void *proc,
+		size_t size,
+		int dir)
+{
+	struct dmm_buffer *tmp;
+	tmp = dmm_buffer_new(handle, proc, dir);
+	dmm_buffer_allocate(tmp, size);
+	memset(tmp->data, 0, size);
+	return tmp;
+}
+
+#endif /* DMM_BUFFER_H */
diff --git a/libavcodec/tidsp/dsp_bridge.c b/libavcodec/tidsp/dsp_bridge.c
new file mode 100644
index 0000000..9290665
--- /dev/null
+++ b/libavcodec/tidsp/dsp_bridge.c
@@ -0,0 +1,1169 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments, Incorporated
+ *
+ * Author: Felipe Contreras <felipe.contreras at gmail.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#include "dsp_bridge.h"
+
+/* for open */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <unistd.h> /* for close */
+#include <sys/ioctl.h> /* for ioctl */
+#include <stdlib.h> /* for free */
+
+#include <malloc.h> /* for memalign */
+
+#define ALLOCATE_SM
+
+#ifdef ALLOCATE_SM
+#include <malloc.h> /* for memalign */
+#include <sys/mman.h> /* for mmap */
+#endif
+
+#if DSP_API < 2
+#include <errno.h>
+#endif
+
+/*
+ * Dspbridge ioctl numbering scheme
+ *
+ *    7                           0
+ *  ---------------------------------
+ *  |  Module   |   ioctl Number    |
+ *  ---------------------------------
+ *  | x | x | x | 0 | 0 | 0 | 0 | 0 |
+ *  ---------------------------------
+ */
+
+/* ioctl driver identifier */
+#define DB 0xDB
+
+/*
+ * Following are used to distinguish between module ioctls, this is needed
+ * in case new ioctls are introduced.
+ */
+#define DB_MODULE_MASK 0xE0
+#define DB_IOC_MASK    0x1F
+
+#if DSP_API >= 1
+
+#include <linux/ioctl.h>
+
+/* ioctl module masks */
+#define DB_MGR  0x0
+#define DB_PROC 0x20
+#define DB_NODE 0x40
+#define DB_STRM 0x60
+#define DB_CMM  0x80
+
+/* Used to calculate the ioctl per dspbridge module */
+#define DB_IOC(module, num) \
+	(((module) & DB_MODULE_MASK) | ((num) & DB_IOC_MASK))
+
+#else
+
+#define DB_MGR  1
+#define DB_PROC 7
+#define DB_NODE 24
+#define DB_STRM 39
+#define DB_CMM  50
+
+#define DB_IOC(module, num)	((module) + (num))
+
+#undef _IOR
+#undef _IOW
+#undef _IOWR
+
+#define _IOR(type, nr, size)	(nr)
+#define _IOW(type, nr, size)	(nr)
+#define _IOWR(type, nr, size)	(nr)
+
+#endif /* DSP_API */
+
+/* MGR Module */
+#define MGR_WAIT		_IOWR(DB, DB_IOC(DB_MGR, 4), unsigned long)
+#define MGR_ENUMNODE_INFO	_IOWR(DB, DB_IOC(DB_MGR, 0), unsigned long)
+#define MGR_REGISTEROBJECT	_IOWR(DB, DB_IOC(DB_MGR, 2), unsigned long)
+#define MGR_UNREGISTEROBJECT	_IOWR(DB, DB_IOC(DB_MGR, 3), unsigned long)
+
+/* PROC Module */
+#define PROC_ATTACH		_IOWR(DB, DB_IOC(DB_PROC, 0), unsigned long)
+/* PROC_DETACH Deprecated */
+#define PROC_DETACH		_IOR(DB, DB_IOC(DB_PROC, 2), unsigned long)
+#define PROC_REGISTERNOTIFY	_IOWR(DB, DB_IOC(DB_PROC, 8), unsigned long)
+#define PROC_RSVMEM		_IOWR(DB, DB_IOC(DB_PROC, 10), unsigned long)
+#define PROC_UNRSVMEM		_IOW(DB, DB_IOC(DB_PROC, 11), unsigned long)
+#define PROC_MAPMEM		_IOWR(DB, DB_IOC(DB_PROC, 12), unsigned long)
+#define PROC_UNMAPMEM		_IOR(DB, DB_IOC(DB_PROC, 13), unsigned long)
+#define PROC_FLUSHMEMORY	_IOW(DB, DB_IOC(DB_PROC, 14), unsigned long)
+#define PROC_INVALIDATEMEMORY	_IOW(DB, DB_IOC(DB_PROC, 16), unsigned long)
+#define PROC_GET_STATE		_IOWR(DB, DB_IOC(DB_PROC, 5), unsigned long)
+#define PROC_ENUMRESOURCES	_IOWR(DB, DB_IOC(DB_PROC, 4), unsigned long)
+#define PROC_ENUMNODE		_IOWR(DB, DB_IOC(DB_PROC, 3), unsigned long)
+
+/* NODE Module */
+#define NODE_REGISTERNOTIFY	_IOWR(DB, DB_IOC(DB_NODE, 11), unsigned long)
+#define NODE_CREATE		_IOW(DB, DB_IOC(DB_NODE, 4), unsigned long)
+#define NODE_RUN		_IOW(DB, DB_IOC(DB_NODE, 12), unsigned long)
+#define NODE_TERMINATE		_IOWR(DB, DB_IOC(DB_NODE, 13), unsigned long)
+#define NODE_PUTMESSAGE		_IOW(DB, DB_IOC(DB_NODE, 10), unsigned long)
+#define NODE_GETMESSAGE		_IOWR(DB, DB_IOC(DB_NODE, 8), unsigned long)
+#define NODE_DELETE		_IOW(DB, DB_IOC(DB_NODE, 5), unsigned long)
+#define NODE_GETATTR		_IOWR(DB, DB_IOC(DB_NODE, 7), unsigned long)
+#define NODE_ALLOCMSGBUF	_IOWR(DB, DB_IOC(DB_NODE, 1), unsigned long)
+#define NODE_GETUUIDPROPS	_IOWR(DB, DB_IOC(DB_NODE, 14), unsigned long)
+#define NODE_ALLOCATE		_IOWR(DB, DB_IOC(DB_NODE, 0), unsigned long)
+#define NODE_CONNECT		_IOW(DB, DB_IOC(DB_NODE, 3), unsigned long)
+
+/* CMM Module */
+#define CMM_GETHANDLE		_IOR(DB, DB_IOC(DB_CMM, 2), unsigned long)
+#define CMM_GETINFO		_IOR(DB, DB_IOC(DB_CMM, 3), unsigned long)
+
+/* STRM Module */
+#define STRM_OPEN		_IOWR(DB, DB_IOC(DB_STRM, 7), unsigned long)
+#define STRM_CLOSE		_IOW(DB, DB_IOC(DB_STRM, 1), unsigned long)
+#define STRM_GETINFO		_IOWR(DB, DB_IOC(DB_STRM, 4), unsigned long)
+#define STRM_ALLOCATEBUFFER	_IOWR(DB, DB_IOC(DB_STRM, 0), unsigned long)
+#define STRM_IDLE		_IOW(DB, DB_IOC(DB_STRM, 5), unsigned long)
+#define STRM_RECLAIM		_IOWR(DB, DB_IOC(DB_STRM, 8), unsigned long)
+#define STRM_FREEBUFFER		_IOWR(DB, DB_IOC(DB_STRM, 2), unsigned long)
+#define STRM_ISSUE		_IOW(DB, DB_IOC(DB_STRM, 6), unsigned long)
+
+/* will not be needed when tidspbridge uses proper error codes */
+#define ioctl(...) (ioctl(__VA_ARGS__) < 0)
+
+int dsp_open(void)
+{
+	return open("/dev/DspBridge", O_RDWR);
+}
+
+int dsp_close(int handle)
+{
+	return close(handle);
+}
+
+struct proc_attach {
+	unsigned int num;
+	const void *info; /* not used */
+	void **ret_handle;
+};
+
+bool dsp_attach(int handle,
+		unsigned int num,
+		const void *info,
+		void **ret_handle)
+{
+	struct proc_attach arg = {
+		.num = num,
+		.info = info,
+		.ret_handle = ret_handle,
+	};
+
+	return !ioctl(handle, PROC_ATTACH, &arg);
+}
+
+struct proc_detach {
+	void *proc_handle;
+};
+
+bool dsp_detach(int handle,
+		void *proc_handle)
+{
+	struct proc_detach arg = {
+		.proc_handle = proc_handle,
+	};
+
+	return !ioctl(handle, PROC_DETACH, &arg);
+}
+
+struct register_notify {
+	void *proc_handle;
+	unsigned int event_mask;
+	unsigned int notify_type;
+	struct dsp_notification *info;
+};
+
+bool dsp_register_notify(int handle,
+		void *proc_handle,
+		unsigned int event_mask,
+		unsigned int notify_type,
+		struct dsp_notification *info)
+{
+	struct register_notify arg = {
+		.proc_handle = proc_handle,
+		.event_mask = event_mask,
+		.notify_type = notify_type,
+		.info = info,
+	};
+
+	return !ioctl(handle, PROC_REGISTERNOTIFY, &arg);
+}
+
+struct node_register_notify {
+	void *node_handle;
+	unsigned int event_mask;
+	unsigned int notify_type;
+	struct dsp_notification *info;
+};
+
+bool dsp_node_register_notify(int handle,
+		struct dsp_node *node,
+		unsigned int event_mask,
+		unsigned int notify_type,
+		struct dsp_notification *info)
+{
+	struct node_register_notify arg = {
+		.node_handle = node->handle,
+		.event_mask = event_mask,
+		.notify_type = notify_type,
+		.info = info,
+	};
+
+	return !ioctl(handle, NODE_REGISTERNOTIFY, &arg);
+}
+
+struct wait_for_events {
+	struct dsp_notification **notifications;
+	unsigned int count;
+	unsigned int *ret_index;
+	unsigned int timeout;
+};
+
+bool dsp_wait_for_events(int handle,
+		struct dsp_notification **notifications,
+		unsigned int count,
+		unsigned int *ret_index,
+		unsigned int timeout)
+{
+	struct wait_for_events arg = {
+		.notifications = notifications,
+		.count = count,
+		.ret_index = ret_index,
+		.timeout = timeout,
+	};
+
+#if DSP_API >= 2
+	return !ioctl(handle, MGR_WAIT, &arg);
+#else
+	/*
+	 * Temporary hack since libc only saves errors -1 to -4095; 0x80008017
+	 * is not stored.
+	 */
+	int r;
+	r = ioctl(handle, MGR_WAIT, &arg);
+	if (r == (int)0x80008017)
+		errno = ETIME;
+	return !r;
+#endif
+}
+
+struct enum_node {
+	unsigned int num;
+	struct dsp_ndb_props *info;
+	unsigned int info_size;
+	unsigned int *ret_num;
+};
+
+bool dsp_enum(int handle,
+		unsigned int num,
+		struct dsp_ndb_props *info,
+		size_t info_size,
+		unsigned int *ret_num)
+{
+	struct enum_node arg = {
+		.num = num,
+		.info = info,
+		.info_size = info_size,
+		.ret_num = ret_num,
+	};
+
+	return !ioctl(handle, MGR_ENUMNODE_INFO, &arg);
+}
+
+struct register_object {
+	const struct dsp_uuid *uuid;
+	enum dsp_dcd_object_type type;
+	const char *path;
+};
+
+bool dsp_register(int handle,
+		const struct dsp_uuid *uuid,
+		enum dsp_dcd_object_type type,
+		const char *path)
+{
+	struct register_object arg = {
+		.uuid = uuid,
+		.type = type,
+		.path = path,
+	};
+
+	return !ioctl(handle, MGR_REGISTEROBJECT, &arg);
+}
+
+struct unregister_object {
+	const struct dsp_uuid *uuid;
+	enum dsp_dcd_object_type type;
+};
+
+bool dsp_unregister(int handle,
+		const struct dsp_uuid *uuid,
+		enum dsp_dcd_object_type type)
+{
+	struct unregister_object arg = {
+		.uuid = uuid,
+		.type = type,
+	};
+
+	return !ioctl(handle, MGR_UNREGISTEROBJECT, &arg);
+}
+
+struct node_create {
+	void *node_handle;
+};
+
+bool dsp_node_create(int handle,
+		struct dsp_node *node)
+{
+	struct node_create arg = {
+		.node_handle = node->handle,
+	};
+
+	return !ioctl(handle, NODE_CREATE, &arg);
+}
+
+struct node_run {
+	void *node_handle;
+};
+
+bool dsp_node_run(int handle,
+		struct dsp_node *node)
+{
+	struct node_run arg = {
+		.node_handle = node->handle,
+	};
+
+	return !ioctl(handle, NODE_RUN, &arg);
+}
+
+struct node_terminate {
+	void *node_handle;
+	unsigned long *status;
+};
+
+bool dsp_node_terminate(int handle,
+		struct dsp_node *node,
+		unsigned long *status)
+{
+	struct node_terminate arg = {
+		.node_handle = node->handle,
+		.status = status,
+	};
+
+	return !ioctl(handle, NODE_TERMINATE, &arg);
+}
+
+struct node_put_message {
+	void *node_handle;
+	const struct dsp_msg *message;
+	unsigned int timeout;
+};
+
+bool dsp_node_put_message(int handle,
+		struct dsp_node *node,
+		const struct dsp_msg *message,
+		unsigned int timeout)
+{
+	struct node_put_message arg = {
+		.node_handle = node->handle,
+		.message = message,
+		.timeout = timeout,
+	};
+
+	return !ioctl(handle, NODE_PUTMESSAGE, &arg);
+}
+
+struct node_get_message {
+	void *node_handle;
+	struct dsp_msg *message;
+	unsigned int timeout;
+};
+
+bool dsp_node_get_message(int handle,
+		struct dsp_node *node,
+		struct dsp_msg *message,
+		unsigned int timeout)
+{
+	struct node_get_message arg = {
+		.node_handle = node->handle,
+		.message = message,
+		.timeout = timeout,
+	};
+
+	return !ioctl(handle, NODE_GETMESSAGE, &arg);
+}
+
+struct node_delete {
+	void *node_handle;
+};
+
+static inline bool dsp_node_delete(int handle,
+		struct dsp_node *node)
+{
+	struct node_delete arg = {
+		.node_handle = node->handle,
+	};
+
+	return !ioctl(handle, NODE_DELETE, &arg);
+}
+
+#ifdef ALLOCATE_SM
+struct node_get_attr {
+	void *node_handle;
+	struct dsp_node_attr *attr;
+	unsigned int attr_size;
+};
+
+bool dsp_node_get_attr(int handle,
+		struct dsp_node *node,
+		struct dsp_node_attr *attr,
+		size_t attr_size)
+{
+	struct node_get_attr arg = {
+		.node_handle = node->handle,
+		.attr = attr,
+		.attr_size = attr_size,
+	};
+
+	return !ioctl(handle, NODE_GETATTR, &arg);
+}
+
+struct dsp_buffer_attr {
+	unsigned long cb;
+	unsigned int segment;
+	unsigned int alignment;
+};
+
+struct node_alloc_buf {
+	void *node_handle;
+	unsigned int size;
+	struct dsp_buffer_attr *attr;
+	void **buffer;
+};
+
+static inline bool dsp_node_alloc_buf(int handle,
+		struct dsp_node *node,
+		size_t size,
+		struct dsp_buffer_attr *attr,
+		void **buffer)
+{
+	struct node_alloc_buf arg = {
+		.node_handle = node->handle,
+		.size = size,
+		.attr = attr,
+		.buffer = buffer,
+	};
+
+	if (ioctl(handle, NODE_ALLOCMSGBUF, &arg)) {
+		*buffer = NULL;
+		return false;
+	}
+
+	return true;
+}
+
+struct dsp_cmm_seg_info {
+	unsigned long base_pa;
+	unsigned long size;
+	unsigned long gpp_base_pa;
+	unsigned long gpp_size;
+	unsigned long dsp_base_va;
+	unsigned long dsp_size;
+	unsigned long use_count;
+	unsigned long base_va;
+};
+
+struct dsp_cmm_info {
+	unsigned long segments;
+	unsigned long use_count;
+	unsigned long min_block_size;
+	struct dsp_cmm_seg_info info[1];
+};
+
+struct cmm_get_handle {
+	void *proc_handle;
+	struct cmm_object **cmm;
+};
+
+struct cmm_get_info {
+	struct cmm_object *cmm;
+	struct dsp_cmm_info *info;
+};
+
+static inline bool get_cmm_info(int handle,
+		void *proc_handle,
+		struct dsp_cmm_info *cmm_info)
+{
+	struct cmm_object *cmm;
+	struct cmm_get_handle cmm_arg = {
+		.proc_handle = proc_handle,
+		.cmm = &cmm,
+	};
+	struct cmm_get_info cmm_info_arg = {
+		.info = cmm_info,
+	};
+
+	if (ioctl(handle, CMM_GETHANDLE, &cmm_arg))
+		return false;
+
+	cmm_info_arg.cmm = cmm;
+	if (ioctl(handle, CMM_GETINFO, &cmm_info_arg))
+		return false;
+
+	return true;
+}
+
+static inline bool allocate_segments(int handle,
+		void *proc_handle,
+		struct dsp_node *node)
+{
+	struct dsp_cmm_info cmm_info;
+	struct dsp_node_attr attr;
+	enum dsp_node_type node_type;
+
+	if (!get_cmm_info(handle, proc_handle, &cmm_info))
+		return false;
+
+	if (!dsp_node_get_attr(handle, node, &attr, sizeof(attr)))
+		return false;
+
+	node_type = attr.info.props.uNodeType;
+
+	if ((node_type != DSP_NODE_DEVICE) && (cmm_info.segments > 0)) {
+		struct dsp_cmm_seg_info *seg;
+
+		seg = &cmm_info.info[0];
+
+		if (seg->base_pa != 0 && seg->size > 0) {
+			void *base;
+			struct dsp_buffer_attr buffer_attr;
+
+			base = mmap(NULL, seg->size,
+					PROT_READ | PROT_WRITE, MAP_SHARED | 0x2000 /* MAP_LOCKED */,
+					handle, seg->base_pa);
+
+			if (!base)
+				return false;
+
+			buffer_attr.alignment = 0;
+			buffer_attr.segment = 1 | 0x10000000;
+			buffer_attr.cb = 0;
+			if (!dsp_node_alloc_buf(handle, node, seg->size,
+						&buffer_attr, &base))
+			{
+				munmap(base, seg->size);
+				return false;
+			}
+
+			node->msgbuf_addr = base;
+			node->msgbuf_size = seg->size;
+		}
+	}
+
+	return true;
+}
+#endif
+
+#ifdef ALLOCATE_HEAP
+struct get_uuid_props {
+	void *proc_handle;
+	const struct dsp_uuid *node_uuid;
+	struct dsp_ndb_props *props;
+};
+
+static inline bool get_uuid_props(int handle,
+		void *proc_handle,
+		const struct dsp_uuid *node_uuid,
+		struct dsp_ndb_props *props)
+{
+	struct get_uuid_props arg = {
+		.proc_handle = proc_handle,
+		.node_uuid = node_uuid,
+		.props = props,
+	};
+
+	return !ioctl(handle, NODE_GETUUIDPROPS, &arg);
+}
+
+#define PG_SIZE_4K 4096
+#define PG_MASK(pg_size) (~((pg_size)-1))
+#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
+#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
+#endif
+
+struct node_allocate {
+	void *proc_handle;
+	const struct dsp_uuid *node_id;
+	const void *cb_data;
+	struct dsp_node_attr_in *attrs;
+	void **ret_node;
+};
+
+bool dsp_node_allocate(int handle,
+		void *proc_handle,
+		const struct dsp_uuid *node_uuid,
+		const void *cb_data,
+		struct dsp_node_attr_in *attrs,
+		struct dsp_node **ret_node)
+{
+	struct dsp_node *node;
+	void *node_handle = NULL;
+	struct node_allocate arg = {
+		.proc_handle = proc_handle,
+		.node_id = node_uuid,
+		.cb_data = cb_data,
+		.attrs = attrs,
+		.ret_node = &node_handle,
+	};
+
+#ifdef ALLOCATE_HEAP
+	if (attrs) {
+		struct dsp_ndb_props props;
+
+		if (!get_uuid_props(handle, proc_handle, node_uuid, &props)) {
+			attrs->gpp_va = NULL;
+			return false;
+		}
+
+		if (attrs->profile_id < props.uCountProfiles) {
+			unsigned int heap_size = 0;
+
+			heap_size = props.aProfiles[attrs->profile_id].ulHeapSize;
+			if (heap_size) {
+				void *virtual = NULL;
+
+				heap_size = PG_ALIGN_HIGH(heap_size, PG_SIZE_4K);
+				virtual = memalign(128, heap_size);
+				if (!virtual)
+					return false;
+				attrs->heap_size = heap_size;
+				attrs->gpp_va = virtual;
+			}
+		}
+	}
+#endif
+
+	if (ioctl(handle, NODE_ALLOCATE, &arg)) {
+		if (attrs) {
+			free(attrs->gpp_va);
+			attrs->gpp_va = NULL;
+		}
+		return false;
+	}
+
+	node = calloc(1, sizeof(*node));
+	node->handle = node_handle;
+	if (attrs)
+		node->heap = attrs->gpp_va;
+
+#ifdef ALLOCATE_SM
+	if (!allocate_segments(handle, proc_handle, node)) {
+		dsp_node_delete(handle, node);
+		free(node->heap);
+		free(node);
+		return false;
+	}
+#endif
+
+	*ret_node = node;
+
+	return true;
+}
+
+struct node_connect {
+	void *node_handle;
+	unsigned int stream;
+	void *other_node_handle;
+	unsigned int other_stream;
+	struct dsp_stream_attr *attrs;
+	void *params;
+};
+
+bool dsp_node_connect(int handle,
+		struct dsp_node *node,
+		unsigned int stream,
+		struct dsp_node *other_node,
+		unsigned int other_stream,
+		struct dsp_stream_attr *attrs,
+		void *params)
+{
+	struct node_connect arg = {
+		.node_handle = node->handle,
+		.stream = stream,
+		.other_node_handle = other_node->handle,
+		.other_stream = other_stream,
+		.attrs = attrs,
+		.params = params,
+	};
+
+	return !ioctl(handle, NODE_CONNECT, &arg);
+}
+
+bool dsp_node_free(int handle,
+		struct dsp_node *node)
+{
+#ifdef ALLOCATE_SM
+	munmap(node->msgbuf_addr, node->msgbuf_size);
+#endif
+	dsp_node_delete(handle, node);
+	free(node->heap);
+	free(node);
+
+	return true;
+}
+
+struct reserve_mem {
+	void *proc_handle;
+	unsigned long size;
+	void **addr;
+};
+
+bool dsp_reserve(int handle,
+		void *proc_handle,
+		unsigned long size,
+		void **addr)
+{
+	struct reserve_mem arg = {
+		.proc_handle = proc_handle,
+		.size = size,
+		.addr = addr,
+	};
+
+	return !ioctl(handle, PROC_RSVMEM, &arg);
+}
+
+struct unreserve_mem {
+	void *proc_handle;
+	unsigned long size;
+	void *addr;
+};
+
+bool dsp_unreserve(int handle,
+		void *proc_handle,
+		void *addr)
+{
+	struct unreserve_mem arg = {
+		.proc_handle = proc_handle,
+		.addr = addr,
+	};
+
+	return !ioctl(handle, PROC_UNRSVMEM, &arg);
+}
+
+struct map_mem {
+	void *proc_handle;
+	void *mpu_addr;
+	unsigned long size;
+	void *req_addr;
+	void **ret_map_addr;
+	unsigned long attr;
+};
+
+bool dsp_map(int handle,
+		void *proc_handle,
+		void *mpu_addr,
+		unsigned long size,
+		void *req_addr,
+		void *ret_map_addr,
+		unsigned long attr)
+{
+	struct map_mem arg = {
+		.proc_handle = proc_handle,
+		.mpu_addr = mpu_addr,
+		.size = size,
+		.req_addr = req_addr,
+		.ret_map_addr = ret_map_addr,
+		.attr = attr,
+	};
+
+	return !ioctl(handle, PROC_MAPMEM, &arg);
+}
+
+struct unmap_mem {
+	void *proc_handle;
+	unsigned long size;
+	void *map_addr;
+};
+
+bool dsp_unmap(int handle,
+		void *proc_handle,
+		void *map_addr)
+{
+	struct unmap_mem arg = {
+		.proc_handle = proc_handle,
+		.map_addr = map_addr,
+	};
+
+	return !ioctl(handle, PROC_UNMAPMEM, &arg);
+}
+
+struct flush_mem {
+	void *proc_handle;
+	void *mpu_addr;
+	unsigned long size;
+	unsigned long flags;
+};
+
+bool dsp_flush(int handle,
+		void *proc_handle,
+		void *mpu_addr,
+		unsigned long size,
+		unsigned long flags)
+{
+	struct flush_mem arg = {
+		.proc_handle = proc_handle,
+		.mpu_addr = mpu_addr,
+		.size = size,
+		.flags = flags,
+	};
+
+	return !ioctl(handle, PROC_FLUSHMEMORY, &arg);
+}
+
+struct invalidate_mem {
+	void *proc_handle;
+	void *mpu_addr;
+	unsigned long size;
+};
+
+bool dsp_invalidate(int handle,
+		void *proc_handle,
+		void *mpu_addr,
+		unsigned long size)
+{
+	struct invalidate_mem arg = {
+		.proc_handle = proc_handle,
+		.mpu_addr = mpu_addr,
+		.size = size,
+	};
+
+	return !ioctl(handle, PROC_INVALIDATEMEMORY, &arg);
+}
+
+struct proc_get_info {
+	void *proc_handle;
+	unsigned type;
+	struct dsp_info *info;
+	unsigned size;
+};
+
+bool dsp_proc_get_info(int handle,
+		void *proc_handle,
+		unsigned type,
+		struct dsp_info *info,
+		unsigned size)
+{
+	struct proc_get_info arg = {
+		.proc_handle = proc_handle,
+		.type = type,
+		.info = info,
+		.size = size,
+	};
+
+	return !ioctl(handle, PROC_ENUMRESOURCES, &arg);
+}
+
+struct enum_nodes {
+	void *proc_handle;
+	void **node_table;
+	unsigned node_table_size;
+	unsigned *num_nodes;
+	unsigned *allocated;
+};
+
+bool dsp_enum_nodes(int handle,
+		void *proc_handle,
+		void **node_table,
+		unsigned node_table_size,
+		unsigned *num_nodes,
+		unsigned *allocated)
+{
+	struct enum_nodes arg = {
+		.proc_handle = proc_handle,
+		.node_table = node_table,
+		.node_table_size = node_table_size,
+		.num_nodes = num_nodes,
+		.allocated = allocated,
+	};
+
+	return !ioctl(handle, PROC_ENUMNODE, &arg);
+}
+
+struct stream_attr {
+	void *event;
+	char *name;
+	void *base;
+	unsigned long size;
+	struct dsp_stream_attr_in *attrin;
+};
+
+struct stream_open {
+	void *node_handle;
+	unsigned int direction;
+	unsigned int index;
+	struct stream_attr *attr;
+	void *stream;
+};
+
+bool dsp_stream_open(int handle,
+		struct dsp_node *node,
+		unsigned int direction,
+		unsigned int index,
+		struct dsp_stream_attr_in *attrin,
+		void *stream)
+{
+	struct stream_attr strm_attr = {
+		.attrin = attrin,
+	};
+	struct stream_open stream_arg = {
+		.node_handle = node->handle,
+		.direction = direction,
+		.index = index,
+		.attr = &strm_attr,
+		.stream = stream,
+	};
+
+	if (attrin && (attrin->mode == STRMMODE_ZEROCOPY ||
+				attrin->mode == STRMMODE_RDMA)) {
+		struct dsp_cmm_info cmm_info;
+
+		if (!get_cmm_info(handle, NULL, &cmm_info))
+			return false;
+
+		if (cmm_info.segments > 0) {
+			void *base;
+			struct dsp_cmm_seg_info *seg;
+
+			seg = &cmm_info.info[0];
+			base = mmap(NULL, seg->size,
+					PROT_READ | PROT_WRITE,
+					MAP_SHARED | 0x2000 /* MAP_LOCKED */,
+					handle, seg->base_pa);
+
+			if (!base)
+				return false;
+
+			strm_attr.base = base;
+			strm_attr.size = seg->size;
+		}
+	}
+
+	return !ioctl(handle, STRM_OPEN, &stream_arg);
+}
+
+struct stream_info {
+	enum dsp_stream_mode mode;
+	unsigned int segment;
+	void *base;
+	struct dsp_stream_info *info;
+};
+
+struct stream_get_info {
+	void *stream;
+	struct stream_info *info;
+	unsigned int size;
+};
+
+static inline bool get_stream_info(int handle,
+		void *stream,
+		struct stream_info *info,
+		unsigned int size)
+{
+	struct stream_get_info arg = {
+		.stream = stream,
+		.info = info,
+		.size = size,
+	};
+
+	return !ioctl(handle, STRM_GETINFO, &arg);
+}
+
+bool dsp_stream_close(int handle,
+		void *stream)
+{
+	struct stream_info info;
+	if (!get_stream_info(handle, stream, &info, sizeof(struct stream_info)))
+		return false;
+
+	if (info.base) {
+		struct dsp_cmm_info cmm_info;
+
+		if (!get_cmm_info(handle, NULL, &cmm_info))
+			return false;
+
+		if (cmm_info.segments > 0) {
+			struct dsp_cmm_seg_info *seg;
+			seg = &cmm_info.info[0];
+			if (munmap(info.base, seg->size))
+				return false;
+		}
+	}
+
+	return !ioctl(handle, STRM_CLOSE, &stream);
+}
+
+struct stream_idle {
+	void *stream;
+	bool flush;
+};
+
+bool dsp_stream_idle(int handle,
+		void *stream,
+		bool flush)
+{
+	struct stream_idle arg = {
+		.stream = stream,
+		.flush = flush,
+	};
+	return !ioctl(handle, STRM_IDLE, &arg);
+}
+
+struct stream_reclaim {
+	void *stream;
+	unsigned char **buff;
+	unsigned long *data_size;
+	unsigned long *buff_size;
+	unsigned long *flag;
+};
+
+bool dsp_stream_reclaim(int handle,
+		void *stream,
+		unsigned char **buff,
+		unsigned long *data_size,
+		unsigned long *buff_size,
+		unsigned long *flag)
+{
+	struct stream_reclaim arg = {
+		.stream = stream,
+		.buff = buff,
+		.data_size = data_size,
+		.buff_size = buff_size,
+		.flag = flag,
+	};
+	return !ioctl(handle, STRM_RECLAIM, &arg);
+}
+
+struct stream_issue {
+	void *stream;
+	unsigned char *buff;
+	unsigned long data_size;
+	unsigned long buff_size;
+	unsigned long flag;
+};
+
+bool dsp_stream_issue(int handle,
+		void *stream,
+		unsigned char *buff,
+		unsigned long data_size,
+		unsigned long buff_size,
+		unsigned long flag)
+{
+	struct stream_issue arg = {
+		.stream = stream,
+		.buff = buff,
+		.data_size = data_size,
+		.buff_size = buff_size,
+		.flag = flag,
+	};
+	return !ioctl(handle, STRM_ISSUE, &arg);
+}
+
+bool dsp_stream_get_info(int handle,
+		void *stream,
+		struct dsp_stream_info *info,
+		unsigned int size)
+{
+	struct stream_info stream_info = {
+		.info = info
+	};
+
+	return get_stream_info(handle, stream, &stream_info, size);
+}
+
+
+struct stream_allocate_buffer {
+	void *stream;
+	unsigned int size;
+	unsigned char **buff;
+	unsigned int num_buf;
+};
+
+bool dsp_stream_allocate_buffers(int handle,
+		void *stream,
+		unsigned int size,
+		unsigned char **buff,
+		unsigned int num_buf)
+{
+	unsigned int i;
+	struct stream_info info;
+	if (!get_stream_info(handle, stream, &info, sizeof(struct stream_info)))
+		return false;
+
+	if (info.segment > 0) {
+		struct stream_allocate_buffer arg = {
+			.stream = stream,
+			.size = size,
+			.buff = buff,
+			.num_buf = num_buf,
+		};
+
+		return !ioctl(handle, STRM_ALLOCATEBUFFER, &arg);
+	}
+
+	for (i = 0; i < num_buf; i++)
+		buff[i] = (unsigned char *) malloc(size);
+
+	return true;
+}
+
+struct stream_free_buffers {
+	void *stream;
+	unsigned char **buff;
+	unsigned int num_buf;
+};
+
+bool dsp_stream_free_buffers(int handle,
+		void *stream,
+		unsigned char **buff,
+		unsigned int num_buf)
+{
+	unsigned int i;
+	struct stream_info info;
+	if (!get_stream_info(handle, stream, &info, sizeof(struct stream_info)))
+		return false;
+
+	if (info.segment) {
+		struct stream_free_buffers arg = {
+			.stream = stream,
+			.buff = buff,
+			.num_buf = num_buf,
+		};
+		return !ioctl(handle, STRM_FREEBUFFER, &arg);
+	}
+
+	for (i = 0; i < num_buf; i++) {
+		free(buff[i]);
+		buff[i] = NULL;
+	}
+
+	return true;
+}
diff --git a/libavcodec/tidsp/dsp_bridge.h b/libavcodec/tidsp/dsp_bridge.h
new file mode 100644
index 0000000..8cd5893
--- /dev/null
+++ b/libavcodec/tidsp/dsp_bridge.h
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ *
+ * Author: Felipe Contreras <felipe.contreras at gmail.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#ifndef DSP_BRIDGE_H
+#define DSP_BRIDGE_H
+
+#define DSP_DIR "/lib/dsp/"
+#define DSP_API 0
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define ALLOCATE_HEAP
+
+#define DSP_MMUFAULT 0x00000010
+#define DSP_SYSERROR 0x00000020
+#define DSP_NODEMESSAGEREADY 0x00000200
+
+struct dsp_uuid {
+	uint32_t field_1;
+	uint16_t field_2;
+	uint16_t field_3;
+	uint8_t field_4;
+	uint8_t field_5;
+	uint8_t field_6[6];
+};
+
+struct dsp_node {
+	void *handle;
+	void *heap;
+	void *msgbuf_addr;
+	size_t msgbuf_size;
+};
+
+/* note: cmd = 0x20000000 has special handling */
+struct dsp_msg {
+	uint32_t cmd;
+	uint32_t arg_1;
+	uint32_t arg_2;
+};
+
+struct dsp_notification {
+	char *name;
+	void *handle;
+};
+
+struct dsp_node_attr_in {
+	unsigned long cb;
+	int priority;
+	unsigned int timeout;
+	unsigned int profile_id;
+	unsigned int heap_size;
+	void *gpp_va;
+};
+
+enum dsp_dcd_object_type {
+	DSP_DCD_NODETYPE,
+	DSP_DCD_PROCESSORTYPE,
+	DSP_DCD_LIBRARYTYPE,
+	DSP_DCD_CREATELIBTYPE,
+	DSP_DCD_EXECUTELIBTYPE,
+	DSP_DCD_DELETELIBTYPE,
+};
+
+enum dsp_node_type {
+	DSP_NODE_DEVICE,
+	DSP_NODE_TASK,
+	DSP_NODE_DAISSOCKET,
+	DSP_NODE_MESSAGE,
+};
+
+#ifdef ALLOCATE_HEAP
+struct DSP_RESOURCEREQMTS {
+	unsigned long cbStruct;
+	unsigned int uStaticDataSize;
+	unsigned int uGlobalDataSize;
+	unsigned int uProgramMemSize;
+	unsigned int uWCExecutionTime;
+	unsigned int uWCPeriod;
+	unsigned int uWCDeadline;
+	unsigned int uAvgExectionTime;
+	unsigned int uMinimumPeriod;
+};
+
+struct DSP_NODEPROFS {
+	unsigned int ulHeapSize;
+};
+
+struct dsp_ndb_props {
+	unsigned long cbStruct;
+	struct dsp_uuid uiNodeID;
+	char acName[32];
+	enum dsp_node_type uNodeType;
+	unsigned int bCacheOnGPP;
+	struct DSP_RESOURCEREQMTS dspResourceReqmts;
+	int iPriority;
+	unsigned int uStackSize;
+	unsigned int uSysStackSize;
+	unsigned int uStackSeg;
+	unsigned int uMessageDepth;
+	unsigned int uNumInputStreams;
+	unsigned int uNumOutputStreams;
+	unsigned int uTimeout;
+	unsigned int uCountProfiles; /* Number of supported profiles */
+	struct DSP_NODEPROFS aProfiles[16];	/* Array of profiles */
+	unsigned int uStackSegName; /* Stack Segment Name */
+};
+#endif
+
+enum dsp_resource {
+	DSP_RESOURCE_DYNDARAM = 0,
+	DSP_RESOURCE_DYNSARAM,
+	DSP_RESOURCE_DYNEXTERNAL,
+	DSP_RESOURCE_DYNSRAM,
+	DSP_RESOURCE_PROCLOAD,
+};
+
+struct dsp_info {
+	unsigned long cb;
+	enum dsp_resource type;
+	union {
+		unsigned long resource;
+		struct {
+			unsigned long size;
+			unsigned long total_free_size;
+			unsigned long len_max_free_block;
+			unsigned long free_blocks;
+			unsigned long alloc_blocks;
+		} mem;
+		struct {
+			unsigned long load;
+			unsigned long pred_load;
+			unsigned long freq;
+			unsigned long pred_freq;
+		} proc;
+	} result;
+};
+
+enum dsp_connect_type {
+	CONNECTTYPE_NODEOUTPUT,
+	CONNECTTYPE_GPPOUTPUT,
+	CONNECTTYPE_NODEINPUT,
+	CONNECTTYPE_GPPINPUT
+};
+
+struct dsp_stream_connect {
+	unsigned long cb;
+	enum dsp_connect_type type;
+	unsigned int index;
+	void *node_handle;
+	struct dsp_uuid node_id;
+	unsigned int stream_index;
+};
+
+enum dsp_stream_mode {
+	STRMMODE_PROCCOPY,
+	STRMMODE_ZEROCOPY,
+	STRMMODE_LDMA,
+	STRMMODE_RDMA
+};
+
+struct dsp_stream_attr {
+	unsigned int seg_id;
+	unsigned int buf_size;
+	unsigned int num_bufs;
+	unsigned int alignment;
+	unsigned int timeout;
+	enum dsp_stream_mode mode;
+	unsigned int dma_chnl_id;
+	unsigned int dma_priority;
+};
+
+struct dsp_stream_attr_in {
+	unsigned long cb;
+	unsigned int timeout;
+	unsigned int segment;
+	unsigned int alignment;
+	unsigned int num_bufs;
+	enum dsp_stream_mode mode;
+	unsigned int dma_chnl_id;
+	unsigned int dma_priority;
+};
+
+enum dsp_stream_state {
+	STREAM_IDLE,
+	STREAM_READY,
+	STREAM_PENDING,
+	STREAM_DONE
+};
+
+struct dsp_stream_info {
+	unsigned long cb;
+	unsigned int num_bufs_allowed;
+	unsigned int num_bufs_in_stream;
+	unsigned long num_bytes;
+	void *sync_handle;
+	enum dsp_stream_state state;
+};
+
+enum dsp_node_state {
+	NODE_ALLOCATED,
+	NODE_CREATED,
+	NODE_RUNNING,
+	NODE_PAUSED,
+	NODE_DONE
+};
+
+struct dsp_node_info {
+	unsigned long cb;
+	struct dsp_ndb_props props;
+	unsigned int priority;
+	enum dsp_node_state state;
+	void *owner;
+	unsigned int num_streams;
+	struct dsp_stream_connect streams[16];
+	unsigned int node_env;
+};
+
+struct dsp_node_attr {
+	unsigned long cb;
+	struct dsp_node_attr_in attr_in;
+	unsigned long inputs;
+	unsigned long outputs;
+	struct dsp_node_info info;
+};
+
+int dsp_open(void);
+
+int dsp_close(int handle);
+
+bool dsp_attach(int handle,
+		unsigned int num,
+		const void *info,
+		void **ret_handle);
+
+bool dsp_detach(int handle,
+		void *proc_handle);
+
+bool dsp_node_allocate(int handle,
+		void *proc_handle,
+		const struct dsp_uuid *node_uuid,
+		const void *cb_data,
+		struct dsp_node_attr_in *attrs,
+		struct dsp_node **ret_node);
+
+bool dsp_node_free(int handle,
+		struct dsp_node *node);
+
+bool dsp_node_connect(int handle,
+		struct dsp_node *node,
+		unsigned int stream,
+		struct dsp_node *other_node,
+		unsigned int other_stream,
+		struct dsp_stream_attr *attrs,
+		void *params);
+
+bool dsp_node_create(int handle,
+		struct dsp_node *node);
+
+bool dsp_node_run(int handle,
+		struct dsp_node *node);
+
+bool dsp_node_terminate(int handle,
+		struct dsp_node *node,
+		unsigned long *status);
+
+bool dsp_node_put_message(int handle,
+		struct dsp_node *node,
+		const struct dsp_msg *message,
+		unsigned int timeout);
+
+bool dsp_node_get_message(int handle,
+		struct dsp_node *node,
+		struct dsp_msg *message,
+		unsigned int timeout);
+
+bool dsp_reserve(int handle,
+		void *proc_handle,
+		unsigned long size,
+		void **addr);
+
+bool dsp_unreserve(int handle,
+		void *proc_handle,
+		void *addr);
+
+bool dsp_map(int handle,
+		void *proc_handle,
+		void *mpu_addr,
+		unsigned long size,
+		void *req_addr,
+		void *ret_map_addr,
+		unsigned long attr);
+
+bool dsp_unmap(int handle,
+		void *proc_handle,
+		void *map_addr);
+
+bool dsp_flush(int handle,
+		void *proc_handle,
+		void *mpu_addr,
+		unsigned long size,
+		unsigned long flags);
+
+bool dsp_invalidate(int handle,
+		void *proc_handle,
+		void *mpu_addr,
+		unsigned long size);
+
+bool dsp_register_notify(int handle,
+		void *proc_handle,
+		unsigned int event_mask,
+		unsigned int notify_type,
+		struct dsp_notification *info);
+
+bool dsp_node_register_notify(int handle,
+		struct dsp_node *node,
+		unsigned int event_mask,
+		unsigned int notify_type,
+		struct dsp_notification *info);
+
+bool dsp_wait_for_events(int handle,
+		struct dsp_notification **notifications,
+		unsigned int count,
+		unsigned int *ret_index,
+		unsigned int timeout);
+
+bool dsp_enum(int handle,
+		unsigned int num,
+		struct dsp_ndb_props *info,
+		size_t info_size,
+		unsigned int *ret_num);
+
+bool dsp_register(int handle,
+		const struct dsp_uuid *uuid,
+		enum dsp_dcd_object_type type,
+		const char *path);
+
+bool dsp_unregister(int handle,
+		const struct dsp_uuid *uuid,
+		enum dsp_dcd_object_type type);
+
+bool dsp_proc_get_info(int handle,
+		void *proc_handle,
+		enum dsp_resource type,
+		struct dsp_info *info,
+		unsigned size);
+
+static inline bool
+dsp_send_message(int handle,
+		struct dsp_node *node,
+		uint32_t cmd,
+		uint32_t arg_1,
+		uint32_t arg_2)
+{
+	struct dsp_msg msg;
+
+	msg.cmd = cmd;
+	msg.arg_1 = arg_1;
+	msg.arg_2 = arg_2;
+
+	return dsp_node_put_message(handle, node, &msg, -1);
+}
+
+bool dsp_node_get_attr(int handle,
+		struct dsp_node *node,
+		struct dsp_node_attr *attr,
+		size_t attr_size);
+
+bool dsp_enum_nodes(int handle,
+		void *proc_handle,
+		void **node_table,
+		unsigned node_table_size,
+		unsigned *num_nodes,
+		unsigned *allocated);
+
+bool dsp_stream_open(int handle,
+		struct dsp_node *node,
+		unsigned int direction,
+		unsigned int index,
+		struct dsp_stream_attr_in *attrin,
+		void *stream);
+
+bool dsp_stream_close(int handle,
+		void *stream);
+
+bool dsp_stream_idle(int handle,
+		void *stream,
+		bool flush);
+
+bool dsp_stream_reclaim(int handle,
+		void *stream,
+		unsigned char **buff,
+		unsigned long *data_size,
+		unsigned long *buff_size,
+		unsigned long *args);
+
+bool dsp_stream_issue(int handle,
+		void *stream,
+		unsigned char *buff,
+		unsigned long data_size,
+		unsigned long buff_size,
+		unsigned long arg);
+
+bool dsp_stream_get_info(int handle,
+		void *stream,
+		struct dsp_stream_info *info,
+		unsigned int size);
+
+bool dsp_stream_allocate_buffers(int handle,
+		void *stream,
+		unsigned int size,
+		unsigned char **buff,
+		unsigned int num_buf);
+
+bool dsp_stream_free_buffers(int handle,
+		void *stream,
+		unsigned char **buff,
+		unsigned int num_buf);
+
+#endif /* DSP_BRIDGE_H */
diff --git a/libavcodec/tidsp/log.c b/libavcodec/tidsp/log.c
new file mode 100644
index 0000000..571ebad
--- /dev/null
+++ b/libavcodec/tidsp/log.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ *
+ * Author: Felipe Contreras <felipe.contreras at gmail.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#define _GNU_SOURCE
+
+#include "log.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#define SYSLOG
+
+#ifdef SYSLOG
+#include <syslog.h>
+#endif
+
+#ifdef SYSLOG
+static inline int
+log_level_to_syslog(unsigned int level)
+{
+	switch (level) {
+	case 0: return LOG_ERR;
+	case 1: return LOG_WARNING;
+	case 2:
+	case 3: return LOG_INFO;
+	default: return LOG_DEBUG;
+	}
+}
+#endif
+
+void pr_helper(unsigned int level,
+		void *object,
+		const char *file,
+		const char *function,
+		unsigned int line,
+		const char *fmt,
+		...)
+{
+	char *tmp;
+	va_list args;
+
+	va_start(args, fmt);
+
+	if (vasprintf(&tmp, fmt, args) < 0)
+		goto leave;
+
+	if (level <= 1) {
+#ifdef SYSLOG
+		syslog(log_level_to_syslog(level), "%s", tmp);
+#endif
+		fprintf(stderr, "%s: %s\n", function, tmp);
+	}
+	else if (level == 2)
+		printf("%s:%s(%u): %s\n", file, function, line, tmp);
+#if defined(DEVEL) || defined(DEBUG)
+	else if (level == 3)
+		printf("%s: %s\n", function, tmp);
+#endif
+#ifdef DEBUG
+	else if (level == 4)
+		printf("%s:%s(%u): %s\n", file, function, line, tmp);
+#endif
+
+	free(tmp);
+
+leave:
+	va_end(args);
+}
diff --git a/libavcodec/tidsp/log.h b/libavcodec/tidsp/log.h
new file mode 100644
index 0000000..b06f501
--- /dev/null
+++ b/libavcodec/tidsp/log.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ *
+ * Author: Felipe Contreras <felipe.contreras at gmail.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#ifndef LOG_H
+#define LOG_H
+
+/* #define DEBUG */
+
+void pr_helper(unsigned int level,
+		void *object,
+		const char *file,
+		const char *function,
+		unsigned int line,
+		const char *fmt,
+		...) __attribute__((format(printf, 6, 7)));
+
+#define pr_base(level, object, ...) pr_helper(level, object, __FILE__, __func__, __LINE__, __VA_ARGS__)
+
+#define pr_err(object, ...) pr_base(0, object, __VA_ARGS__)
+#define pr_warn(object, ...) pr_base(1, object, __VA_ARGS__)
+#define pr_test(object, ...) pr_base(2, object, __VA_ARGS__)
+
+#if !defined(GST_DISABLE_GST_DEBUG) || defined(DEBUG)
+#define pr_info(object, ...) pr_base(3, object, __VA_ARGS__)
+#define pr_debug(object, ...) pr_base(4, object, __VA_ARGS__)
+#else
+#define pr_info(object, ...) ({ if (0) pr_base(3, object, __VA_ARGS__); })
+#define pr_debug(object, ...) ({ if (0) pr_base(4, object, __VA_ARGS__); })
+#endif
+
+#endif /* LOG_H */
diff --git a/libavcodec/tidsp/tidsp.c b/libavcodec/tidsp/tidsp.c
new file mode 100644
index 0000000..a66c158
--- /dev/null
+++ b/libavcodec/tidsp/tidsp.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ *
+ * Author: Felipe Contreras <felipe.contreras at gmail.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#include "tidsp.h"
+#include "dsp_bridge.h"
+#include "dmm_buffer.h"
+#include "log.h"
+
+#include <errno.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct td_context;
+struct td_port;
+struct td_buffer;
+
+/* mpu <-> dsp communication structure */
+struct usn_comm {
+	uint32_t buffer_data;
+	uint32_t buffer_size;
+	uint32_t param_data;
+	uint32_t param_size;
+	uint32_t buffer_len;
+	uint32_t silly_eos;
+	uint32_t silly_buf_state;
+	uint32_t silly_buf_active;
+	uint32_t silly_buf_id;
+	uint32_t reserved;
+	uint32_t msg_virt;
+	uint32_t buffer_virt;
+	uint32_t param_virt;
+	uint32_t silly_out_buffer_index;
+	uint32_t silly_in_buffer_index;
+	uint32_t user_data;
+	uint32_t stream_id;
+};
+
+static struct td_port *td_port_new(unsigned id, int dir)
+{
+	struct td_port *p;
+	p = calloc(1, sizeof(*p));
+
+	p->id = id;
+	p->dir = dir;
+
+	return p;
+}
+
+static void td_port_free(struct td_port *p)
+{
+	if (!p)
+		return;
+
+	free(p->buffers);
+	free(p);
+}
+
+static void td_port_alloc_buffers(struct td_port *p, unsigned nr_buffers)
+{
+	unsigned i;
+	p->nr_buffers = nr_buffers;
+	p->buffers = calloc(nr_buffers, sizeof(*p->buffers));
+	for (i = 0; i < p->nr_buffers; i++)
+		p->buffers[i].port = p;
+}
+
+void td_port_setup_params(struct td_context *ctx,
+		struct td_port *p,
+		size_t size,
+		usn_setup_params_func func)
+{
+	unsigned i;
+	for (i = 0; i < p->nr_buffers; i++) {
+		struct dmm_buffer *mb;
+		mb = dmm_buffer_calloc(ctx->dsp_handle,
+				ctx->proc, size, p->dir);
+		if (func)
+			func(ctx, mb);
+		dmm_buffer_map(mb);
+		p->buffers[i].params = mb;
+	}
+}
+
+struct td_context *td_new(void *client)
+{
+	struct td_context *ctx;
+
+	ctx = calloc(1, sizeof(*ctx));
+	if (!ctx) {
+		pr_err(ctx->client, "failed to allocate");
+		return NULL;
+	}
+
+	ctx->client = client;
+
+	ctx->ports[0] = td_port_new(0, DMA_TO_DEVICE);
+	ctx->ports[1] = td_port_new(1, DMA_FROM_DEVICE);
+
+	return ctx;
+}
+
+void td_free(struct td_context *ctx)
+{
+	if (!ctx)
+		return;
+
+	td_port_free(ctx->ports[1]);
+	td_port_free(ctx->ports[0]);
+
+	free(ctx);
+}
+
+bool td_send_buffer(struct td_context *ctx, struct td_buffer *b)
+{
+	struct usn_comm *msg_data;
+	struct td_port *p;
+	unsigned id = b->port->id;
+
+	pr_debug(ctx->client, "sending %s buffer", id == 0 ? "input" : "output");
+
+	b->data->len = b->data->size;
+	b->used = true;
+
+	p = ctx->ports[id];
+
+	msg_data = b->comm->data;
+
+	if (p->send_cb)
+		p->send_cb(ctx, b);
+
+	if (b->params)
+		dmm_buffer_begin(b->params, b->params->size);
+
+	dmm_buffer_map(b->data);
+
+	memset(msg_data, 0, sizeof(*msg_data));
+
+	msg_data->buffer_data = (uint32_t) b->data->map;
+	msg_data->buffer_size = b->data->size;
+	msg_data->stream_id = id;
+	msg_data->buffer_len = id == 0 ? b->data->len : 0;
+
+	msg_data->user_data = (uint32_t) b->data;
+
+	if (b->params) {
+		msg_data->param_data = (uint32_t) b->params->map;
+		msg_data->param_size = b->params->size;
+		msg_data->param_virt = (uint32_t) b->params;
+	}
+
+	dmm_buffer_begin(b->comm, sizeof(*msg_data));
+
+	dsp_send_message(ctx->dsp_handle, ctx->node,
+			0x0600 | id, (uint32_t) b->comm->map, 0);
+
+	return true;
+}
+
+static void *create_node(struct td_context *ctx)
+{
+	struct dsp_node *node;
+	struct td_codec *codec;
+	int dsp_handle;
+
+	const struct dsp_uuid usn_uuid = { 0x79A3C8B3, 0x95F2, 0x403F, 0x9A, 0x4B,
+		{ 0xCF, 0x80, 0x57, 0x73, 0x05, 0x41 } };
+
+	const struct dsp_uuid ringio_uuid = { 0x47698bfb, 0xa7ee, 0x417e, 0xa6, 0x7a,
+		{ 0x41, 0xc0, 0x27, 0x9e, 0xb8, 0x05 } };
+
+	const struct dsp_uuid conversions_uuid = { 0x722DD0DA, 0xF532, 0x4238, 0xB8, 0x46,
+		{ 0xAB, 0xFF, 0x5D, 0xA4, 0xBA, 0x02 } };
+
+	dsp_handle = ctx->dsp_handle;
+	codec = ctx->codec;
+
+	if (!dsp_register(dsp_handle, &ringio_uuid, DSP_DCD_LIBRARYTYPE, DSP_DIR "ringio.dll64P")) {
+		pr_err(ctx->client, "failed to register ringio node library");
+		return NULL;
+	}
+
+	if (!dsp_register(dsp_handle, &usn_uuid, DSP_DCD_LIBRARYTYPE, DSP_DIR "usn.dll64P")) {
+		pr_err(ctx->client, "failed to register usn node library");
+		return NULL;
+	}
+
+	/* SN_API == 0 doesn't have it, so don't fail */
+	dsp_register(dsp_handle, &conversions_uuid, DSP_DCD_LIBRARYTYPE, DSP_DIR "conversions.dll64P");
+
+	if (!dsp_register(dsp_handle, codec->uuid, DSP_DCD_LIBRARYTYPE, codec->filename)) {
+		pr_err(ctx->client, "failed to register algo node library");
+		return NULL;
+	}
+
+	if (!dsp_register(dsp_handle, codec->uuid, DSP_DCD_NODETYPE, codec->filename)) {
+		pr_err(ctx->client, "failed to register algo node");
+		return NULL;
+	}
+
+	{
+		struct dsp_node_attr_in attrs = {
+			.cb = sizeof(attrs),
+			.priority = 5,
+			.timeout = 1000,
+		};
+		void *arg_data;
+
+		codec->create_args(ctx, &attrs.profile_id, &arg_data);
+
+		if (!dsp_node_allocate(dsp_handle, ctx->proc, codec->uuid, arg_data, &attrs, &node)) {
+			pr_err(ctx->client, "dsp node allocate failed");
+			free(arg_data);
+			return NULL;
+		}
+		free(arg_data);
+	}
+
+	if (!dsp_node_create(dsp_handle, node)) {
+		pr_err(ctx->client, "dsp node create failed");
+		dsp_node_free(dsp_handle, node);
+		return NULL;
+	}
+
+	pr_info(ctx->client, "dsp node created");
+
+	if (codec->setup_params)
+		codec->setup_params(ctx);
+
+	return node;
+}
+
+static void setup_buffers(struct td_context *ctx)
+{
+	struct dmm_buffer *mb;
+	struct td_port *p;
+	unsigned i;
+
+	p = ctx->ports[0];
+	for (i = 0; i < p->nr_buffers; i++) {
+		p->buffers[i].data = mb = dmm_buffer_new(ctx->dsp_handle, ctx->proc, p->dir);
+		mb->alignment = 0;
+		dmm_buffer_allocate(mb, ctx->output_buffer_size);
+	}
+
+	p = ctx->ports[1];
+	for (i = 0; i < p->nr_buffers; i++) {
+		p->buffers[i].data = mb = dmm_buffer_new(ctx->dsp_handle, ctx->proc, p->dir);
+		dmm_buffer_allocate(mb, ctx->output_buffer_size);
+		td_send_buffer(ctx, &p->buffers[i]);
+	}
+}
+
+static bool dsp_start(struct td_context *ctx)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(ctx->ports); i++) {
+		struct td_port *p = ctx->ports[i];
+		unsigned j;
+		for (j = 0; j < p->nr_buffers; j++) {
+			struct td_buffer *b = &p->buffers[j];
+			b->comm = dmm_buffer_new(ctx->dsp_handle, ctx->proc, DMA_BIDIRECTIONAL);
+			dmm_buffer_allocate(b->comm, sizeof(*b->comm));
+			dmm_buffer_map(b->comm);
+		}
+	}
+
+	if (!dsp_node_run(ctx->dsp_handle, ctx->node)) {
+		pr_err(ctx->client, "dsp node run failed");
+		return false;
+	}
+
+	pr_info(ctx->client, "dsp node running");
+
+	ctx->events[0] = calloc(1, sizeof(struct dsp_notification));
+	if (!dsp_node_register_notify(ctx->dsp_handle, ctx->node,
+				DSP_NODEMESSAGEREADY, 1,
+				ctx->events[0]))
+	{
+		pr_err(ctx->client, "failed to register for notifications");
+		return false;
+	}
+
+	ctx->events[1] = calloc(1, sizeof(struct dsp_notification));
+	if (!dsp_register_notify(ctx->dsp_handle, ctx->proc,
+				DSP_MMUFAULT, 1,
+				ctx->events[1]))
+	{
+		pr_err(ctx->client, "failed to register for DSP_MMUFAULT");
+		return false;
+	}
+
+	ctx->events[2] = calloc(1, sizeof(struct dsp_notification));
+	if (!dsp_register_notify(ctx->dsp_handle, ctx->proc,
+				DSP_SYSERROR, 1,
+				ctx->events[2]))
+	{
+		pr_err(ctx->client, "failed to register for DSP_SYSERROR");
+		return false;
+	}
+
+	/* play */
+	dsp_send_message(ctx->dsp_handle, ctx->node, 0x0100, 0, 0);
+
+	setup_buffers(ctx);
+
+	return true;
+}
+
+static bool init_node(struct td_context *ctx)
+{
+	ctx->output_buffer_size = ctx->width * ctx->height * 3 / 2;
+
+	ctx->node = create_node(ctx);
+	if (!ctx->node) {
+		pr_err(ctx->client, "dsp node creation failed");
+		return false;
+	}
+
+	if (!dsp_start(ctx)) {
+		pr_err(ctx->client, "dsp start failed");
+		return false;
+	}
+
+	return true;
+}
+
+bool td_init(struct td_context *ctx)
+{
+	int dsp_handle;
+
+	ctx->dsp_handle = dsp_handle = dsp_open();
+
+	if (dsp_handle < 0) {
+		pr_err(ctx->client, "dsp open failed");
+		goto fail;
+	}
+
+	if (!dsp_attach(dsp_handle, 0, NULL, &ctx->proc)) {
+		pr_err(ctx->client, "dsp attach failed");
+		goto fail;
+	}
+
+	td_port_alloc_buffers(ctx->ports[0], 2);
+	td_port_alloc_buffers(ctx->ports[1], 2);
+
+	if (!init_node(ctx)) {
+		pr_err(ctx->client, "dsp node init failed");
+		goto fail;
+	}
+
+	return true;
+
+fail:
+	if (ctx->proc) {
+		if (!dsp_detach(dsp_handle, ctx->proc))
+			pr_err(ctx->client, "dsp detach failed");
+		ctx->proc = NULL;
+	}
+
+	if (ctx->dsp_handle >= 0) {
+		if (dsp_close(dsp_handle) < 0)
+			pr_err(ctx->client, "dsp close failed");
+		ctx->dsp_handle = -1;
+	}
+
+	return false;
+}
+
+static bool destroy_node(struct td_context *ctx, int dsp_handle, struct dsp_node *node)
+{
+	if (!node)
+		return true;
+
+	if (!dsp_node_free(dsp_handle, node)) {
+		pr_err(ctx->client, "dsp node free failed");
+		return false;
+	}
+
+	pr_info(ctx->client, "dsp node deleted");
+
+	return true;
+}
+
+static bool dsp_stop(struct td_context *ctx)
+{
+	unsigned i;
+
+	if (!ctx->node)
+		return 0;
+
+	dsp_send_message(ctx->dsp_handle, ctx->node, 0x0200, 0, 0);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->ports); i++) {
+		unsigned j;
+		struct td_port *port = ctx->ports[i];
+		for (j = 0; j < port->nr_buffers; j++) {
+			dmm_buffer_free(port->buffers[j].params);
+			port->buffers[j].params = NULL;
+		}
+	}
+
+	if (ctx->alg_ctrl) {
+		dmm_buffer_free(ctx->alg_ctrl);
+		ctx->alg_ctrl = NULL;
+	}
+
+	if (!destroy_node(ctx, ctx->dsp_handle, ctx->node))
+		pr_err(ctx->client, "dsp node destroy failed");
+
+	ctx->node = NULL;
+
+	pr_info(ctx->client, "dsp node terminated");
+
+	return 0;
+}
+
+bool td_close(struct td_context *ctx)
+{
+	bool ret = true;
+	unsigned i;
+
+	dsp_stop(ctx);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->ports); i++) {
+		struct td_port *p = ctx->ports[i];
+		unsigned j;
+		for (j = 0; j < p->nr_buffers; j++) {
+			dmm_buffer_free(p->buffers[j].comm);
+			p->buffers[j].comm = NULL;
+		}
+	}
+
+	if (ctx->proc) {
+		if (!dsp_detach(ctx->dsp_handle, ctx->proc)) {
+			pr_err(ctx->client, "dsp detach failed");
+			ret = false;
+		}
+		ctx->proc = NULL;
+	}
+
+	if (ctx->dsp_handle >= 0) {
+		if (dsp_close(ctx->dsp_handle) < 0) {
+			pr_err(ctx->client, "dsp close failed");
+			ret = false;
+		}
+		ctx->dsp_handle = -1;
+	}
+
+	return ret;
+}
+
+static void got_message(struct td_context *ctx, struct dsp_msg *msg)
+{
+	uint32_t id;
+	uint32_t command_id;
+
+	id = msg->cmd & 0x000000ff;
+	command_id = msg->cmd & 0xffffff00;
+
+	switch (command_id) {
+	case 0x0600: {
+		struct dmm_buffer *mb;
+		struct td_port *p = ctx->ports[id];
+		struct usn_comm *msg_data;
+		struct dmm_buffer *param;
+		unsigned i;
+		struct td_buffer *b = NULL;
+
+		pr_debug(ctx->client, "got %s buffer", id == 0 ? "input" : "output");
+
+		for (i = 0; i < p->nr_buffers; i++) {
+			if (msg->arg_1 == (uint32_t) p->buffers[i].comm->map) {
+				b = &p->buffers[i];
+				break;
+			}
+		}
+
+		if (!b) {
+			pr_err(ctx->client, "bufer mismatch");
+			abort();
+		}
+
+		dmm_buffer_end(b->comm, b->comm->size);
+
+		msg_data = b->comm->data;
+		mb = (void *) msg_data->user_data;
+		mb->len = msg_data->buffer_len;
+
+		if (mb->len > mb->size) {
+			pr_err(ctx->client, "wrong buffer size");
+			abort();
+		}
+
+		dmm_buffer_unmap(mb);
+
+		param = (void *) msg_data->param_virt;
+		if (param)
+			dmm_buffer_end(param, param->size);
+
+		if (p->recv_cb)
+			p->recv_cb(ctx, b);
+
+		b->used = false;
+
+		if (ctx->handle_buffer)
+			ctx->handle_buffer(ctx, b);
+		break;
+	}
+	case 0x0400:
+		pr_debug(ctx->client, "got alg ctrl");
+		dmm_buffer_free(ctx->alg_ctrl);
+		ctx->alg_ctrl = NULL;
+		break;
+	default:
+		pr_warn(ctx->client, "unhandled command: %u\n", command_id);
+		break;
+	}
+}
+
+bool td_get_event(struct td_context *ctx)
+{
+	unsigned index = 0;
+
+	pr_debug(ctx->client, "waiting for events");
+
+	if (!dsp_wait_for_events(ctx->dsp_handle, ctx->events, 3, &index, 100)) {
+		if (errno == ETIME) {
+			pr_warn(ctx->client, "timed out waiting for events\n");
+			return false;
+		}
+		pr_err(ctx->client, "failed waiting for events: %i", errno);
+		return true;
+	}
+
+	if (index == 0) {
+		struct dsp_msg msg;
+		while (true) {
+			if (!dsp_node_get_message(ctx->dsp_handle, ctx->node, &msg, 0))
+				break;
+			pr_debug(ctx->client, "got dsp message: 0x%0x 0x%0x 0x%0x",
+					msg.cmd, msg.arg_1, msg.arg_2);
+			got_message(ctx, &msg);
+		}
+	}
+
+	return true;
+}
diff --git a/libavcodec/tidsp/tidsp.h b/libavcodec/tidsp/tidsp.h
new file mode 100644
index 0000000..de75abb
--- /dev/null
+++ b/libavcodec/tidsp/tidsp.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ *
+ * Author: Felipe Contreras <felipe.contreras at gmail.com>
+ *
+ * This file may be used under the terms of the GNU Lesser General Public
+ * License version 2.1, a copy of which is found in COPYING.LGPLv2.1 included
+ * in the packaging of this file.
+ */
+
+#ifndef TIDSP_H
+#define TIDSP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+struct td_context;
+struct td_buffer;
+struct td_port;
+
+struct dsp_node;
+struct dsp_notification;
+struct dmm_buffer;
+
+typedef void (*td_port_cb_t) (struct td_context *ctx, struct td_buffer *b);
+
+struct td_codec {
+	const struct dsp_uuid *uuid;
+	const char *filename;
+	void (*setup_params)(struct td_context *ctx);
+	void (*create_args)(struct td_context *ctx, unsigned *profile_id, void **arg_data);
+};
+
+struct td_buffer {
+	struct td_port *port;
+	struct dmm_buffer *data;
+	struct dmm_buffer *comm;
+	struct dmm_buffer *params;
+	bool used;
+};
+
+struct td_port {
+	unsigned id;
+	int dir;
+	struct td_buffer *buffers;
+	unsigned nr_buffers;
+	td_port_cb_t send_cb;
+	td_port_cb_t recv_cb;
+};
+
+struct td_context {
+	int dsp_handle;
+	void *proc;
+	struct dsp_node *node;
+	struct td_port *ports[2];
+	struct dmm_buffer *alg_ctrl;
+	struct dsp_notification *events[3];
+	size_t output_buffer_size;
+	void *client;
+	unsigned width, height;
+	void (*handle_buffer) (struct td_context *ctx, struct td_buffer *b);
+	struct td_codec *codec;
+};
+
+struct td_context *td_new(void *client);
+void td_free(struct td_context *ctx);
+bool td_init(struct td_context *ctx);
+bool td_close(struct td_context *ctx);
+bool td_send_buffer(struct td_context *ctx, struct td_buffer *b);
+bool td_get_event(struct td_context *ctx);
+
+typedef void (*usn_setup_params_func)(struct td_context *ctx, struct dmm_buffer *mb);
+
+void td_port_setup_params(struct td_context *ctx, struct td_port *p, size_t size,
+		usn_setup_params_func func);
+
+#endif /* TIDSP_H */
-- 
1.7.2.2




More information about the ffmpeg-devel mailing list