[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