diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | README.txt | 51 | ||||
-rw-r--r-- | common.mk | 62 | ||||
-rw-r--r-- | dce_priv.h | 64 | ||||
-rw-r--r-- | dce_rpc.h | 145 | ||||
-rw-r--r-- | libdce.c | 711 | ||||
-rw-r--r-- | libdce.h | 79 | ||||
-rw-r--r-- | memplugin.h | 81 | ||||
-rw-r--r-- | memplugin_qnx.c | 158 | ||||
-rw-r--r-- | nto/Makefile | 2 | ||||
-rw-r--r-- | nto/README.txt | 1 | ||||
-rw-r--r-- | nto/arm/Makefile | 2 | ||||
-rw-r--r-- | nto/arm/a.le.v7/Makefile | 1 | ||||
-rw-r--r-- | nto/arm/so.le.v7/Makefile | 1 | ||||
-rw-r--r-- | nto/qconf-override.mk | 9 | ||||
-rw-r--r-- | test_qnx/Makefile | 2 | ||||
-rw-r--r-- | test_qnx/arm/Makefile | 8 | ||||
-rw-r--r-- | test_qnx/arm/le.v7/Makefile | 1 | ||||
-rw-r--r-- | test_qnx/common.mk | 50 | ||||
-rw-r--r-- | test_qnx/dce_test.c | 1437 | ||||
-rw-r--r-- | test_qnx/dce_test.use | 38 |
21 files changed, 2906 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..18dffdd --- /dev/null +++ b/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | LIST=libdce | ||
2 | LATE_DIRS=test_qnx | ||
3 | include recurse.mk | ||
diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..05996e8 --- /dev/null +++ b/README.txt | |||
@@ -0,0 +1,51 @@ | |||
1 | ## Building LIBDCE for QNX ## | ||
2 | |||
3 | Exporting QNX variables: | ||
4 | export QNX_ROOT=/opt/qnx650 | ||
5 | export QNX_HOST=${QNX_ROOT}/host/linux/x86 | ||
6 | export LD_LIBRARY_PATH=${QNX_HOST}/usr/lib | ||
7 | export QNX_TARGET=${QNX_ROOT}/target/qnx6 | ||
8 | export MAKEFLAGS=-I${QNX_TARGET}/usr/include | ||
9 | export QNX_CONFIGURATION=/etc/qnx | ||
10 | export QNX_JAVAHOME=${QNX_ROOT}/_jvm | ||
11 | export PATH=${QNX_HOST}/usr/bin:${PATH}:${QNX_CONFIGURATION}/bin | ||
12 | export QNX_USERNAME=<registered email-id at QNX> //not important | ||
13 | eval `qconfig -n "QNX Software Development Platform 6.5.0" -e` | ||
14 | |||
15 | If previous eval doesn't work, that is it doesn't output: | ||
16 | export QNX_HOST="/opt/qnx650/host/linux/x86"; | ||
17 | export QNX_TARGET="/opt/qnx650/target/qnx6"; | ||
18 | export PATH="/opt/qnx650/host/linux/x86/usr/bin:/opt/qnx650/host/linux/x86/bin:/opt/qnx650/host/ | ||
19 | linux/x86/sbin:/opt/qnx650/host/linux/x86/usr/sbin:/opt/qnx650/host/linux/x86/usr/photon/appbuilder: | ||
20 | /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/etc/qnx/bin:/etc/qnx/bin: | ||
21 | /opt/qnx650:/etc/qnx/bin:/etc/qnx/bin:/etc/qnx/bin:/etc/qnx/bin"; | ||
22 | export LD_LIBRARY_PATH="/opt/qnx650/host/linux/x86/usr/lib"; | ||
23 | export MAKEFLAGS="-I/opt/qnx650/target/qnx6/usr/include"; | ||
24 | |||
25 | then try : /opt/qnx650/host/linux/x86/usr/bin/qconfig -n "QNX Software Development Platform 6.5.0" -e | ||
26 | |||
27 | Exporting LIBDCE variables: | ||
28 | export TITOOLSROOT=<path to XDC, XDAIS> | ||
29 | export TIVIDEOTOOLSROOT=<path to CE, FC> | ||
30 | export IPCHEADERS=<path to IPC Headers> | ||
31 | export INSTALL_ROOT=<path for copying output binaries> | ||
32 | export QCONF_OVERRIDE=<absolute path to libdce/nto/qconf-override.mk> | ||
33 | export IVAHDCODECS=<path to ipumm/extrel/ti/ivahd_codecs> | ||
34 | |||
35 | For IPCHEADERS - Headers should be at: | ||
36 | $(IPCHEADERS)/usr/include/memmgr | ||
37 | $(IPCHEADERS)/usr/include/ti/syslink/ | ||
38 | $(IPCHEADERS)/usr/include/ti/ipc/mm | ||
39 | $(IPCHEADERS)/usr/include/ti/shmemallocator | ||
40 | $(IPCHEADERS)/usr/include/ | ||
41 | |||
42 | Building: | ||
43 | make install | ||
44 | |||
45 | Clean: | ||
46 | make clean | ||
47 | |||
48 | Location of Binaries: | ||
49 | INSTALL_ROOT/armle-v7/usr/lib/libdce.so | ||
50 | INSTALL_ROOT/armle-v7/usr/lib/libdce.so.1 | ||
51 | INSTALL_ROOT/armle-v7/bin/dce_test | ||
diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..b430901 --- /dev/null +++ b/common.mk | |||
@@ -0,0 +1,62 @@ | |||
1 | ###################### QNX DCE Build Config ####################### | ||
2 | |||
3 | #### Include qconfig.mk | ||
4 | ifndef QCONFIG | ||
5 | QCONFIG=qconfig.mk | ||
6 | endif | ||
7 | |||
8 | include $(QCONFIG) | ||
9 | |||
10 | #### Overriding qrules.mk macros before including qtargets.mk | ||
11 | |||
12 | # Flags to add to the C compiler command line | ||
13 | CCFLAGS+=-O2 -Dxdc_target_types__=qnx/targets/arm/std.h -DBUILDOS_QNX=1 | ||
14 | |||
15 | # To get final library name as "libdce". Needed as project name is not dce | ||
16 | NAME=dce | ||
17 | |||
18 | ### Add files to be included for Build | ||
19 | TITOOLSROOT ?= /usr/local | ||
20 | TIVIDEOTOOLSROOT ?= $(TITOOLSROOT) | ||
21 | # Different tool versions can easily be programmed by defining below variables | ||
22 | # in your environment. | ||
23 | CEVERSION ?= codec_engine_3_23_00_07 | ||
24 | FCVERSION ?= framework_components_3_23_03_17 | ||
25 | XDAISVERSION ?= xdais_7_23_00_06 | ||
26 | XDCVERSION ?= xdctools_3_25_00_48 | ||
27 | IPCHEADERS ?= $(INSTALL_ROOT_nto) | ||
28 | |||
29 | # Generate the full package paths for tools | ||
30 | CEPROD = $(TIVIDEOTOOLSROOT)/$(CEVERSION) | ||
31 | FCPROD = $(TIVIDEOTOOLSROOT)/$(FCVERSION) | ||
32 | XDAISPROD = $(TITOOLSROOT)/$(XDAISVERSION) | ||
33 | XDCPROD = $(TITOOLSROOT)/$(XDCVERSION) | ||
34 | |||
35 | EXTRA_INCVPATH += $(CEPROD)/packages | ||
36 | EXTRA_INCVPATH += $(FCPROD)/packages | ||
37 | EXTRA_INCVPATH += $(XDAISPROD)/packages | ||
38 | EXTRA_INCVPATH += $(XDCPROD)/packages | ||
39 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/memmgr | ||
40 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/ti/syslink/ | ||
41 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/ti/ipc/mm | ||
42 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/ti/shmemallocator | ||
43 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/ | ||
44 | |||
45 | # Include IPC libraries | ||
46 | LIBS += memmgr mmrpc sharedmemallocatorS | ||
47 | |||
48 | # Include qmacros.mk | ||
49 | include $(MKFILES_ROOT)/qmacros.mk | ||
50 | |||
51 | #### Overriding qtargets.mk macros before including qtargets.mk | ||
52 | INSTALLDIR=usr/lib | ||
53 | INSTALLDIR+=usr/local | ||
54 | |||
55 | define PINFO | ||
56 | PINFO DESCRIPTION = libdce codec | ||
57 | endef | ||
58 | |||
59 | #### Include qtargets.mk, it internally includes qrules.mk | ||
60 | include $(MKFILES_ROOT)/qtargets.mk | ||
61 | |||
62 | #### Post-set make macros after including qtargets.mk (if-any) | ||
diff --git a/dce_priv.h b/dce_priv.h new file mode 100644 index 0000000..dea43d4 --- /dev/null +++ b/dce_priv.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | #ifndef __DCE_PRIV_H__ | ||
34 | #define __DCE_PRIV_H__ | ||
35 | |||
36 | #include <sys/slog.h> | ||
37 | |||
38 | /********************* MACROS ************************/ | ||
39 | /***************** TRACE MACROS *********************/ | ||
40 | /* Need to make it OS specific and support different trace levels */ | ||
41 | #define ERROR(FMT, ...) do { \ | ||
42 | slogf(42, _SLOG_INFO, "%s:%d:\t%s\terror: " FMT, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ | ||
43 | } while( 0 ) | ||
44 | #define DEBUG(FMT, ...) do { \ | ||
45 | slogf(42, _SLOG_DEBUG2, "%s:%d:\t%s\tdebug: " FMT, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ | ||
46 | } while( 0 ) | ||
47 | |||
48 | |||
49 | /***************** ASSERT MACROS *********************/ | ||
50 | #define _ASSERT_AND_EXECUTE(_COND_, _ERRORCODE_, _EXPR_) do { \ | ||
51 | if( !(_COND_)) { eError = _ERRORCODE_; \ | ||
52 | ERROR("Failed %s error val %d", # _COND_, _ERRORCODE_); \ | ||
53 | _EXPR_; \ | ||
54 | goto EXIT; } \ | ||
55 | } while( 0 ) | ||
56 | |||
57 | #define _ASSERT(_COND_, _ERRORCODE_) do { \ | ||
58 | if( !(_COND_)) { eError = _ERRORCODE_; \ | ||
59 | ERROR("Failed %s error val %d", # _COND_, _ERRORCODE_); \ | ||
60 | goto EXIT; } \ | ||
61 | } while( 0 ) | ||
62 | |||
63 | #endif /* __DCE_PRIV_H__ */ | ||
64 | |||
diff --git a/dce_rpc.h b/dce_rpc.h new file mode 100644 index 0000000..8082d76 --- /dev/null +++ b/dce_rpc.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | #ifndef __DCE_RPC_H__ | ||
34 | #define __DCE_RPC_H__ | ||
35 | |||
36 | /* RPC layer types.. these define the payload of messages between IPUMM | ||
37 | * and MPU. This should be kept in sync between firmware build and | ||
38 | * driver. | ||
39 | * | ||
40 | * TODO: xxx_control(XDM_GETVERSION) is a bit awkward to deal with, because | ||
41 | * this seems to be the one special case where status->data is used.. | ||
42 | * possibly we should define a special ioctl and msg to handle this case. | ||
43 | */ | ||
44 | |||
45 | #define DCE_DEVICE_NAME "rpmsg-dce" | ||
46 | |||
47 | /* Message-Ids: | ||
48 | */ | ||
49 | //#define DCE_RPC_CONNECT (0x80000000 | 00) Connect not needed anymore. | ||
50 | typedef enum dce_rpc_call { | ||
51 | DCE_RPC_ENGINE_OPEN = 0, | ||
52 | DCE_RPC_ENGINE_CLOSE, | ||
53 | DCE_RPC_CODEC_CREATE, | ||
54 | DCE_RPC_CODEC_CONTROL, | ||
55 | DCE_RPC_CODEC_GET_VERSION, | ||
56 | DCE_RPC_CODEC_PROCESS, | ||
57 | DCE_RPC_CODEC_DELETE | ||
58 | } dce_rpc_call; | ||
59 | |||
60 | |||
61 | typedef enum dce_codec_type { | ||
62 | OMAP_DCE_VIDENC2 = 1, | ||
63 | OMAP_DCE_VIDDEC3 = 2 | ||
64 | } dce_codec_type; | ||
65 | |||
66 | /* Structures of RPC */ | ||
67 | typedef struct dce_connect { | ||
68 | uint32_t chipset_id; | ||
69 | uint32_t debug; | ||
70 | } dce_connect; | ||
71 | |||
72 | typedef struct dce_engine_open { | ||
73 | char name[32]; /* engine name (in) */ | ||
74 | Engine_Error error_code; /* error code (out) */ | ||
75 | Engine_Handle eng_handle; /* engine handle (out) */ | ||
76 | } dce_engine_open; | ||
77 | |||
78 | typedef struct dce_engine_close { | ||
79 | Engine_Handle eng_handle; /* engine handle (in) */ | ||
80 | } dce_engine_close; | ||
81 | |||
82 | typedef struct dce_codec_create { | ||
83 | Engine_Handle engine; | ||
84 | char codec_name[32]; | ||
85 | void *static_params; | ||
86 | dce_codec_type codec_id; | ||
87 | void *codec_handle; | ||
88 | } dce_codec_create; | ||
89 | |||
90 | typedef struct dce_codec_control { | ||
91 | void *codec_handle; | ||
92 | uint32_t cmd_id; | ||
93 | void *dyn_params; | ||
94 | void *status; | ||
95 | dce_codec_type codec_id; | ||
96 | int32_t result; | ||
97 | } dce_codec_control; | ||
98 | |||
99 | typedef struct dce_codec_get_version { | ||
100 | void *codec_handle; | ||
101 | void *dyn_params; | ||
102 | void *status; | ||
103 | void *version; | ||
104 | dce_codec_type codec_id; | ||
105 | int32_t result; | ||
106 | } dce_codec_get_version; | ||
107 | |||
108 | typedef struct dce_codec_delete { | ||
109 | void *codec_handle; | ||
110 | dce_codec_type codec_id; | ||
111 | } dce_codec_delete; | ||
112 | |||
113 | /* ---------------------- For GLP DCE -----------------------------*/ | ||
114 | /* NOTE: CODEC_PROCESS does somewhat more than the other ioctls, in that it | ||
115 | * handles buffer mapping/unmapping. So the inBufs/outBufs are copied inline | ||
116 | * (with translated addresses in the copy sent inline with codec_process_req). | ||
117 | * Since we need the inputID from inArgs, and it is a small struct, it is also | ||
118 | * copied inline. | ||
119 | * | ||
120 | * Therefore, the variable length data[] section has the format: | ||
121 | * uint8_t reloc[reloc_length * 4]; | ||
122 | * uint8_t inargs[in_args_length * 4]; | ||
123 | * uint8_t outbufs[in_bufs_length * 4]; | ||
124 | * uint8_t inbufs[in_bufs_length * 4]; | ||
125 | */ | ||
126 | |||
127 | #define MAX_INPUT_BUF 2 // Need to confirm for interlaced YUVs for Encoders | ||
128 | #define MAX_OUTPUT_BUF 2 | ||
129 | #define MAX_TOTAl_BUF (MAX_INPUT_BUF + MAX_OUTPUT_BUF) | ||
130 | |||
131 | /* Struct to be used if approach [3] of Mmrpc call is followed */ | ||
132 | typedef struct dce_codec_process { | ||
133 | void *codec_handle; | ||
134 | void *inBufs; | ||
135 | void *outBufs; | ||
136 | void *inArgs; | ||
137 | void *outArgs; | ||
138 | int32_t input_Buf[MAX_INPUT_BUF]; | ||
139 | int32_t output_Buf[MAX_OUTPUT_BUF]; | ||
140 | dce_codec_type codec_id; | ||
141 | int32_t result; | ||
142 | } dce_codec_process; | ||
143 | |||
144 | #endif /* __DCE_RPC_H__ */ | ||
145 | |||
diff --git a/libdce.c b/libdce.c new file mode 100644 index 0000000..bffebac --- /dev/null +++ b/libdce.c | |||
@@ -0,0 +1,711 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | ********************************** Notes ****************************************** | ||
35 | ******* | ||
36 | ********************************* Memory ***************************************** | ||
37 | * | ||
38 | ******* | ||
39 | ********************************* IPC 3.x ***************************************** | ||
40 | * Two approaches are followed for IPC MmRpc calls. | ||
41 | * 1. All the parameters which need to be sent and received to/from IPU are coupled in a struct | ||
42 | * allocated from Shared Memory. Only the adrress of the struct is passed to MmRpc | ||
43 | * as a pointer argument. This approach is useful as MmRpc in some cases to avoid multiple | ||
44 | * translations. | ||
45 | * This approach is followed for : | ||
46 | * Engine_open(), Engine_close(), create(), control(), delete() | ||
47 | * For understanding refer to the Mmrpc_test.c in IPC 3.x | ||
48 | * 2. All the parameters which need to be sent are given as separate arguments to | ||
49 | * MmRpc. This appraoch is needed when you need to translate an address which is | ||
50 | * ofsetted from a pointer which in itself needs to be translated. | ||
51 | * This apporach is followed for : process() | ||
52 | * For understanding, take the example of inbufs argument in process call(). Inbufs | ||
53 | * allocated in Shared memory and needs to be translated, has the address of Input | ||
54 | * buffer (allocated from Tiler). It is not possible to give the Input buffer as an argument | ||
55 | * to Mmrpc for translation until inbufs is given as a parameter to Mmrpc. Therefore inbuf | ||
56 | * can't be populated inside another Shared memory struct. | ||
57 | * 3. This approach is a workaround to use approach [1] by solving the issue posed by [2]. | ||
58 | * This approach is followed for : get_version() | ||
59 | * Taking the example of inbufs to explain, the Input buffer address will be one of the | ||
60 | * parameters of the struct (explained in [1]) along with inbufs address. Therefore the | ||
61 | * Input buffer address will get translated here. At the IPU, this address needs to be | ||
62 | * copied back to inbufs. | ||
63 | ********************************************************************************* | ||
64 | */ | ||
65 | |||
66 | #include <stdlib.h> | ||
67 | #include <string.h> | ||
68 | #include <stdio.h> | ||
69 | #include <pthread.h> | ||
70 | #include <errno.h> | ||
71 | |||
72 | #include <xdc/std.h> | ||
73 | |||
74 | #if defined(BUILDOS_GLP) | ||
75 | #include <xf86drm.h> | ||
76 | #include <omap_drm.h> | ||
77 | #include <omap_dce.h> | ||
78 | #include <omap_drmif.h> | ||
79 | #endif /* BUILDOS_GLP */ | ||
80 | |||
81 | /* IPC Headers */ | ||
82 | #include <MmRpc.h> | ||
83 | |||
84 | /*DCE Headers */ | ||
85 | #include "libdce.h" | ||
86 | #include "dce_rpc.h" | ||
87 | #include "dce_priv.h" | ||
88 | #include "memplugin.h" | ||
89 | |||
90 | |||
91 | #if defined(BUILDOS_GLP) | ||
92 | #ifdef GLP_X11 | ||
93 | int dce_auth_x11(int *fd); | ||
94 | #endif /* GLP_X11 */ | ||
95 | #ifdef GLP_WAYLAND | ||
96 | int dce_auth_wayland(int *fd); | ||
97 | #endif /* GLP_WAYLAND */ | ||
98 | |||
99 | static int fd = -1; | ||
100 | static struct omap_device *dev; | ||
101 | static int ioctl_base; | ||
102 | #define CMD(name) (ioctl_base + DRM_OMAP_DCE_##name) | ||
103 | |||
104 | uint32_t dce_debug = 3; | ||
105 | #endif /* BUILDOS_GLP */ | ||
106 | |||
107 | |||
108 | /********************* GLOBALS ***********************/ | ||
109 | /* Hande used for Remote Communication */ | ||
110 | static MmRpc_Handle MmRpcHandle = NULL; | ||
111 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | ||
112 | static int count = 0; | ||
113 | |||
114 | |||
115 | /****************** INLINE FUNCTIONS ********************/ | ||
116 | |||
117 | static inline void Fill_MmRpc_fxnCtx(MmRpc_FxnCtx *fxnCtx, int fxn_id, int num_params, int num_xlts, MmRpc_Xlt *xltAry) | ||
118 | { | ||
119 | fxnCtx->fxn_id = fxn_id; | ||
120 | fxnCtx->num_params = num_params; | ||
121 | fxnCtx->num_xlts = num_xlts; | ||
122 | fxnCtx->xltAry = xltAry; | ||
123 | } | ||
124 | |||
125 | static inline void Fill_MmRpc_fxnCtx_Ptr_Params(MmRpc_Param *mmrpc_params, int size, void *addr, void *handle) | ||
126 | { | ||
127 | mmrpc_params->type = MmRpc_ParamType_Ptr; | ||
128 | mmrpc_params->param.ptr.size = size; | ||
129 | mmrpc_params->param.ptr.addr = (size_t)addr; | ||
130 | mmrpc_params->param.ptr.handle = (size_t)handle; | ||
131 | } | ||
132 | |||
133 | static inline void Fill_MmRpc_fxnCtx_Scalar_Params(MmRpc_Param *mmrpc_params, int size, int data) | ||
134 | { | ||
135 | mmrpc_params->type = MmRpc_ParamType_Scalar; | ||
136 | mmrpc_params->param.scalar.size = size; | ||
137 | mmrpc_params->param.scalar.data = (size_t)data; | ||
138 | } | ||
139 | |||
140 | static inline void Fill_MmRpc_fxnCtx_Xlt_Array(MmRpc_Xlt *mmrpc_xlt, int index, int32_t base, int32_t addr, void *handle) | ||
141 | { | ||
142 | /* index : index of params filled in FxnCtx */ | ||
143 | /* base : user Virtual Address as per definition in MmRpc and not base from where offset is calculated */ | ||
144 | /* offset : calculated from address of index */ | ||
145 | mmrpc_xlt->index = index; | ||
146 | mmrpc_xlt->offset = MmRpc_OFFSET(base, addr); | ||
147 | mmrpc_xlt->base = (size_t)addr; | ||
148 | mmrpc_xlt->handle = (size_t)handle; | ||
149 | } | ||
150 | |||
151 | /************************ FUNCTIONS **************************/ | ||
152 | /* Interface for QNX for parameter buffer allocation */ | ||
153 | /* These interfaces are implemented to maintain Backward Compatability */ | ||
154 | void *dce_alloc(int sz) | ||
155 | { | ||
156 | return (memplugin_alloc(sz, 0, TILER_1D_BUFFER)); | ||
157 | } | ||
158 | |||
159 | void dce_free(void *ptr) | ||
160 | { | ||
161 | memplugin_free(ptr, TILER_1D_BUFFER); | ||
162 | } | ||
163 | |||
164 | /*************** Startup/Shutdown Functions ***********************/ | ||
165 | static int dce_init(void) | ||
166 | { | ||
167 | dce_error_status eError = DCE_EOK; | ||
168 | MmRpc_Params args; | ||
169 | |||
170 | printf(" >> dce_init\n"); | ||
171 | |||
172 | pthread_mutex_lock(&mutex); | ||
173 | |||
174 | count++; | ||
175 | /* Check if already Initialized */ | ||
176 | _ASSERT(count == 1, DCE_EOK); | ||
177 | |||
178 | /* Create remote server insance */ | ||
179 | MmRpc_Params_init(&args); | ||
180 | |||
181 | eError = MmRpc_create(DCE_DEVICE_NAME, &args, &MmRpcHandle); | ||
182 | |||
183 | _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CREATE_FAIL, count--); | ||
184 | |||
185 | printf("open(/dev/" DCE_DEVICE_NAME ") -> 0x%x\n", (int)MmRpcHandle); | ||
186 | EXIT: | ||
187 | pthread_mutex_unlock(&mutex); | ||
188 | return (eError); | ||
189 | } | ||
190 | |||
191 | static void dce_deinit(void) | ||
192 | { | ||
193 | pthread_mutex_lock(&mutex); | ||
194 | |||
195 | count--; | ||
196 | if( count > 0 ) { | ||
197 | goto EXIT; | ||
198 | } | ||
199 | |||
200 | if( MmRpcHandle != NULL ) { | ||
201 | MmRpc_delete(&MmRpcHandle); | ||
202 | } | ||
203 | MmRpcHandle = NULL; | ||
204 | EXIT: | ||
205 | pthread_mutex_unlock(&mutex); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | /*===============================================================*/ | ||
210 | /** Engine_open : Open Codec Engine. | ||
211 | * | ||
212 | * @ param attrs [in] : Engine Attributes. This param is not passed to Remote core. | ||
213 | * @ param name [in] : Name of Encoder or Decoder codec. | ||
214 | * @ param ec [out] : Error returned by Codec Engine. | ||
215 | * @ return : Codec Engine Handle is returned to be used to create codec. | ||
216 | * In case of error, NULL is returned as Engine Handle. | ||
217 | */ | ||
218 | Engine_Handle Engine_open(String name, Engine_Attrs *attrs, Engine_Error *ec) | ||
219 | { | ||
220 | MmRpc_FxnCtx fxnCtx; | ||
221 | int32_t fxnRet; | ||
222 | dce_error_status eError = DCE_EOK; | ||
223 | dce_engine_open *engine_open_msg = NULL; | ||
224 | Engine_Handle eng_handle = NULL; | ||
225 | |||
226 | _ASSERT(name != '\0', DCE_EINVALID_INPUT); | ||
227 | _ASSERT(ec != NULL, DCE_EINVALID_INPUT); | ||
228 | |||
229 | /* Initialize DCE and IPC. In case of Error Deinitialize them */ | ||
230 | _ASSERT_AND_EXECUTE(dce_init() == DCE_EOK, DCE_EIPC_CREATE_FAIL, dce_deinit()); | ||
231 | |||
232 | printf(">> Engine_open Params::name = %s size = %d\n", name, strlen(name)); | ||
233 | /* Allocate Shared memory for the engine_open rpc msg structure*/ | ||
234 | /* Tiler Memory preferred for now for First level testing */ | ||
235 | engine_open_msg = memplugin_alloc(sizeof(dce_engine_open), 0, TILER_1D_BUFFER); | ||
236 | |||
237 | _ASSERT_AND_EXECUTE(engine_open_msg != NULL, DCE_EOUT_OF_MEMORY, eng_handle = NULL); | ||
238 | |||
239 | /* Populating the msg structure with all the params */ | ||
240 | /* Populating all params into a struct avoid individual address translations of name, ec */ | ||
241 | strncpy(engine_open_msg->name, name, strlen(name)); | ||
242 | engine_open_msg->eng_handle = NULL; | ||
243 | |||
244 | /* Marshall function arguments into the send buffer */ | ||
245 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_ENGINE_OPEN, 1, 0, NULL); | ||
246 | Fill_MmRpc_fxnCtx_Ptr_Params(fxnCtx.params, sizeof(dce_engine_open), engine_open_msg, NULL); | ||
247 | |||
248 | /* Invoke the Remote function through MmRpc */ | ||
249 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
250 | |||
251 | /* In case of Error, the Application will get a NULL Engine Handle */ | ||
252 | _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CALL_FAIL, eng_handle = NULL); | ||
253 | |||
254 | /* Populate return arguments */ | ||
255 | eng_handle = engine_open_msg->eng_handle; | ||
256 | ec[0] = engine_open_msg->error_code; | ||
257 | |||
258 | EXIT: | ||
259 | memplugin_free(engine_open_msg, TILER_1D_BUFFER); | ||
260 | |||
261 | return (eng_handle); | ||
262 | } | ||
263 | |||
264 | /*===============================================================*/ | ||
265 | /** Engine_close : Close Engine. | ||
266 | * | ||
267 | * @ param engine [in] : Engine Handle obtained in Engine_open() call. | ||
268 | */ | ||
269 | Void Engine_close(Engine_Handle engine) | ||
270 | { | ||
271 | MmRpc_FxnCtx fxnCtx; | ||
272 | int32_t fxnRet; | ||
273 | dce_error_status eError = DCE_EOK; | ||
274 | dce_engine_close *engine_close_msg = NULL; | ||
275 | |||
276 | _ASSERT(engine != NULL, DCE_EINVALID_INPUT); | ||
277 | |||
278 | /* Allocate Shared/Tiler memory for the engine_close rpc msg structure*/ | ||
279 | engine_close_msg = memplugin_alloc(sizeof(dce_engine_close), 0, TILER_1D_BUFFER); | ||
280 | |||
281 | _ASSERT(engine_close_msg != NULL, DCE_EOUT_OF_MEMORY); | ||
282 | |||
283 | /* Populating the msg structure with all the params */ | ||
284 | engine_close_msg->eng_handle = engine; | ||
285 | |||
286 | /* Marshall function arguments into the send buffer */ | ||
287 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_ENGINE_CLOSE, 1, 0, NULL); | ||
288 | Fill_MmRpc_fxnCtx_Ptr_Params(fxnCtx.params, sizeof(dce_engine_close), engine_close_msg, NULL); | ||
289 | |||
290 | /* Invoke the Remote function through MmRpc */ | ||
291 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
292 | |||
293 | _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); | ||
294 | |||
295 | EXIT: | ||
296 | memplugin_free(engine_close_msg, TILER_1D_BUFFER); | ||
297 | |||
298 | dce_deinit(); | ||
299 | return; | ||
300 | } | ||
301 | |||
302 | /*===============================================================*/ | ||
303 | /** Functions create(), control(), get_version(), process(), delete() are common codec | ||
304 | * glue function signatures which are same for both encoder and decoder | ||
305 | */ | ||
306 | /*===============================================================*/ | ||
307 | /** create : Create Encoder/Decoder codec. | ||
308 | * | ||
309 | * @ param engine [in] : Engine Handle obtained in Engine_open() call. | ||
310 | * @ param name [in] : Name of Encoder or Decoder codec. | ||
311 | * @ param params [in] : Static parameters of codec. | ||
312 | * @ param codec_id [in] : To differentiate between Encoder and Decoder codecs. | ||
313 | * @ return : Codec Handle is returned to be used for control, process, delete calls. | ||
314 | * In case of error, NULL is returned. | ||
315 | */ | ||
316 | static void *create(Engine_Handle engine, String name, void *params, dce_codec_type codec_id) | ||
317 | { | ||
318 | MmRpc_FxnCtx fxnCtx; | ||
319 | MmRpc_Xlt xltAry; | ||
320 | int32_t fxnRet; | ||
321 | dce_error_status eError = DCE_EOK; | ||
322 | dce_codec_create *codec_create_msg = NULL; | ||
323 | void *codec_handle = NULL; | ||
324 | |||
325 | _ASSERT(name != '\0', DCE_EINVALID_INPUT); | ||
326 | _ASSERT(engine != NULL, DCE_EINVALID_INPUT); | ||
327 | _ASSERT(params != NULL, DCE_EINVALID_INPUT); | ||
328 | |||
329 | /* Allocate Shared/Tiler memory for the codec_create rpc msg structure*/ | ||
330 | codec_create_msg = memplugin_alloc(sizeof(dce_codec_create), 0, TILER_1D_BUFFER); | ||
331 | |||
332 | _ASSERT_AND_EXECUTE(codec_create_msg != NULL, DCE_EOUT_OF_MEMORY, codec_handle = NULL); | ||
333 | |||
334 | /* Populating the msg structure with all the params */ | ||
335 | codec_create_msg->engine = engine; | ||
336 | strncpy(codec_create_msg->codec_name, name, strlen(name)); | ||
337 | codec_create_msg->codec_id = codec_id; | ||
338 | codec_create_msg->codec_handle = NULL; | ||
339 | codec_create_msg->static_params = params; | ||
340 | |||
341 | /* Marshall function arguments into the send buffer */ | ||
342 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_CREATE, 1, 1, &xltAry); | ||
343 | Fill_MmRpc_fxnCtx_Ptr_Params(&(fxnCtx.params[0]), sizeof(dce_codec_create), codec_create_msg, NULL); | ||
344 | |||
345 | /* Mention the virtual pointers that need translation */ | ||
346 | /* Allocations through dce_alloc need translation */ | ||
347 | /* In this case the static params buffer need translation */ | ||
348 | Fill_MmRpc_fxnCtx_Xlt_Array(fxnCtx.xltAry, 0, (int32_t)codec_create_msg, (int32_t)&(codec_create_msg->static_params), NULL); | ||
349 | |||
350 | /* Invoke the Remote function through MmRpc */ | ||
351 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
352 | |||
353 | /* In case of Error, the Application will get a NULL Codec Handle */ | ||
354 | _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CALL_FAIL, codec_handle = NULL); | ||
355 | |||
356 | codec_handle = codec_create_msg->codec_handle; | ||
357 | |||
358 | EXIT: | ||
359 | memplugin_free(codec_create_msg, TILER_1D_BUFFER); | ||
360 | |||
361 | return (codec_handle); | ||
362 | } | ||
363 | |||
364 | /*===============================================================*/ | ||
365 | /** control : Codec control call. | ||
366 | * | ||
367 | * @ param codec [in] : Codec Handle obtained in create() call. | ||
368 | * @ param id [in] : Command id for XDM control operation. | ||
369 | * @ param dynParams [in] : Dynamic input parameters to Codec. | ||
370 | * @ param status [out] : Codec returned status parameters. | ||
371 | * @ param codec_id [in] : To differentiate between Encoder and Decoder codecs. | ||
372 | * @ return : Status of control() call is returned. | ||
373 | * #XDM_EOK [0] : Success. | ||
374 | * #XDM_EFAIL [-1] : Failure. | ||
375 | * #IPC_FAIL [-2] : MmRpc Call failed. | ||
376 | * #XDM_EUNSUPPORTED [-3] : Unsupported request. | ||
377 | * #OUT_OF_MEMORY [-4] : Out of Shared Memory. | ||
378 | */ | ||
379 | static XDAS_Int32 control(void *codec, int id, void *dynParams, void *status, dce_codec_type codec_id) | ||
380 | { | ||
381 | MmRpc_FxnCtx fxnCtx; | ||
382 | MmRpc_Xlt xltAry[2]; | ||
383 | int32_t fxnRet; | ||
384 | dce_error_status eError = DCE_EOK; | ||
385 | dce_codec_control *codec_control_msg = NULL; | ||
386 | |||
387 | _ASSERT(codec != NULL, DCE_EINVALID_INPUT); | ||
388 | _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT); | ||
389 | _ASSERT(status != NULL, DCE_EINVALID_INPUT); | ||
390 | |||
391 | /* Allocate Shared/Tiler memory for the codec_control rpc msg structure*/ | ||
392 | codec_control_msg = memplugin_alloc(sizeof(dce_codec_control), 0, TILER_1D_BUFFER); | ||
393 | |||
394 | _ASSERT(codec_control_msg != NULL, DCE_EOUT_OF_MEMORY); | ||
395 | |||
396 | /* Populating the msg structure with all the params */ | ||
397 | codec_control_msg->codec_handle = codec; | ||
398 | codec_control_msg->cmd_id = id; | ||
399 | codec_control_msg->codec_id = codec_id; | ||
400 | codec_control_msg->dyn_params = dynParams; | ||
401 | codec_control_msg->status = status; | ||
402 | |||
403 | /* Marshall function arguments into the send buffer */ | ||
404 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_CONTROL, 1, 2, xltAry); | ||
405 | Fill_MmRpc_fxnCtx_Ptr_Params(fxnCtx.params, sizeof(dce_codec_control), codec_control_msg, NULL); | ||
406 | |||
407 | /* Dynamic and status params buffer need translation */ | ||
408 | Fill_MmRpc_fxnCtx_Xlt_Array(fxnCtx.xltAry, 0, (int32_t)codec_control_msg, (int32_t)&(codec_control_msg->dyn_params), NULL); | ||
409 | Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[1]), 0, (int32_t)codec_control_msg, (int32_t)&(codec_control_msg->status), NULL); | ||
410 | |||
411 | /* Invoke the Remote function through MmRpc */ | ||
412 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
413 | |||
414 | _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); | ||
415 | |||
416 | eError = codec_control_msg->result; | ||
417 | |||
418 | EXIT: | ||
419 | memplugin_free(codec_control_msg, TILER_1D_BUFFER); | ||
420 | |||
421 | return (eError); | ||
422 | } | ||
423 | |||
424 | /*===============================================================*/ | ||
425 | /** get_version : Codec control call to get the codec version. This call has been made | ||
426 | * separate from control call because it involves an additional version | ||
427 | * buffer translation. | ||
428 | * | ||
429 | * @ param codec [in] : Codec Handle obtained in create() call. | ||
430 | * @ param id [in] : Command id for XDM control operation. | ||
431 | * @ param dynParams [in] : Dynamic input parameters to Codec. | ||
432 | * @ param status [out] : Codec returned status parameters. | ||
433 | * @ param codec_id [in] : To differentiate between Encoder and Decoder codecs. | ||
434 | * @ return : Status of control() call is returned. | ||
435 | * #XDM_EOK [0] : Success. | ||
436 | * #XDM_EFAIL [-1] : Failure. | ||
437 | * #IPC_FAIL [-2] : MmRpc Call failed. | ||
438 | * #XDM_EUNSUPPORTED [-3] : Unsupported request. | ||
439 | * #OUT_OF_MEMORY [-4] : Out of Shared Memory. | ||
440 | */ | ||
441 | static XDAS_Int32 get_version(void *codec, void *dynParams, void *status, dce_codec_type codec_id) | ||
442 | { | ||
443 | MmRpc_FxnCtx fxnCtx; | ||
444 | MmRpc_Xlt xltAry[3]; | ||
445 | int32_t fxnRet; | ||
446 | dce_error_status eError = DCE_EOK; | ||
447 | dce_codec_get_version *codec_get_version_msg = NULL; | ||
448 | |||
449 | _ASSERT(codec != NULL, DCE_EINVALID_INPUT); | ||
450 | _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT); | ||
451 | _ASSERT(status != NULL, DCE_EINVALID_INPUT); | ||
452 | |||
453 | /* Allocate Shared/Tiler memory for the codec_get_version rpc msg structure*/ | ||
454 | codec_get_version_msg = memplugin_alloc(sizeof(dce_codec_get_version), 0, TILER_1D_BUFFER); | ||
455 | |||
456 | _ASSERT(codec_get_version_msg != NULL, DCE_EOUT_OF_MEMORY); | ||
457 | |||
458 | /* Populating the msg structure with all the params */ | ||
459 | codec_get_version_msg->codec_handle = codec; | ||
460 | codec_get_version_msg->codec_id = codec_id; | ||
461 | codec_get_version_msg->dyn_params = dynParams; | ||
462 | codec_get_version_msg->status = status; | ||
463 | if( codec_id == OMAP_DCE_VIDDEC3 ) { | ||
464 | codec_get_version_msg->version = ((IVIDDEC3_Status *)status)->data.buf; | ||
465 | } else if( codec_id == OMAP_DCE_VIDENC2 ) { | ||
466 | codec_get_version_msg->version = ((IVIDDEC3_Status *)status)->data.buf; | ||
467 | } | ||
468 | |||
469 | /* Marshall function arguments into the send buffer */ | ||
470 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_CONTROL, 1, 3, xltAry); | ||
471 | Fill_MmRpc_fxnCtx_Ptr_Params(fxnCtx.params, sizeof(dce_codec_get_version), codec_get_version_msg, NULL); | ||
472 | |||
473 | /* Dynamic, status params and version info buffer need translation */ | ||
474 | Fill_MmRpc_fxnCtx_Xlt_Array(fxnCtx.xltAry, 0, (int32_t)codec_get_version_msg, (int32_t)&(codec_get_version_msg->dyn_params), NULL); | ||
475 | Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[1]), 0, (int32_t)codec_get_version_msg, (int32_t)&(codec_get_version_msg->status), NULL); | ||
476 | Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[2]), 0, (int32_t)codec_get_version_msg, (int32_t)&(codec_get_version_msg->version), NULL); | ||
477 | |||
478 | /* Invoke the Remote function through MmRpc */ | ||
479 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
480 | |||
481 | _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); | ||
482 | |||
483 | eError = codec_get_version_msg->result; | ||
484 | |||
485 | EXIT: | ||
486 | memplugin_free(codec_get_version_msg, TILER_1D_BUFFER); | ||
487 | |||
488 | return (eError); | ||
489 | } | ||
490 | |||
491 | typedef enum process_call_params { | ||
492 | CODEC_HANDLE_INDEX = 0, | ||
493 | INBUFS_INDEX, | ||
494 | OUTBUFS_INDEX, | ||
495 | INARGS_INDEX, | ||
496 | OUTARGS_INDEX, | ||
497 | CODEC_ID_INDEX | ||
498 | } process_call_params; | ||
499 | |||
500 | /*===============================================================*/ | ||
501 | /** process : Encode/Decode process. | ||
502 | * | ||
503 | * @ param codec [in] : Codec Handle obtained in create() call. | ||
504 | * @ param inBufs [in] : Input buffer details. | ||
505 | * @ param outBufs [in] : Output buffer details. | ||
506 | * @ param inArgs [in] : Input arguments. | ||
507 | * @ param outArgs [out] : Output arguments. | ||
508 | * @ param codec_id [in] : To differentiate between Encoder and Decoder codecs. | ||
509 | * @ return : Status of the process call. | ||
510 | * #XDM_EOK [0] : Success. | ||
511 | * #XDM_EFAIL [-1] : Failure. | ||
512 | * #IPC_FAIL [-2] : MmRpc Call failed. | ||
513 | * #XDM_EUNSUPPORTED [-3] : Unsupported request. | ||
514 | */ | ||
515 | static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs, | ||
516 | void *inArgs, void *outArgs, dce_codec_type codec_id) | ||
517 | { | ||
518 | MmRpc_FxnCtx fxnCtx; | ||
519 | MmRpc_Xlt xltAry[MAX_TOTAl_BUF]; | ||
520 | int fxnRet, count, total_count, numInBufs = 0, numOutBufs = 0, sz[5] = { 0 }; | ||
521 | dce_error_status eError = DCE_EOK; | ||
522 | |||
523 | _ASSERT(codec != NULL, DCE_EINVALID_INPUT); | ||
524 | _ASSERT(inBufs != NULL, DCE_EINVALID_INPUT); | ||
525 | _ASSERT(outBufs != NULL, DCE_EINVALID_INPUT); | ||
526 | _ASSERT(inArgs != NULL, DCE_EINVALID_INPUT); | ||
527 | _ASSERT(outArgs != NULL, DCE_EINVALID_INPUT); | ||
528 | |||
529 | if( codec_id == OMAP_DCE_VIDDEC3 ) { | ||
530 | numInBufs = ((XDM2_BufDesc *)inBufs)->numBufs; | ||
531 | numOutBufs = ((XDM2_BufDesc *)outBufs)->numBufs; | ||
532 | sz[INBUFS_INDEX] = sizeof(XDM2_BufDesc); | ||
533 | sz[OUTBUFS_INDEX] = sizeof(XDM2_BufDesc); | ||
534 | sz[INARGS_INDEX] = sizeof(VIDDEC3_InArgs); | ||
535 | sz[OUTARGS_INDEX] = sizeof(VIDDEC3_OutArgs); | ||
536 | } else if( codec_id == OMAP_DCE_VIDENC2 ) { | ||
537 | numInBufs = ((IVIDEO2_BufDesc *)inBufs)->numPlanes; | ||
538 | numOutBufs = ((XDM2_BufDesc *)outBufs)->numBufs; | ||
539 | sz[INBUFS_INDEX] = sizeof(IVIDEO2_BufDesc); | ||
540 | sz[OUTBUFS_INDEX] = sizeof(XDM2_BufDesc); | ||
541 | sz[INARGS_INDEX] = sizeof(VIDENC2_InArgs); | ||
542 | sz[OUTARGS_INDEX] = sizeof(VIDENC2_OutArgs); | ||
543 | } | ||
544 | |||
545 | /* marshall function arguments into the send buffer */ | ||
546 | /* Approach [2] as explained in "Notes" used for process */ | ||
547 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_PROCESS, 6, numInBufs + numOutBufs, xltAry); | ||
548 | Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[CODEC_HANDLE_INDEX]), sizeof(int32_t), (int32_t)codec); | ||
549 | Fill_MmRpc_fxnCtx_Ptr_Params(&(fxnCtx.params[INBUFS_INDEX]), sz[INBUFS_INDEX], inBufs, NULL); | ||
550 | Fill_MmRpc_fxnCtx_Ptr_Params(&(fxnCtx.params[OUTBUFS_INDEX]), sz[OUTBUFS_INDEX], outBufs, NULL); | ||
551 | Fill_MmRpc_fxnCtx_Ptr_Params(&(fxnCtx.params[INARGS_INDEX]), sz[INARGS_INDEX], inArgs, NULL); | ||
552 | Fill_MmRpc_fxnCtx_Ptr_Params(&(fxnCtx.params[OUTARGS_INDEX]), sz[OUTARGS_INDEX], outArgs, NULL); | ||
553 | Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[CODEC_ID_INDEX]), sizeof(int32_t), codec_id); | ||
554 | |||
555 | /* InBufs, OutBufs, InArgs, OutArgs buffer need translation but since they have been */ | ||
556 | /* individually mentioned as fxnCtx Params, they need not be mentioned below again */ | ||
557 | /* Input and Output Buffers have to be mentioned for translation */ | ||
558 | for( count = 0, total_count = 0; count < numInBufs; count++, total_count++ ) { | ||
559 | if( codec_id == OMAP_DCE_VIDDEC3 ) { | ||
560 | Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), INBUFS_INDEX, (int32_t)inBufs, (int32_t)&(((XDM2_BufDesc *)inBufs)->descs[count].buf), NULL); | ||
561 | } else if( codec_id == OMAP_DCE_VIDENC2 ) { | ||
562 | Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), INBUFS_INDEX, (int32_t)inBufs, (int32_t)&(((IVIDEO2_BufDesc *)inBufs)->planeDesc[count].buf), NULL); | ||
563 | } | ||
564 | } | ||
565 | |||
566 | for( count = 0; count < numOutBufs; count++, total_count++ ) { | ||
567 | Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), OUTBUFS_INDEX, (int32_t)outBufs, (int32_t)&(((XDM2_BufDesc *)outBufs)->descs[count].buf), NULL); | ||
568 | } | ||
569 | |||
570 | /* Invoke the Remote function through MmRpc */ | ||
571 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
572 | |||
573 | _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); | ||
574 | |||
575 | eError = (dce_error_status)(fxnRet); | ||
576 | EXIT: | ||
577 | return (eError); | ||
578 | } | ||
579 | |||
580 | /*===============================================================*/ | ||
581 | /** delete : Delete Encode/Decode codec instance. | ||
582 | * | ||
583 | * @ param codec [in] : Codec Handle obtained in create() call. | ||
584 | * @ param codec_id [in] : To differentiate between Encoder and Decoder codecs. | ||
585 | * @ return : NIL. | ||
586 | */ | ||
587 | static void delete(void *codec, dce_codec_type codec_id) | ||
588 | { | ||
589 | MmRpc_FxnCtx fxnCtx; | ||
590 | int32_t fxnRet; | ||
591 | dce_error_status eError = DCE_EOK; | ||
592 | dce_codec_delete *codec_delete_msg = NULL; | ||
593 | |||
594 | _ASSERT(codec != NULL, DCE_EINVALID_INPUT); | ||
595 | |||
596 | /* Allocate Shared/Tiler memory for the codec_delete rpc msg structure*/ | ||
597 | codec_delete_msg = memplugin_alloc(sizeof(dce_codec_delete), 0, TILER_1D_BUFFER); | ||
598 | |||
599 | _ASSERT(codec_delete_msg != NULL, DCE_EOUT_OF_MEMORY); | ||
600 | |||
601 | /* Populating the msg structure with all the params */ | ||
602 | codec_delete_msg->codec_handle = codec; | ||
603 | codec_delete_msg->codec_id = codec_id; | ||
604 | |||
605 | /* Marshall function arguments into the send buffer */ | ||
606 | Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_DELETE, 1, 0, NULL); | ||
607 | Fill_MmRpc_fxnCtx_Ptr_Params(fxnCtx.params, sizeof(dce_codec_delete), codec_delete_msg, NULL); | ||
608 | |||
609 | /* Invoke the Remote function through MmRpc */ | ||
610 | eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet); | ||
611 | |||
612 | _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); | ||
613 | |||
614 | EXIT: | ||
615 | memplugin_free(codec_delete_msg, TILER_1D_BUFFER); | ||
616 | |||
617 | return; | ||
618 | } | ||
619 | |||
620 | /*************** Deocder Codec Engine Functions ***********************/ | ||
621 | VIDDEC3_Handle VIDDEC3_create(Engine_Handle engine, String name, | ||
622 | VIDDEC3_Params *params) | ||
623 | { | ||
624 | VIDDEC3_Handle codec; | ||
625 | |||
626 | DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params); | ||
627 | codec = create(engine, name, params, OMAP_DCE_VIDDEC3); | ||
628 | DEBUG("<< codec=%p", codec); | ||
629 | return (codec); | ||
630 | } | ||
631 | |||
632 | XDAS_Int32 VIDDEC3_control(VIDDEC3_Handle codec, VIDDEC3_Cmd id, | ||
633 | VIDDEC3_DynamicParams *dynParams, VIDDEC3_Status *status) | ||
634 | { | ||
635 | XDAS_Int32 ret; | ||
636 | |||
637 | DEBUG(">> codec=%p, id=%d, dynParams=%p, status=%p", | ||
638 | codec, id, dynParams, status); | ||
639 | if( id == XDM_GETVERSION ) { | ||
640 | ret = get_version(codec, dynParams, status, OMAP_DCE_VIDDEC3); | ||
641 | } else { | ||
642 | ret = control(codec, id, dynParams, status, OMAP_DCE_VIDDEC3); | ||
643 | } | ||
644 | DEBUG("<< ret=%d", ret); | ||
645 | return (ret); | ||
646 | } | ||
647 | |||
648 | XDAS_Int32 VIDDEC3_process(VIDDEC3_Handle codec, | ||
649 | XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs, | ||
650 | VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs) | ||
651 | { | ||
652 | XDAS_Int32 ret; | ||
653 | |||
654 | DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p", | ||
655 | codec, inBufs, outBufs, inArgs, outArgs); | ||
656 | ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDDEC3); | ||
657 | DEBUG("<< ret=%d", ret); | ||
658 | return (ret); | ||
659 | } | ||
660 | |||
661 | Void VIDDEC3_delete(VIDDEC3_Handle codec) | ||
662 | { | ||
663 | DEBUG(">> codec=%p", codec); | ||
664 | delete(codec, OMAP_DCE_VIDDEC3); | ||
665 | DEBUG("<<"); | ||
666 | } | ||
667 | |||
668 | /*************** Enocder Codec Engine Functions ***********************/ | ||
669 | VIDENC2_Handle VIDENC2_create(Engine_Handle engine, String name, | ||
670 | VIDENC2_Params *params) | ||
671 | { | ||
672 | VIDENC2_Handle codec; | ||
673 | |||
674 | DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params); | ||
675 | codec = create(engine, name, params, OMAP_DCE_VIDENC2); | ||
676 | DEBUG("<< codec=%p", codec); | ||
677 | return (codec); | ||
678 | } | ||
679 | |||
680 | XDAS_Int32 VIDENC2_control(VIDENC2_Handle codec, VIDENC2_Cmd id, | ||
681 | VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status) | ||
682 | { | ||
683 | XDAS_Int32 ret; | ||
684 | |||
685 | DEBUG(">> codec=%p, id=%d, dynParams=%p, status=%p", | ||
686 | codec, id, dynParams, status); | ||
687 | ret = control(codec, id, dynParams, status, OMAP_DCE_VIDENC2); | ||
688 | DEBUG("<< ret=%d", ret); | ||
689 | return (ret); | ||
690 | } | ||
691 | |||
692 | XDAS_Int32 VIDENC2_process(VIDENC2_Handle codec, | ||
693 | IVIDEO2_BufDesc *inBufs, XDM2_BufDesc *outBufs, | ||
694 | VIDENC2_InArgs *inArgs, VIDENC2_OutArgs *outArgs) | ||
695 | { | ||
696 | XDAS_Int32 ret; | ||
697 | |||
698 | DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p", | ||
699 | codec, inBufs, outBufs, inArgs, outArgs); | ||
700 | ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDENC2); | ||
701 | DEBUG("<< ret=%d", ret); | ||
702 | return (ret); | ||
703 | } | ||
704 | |||
705 | Void VIDENC2_delete(VIDENC2_Handle codec) | ||
706 | { | ||
707 | DEBUG(">> codec=%p", codec); | ||
708 | delete(codec, OMAP_DCE_VIDENC2); | ||
709 | DEBUG("<<"); | ||
710 | } | ||
711 | |||
diff --git a/libdce.h b/libdce.h new file mode 100644 index 0000000..c64456a --- /dev/null +++ b/libdce.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | #ifndef __LIBDCE_H__ | ||
34 | #define __LIBDCE_H__ | ||
35 | |||
36 | |||
37 | #include <ti/sdo/ce/Engine.h> | ||
38 | #include <ti/sdo/ce/video3/viddec3.h> | ||
39 | #include <ti/sdo/ce/video2/videnc2.h> | ||
40 | |||
41 | |||
42 | /* DCE Error Types */ | ||
43 | typedef enum dce_error_status { | ||
44 | DCE_EOK = 0, | ||
45 | DCE_EXDM_FAIL = -1, | ||
46 | DCE_EOUT_OF_MEMORY = -2, | ||
47 | DCE_EXDM_UNSUPPORTED = -3, | ||
48 | DCE_EIPC_CREATE_FAIL = -4, | ||
49 | DCE_EIPC_CALL_FAIL = -5, | ||
50 | DCE_EINVALID_INPUT = -6 | ||
51 | } dce_error_status; | ||
52 | |||
53 | |||
54 | /* other than the codec-engine API, you must use the following two functions | ||
55 | * to allocate the data structures passed to codec-engine APIs (other than the | ||
56 | * raw input/output buffers which should be passed as virtual addresses in | ||
57 | * TILER space | ||
58 | */ | ||
59 | void *dce_alloc(int sz); | ||
60 | void dce_free(void *ptr); | ||
61 | |||
62 | |||
63 | #if defined(BUILDOS_GLP) | ||
64 | void dce_set_fd(int fd); | ||
65 | int dce_get_fd(); | ||
66 | |||
67 | /* avoid some messy stuff in xdc/std.h which leads to gcc issues */ | ||
68 | #define xdc__ARGTOPTR | ||
69 | #define xdc__ARGTOFXN | ||
70 | |||
71 | struct omap_device *dce_init(void); | ||
72 | void dce_deinit(struct omap_device *dev); | ||
73 | |||
74 | #define XDM_MEMTYPE_BO 10 | ||
75 | #define XDM_MEMTYPE_BO_OFFSET 11 | ||
76 | #endif /* BUILDOS_GLP */ | ||
77 | |||
78 | #endif /* __LIBDCE_H__ */ | ||
79 | |||
diff --git a/memplugin.h b/memplugin.h new file mode 100644 index 0000000..f4dda8e --- /dev/null +++ b/memplugin.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | #ifndef __MEMPLUGIN_H__ | ||
34 | #define __MEMPLUGIN_H__ | ||
35 | |||
36 | #include <stdlib.h> | ||
37 | #include <string.h> | ||
38 | #include <stdio.h> | ||
39 | |||
40 | #if defined(BUILDOS_QNX) | ||
41 | #include <memmgr.h> | ||
42 | #endif /* BUILDOS_QNX */ | ||
43 | |||
44 | #if defined(BUILDOS_GLP) | ||
45 | #include <xf86drm.h> | ||
46 | #endif /* BUILDOS_GLP */ | ||
47 | |||
48 | /* IPC Headers */ | ||
49 | #include <tilermem.h> | ||
50 | #include <SharedMemoryAllocatorUsr.h> | ||
51 | |||
52 | |||
53 | #define P2H(p) (&(((MemHeader *)(p))[-1])) | ||
54 | #define H2P(h) ((void *)&(h)[1]) | ||
55 | |||
56 | typedef enum mem_type { | ||
57 | TILER_1D_BUFFER, | ||
58 | TILER8_2D_BUFFER, | ||
59 | TILER16_2D_BUFFER, | ||
60 | SHARED_MEMORY_BUFFER, | ||
61 | MEM_MAX | ||
62 | } mem_type; | ||
63 | |||
64 | |||
65 | /* DCE Error Types */ | ||
66 | typedef enum mem_error_status { | ||
67 | MEM_EOK = 0, | ||
68 | MEM_EINVALID_INPUT = -1, | ||
69 | MEM_EOUT_OF_TILER_MEMORY = -2, | ||
70 | MEM_EOUT_OF_SHMEMORY = -3, | ||
71 | MEM_EOUT_OF_SYSTEM_MEMORY = -4 | ||
72 | } mem_error_status; | ||
73 | |||
74 | void *memplugin_alloc(int sz, int height, mem_type memory_type); | ||
75 | |||
76 | void memplugin_free(void *ptr, mem_type memory_type); | ||
77 | |||
78 | void *memplugin_share(void *ptr, mem_type memory_type); | ||
79 | |||
80 | #endif /* __MEMPLUGIN_H__ */ | ||
81 | |||
diff --git a/memplugin_qnx.c b/memplugin_qnx.c new file mode 100644 index 0000000..5555037 --- /dev/null +++ b/memplugin_qnx.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | #include "memplugin.h" | ||
34 | #include "dce_priv.h" | ||
35 | |||
36 | |||
37 | /* Would it be good to have MemHeaders for Tiler 2D buffers?? */ | ||
38 | /* Since the decision is to not support allocation of IO buffers, no */ | ||
39 | /* need to worry about Tiler 2D Buffers. Hence below Memheader */ | ||
40 | /* can be used. */ | ||
41 | /* | ||
42 | typedef struct { | ||
43 | dce_memory_type memory_type; | ||
44 | union { | ||
45 | struct { | ||
46 | Uint32 size; | ||
47 | Uint32 ducati_addr; | ||
48 | } tilerHeader; | ||
49 | shm_buf shm_bufHeader; | ||
50 | } | ||
51 | } MemHeader; | ||
52 | else for Tiler 1D buffers */ | ||
53 | |||
54 | /* MemHeader is important because it is necessary to know the */ | ||
55 | /* size of the parameter buffers on IPU for Cache operations */ | ||
56 | /* The size can't be assumed as codec supports different inputs */ | ||
57 | /* For ex: static params can be VIDDEC3_Params, IVIDDEC3_Params */ | ||
58 | /* or IH264DEC_Params */ | ||
59 | typedef struct MemHeader { | ||
60 | int size; | ||
61 | void *ptr; | ||
62 | } MemHeader; | ||
63 | |||
64 | |||
65 | /* For TILER 2D Buffers : sz = width */ | ||
66 | /* : height = nonzero */ | ||
67 | /* For other memory_types : height = 0 */ | ||
68 | void *memplugin_alloc(int sz, int height, mem_type memory_type) | ||
69 | { | ||
70 | MemHeader *h; | ||
71 | shm_buf *handle; | ||
72 | MemAllocBlock block; | ||
73 | int num_block; | ||
74 | mem_error_status eError = MEM_EOK; | ||
75 | |||
76 | _ASSERT(sz != 0, MEM_EINVALID_INPUT); | ||
77 | _ASSERT((memory_type < MEM_MAX) && (memory_type >= TILER_1D_BUFFER), MEM_EINVALID_INPUT); | ||
78 | |||
79 | /* Tiler buffer Allocations : Only Tiler 1D used for Parameter Buffers and RPC Message buffers */ | ||
80 | if( memory_type == TILER_1D_BUFFER || memory_type == TILER8_2D_BUFFER || memory_type == TILER16_2D_BUFFER ) { | ||
81 | num_block = 1; | ||
82 | |||
83 | if( memory_type == TILER_1D_BUFFER ) { | ||
84 | /* Allocate in tiler paged mode (1d) container */ | ||
85 | block.pixelFormat = PIXEL_FMT_PAGE; | ||
86 | block.dim.len = sz + sizeof(MemHeader); | ||
87 | #if 0 /* Data Tiler Buffers not to be allocated by DCE */ | ||
88 | } else if( memory_type == TILER8_2D_BUFFER ) { | ||
89 | /* Allocate in tiler 8 bit mode (2d) container */ | ||
90 | _ASSERT(height != 0, MEM_EINVALID_INPUT); | ||
91 | block.pixelFormat = PIXEL_FMT_8BIT; | ||
92 | block.dim.area.width = sz; | ||
93 | block.dim.area.height = height; | ||
94 | } else { | ||
95 | /* Allocate in tiler 16 bit mode (2d) container */ | ||
96 | _ASSERT(height != 0, MEM_EINVALID_INPUT); | ||
97 | block.pixelFormat = PIXEL_FMT_16BIT; | ||
98 | block.dim.area.width = sz; | ||
99 | block.dim.area.height = height; | ||
100 | #endif | ||
101 | } | ||
102 | block.stride = 0; | ||
103 | |||
104 | h = MemMgr_Alloc(&block, num_block); | ||
105 | |||
106 | _ASSERT(h != NULL, MEM_EOUT_OF_TILER_MEMORY); | ||
107 | |||
108 | h->size = sz; | ||
109 | memset(H2P(h), 0, sz); | ||
110 | return (H2P(h)); | ||
111 | } else { | ||
112 | |||
113 | handle = malloc(sizeof(shm_buf)); | ||
114 | _ASSERT(handle != NULL, MEM_EOUT_OF_SYSTEM_MEMORY); | ||
115 | |||
116 | /* Parameter Buffers : Allocate from Shared Memory considering MemHeader*/ | ||
117 | SHM_alloc(sz + sizeof(MemHeader), handle); | ||
118 | |||
119 | h = (MemHeader *)handle->vir_addr; | ||
120 | _ASSERT_AND_EXECUTE(h != NULL, MEM_EOUT_OF_SHMEMORY, free(handle)); | ||
121 | |||
122 | h->size = sz; | ||
123 | h->ptr = handle; | ||
124 | memset(H2P(h), 0, sz); | ||
125 | return (H2P(h)); | ||
126 | } | ||
127 | EXIT: | ||
128 | return (NULL); | ||
129 | } | ||
130 | |||
131 | /* memory_type is not added if MemHeader is used for Tiler Buffers */ | ||
132 | void memplugin_free(void *ptr, mem_type memory_type) | ||
133 | { | ||
134 | shm_buf *handle; | ||
135 | mem_error_status eError = MEM_EOK; | ||
136 | |||
137 | _ASSERT(ptr != NULL, MEM_EINVALID_INPUT); | ||
138 | _ASSERT((memory_type < MEM_MAX) && (memory_type >= TILER_1D_BUFFER), MEM_EINVALID_INPUT); | ||
139 | |||
140 | if( memory_type == TILER_1D_BUFFER ) { | ||
141 | MemMgr_Free(P2H(ptr)); | ||
142 | } else if( memory_type == SHARED_MEMORY_BUFFER ) { | ||
143 | handle = (P2H(ptr))->ptr; | ||
144 | SHM_release(handle); | ||
145 | free(handle); | ||
146 | } else { | ||
147 | ERROR("Tiler 2D Allocation/Free not implemented"); | ||
148 | } | ||
149 | EXIT:; | ||
150 | } | ||
151 | |||
152 | void *memplugin_share(void *ptr, mem_type memory_type) | ||
153 | { | ||
154 | /* No Userspace Virtual pointers to DMA BUF Handles conversion required*/ | ||
155 | /* Do nothing */ | ||
156 | return (ptr); | ||
157 | } | ||
158 | |||
diff --git a/nto/Makefile b/nto/Makefile new file mode 100644 index 0000000..5323e99 --- /dev/null +++ b/nto/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | LIST=CPU | ||
2 | include recurse.mk | ||
diff --git a/nto/README.txt b/nto/README.txt new file mode 100644 index 0000000..bf43f03 --- /dev/null +++ b/nto/README.txt | |||
@@ -0,0 +1 @@ | |||
This Directory is QNX/Neutrino specific. | |||
diff --git a/nto/arm/Makefile b/nto/arm/Makefile new file mode 100644 index 0000000..a5e4d9b --- /dev/null +++ b/nto/arm/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | LIST=VARIANT | ||
2 | include recurse.mk | ||
diff --git a/nto/arm/a.le.v7/Makefile b/nto/arm/a.le.v7/Makefile new file mode 100644 index 0000000..9d6821f --- /dev/null +++ b/nto/arm/a.le.v7/Makefile | |||
@@ -0,0 +1 @@ | |||
include ../../../common.mk | |||
diff --git a/nto/arm/so.le.v7/Makefile b/nto/arm/so.le.v7/Makefile new file mode 100644 index 0000000..9d6821f --- /dev/null +++ b/nto/arm/so.le.v7/Makefile | |||
@@ -0,0 +1 @@ | |||
include ../../../common.mk | |||
diff --git a/nto/qconf-override.mk b/nto/qconf-override.mk new file mode 100644 index 0000000..cf6c23c --- /dev/null +++ b/nto/qconf-override.mk | |||
@@ -0,0 +1,9 @@ | |||
1 | # If you wish to override the values of some of the macros defined in qconfig.mk | ||
2 | # without modifying the contents of the file, set the QCONF_OVERRIDE environment | ||
3 | # variable to this file (which will be included at the end of the qconfig.mk file) | ||
4 | # and override the qconfig.mk macros here. | ||
5 | |||
6 | # Override INSTALL_ROOT_nto macro | ||
7 | INSTALL_ROOT ?= $(shell pwd) | ||
8 | INSTALL_ROOT_nto := $(INSTALL_ROOT) | ||
9 | USE_INSTALL_ROOT = 1 | ||
diff --git a/test_qnx/Makefile b/test_qnx/Makefile new file mode 100644 index 0000000..5323e99 --- /dev/null +++ b/test_qnx/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | LIST=CPU | ||
2 | include recurse.mk | ||
diff --git a/test_qnx/arm/Makefile b/test_qnx/arm/Makefile new file mode 100644 index 0000000..6a18617 --- /dev/null +++ b/test_qnx/arm/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | LIST=VARIANT | ||
2 | ifndef QRECURSE | ||
3 | QRECURSE=recurse.mk | ||
4 | ifdef QCONFIG | ||
5 | QRDIR=$(dir $(QCONFIG)) | ||
6 | endif | ||
7 | endif | ||
8 | include $(QRDIR)$(QRECURSE) | ||
diff --git a/test_qnx/arm/le.v7/Makefile b/test_qnx/arm/le.v7/Makefile new file mode 100644 index 0000000..cc39927 --- /dev/null +++ b/test_qnx/arm/le.v7/Makefile | |||
@@ -0,0 +1 @@ | |||
include ../../common.mk | |||
diff --git a/test_qnx/common.mk b/test_qnx/common.mk new file mode 100644 index 0000000..be901c0 --- /dev/null +++ b/test_qnx/common.mk | |||
@@ -0,0 +1,50 @@ | |||
1 | ###################### QNX DCE Test App Build Config ####################### | ||
2 | |||
3 | #### Include qconfig.mk | ||
4 | ifndef QCONFIG | ||
5 | QCONFIG=qconfig.mk | ||
6 | endif | ||
7 | include $(QCONFIG) | ||
8 | |||
9 | define PINFO | ||
10 | PINFO DESCRIPTION=DCE Test | ||
11 | endef | ||
12 | |||
13 | NAME = dce_test | ||
14 | INSTALLDIR = bin | ||
15 | |||
16 | # Different tool versions can easily be programmed by defining below variables | ||
17 | # in your environment. | ||
18 | CEVERSION ?= codec_engine_3_23_00_07 | ||
19 | FCVERSION ?= framework_components_3_23_03_17 | ||
20 | XDAISVERSION ?= xdais_7_23_00_06 | ||
21 | XDCVERSION ?= xdctools_3_25_00_48 | ||
22 | IPCHEADERS ?= $(INSTALL_ROOT_nto) | ||
23 | IVAHDCODECS ?= ipumm/extrel/ti/ivahd_codecs | ||
24 | |||
25 | # Generate the full package paths for tools | ||
26 | CEPROD = $(TIVIDEOTOOLSROOT)/$(CEVERSION) | ||
27 | FCPROD = $(TIVIDEOTOOLSROOT)/$(FCVERSION) | ||
28 | XDAISPROD = $(TITOOLSROOT)/$(XDAISVERSION) | ||
29 | XDCPROD = $(TITOOLSROOT)/$(XDCVERSION) | ||
30 | |||
31 | #Add extra include path | ||
32 | EXTRA_INCVPATH += $(CEPROD)/packages | ||
33 | EXTRA_INCVPATH += $(FCPROD)/packages | ||
34 | EXTRA_INCVPATH += $(XDAISPROD)/packages | ||
35 | EXTRA_INCVPATH += $(XDCPROD)/packages | ||
36 | EXTRA_INCVPATH += $(IVAHDCODECS)/packages | ||
37 | EXTRA_INCVPATH += $(PROJECT_ROOT)/../ | ||
38 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/memmgr | ||
39 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include/ti/syslink | ||
40 | EXTRA_INCVPATH += $(IPCHEADERS)/usr/include | ||
41 | |||
42 | CCOPTS+=-g -O0 -Dxdc_target_types__=qnx/targets/arm/std.h | ||
43 | |||
44 | EXTRA_LIBVPATH += $(PROJECT_ROOT)/../nto/arm/so.le.v7 \ | ||
45 | $(INSTALL_ROOT_nto)/armle-v7/usr/lib | ||
46 | |||
47 | LDOPTS+= -ldce -lmemmgr -ltilerusr -lsyslink_client -lsharedmemallocator | ||
48 | |||
49 | include $(MKFILES_ROOT)/qtargets.mk | ||
50 | |||
diff --git a/test_qnx/dce_test.c b/test_qnx/dce_test.c new file mode 100644 index 0000000..805b240 --- /dev/null +++ b/test_qnx/dce_test.c | |||
@@ -0,0 +1,1437 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Texas Instruments Incorporated | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * | ||
9 | * * Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * | ||
12 | * * Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * * Neither the name of Texas Instruments Incorporated nor the names of | ||
17 | * its contributors may be used to endorse or promote products derived | ||
18 | * from this software without specific prior written permission. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | #include <xdc/std.h> | ||
33 | #include <stdlib.h> | ||
34 | #include <string.h> | ||
35 | #include <stdio.h> | ||
36 | #include <stdint.h> | ||
37 | #include <sys/types.h> | ||
38 | #include <sys/stat.h> | ||
39 | #include <sys/time.h> | ||
40 | #include <fcntl.h> | ||
41 | #include <errno.h> | ||
42 | #include <time.h> | ||
43 | #include <sys/mman.h> | ||
44 | |||
45 | #include <tilermem.h> | ||
46 | #include <memmgr.h> | ||
47 | #include <xdc/std.h> | ||
48 | #include <ti/sdo/ce/Engine.h> | ||
49 | #include <ti/sdo/ce/video3/viddec3.h> | ||
50 | #include <ti/sdo/codecs/h264vdec/ih264vdec.h> | ||
51 | #include <ti/sdo/codecs/mpeg4vdec/impeg4vdec.h> | ||
52 | #include <ti/sdo/codecs/vc1vdec/ivc1vdec.h> | ||
53 | #include <ti/sdo/codecs/jpegvdec/ijpegvdec.h> | ||
54 | #ifdef ENABLE_MPEG2 | ||
55 | #include <ti/sdo/codecs/mpeg2vdec/impeg2vdec.h> | ||
56 | #endif | ||
57 | #include "ti/shmemallocator/SharedMemoryAllocatorUsr.h" | ||
58 | #include "libdce.h" | ||
59 | |||
60 | #define OMAP5 | ||
61 | |||
62 | #define PRINT_DEBUG | ||
63 | #define ERROR(FMT, ...) printf("%s:%d:\t%s\terror: " FMT "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) | ||
64 | // enable below to print debug information | ||
65 | #ifdef PRINT_DEBUG | ||
66 | #define DEBUG(FMT, ...) printf("%s:%d:\t%s\tdebug: " FMT "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) | ||
67 | #else | ||
68 | #define DEBUG(FMT, ...) | ||
69 | #endif | ||
70 | #define INFO(FMT, ...) printf("%s:%d:\t%s\tinfo: " FMT "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) | ||
71 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | ||
72 | |||
73 | /* align x to next highest multiple of 2^n */ | ||
74 | #define ALIGN2(x, n) (((x) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1)) | ||
75 | |||
76 | // Profile the init and decode calls | ||
77 | //#define PROFILE_TIME | ||
78 | |||
79 | enum { | ||
80 | IVAHD_AVC1_DECODE, | ||
81 | IVAHD_H264_DECODE, | ||
82 | IVAHD_MP4V_DECODE, | ||
83 | IVAHD_S263_DECODE, | ||
84 | IVAHD_VC1AP_DECODE, | ||
85 | IVAHD_VC1SMP_DECODE, | ||
86 | IVAHD_VP6V_DECODE, | ||
87 | IVAHD_MP2V_DECODE, | ||
88 | IVAHD_JPEGV_DECODE | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * A very simple VIDDEC3 client which will decode h264 frames (one per file), | ||
93 | * and write out raw (unstrided) nv12 frames (one per file). | ||
94 | */ | ||
95 | |||
96 | int width, height, padded_width, padded_height, num_buffers, tiler; | ||
97 | Engine_Handle engine = NULL; | ||
98 | VIDDEC3_Handle codec = NULL; | ||
99 | VIDDEC3_Params *params = NULL; | ||
100 | VIDDEC3_DynamicParams *dynParams = NULL; | ||
101 | VIDDEC3_Status *status = NULL; | ||
102 | XDM2_BufDesc *inBufs = NULL; | ||
103 | XDM2_BufDesc *outBufs = NULL; | ||
104 | VIDDEC3_InArgs *inArgs = NULL; | ||
105 | VIDDEC3_OutArgs *outArgs = NULL; | ||
106 | |||
107 | IH264VDEC_Params *h264_params = NULL; | ||
108 | IH264VDEC_DynamicParams *h264_dynParams = NULL; | ||
109 | IH264VDEC_Status *h264_status = NULL; | ||
110 | |||
111 | IMPEG4VDEC_Params *mpeg4_params = NULL; | ||
112 | IMPEG4VDEC_DynamicParams *mpeg4_dynParams = NULL; | ||
113 | IMPEG4VDEC_Status *mpeg4_status = NULL; | ||
114 | |||
115 | IVC1VDEC_Params *vc1_params = NULL; | ||
116 | IVC1VDEC_DynamicParams *vc1_dynParams = NULL; | ||
117 | IVC1VDEC_Status *vc1_status = NULL; | ||
118 | |||
119 | IJPEGVDEC_Params *mjpeg_params = NULL; | ||
120 | IJPEGVDEC_DynamicParams *mjpeg_dynParams = NULL; | ||
121 | IJPEGVDEC_Status *mjpeg_status = NULL; | ||
122 | #ifdef ENABLE_MPEG2 | ||
123 | IMPEG2VDEC_Params *mpeg2_params = NULL; | ||
124 | IMPEG2VDEC_DynamicParams *mpeg2_dynParams = NULL; | ||
125 | IMPEG2VDEC_Status *mpeg2_status = NULL; | ||
126 | #endif | ||
127 | unsigned int frameSize[64000]; /* Buffer for keeping frame sizes */ | ||
128 | static int input_offset = 0; | ||
129 | |||
130 | /*! Padding for width as per Codec Requirement */ | ||
131 | #define PADX_H264 32 | ||
132 | #define PADX_MPEG4 32 | ||
133 | #define PADX_VC1 32 | ||
134 | /*! Padding for height as per Codec Requirement */ | ||
135 | #define PADY_H264 24 | ||
136 | #define PADY_MPEG4 32 | ||
137 | #define PADY_VC1 40 | ||
138 | |||
139 | static void *tiler_alloc(int width, int height) | ||
140 | { | ||
141 | int dimensions; | ||
142 | void *bufPtr = NULL; | ||
143 | MemAllocBlock block; | ||
144 | MemAllocBlock blocks[2]; | ||
145 | |||
146 | memset(&block, 0, sizeof(MemAllocBlock)); | ||
147 | memset(blocks, 0, sizeof(MemAllocBlock) * 2); | ||
148 | |||
149 | if( !height ) { | ||
150 | DEBUG("tiler alloc 1D allocation width=%d", width); | ||
151 | /* 1d allocation: */ | ||
152 | dimensions = 1; | ||
153 | |||
154 | block.pixelFormat = PIXEL_FMT_PAGE; | ||
155 | block.dim.len = width; | ||
156 | block.stride = 0; | ||
157 | |||
158 | bufPtr = MemMgr_Alloc(&block, dimensions); | ||
159 | } else { | ||
160 | DEBUG("tiler alloc 2D allocation width=%d height=%d", width, height); | ||
161 | /* 2d allocation: */ | ||
162 | dimensions = 2; | ||
163 | blocks[0].pixelFormat = PIXEL_FMT_8BIT; | ||
164 | blocks[0].dim.area.width = width; | ||
165 | blocks[0].dim.area.height = height; | ||
166 | blocks[0].stride = 0; | ||
167 | |||
168 | blocks[1].pixelFormat = PIXEL_FMT_16BIT; | ||
169 | blocks[1].dim.area.width = width >> 1; | ||
170 | blocks[1].dim.area.height = height >> 1; | ||
171 | blocks[1].stride = 0; | ||
172 | |||
173 | bufPtr = MemMgr_Alloc(blocks, dimensions); | ||
174 | } | ||
175 | DEBUG("tiler alloc return bufPtr %p", bufPtr); | ||
176 | |||
177 | return (bufPtr); | ||
178 | } | ||
179 | |||
180 | /* ************************************************************************* */ | ||
181 | /* utilities to allocate/manage 2d output buffers */ | ||
182 | |||
183 | typedef struct OutputBuffer OutputBuffer; | ||
184 | |||
185 | struct OutputBuffer { | ||
186 | char *buf; /* virtual address for local access, 4kb stride */ | ||
187 | uint32_t y, uv; /* virtual address of Y and UV for remote access */ | ||
188 | OutputBuffer *next; /* next free buffer */ | ||
189 | bool tiler; | ||
190 | uint32_t len; | ||
191 | shm_buf shmBuf; | ||
192 | }; | ||
193 | |||
194 | static XDAS_Int16 | ||
195 | get_mem_type (uint32_t paddr) | ||
196 | { | ||
197 | if((0x60000000 <= paddr) && (paddr < 0x68000000)) { | ||
198 | return (XDM_MEMTYPE_TILED8); | ||
199 | } | ||
200 | if((0x68000000 <= paddr) && (paddr < 0x70000000)) { | ||
201 | return (XDM_MEMTYPE_TILED16); | ||
202 | } | ||
203 | if((0x70000000 <= paddr) && (paddr < 0x78000000)) { | ||
204 | return (XDM_MEMTYPE_TILED32); | ||
205 | } | ||
206 | if((0x78000000 <= paddr) && (paddr < 0x80000000)) { | ||
207 | return (XDM_MEMTYPE_RAW); | ||
208 | } | ||
209 | return (-1); | ||
210 | } | ||
211 | |||
212 | /* list of free buffers, not locked by codec! */ | ||
213 | static OutputBuffer *head = NULL; | ||
214 | |||
215 | #if 0 | ||
216 | /*! @brief Start address of DDR region for 1GB RAM */ | ||
217 | #define DDR_1G_ADDRESS_START 0x80000000 | ||
218 | /*! @brief End address of DDR region for 1GB RAM */ | ||
219 | #define DDR_1G_ADDRESS_END 0xBFFFFFFF | ||
220 | #define DDR_1G_DUCATI_OFFSET 0x40000000 | ||
221 | |||
222 | /*! @brief Start address of DDR region for 2GB RAM */ | ||
223 | #define DDR_2G_ADDRESS_START 0xC0000000 | ||
224 | /*! @brief End address of DDR region for 2GB RAM */ | ||
225 | #define DDR_2G_ADDRESS_END 0xFFFFFFFF | ||
226 | #define DDR_2G_DUCATI_OFFSET 0xA0000000 | ||
227 | |||
228 | static Int | ||
229 | SysLinkMemUtils_translateAddr (UInt32 physAddr) | ||
230 | { | ||
231 | Int ret = 0; | ||
232 | |||
233 | if( physAddr >= DDR_1G_ADDRESS_START && physAddr <= DDR_1G_ADDRESS_END ) { | ||
234 | ret = physAddr + DDR_1G_DUCATI_OFFSET; | ||
235 | } else if( physAddr >= DDR_2G_ADDRESS_START && physAddr <= DDR_2G_ADDRESS_END ) { | ||
236 | ret = physAddr - DDR_2G_DUCATI_OFFSET; | ||
237 | } | ||
238 | |||
239 | return (ret); | ||
240 | } | ||
241 | |||
242 | #endif | ||
243 | |||
244 | int output_allocate(XDM2_BufDesc *outBufs, int cnt, | ||
245 | int width, int height, int stride) | ||
246 | { | ||
247 | int tw, th; | ||
248 | |||
249 | outBufs->numBufs = 2; | ||
250 | |||
251 | if( stride != 4096 ) { | ||
252 | /* non-2d allocation! */ | ||
253 | int size_y = stride * height; | ||
254 | int size_uv = stride * height / 2; | ||
255 | tw = size_y + size_uv; | ||
256 | th = 0; | ||
257 | outBufs->descs[0].memType = XDM_MEMTYPE_TILEDPAGE; | ||
258 | outBufs->descs[0].bufSize.bytes = size_y; | ||
259 | outBufs->descs[1].memType = XDM_MEMTYPE_TILEDPAGE; | ||
260 | outBufs->descs[1].bufSize.bytes = size_uv; | ||
261 | } else { | ||
262 | tw = width; | ||
263 | th = height; | ||
264 | outBufs->descs[0].memType = XDM_MEMTYPE_TILED8; | ||
265 | outBufs->descs[0].bufSize.tileMem.width = width; | ||
266 | outBufs->descs[0].bufSize.tileMem.height = height; | ||
267 | outBufs->descs[1].memType = XDM_MEMTYPE_TILED16; | ||
268 | outBufs->descs[1].bufSize.tileMem.width = width; /* UV interleaved width is same a Y */ | ||
269 | outBufs->descs[1].bufSize.tileMem.height = height / 2; | ||
270 | } | ||
271 | |||
272 | while( cnt ) { | ||
273 | OutputBuffer *buf = calloc(sizeof(OutputBuffer), 1); | ||
274 | |||
275 | DEBUG(" ----------------- create TILER buf 0x%x --------------------", (unsigned int)buf); | ||
276 | |||
277 | buf->buf = tiler_alloc(tw, th); | ||
278 | if( buf->buf ) { | ||
279 | buf->y = (uint32_t) buf->buf; | ||
280 | buf->uv = (uint32_t)(buf->buf + (height * stride)); | ||
281 | |||
282 | DEBUG("cnt=%d buf=%p, y=%08x, uv=%08x", cnt, buf, buf->y, buf->uv); | ||
283 | |||
284 | buf->tiler = TRUE; | ||
285 | buf->next = head; | ||
286 | head = buf; | ||
287 | } else { | ||
288 | ERROR(" ---------------- tiler_alloc failed --------------------"); | ||
289 | free(buf); | ||
290 | return (-EAGAIN); | ||
291 | } | ||
292 | cnt--; | ||
293 | } | ||
294 | |||
295 | return (0); | ||
296 | } | ||
297 | |||
298 | int output_allocate_nonTiler(XDM2_BufDesc *outBufs, int cnt, | ||
299 | int width, int height, int stride) | ||
300 | { | ||
301 | int tw; | ||
302 | XDAS_Int16 y_type, uv_type; | ||
303 | |||
304 | outBufs->numBufs = 2; | ||
305 | |||
306 | while( cnt ) { | ||
307 | OutputBuffer *buf = calloc(sizeof(OutputBuffer), 1); | ||
308 | |||
309 | DEBUG(" ----------------- create nonTILER buf 0x%x --------------------", (unsigned int)buf); | ||
310 | int size_y = width * height; | ||
311 | int size_uv = width * height * 1 / 2; | ||
312 | tw = size_y + size_uv; | ||
313 | |||
314 | // Allocation through mmap | ||
315 | uint64_t *vaddr; | ||
316 | int32_t ret, len = 0; | ||
317 | int64_t paddr = 0; | ||
318 | uint32_t uv_addr; | ||
319 | |||
320 | //vaddr = mmap64(0, tw, PROT_NOCACHE | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PHYS | MAP_SHARED, NOFD, 0); | ||
321 | ret = SHM_alloc(tw, &buf->shmBuf); | ||
322 | //if (vaddr == MAP_FAILED) { | ||
323 | if( ret < 0 ) { | ||
324 | //ERROR("Failed to do memory mapping\n"); | ||
325 | ERROR("Failed to alloc shmem buffer\n"); | ||
326 | free(buf); | ||
327 | return (-ENOMEM); | ||
328 | } | ||
329 | vaddr = (uint64_t *)buf->shmBuf.vir_addr; | ||
330 | |||
331 | // Make sure the memory is contiguous | ||
332 | ret = mem_offset64(vaddr, NOFD, (size_t) tw, &paddr, (size_t *) &len); | ||
333 | if( ret ) { | ||
334 | ERROR("Failed to check memory contiguous ret %d errno %d\n", ret, errno); | ||
335 | //munmap(vaddr, tw); | ||
336 | SHM_release(&buf->shmBuf); | ||
337 | free(buf); | ||
338 | return (-ENOMEM); | ||
339 | } else if( len != (tw)) { | ||
340 | ERROR("Failed to check len %d != %d\n", len, tw); | ||
341 | //munmap(vaddr, tw); | ||
342 | SHM_release(&buf->shmBuf); | ||
343 | free(buf); | ||
344 | return (-ENOMEM); | ||
345 | } | ||
346 | |||
347 | buf->buf = (char *) vaddr; | ||
348 | buf->y = (uint32_t)vaddr; | ||
349 | uv_addr = (uint32_t) vaddr + (width * height); | ||
350 | buf->uv = uv_addr; | ||
351 | |||
352 | DEBUG("cnt=%d nonTILER buf=%p, y=%08x, uv=%08x paddr=%08x", cnt, buf, buf->y, buf->uv, (unsigned int) paddr); | ||
353 | |||
354 | y_type = get_mem_type(buf->y); | ||
355 | uv_type = get_mem_type(buf->uv); | ||
356 | |||
357 | if((y_type < 0) || (uv_type < 0)) { | ||
358 | DEBUG("non TILER buffer address translation buf->y %x buf->uv %x", buf->y, buf->uv); | ||
359 | //buf->y = SysLinkMemUtils_translateAddr(buf->y); | ||
360 | //buf->uv = SysLinkMemUtils_translateAddr(buf->uv); | ||
361 | y_type = XDM_MEMTYPE_RAW; | ||
362 | uv_type = XDM_MEMTYPE_RAW; | ||
363 | DEBUG("buf->y %x buf->uv %x", buf->y, buf->uv); | ||
364 | if( !buf->y || !buf->uv ) { | ||
365 | //munmap(vaddr, tw); | ||
366 | SHM_release(&buf->shmBuf); | ||
367 | free(buf); | ||
368 | return (-ENOMEM); | ||
369 | } | ||
370 | } | ||
371 | |||
372 | buf->next = head; | ||
373 | buf->tiler = FALSE; | ||
374 | buf->len = tw; | ||
375 | head = buf; | ||
376 | |||
377 | cnt--; | ||
378 | } | ||
379 | |||
380 | if((y_type == XDM_MEMTYPE_RAW) && (uv_type == XDM_MEMTYPE_RAW)) { | ||
381 | outBufs->descs[0].memType = y_type; | ||
382 | outBufs->descs[0].bufSize.bytes = width * height; | ||
383 | outBufs->descs[1].memType = uv_type; | ||
384 | outBufs->descs[1].bufSize.bytes = width * height * 1 / 2; | ||
385 | } | ||
386 | |||
387 | return (0); | ||
388 | } | ||
389 | |||
390 | void output_free(void) | ||
391 | { | ||
392 | OutputBuffer *buf = head; | ||
393 | |||
394 | while((buf=head)) { | ||
395 | if( buf->tiler ) { | ||
396 | MemMgr_Free(buf->buf); | ||
397 | } else { | ||
398 | //munmap(buf->buf, buf->len); | ||
399 | SHM_release(&buf->shmBuf); | ||
400 | } | ||
401 | head = buf->next; | ||
402 | free(buf); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | OutputBuffer *output_get(void) | ||
407 | { | ||
408 | OutputBuffer *buf = head; | ||
409 | |||
410 | if( buf ) { | ||
411 | head = buf->next; | ||
412 | } | ||
413 | DEBUG("output_get: %p", buf); | ||
414 | return (buf); | ||
415 | } | ||
416 | |||
417 | void output_release(OutputBuffer *buf) | ||
418 | { | ||
419 | DEBUG("output_release: %p", buf); | ||
420 | buf->next = head; | ||
421 | head = buf; | ||
422 | } | ||
423 | |||
424 | /* ************************************************************************* */ | ||
425 | |||
426 | /* get file path.. return path is only valid until next time this is called */ | ||
427 | static const char *get_path(const char *pattern, int cnt) | ||
428 | { | ||
429 | static int len = 0; | ||
430 | static char *path = NULL; | ||
431 | |||
432 | /* It would be better to not assume the pattern doesn't expand to | ||
433 | * less than 10 chars it's original length.. | ||
434 | */ | ||
435 | if((strlen(pattern) + 10) > len ) { | ||
436 | len = strlen(pattern) + 10; | ||
437 | path = realloc(path, len); | ||
438 | } | ||
439 | |||
440 | snprintf(path, len - 1, pattern, cnt); | ||
441 | |||
442 | return (path); | ||
443 | } | ||
444 | |||
445 | /* helper to read one frame of input */ | ||
446 | int read_input(const char *pattern, int cnt, char *input) | ||
447 | { | ||
448 | int sz = 0, n = 0; | ||
449 | const char *path = get_path(pattern, cnt); | ||
450 | int fd = open(path, O_RDONLY); | ||
451 | |||
452 | //DEBUG("Open file fd %d errno %d", fd, errno); | ||
453 | /* if we can't find the file, then at the end of stream */ | ||
454 | if( fd < 0 ) { | ||
455 | DEBUG("open input file failed"); | ||
456 | return (0); | ||
457 | } | ||
458 | |||
459 | if( frameSize[cnt] && (frameSize[cnt] != -1)) { | ||
460 | lseek(fd, input_offset, SEEK_SET); | ||
461 | n = read(fd, input, frameSize[cnt]); | ||
462 | //DEBUG("reading input frameSize[%d] = n =%d", cnt, n); | ||
463 | sz += n; | ||
464 | input_offset += n; | ||
465 | } else if((frameSize[cnt] == -1)) { | ||
466 | // This happens to indicate flush command | ||
467 | DEBUG("Flush requested from file size -1,frameSize[%d] is %d", cnt, frameSize[cnt]); | ||
468 | sz = -1; | ||
469 | } | ||
470 | |||
471 | close(fd); | ||
472 | |||
473 | DEBUG("sz=%d", sz); | ||
474 | return (sz); | ||
475 | } | ||
476 | |||
477 | /* helper to write one frame of output */ | ||
478 | int write_output(const char *pattern, int cnt, char *y, char *uv, int stride) | ||
479 | { | ||
480 | int sz = 0, n, i; | ||
481 | const char *path = get_path(pattern, cnt); | ||
482 | int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644); | ||
483 | |||
484 | if( fd < 0 ) { | ||
485 | ERROR("could open output file: %s (%d)", path, errno); | ||
486 | return (0); | ||
487 | } | ||
488 | |||
489 | for( i = 0; i < height; i++ ) { | ||
490 | char *p = y; | ||
491 | int len = width; | ||
492 | |||
493 | while( len && ((n = write(fd, p, len)) > 0)) { | ||
494 | sz += n; | ||
495 | p += n; | ||
496 | len -= n; | ||
497 | } | ||
498 | |||
499 | if( n < 0 ) { | ||
500 | ERROR("couldn't write to output file: (%d)", errno); | ||
501 | break; | ||
502 | } | ||
503 | y += stride; | ||
504 | } | ||
505 | |||
506 | if( n >= 0 ) { | ||
507 | for( i = 0; i < height / 2; i++ ) { | ||
508 | char *p = uv; | ||
509 | int len = width; | ||
510 | |||
511 | while( len && ((n = write(fd, p, len)) > 0)) { | ||
512 | sz += n; | ||
513 | p += n; | ||
514 | len -= n; | ||
515 | } | ||
516 | |||
517 | if( n < 0 ) { | ||
518 | ERROR("couldn't write to output file: (%d)", errno); | ||
519 | break; | ||
520 | } | ||
521 | uv += stride; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | close(fd); | ||
526 | |||
527 | return (sz); | ||
528 | } | ||
529 | |||
530 | #ifdef PROFILE_TIME | ||
531 | /* for timing in microsecond */ | ||
532 | uint64_t mark_microsecond(uint64_t *last) | ||
533 | { | ||
534 | #if 0 | ||
535 | struct timespec time; | ||
536 | uint64_t t1 = 0; | ||
537 | |||
538 | clock_gettime(CLOCK_REALTIME, &time); | ||
539 | t1 = timespec2nsec(&time); | ||
540 | t1 = t1 / 1000; | ||
541 | #else | ||
542 | uint64_t t1 = 0; | ||
543 | |||
544 | t1 = ClockCycles(); | ||
545 | t1 = t1 * 1000000000 / SYSPAGE_ENTRY(qtime)->cycles_per_sec; | ||
546 | t1 = t1 / 1000; | ||
547 | #endif | ||
548 | if( last ) { | ||
549 | return (t1 - *last); | ||
550 | } | ||
551 | return (t1); | ||
552 | } | ||
553 | |||
554 | #endif | ||
555 | //#define DUMPINPUTDATA | ||
556 | |||
557 | #ifdef DUMPINPUTDATA | ||
558 | FILE *inputDump; | ||
559 | #endif | ||
560 | |||
561 | #define VERSION_SIZE 128 | ||
562 | static char version_buffer[VERSION_SIZE]; | ||
563 | |||
564 | /* decoder body */ | ||
565 | int main(int argc, char * *argv) | ||
566 | { | ||
567 | Engine_Error ec; | ||
568 | XDAS_Int32 err; | ||
569 | char *input = NULL; | ||
570 | char *in_pattern, *out_pattern, *frameData; | ||
571 | int in_cnt = 0, out_cnt = 0; | ||
572 | int oned, stride; | ||
573 | unsigned int frameCount = 0; | ||
574 | FILE *frameFile; | ||
575 | unsigned char frameinput[10] = { "\0" }; | ||
576 | int eof = 0; | ||
577 | int ivahd_decode_type; | ||
578 | char vid_codec[10]; | ||
579 | char tilerbuffer[10]; | ||
580 | unsigned int codec_switch = 0; | ||
581 | unsigned int vc1_flush = 0; | ||
582 | Bool outBufsInUse = FALSE; | ||
583 | |||
584 | #ifdef PROFILE_TIME | ||
585 | uint64_t init_start_time = 0; | ||
586 | uint64_t codec_process_time = 0; | ||
587 | uint64_t total_init_time = 0; | ||
588 | uint64_t output_alloc_time = 0; | ||
589 | #endif | ||
590 | |||
591 | #if 0 | ||
592 | int loop = 0; | ||
593 | |||
594 | while( loop == 0 ) { | ||
595 | loop = 0; | ||
596 | } | ||
597 | |||
598 | #endif | ||
599 | |||
600 | if((argc >= 2) && !strcmp(argv[1], "-1")) { | ||
601 | oned = TRUE; | ||
602 | argc--; | ||
603 | argv++; | ||
604 | } else { | ||
605 | oned = FALSE; | ||
606 | } | ||
607 | |||
608 | if( argc != 8 ) { | ||
609 | printf("usage: %s width height framefile inpattern outpattern codec tilerbuffer\n", argv[0]); | ||
610 | printf("example: %s 320 240 frame.txt in.h264 out.yuv h264 tiler\n", argv[0]); | ||
611 | printf("example: %s 640 480 frame.txt in.m4v out.yuv mpeg4 nontiler\n", argv[0]); | ||
612 | printf("example: %s 720 480 frame.txt in.vc1 out.yuv vc1ap tiler\n", argv[0]); | ||
613 | printf("example: %s 320 240 frame.txt in.vc1 out.yuv vc1smp nontiler\n", argv[0]); | ||
614 | printf("example: %s 1280 720 frame.txt in.bin out.yuv mjpeg tiler\n", argv[0]); | ||
615 | printf("example: %s 1920 1088 frame.txt in.bin out.yuv mpeg2 nontiler\n", argv[0]); | ||
616 | printf("Currently supported codecs: h264, mpeg4, vc1ap, vc1smp, mjpeg, mpeg2\n"); | ||
617 | return (1); | ||
618 | } | ||
619 | |||
620 | /* error checking? */ | ||
621 | width = atoi(argv[1]); | ||
622 | height = atoi(argv[2]); | ||
623 | frameData = argv[3]; | ||
624 | in_pattern = argv[4]; | ||
625 | out_pattern = argv[5]; | ||
626 | strcpy(vid_codec, argv[6]); | ||
627 | strcpy(tilerbuffer, argv[7]); | ||
628 | |||
629 | printf("Selected codec: %s\n", vid_codec); | ||
630 | printf("Selected buffer: %s\n", tilerbuffer); | ||
631 | |||
632 | enum { | ||
633 | DCE_TEST_H264 = 1, | ||
634 | DCE_TEST_MPEG4 = 2, | ||
635 | DCE_TEST_VC1SMP = 3, | ||
636 | DCE_TEST_VC1AP = 4, | ||
637 | DCE_TEST_MJPEG = 5, | ||
638 | DCE_TEST_MPEG2 = 6 | ||
639 | }; | ||
640 | |||
641 | if((!(strcmp(vid_codec, "h264")))) { | ||
642 | ivahd_decode_type = IVAHD_H264_DECODE; | ||
643 | codec_switch = DCE_TEST_H264; | ||
644 | |||
645 | } else if((!(strcmp(vid_codec, "mpeg4")))) { | ||
646 | ivahd_decode_type = IVAHD_MP4V_DECODE; | ||
647 | codec_switch = DCE_TEST_MPEG4; | ||
648 | |||
649 | } else if((!(strcmp(vid_codec, "vc1smp")))) { | ||
650 | ivahd_decode_type = IVAHD_VC1SMP_DECODE; | ||
651 | codec_switch = DCE_TEST_VC1SMP; | ||
652 | vc1_flush = 1; | ||
653 | |||
654 | } else if((!(strcmp(vid_codec, "vc1ap")))) { | ||
655 | ivahd_decode_type = IVAHD_VC1AP_DECODE; | ||
656 | codec_switch = DCE_TEST_VC1AP; | ||
657 | vc1_flush = 1; | ||
658 | |||
659 | } else if((!(strcmp(vid_codec, "mjpeg")))) { | ||
660 | ivahd_decode_type = IVAHD_JPEGV_DECODE; | ||
661 | codec_switch = DCE_TEST_MJPEG; | ||
662 | |||
663 | } else if((!(strcmp(vid_codec, "mpeg2")))) { | ||
664 | ivahd_decode_type = IVAHD_MP2V_DECODE; | ||
665 | codec_switch = DCE_TEST_MPEG2; | ||
666 | |||
667 | } else { | ||
668 | printf("No valid codec entry. Please use: h264, mpeg4, vc1ap, vc1smp, mjpeg or mpeg2\n"); | ||
669 | return (1); | ||
670 | } | ||
671 | |||
672 | DEBUG("Storing frame size data"); | ||
673 | frameFile = fopen(frameData, "rb"); | ||
674 | DEBUG("frameFile open %p errno %d", frameFile, errno); | ||
675 | if( frameFile == NULL ) { | ||
676 | DEBUG("Opening framesize file FAILED"); | ||
677 | } | ||
678 | |||
679 | /* Read the frame Size from the frame size file */ | ||
680 | while( NULL != fgets((char *)frameinput, 10, frameFile)) { | ||
681 | frameSize[frameCount] = atoi((char *)frameinput); | ||
682 | //DEBUG("frameSize[%d] = %d \n", frameCount, frameSize[frameCount]); | ||
683 | |||
684 | if( frameCount > 64000 ) { | ||
685 | DEBUG("Num Frames %d exceeded MAX limit %d \n", frameCount, 64000); | ||
686 | goto out; | ||
687 | } | ||
688 | frameCount++; | ||
689 | } | ||
690 | |||
691 | DEBUG("Num Frames is %d width=%d, height=%d", frameCount, width, height); | ||
692 | |||
693 | /* calculate output buffer parameters: */ | ||
694 | width = ALIGN2(width, 4); /* round up to MB */ | ||
695 | height = ALIGN2(height, 4); /* round up to MB */ | ||
696 | |||
697 | switch( codec_switch ) { | ||
698 | case DCE_TEST_H264 : | ||
699 | padded_width = ALIGN2(width + (2 * PADX_H264), 7); | ||
700 | padded_height = height + 4 * PADY_H264; | ||
701 | // Some clips don't have enough buffers based on N+3 formula | ||
702 | // Need sps->num_ref_frames data to match filter precisely | ||
703 | //num_buffers = 2 * (MIN(16, 32768 / ((width / 16) * (height / 16)))) + 1; | ||
704 | num_buffers = (MIN(16, 32768 / ((width / 16) * (height / 16)))) + 3; | ||
705 | break; | ||
706 | case DCE_TEST_MPEG4 : | ||
707 | padded_width = ALIGN2(width + PADX_MPEG4, 7); | ||
708 | padded_height = height + PADY_MPEG4; | ||
709 | num_buffers = 8; | ||
710 | break; | ||
711 | case DCE_TEST_VC1SMP : | ||
712 | case DCE_TEST_VC1AP : | ||
713 | padded_width = ALIGN2(width + (2 * PADX_VC1), 7); | ||
714 | padded_height = (ALIGN2(height / 2, 4) * 2) + 4 * PADY_VC1; | ||
715 | num_buffers = 5; | ||
716 | break; | ||
717 | case DCE_TEST_MJPEG : | ||
718 | padded_width = ALIGN2(width, 4); | ||
719 | padded_height = ALIGN2(height, 4); | ||
720 | num_buffers = 5; | ||
721 | break; | ||
722 | case DCE_TEST_MPEG2 : | ||
723 | padded_width = ALIGN2(width, 7); | ||
724 | padded_height = height; | ||
725 | num_buffers = 4; | ||
726 | break; | ||
727 | } | ||
728 | |||
729 | if( oned ) { | ||
730 | stride = padded_width; | ||
731 | } else { | ||
732 | stride = 4096; | ||
733 | } | ||
734 | |||
735 | DEBUG("padded_width=%d, padded_height=%d, stride=%d, num_buffers=%d", | ||
736 | padded_width, padded_height, stride, num_buffers); | ||
737 | #ifdef PROFILE_TIME | ||
738 | init_start_time = mark_microsecond(NULL); | ||
739 | #endif | ||
740 | engine = Engine_open("ivahd_vidsvr", NULL, &ec); | ||
741 | |||
742 | if( !engine ) { | ||
743 | ERROR("fail"); | ||
744 | goto out; | ||
745 | } | ||
746 | |||
747 | DEBUG("Engine_open successful engine=%p", engine); | ||
748 | |||
749 | switch( codec_switch ) { | ||
750 | case DCE_TEST_H264 : | ||
751 | params = dce_alloc(sizeof(IH264VDEC_Params)); | ||
752 | if( !params ) { | ||
753 | ERROR("dce_alloc fail"); | ||
754 | goto out; | ||
755 | } | ||
756 | params->size = sizeof(IH264VDEC_Params); | ||
757 | params->maxBitRate = 10000000; | ||
758 | params->displayDelay = IVIDDEC3_DISPLAY_DELAY_AUTO; | ||
759 | params->numOutputDataUnits = 0; | ||
760 | params->maxWidth = width; | ||
761 | break; | ||
762 | case DCE_TEST_MPEG4 : | ||
763 | params = dce_alloc(sizeof(IMPEG4VDEC_Params)); | ||
764 | if( !params ) { | ||
765 | ERROR("dce_alloc fail"); | ||
766 | goto out; | ||
767 | } | ||
768 | params->size = sizeof(IMPEG4VDEC_Params); | ||
769 | params->maxBitRate = 10000000; | ||
770 | params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; | ||
771 | params->numOutputDataUnits = 0; | ||
772 | params->maxWidth = width; | ||
773 | break; | ||
774 | case DCE_TEST_VC1SMP : | ||
775 | case DCE_TEST_VC1AP : | ||
776 | params = dce_alloc(sizeof(IVC1VDEC_Params)); | ||
777 | if( !params ) { | ||
778 | ERROR("dce_alloc fail"); | ||
779 | goto out; | ||
780 | } | ||
781 | params->size = sizeof(IVC1VDEC_Params); | ||
782 | params->maxBitRate = 45000000; | ||
783 | params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; | ||
784 | params->numOutputDataUnits = 0; | ||
785 | params->maxWidth = width; | ||
786 | break; | ||
787 | case DCE_TEST_MJPEG : | ||
788 | params = dce_alloc(sizeof(IJPEGVDEC_Params)); | ||
789 | if( !params ) { | ||
790 | ERROR("dce_alloc fail"); | ||
791 | goto out; | ||
792 | } | ||
793 | params->size = sizeof(IJPEGVDEC_Params); | ||
794 | params->maxBitRate = 10000000; | ||
795 | params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; | ||
796 | params->numOutputDataUnits = 1; | ||
797 | params->maxWidth = width; | ||
798 | break; | ||
799 | #ifdef ENABLE_MPEG2 | ||
800 | case DCE_TEST_MPEG2 : | ||
801 | params = dce_alloc(sizeof(IMPEG2VDEC_Params)); | ||
802 | if( !params ) { | ||
803 | ERROR("dce_alloc fail"); | ||
804 | goto out; | ||
805 | } | ||
806 | params->size = sizeof(IMPEG2VDEC_Params); | ||
807 | params->maxBitRate = 10000000; | ||
808 | params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; | ||
809 | params->numOutputDataUnits = 0; | ||
810 | params->maxWidth = padded_width; | ||
811 | break; | ||
812 | #endif | ||
813 | } | ||
814 | |||
815 | params->maxHeight = height; | ||
816 | params->maxFrameRate = 30000; | ||
817 | params->dataEndianness = XDM_BYTE; | ||
818 | params->forceChromaFormat = XDM_YUV_420SP; | ||
819 | params->operatingMode = IVIDEO_DECODE_ONLY; | ||
820 | //params->displayDelay = IVIDDEC3_DECODE_ORDER; | ||
821 | params->displayBufsMode = IVIDDEC3_DISPLAYBUFS_EMBEDDED; | ||
822 | params->inputDataMode = IVIDEO_ENTIREFRAME; | ||
823 | params->metadataType[0] = IVIDEO_METADATAPLANE_NONE; | ||
824 | params->metadataType[1] = IVIDEO_METADATAPLANE_NONE; | ||
825 | params->metadataType[2] = IVIDEO_METADATAPLANE_NONE; | ||
826 | params->outputDataMode = IVIDEO_ENTIREFRAME; | ||
827 | params->numInputDataUnits = 0; | ||
828 | params->errorInfoMode = IVIDEO_ERRORINFO_OFF; | ||
829 | |||
830 | DEBUG("dce_alloc VIDDEC3_Params successful params=%p", params); | ||
831 | |||
832 | switch( codec_switch ) { | ||
833 | case DCE_TEST_H264 : | ||
834 | h264_params = (IH264VDEC_Params *) params; | ||
835 | h264_params->dpbSizeInFrames = IH264VDEC_DPB_NUMFRAMES_AUTO; | ||
836 | h264_params->pConstantMemory = 0; | ||
837 | h264_params->presetLevelIdc = IH264VDEC_LEVEL41; | ||
838 | h264_params->errConcealmentMode = IH264VDEC_APPLY_CONCEALMENT; | ||
839 | h264_params->temporalDirModePred = TRUE; | ||
840 | h264_params->detectCabacAlignErr = IH264VDEC_DISABLE_CABACALIGNERR_DETECTION; | ||
841 | |||
842 | DEBUG("dce_alloc VIDDEC3_Params successful h264_params=%p", h264_params); | ||
843 | |||
844 | err = msync((Ptr)h264_params, sizeof(IH264VDEC_Params), MS_CACHE_ONLY | MS_SYNC); | ||
845 | |||
846 | codec = VIDDEC3_create(engine, "ivahd_h264dec", (VIDDEC3_Params *)h264_params); | ||
847 | break; | ||
848 | |||
849 | case DCE_TEST_MPEG4 : | ||
850 | mpeg4_params = (IMPEG4VDEC_Params *) params; | ||
851 | mpeg4_params->outloopDeBlocking = TRUE; | ||
852 | mpeg4_params->sorensonSparkStream = FALSE; | ||
853 | mpeg4_params->errorConcealmentEnable = FALSE; | ||
854 | mpeg4_params->debugTraceLevel = 0; | ||
855 | mpeg4_params->lastNFramesToLog = 0; | ||
856 | mpeg4_params->paddingMode = IMPEG4VDEC_DEFAULT_MODE_PADDING; | ||
857 | |||
858 | DEBUG("dce_alloc VIDDEC3_Params successful mpeg4_params=%p", mpeg4_params); | ||
859 | |||
860 | err = msync((Ptr)mpeg4_params, sizeof(IMPEG4VDEC_Params), MS_CACHE_ONLY | MS_SYNC); | ||
861 | #ifdef OMAP5 | ||
862 | codec = VIDDEC3_create(engine, "ivahd_mpeg4dec", (VIDDEC3_Params *)mpeg4_params); | ||
863 | #else | ||
864 | codec = VIDDEC3_create(engine, "ivahd_mpeg4vdec", (VIDDEC3_Params *)mpeg4_params); | ||
865 | #endif | ||
866 | break; | ||
867 | |||
868 | case DCE_TEST_VC1SMP : | ||
869 | case DCE_TEST_VC1AP : | ||
870 | vc1_params = (IVC1VDEC_Params *) params; | ||
871 | |||
872 | DEBUG("dce_alloc VIDDEC3_Params successful vc1_params=%p", vc1_params); | ||
873 | |||
874 | err = msync((Ptr)vc1_params, sizeof(IVC1VDEC_Params), MS_CACHE_ONLY | MS_SYNC); | ||
875 | |||
876 | codec = VIDDEC3_create(engine, "ivahd_vc1vdec", (VIDDEC3_Params *)vc1_params); | ||
877 | break; | ||
878 | |||
879 | case DCE_TEST_MJPEG : | ||
880 | mjpeg_params = (IJPEGVDEC_Params *) params; | ||
881 | mjpeg_params->ErrorConcealmentON = TRUE; | ||
882 | mjpeg_params->debugTraceLevel = 0; | ||
883 | mjpeg_params->lastNFramesToLog = 0; | ||
884 | mjpeg_params->sliceSwitchON = 0; | ||
885 | mjpeg_params->numSwitchPerFrame = 0; | ||
886 | mjpeg_params->numRestartMarkerPerSwitch = 0; | ||
887 | |||
888 | DEBUG("dce_alloc VIDDEC3_Params successful mjpeg_params=%p", mjpeg_params); | ||
889 | |||
890 | err = msync((Ptr)mjpeg_params, sizeof(IJPEGVDEC_Params), MS_CACHE_ONLY | MS_SYNC); | ||
891 | |||
892 | codec = VIDDEC3_create(engine, "ivahd_jpegvdec", (VIDDEC3_Params *)mjpeg_params); | ||
893 | break; | ||
894 | #ifdef ENABLE_MPEG2 | ||
895 | case DCE_TEST_MPEG2 : | ||
896 | mpeg2_params = (IMPEG2VDEC_Params *) params; | ||
897 | mpeg2_params->outloopDeBlocking = TRUE; | ||
898 | mpeg2_params->ErrorConcealmentON = FALSE; | ||
899 | mpeg2_params->debugTraceLevel = 0; | ||
900 | mpeg2_params->lastNFramesToLog = 0; | ||
901 | |||
902 | DEBUG("dce_alloc VIDDEC3_Params successful mpeg2_params=%p", mpeg2_params); | ||
903 | |||
904 | err = msync((Ptr)mpeg2_params, sizeof(IMPEG2VDEC_Params), MS_CACHE_ONLY | MS_SYNC); | ||
905 | |||
906 | codec = VIDDEC3_create(engine, "ivahd_mpeg2vdec", (VIDDEC3_Params *)mpeg2_params); | ||
907 | break; | ||
908 | #endif | ||
909 | } | ||
910 | |||
911 | if( !codec ) { | ||
912 | ERROR("fail"); | ||
913 | goto out; | ||
914 | } | ||
915 | |||
916 | DEBUG("VIDDEC3_create successful codec=%p", codec); | ||
917 | |||
918 | switch( codec_switch ) { | ||
919 | case DCE_TEST_H264 : | ||
920 | dynParams = dce_alloc(sizeof(IH264VDEC_DynamicParams)); | ||
921 | dynParams->size = sizeof(IH264VDEC_DynamicParams); | ||
922 | break; | ||
923 | case DCE_TEST_MPEG4 : | ||
924 | dynParams = dce_alloc(sizeof(IMPEG4VDEC_DynamicParams)); | ||
925 | dynParams->size = sizeof(IMPEG4VDEC_DynamicParams); | ||
926 | dynParams->lateAcquireArg = -1; | ||
927 | break; | ||
928 | case DCE_TEST_VC1SMP : | ||
929 | case DCE_TEST_VC1AP : | ||
930 | dynParams = dce_alloc(sizeof(IVC1VDEC_DynamicParams)); | ||
931 | dynParams->size = sizeof(IVC1VDEC_DynamicParams); | ||
932 | dynParams->lateAcquireArg = -1; | ||
933 | break; | ||
934 | case DCE_TEST_MJPEG : | ||
935 | dynParams = dce_alloc(sizeof(IJPEGVDEC_DynamicParams)); | ||
936 | dynParams->size = sizeof(IJPEGVDEC_DynamicParams); | ||
937 | dynParams->lateAcquireArg = -1; | ||
938 | break; | ||
939 | #ifdef ENABLE_MPEG2 | ||
940 | case DCE_TEST_MPEG2 : | ||
941 | dynParams = dce_alloc(sizeof(IMPEG2VDEC_DynamicParams)); | ||
942 | dynParams->size = sizeof(IMPEG2VDEC_DynamicParams); | ||
943 | dynParams->lateAcquireArg = -1; | ||
944 | break; | ||
945 | #endif | ||
946 | } | ||
947 | |||
948 | dynParams->decodeHeader = XDM_DECODE_AU; | ||
949 | /*Not Supported: Set default*/ | ||
950 | dynParams->displayWidth = 0; | ||
951 | dynParams->frameSkipMode = IVIDEO_NO_SKIP; | ||
952 | dynParams->newFrameFlag = XDAS_TRUE; | ||
953 | |||
954 | |||
955 | //Testing XDM_GETVERSION | ||
956 | // NOT WORKING | ||
957 | #if 0 | ||
958 | |||
959 | switch( codec_switch ) { | ||
960 | case DCE_TEST_H264 : | ||
961 | |||
962 | DEBUG("dce_alloc IH264VDEC_DynamicParams successful dynParams=%p", dynParams); | ||
963 | h264_dynParams = (IH264VDEC_DynamicParams *) dynParams; | ||
964 | DEBUG("dce_alloc IH264VDEC_DynamicParams successful h264_dynParams=%p", h264_dynParams); | ||
965 | |||
966 | status = dce_alloc(sizeof(IH264VDEC_Status)); | ||
967 | status->size = sizeof(IH264VDEC_Status); | ||
968 | DEBUG("dce_alloc IH264VDEC_Status successful status=%p", status); | ||
969 | |||
970 | status->data.buf = (XDAS_Int8 *) version_buffer; | ||
971 | h264_status = (IH264VDEC_Status *) status; | ||
972 | DEBUG("dce_alloc IH264VDEC_Status successful h264_status=%p", h264_status); | ||
973 | |||
974 | //((IH264VDEC_Status*)h264_status)->viddec3Status->data.buf = version_buffer; | ||
975 | err = VIDDEC3_control(codec, XDM_GETVERSION, (VIDDEC3_DynamicParams *) h264_dynParams, (VIDDEC3_Status *) h264_status); | ||
976 | |||
977 | DEBUG("dce_alloc IH264VDEC_Status get_version h264_status=%s", (((VIDDEC3_Status *)h264_status)->data.buf)); | ||
978 | break; | ||
979 | default : | ||
980 | DEBUG("Not implemented or supported codec_switch %d", codec_switch); | ||
981 | } | ||
982 | |||
983 | if( status ) { | ||
984 | dce_free(status); | ||
985 | } | ||
986 | #endif | ||
987 | |||
988 | switch( codec_switch ) { | ||
989 | case DCE_TEST_H264 : | ||
990 | |||
991 | DEBUG("dce_alloc IH264VDEC_DynamicParams successful dynParams=%p", dynParams); | ||
992 | h264_dynParams = (IH264VDEC_DynamicParams *) dynParams; | ||
993 | DEBUG("dce_alloc IH264VDEC_DynamicParams successful h264_dynParams=%p", h264_dynParams); | ||
994 | |||
995 | status = dce_alloc(sizeof(IH264VDEC_Status)); | ||
996 | status->size = sizeof(IH264VDEC_Status); | ||
997 | DEBUG("dce_alloc IH264VDEC_Status successful status=%p", status); | ||
998 | |||
999 | h264_status = (IH264VDEC_Status *) status; | ||
1000 | DEBUG("dce_alloc IH264VDEC_Status successful h264_status=%p", h264_status); | ||
1001 | err = VIDDEC3_control(codec, XDM_SETPARAMS, (VIDDEC3_DynamicParams *) h264_dynParams, (VIDDEC3_Status *) h264_status); | ||
1002 | break; | ||
1003 | |||
1004 | case DCE_TEST_MPEG4 : | ||
1005 | |||
1006 | DEBUG("dce_alloc IMPEG4VDEC_DynamicParams successful dynParams=%p", dynParams); | ||
1007 | mpeg4_dynParams = (IMPEG4VDEC_DynamicParams *) dynParams; | ||
1008 | DEBUG("dce_alloc IMPEG4VDEC_DynamicParams successful mpeg4_dynParams=%p", mpeg4_dynParams); | ||
1009 | |||
1010 | status = dce_alloc(sizeof(IMPEG4VDEC_Status)); | ||
1011 | status->size = sizeof(IMPEG4VDEC_Status); | ||
1012 | DEBUG("dce_alloc IMPEG4VDEC_Status successful status=%p", status); | ||
1013 | |||
1014 | mpeg4_status = (IMPEG4VDEC_Status *) status; | ||
1015 | DEBUG("dce_alloc IMPEG4VDEC_Status successful mpeg4_status=%p", mpeg4_status); | ||
1016 | err = VIDDEC3_control(codec, XDM_SETPARAMS, (VIDDEC3_DynamicParams *) mpeg4_dynParams, (VIDDEC3_Status *) mpeg4_status); | ||
1017 | break; | ||
1018 | |||
1019 | case DCE_TEST_VC1SMP : | ||
1020 | case DCE_TEST_VC1AP : | ||
1021 | |||
1022 | DEBUG("dce_alloc IVC1VDEC_DynamicParams successful dynParams=%p", dynParams); | ||
1023 | vc1_dynParams = (IVC1VDEC_DynamicParams *) dynParams; | ||
1024 | DEBUG("dce_alloc IVC1VDEC_DynamicParams successful vc1_dynParams=%p", vc1_dynParams); | ||
1025 | |||
1026 | status = dce_alloc(sizeof(IVC1VDEC_Status)); | ||
1027 | status->size = sizeof(IVC1VDEC_Status); | ||
1028 | DEBUG("dce_alloc IVC1VDEC_Status successful status=%p", status); | ||
1029 | |||
1030 | vc1_status = (IVC1VDEC_Status *) status; | ||
1031 | DEBUG("dce_alloc IVC1VDEC_Status successful vc1_status=%p", vc1_status); | ||
1032 | err = VIDDEC3_control(codec, XDM_SETPARAMS, (VIDDEC3_DynamicParams *) vc1_dynParams, (VIDDEC3_Status *) vc1_status); | ||
1033 | break; | ||
1034 | |||
1035 | case DCE_TEST_MJPEG : | ||
1036 | |||
1037 | DEBUG("dce_alloc IJPEGVDEC_DynamicParams successful dynParams=%p", dynParams); | ||
1038 | mjpeg_dynParams = (IJPEGVDEC_DynamicParams *) dynParams; | ||
1039 | mjpeg_dynParams->decodeThumbnail = 0; | ||
1040 | mjpeg_dynParams->thumbnailMode = IJPEGVDEC_THUMBNAIL_DOWNSAMPLE; | ||
1041 | mjpeg_dynParams->downsamplingFactor = IJPEGVDEC_NODOWNSAMPLE; | ||
1042 | mjpeg_dynParams->streamingCompliant = 1; | ||
1043 | |||
1044 | DEBUG("dce_alloc IJPEGVDEC_DynamicParams successful mjpeg_dynParams=%p", mjpeg_dynParams); | ||
1045 | |||
1046 | status = dce_alloc(sizeof(IVC1VDEC_Status)); | ||
1047 | status->size = sizeof(IJPEGVDEC_Status); | ||
1048 | DEBUG("dce_alloc IVC1VDEC_Status successful status=%p", status); | ||
1049 | |||
1050 | mjpeg_status = (IJPEGVDEC_Status *) status; | ||
1051 | DEBUG("dce_alloc IJPEGVDEC_Status successful mjpeg_status=%p", mjpeg_status); | ||
1052 | err = VIDDEC3_control(codec, XDM_SETPARAMS, (VIDDEC3_DynamicParams *) mjpeg_dynParams, (VIDDEC3_Status *) mjpeg_status); | ||
1053 | break; | ||
1054 | #ifdef ENABLE_MPEG2 | ||
1055 | case DCE_TEST_MPEG2 : | ||
1056 | |||
1057 | DEBUG("dce_alloc IMPEG2VDEC_DynamicParams successful dynParams=%p", dynParams); | ||
1058 | mpeg2_dynParams = (IMPEG2VDEC_DynamicParams *) dynParams; | ||
1059 | //MPEG2 buffer width should be 128 byte aligned for non TILER (atleast) | ||
1060 | //If displayWidth=0 then MPEG2 codec does not have a way to calculate | ||
1061 | //the stride as compared to other codecs which can calculate it from | ||
1062 | //buffer size and image height.stride=buffersize/(height*1.5) | ||
1063 | mpeg2_dynParams->viddecDynamicParams.displayWidth = padded_width; | ||
1064 | |||
1065 | DEBUG("dce_alloc IMPEG2VDEC_DynamicParams successful mpeg2_dynParams=%p", mpeg2_dynParams); | ||
1066 | |||
1067 | status = dce_alloc(sizeof(IMPEG2VDEC_Status)); | ||
1068 | status->size = sizeof(IMPEG2VDEC_Status); | ||
1069 | DEBUG("dce_alloc IMPEG2VDEC_Status successful status=%p", status); | ||
1070 | |||
1071 | mpeg2_status = (IMPEG2VDEC_Status *) status; | ||
1072 | DEBUG("dce_alloc IMPEG2VDEC_Status successful mpeg2_status=%p", mpeg2_status); | ||
1073 | err = VIDDEC3_control(codec, XDM_SETPARAMS, (VIDDEC3_DynamicParams *) mpeg2_dynParams, (VIDDEC3_Status *) mpeg2_status); | ||
1074 | break; | ||
1075 | #endif | ||
1076 | default : | ||
1077 | DEBUG("Not implemented or supported codec_switch %d", codec_switch); | ||
1078 | } | ||
1079 | |||
1080 | if( err ) { | ||
1081 | ERROR("fail: %d", err); | ||
1082 | goto shutdown; | ||
1083 | } | ||
1084 | |||
1085 | DEBUG("VIDDEC3_control XDM_SETPARAMS successful"); | ||
1086 | |||
1087 | DEBUG("input buffer configuration width %d height %d", width, height); | ||
1088 | inBufs = dce_alloc(sizeof(XDM2_BufDesc)); | ||
1089 | inBufs->numBufs = 1; | ||
1090 | input = tiler_alloc(width * height, 0); | ||
1091 | inBufs->descs[0].buf = (XDAS_Int8 *)input; | ||
1092 | inBufs->descs[0].memType = XDM_MEMTYPE_RAW; | ||
1093 | |||
1094 | DEBUG("inBufs->descs[0].buf %p input %p", inBufs->descs[0].buf, input); | ||
1095 | |||
1096 | outBufs = dce_alloc(sizeof(XDM2_BufDesc)); | ||
1097 | |||
1098 | DEBUG("output buffer configuration num_buffers %d padded_width %d padded_height %d", num_buffers, padded_width, padded_height); | ||
1099 | |||
1100 | #ifdef PROFILE_TIME | ||
1101 | uint64_t alloc_time_start = mark_microsecond(NULL); | ||
1102 | #endif | ||
1103 | |||
1104 | if( !(strcmp(tilerbuffer, "tiler"))) { | ||
1105 | DEBUG("Output allocate through tiler"); | ||
1106 | tiler = 1; | ||
1107 | err = output_allocate(outBufs, num_buffers, | ||
1108 | padded_width, padded_height, stride); | ||
1109 | } else { | ||
1110 | DEBUG("Output allocate through non-tiler"); | ||
1111 | tiler = 0; | ||
1112 | err = output_allocate_nonTiler(outBufs, num_buffers, | ||
1113 | padded_width, padded_height, stride); | ||
1114 | } | ||
1115 | |||
1116 | #ifdef PROFILE_TIME | ||
1117 | output_alloc_time = mark_microsecond(&alloc_time_start); | ||
1118 | #endif | ||
1119 | |||
1120 | if( err ) { | ||
1121 | ERROR("fail: %d", err); | ||
1122 | goto shutdown; | ||
1123 | } | ||
1124 | |||
1125 | inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs)); | ||
1126 | inArgs->size = sizeof(IVIDDEC3_InArgs); | ||
1127 | |||
1128 | outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs)); | ||
1129 | outArgs->size = sizeof(IVIDDEC3_OutArgs); | ||
1130 | |||
1131 | #ifdef PROFILE_TIME | ||
1132 | total_init_time = (uint64_t)mark_microsecond(&init_start_time); | ||
1133 | INFO("total_init_time %llu output_alloc_time %llu actual init time in: %lld us", total_init_time, output_alloc_time, total_init_time - output_alloc_time); | ||
1134 | #endif | ||
1135 | |||
1136 | while( inBufs->numBufs && outBufs->numBufs ) { | ||
1137 | OutputBuffer *buf; | ||
1138 | int n, i; | ||
1139 | |||
1140 | if( !outBufsInUse ) { | ||
1141 | buf = output_get(); | ||
1142 | if( !buf ) { | ||
1143 | ERROR("fail: out of buffers"); | ||
1144 | goto shutdown; | ||
1145 | } | ||
1146 | } else { | ||
1147 | buf = 0; | ||
1148 | } | ||
1149 | |||
1150 | n = read_input(in_pattern, in_cnt, input); | ||
1151 | if( n && (n != -1)) { | ||
1152 | eof = 0; | ||
1153 | inBufs->numBufs = 1; | ||
1154 | inBufs->descs[0].buf = (XDAS_Int8 *)input; | ||
1155 | inBufs->descs[0].bufSize.bytes = n; | ||
1156 | inArgs->numBytes = n; | ||
1157 | DEBUG("push: %d (%d bytes) (%p)", in_cnt, n, buf); | ||
1158 | in_cnt++; | ||
1159 | |||
1160 | /* | ||
1161 | * Input buffer has data to be decoded. | ||
1162 | */ | ||
1163 | inArgs->inputID = (XDAS_Int32)buf; | ||
1164 | if( !outBufsInUse ) { | ||
1165 | outBufs->numBufs = 2; | ||
1166 | outBufs->descs[0].buf = (XDAS_Int8 *)buf->y; | ||
1167 | outBufs->descs[1].buf = (XDAS_Int8 *)buf->uv; | ||
1168 | } | ||
1169 | } else if( n == -1 ) { | ||
1170 | |||
1171 | // Set EOF as 1 to ensure flush completes | ||
1172 | eof = 1; | ||
1173 | in_cnt++; | ||
1174 | |||
1175 | switch( codec_switch ) { | ||
1176 | case DCE_TEST_H264 : | ||
1177 | DEBUG("Calling VIDDEC3_control XDM_FLUSH h264_dynParams %p h264_status %p", h264_dynParams, h264_status); | ||
1178 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) h264_dynParams, (VIDDEC3_Status *) h264_status); | ||
1179 | break; | ||
1180 | case DCE_TEST_MPEG4 : | ||
1181 | DEBUG("Calling VIDDEC3_control XDM_FLUSH mpeg4_dynParams %p mpeg4_status %p", mpeg4_dynParams, mpeg4_status); | ||
1182 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) mpeg4_dynParams, (VIDDEC3_Status *) mpeg4_status); | ||
1183 | break; | ||
1184 | case DCE_TEST_VC1SMP : | ||
1185 | case DCE_TEST_VC1AP : | ||
1186 | DEBUG("Calling VIDDEC3_control XDM_FLUSH vc1_dynParams %p vc1_status %p", vc1_dynParams, vc1_status); | ||
1187 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) vc1_dynParams, (VIDDEC3_Status *) vc1_status); | ||
1188 | break; | ||
1189 | case DCE_TEST_MJPEG : | ||
1190 | DEBUG("Calling VIDDEC3_control XDM_FLUSH mjpeg_dynParams %p mjpeg_status %p", mjpeg_dynParams, mjpeg_status); | ||
1191 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) mjpeg_dynParams, (VIDDEC3_Status *) mjpeg_status); | ||
1192 | break; | ||
1193 | #ifdef ENABLE_MPEG2 | ||
1194 | case DCE_TEST_MPEG2 : | ||
1195 | DEBUG("Calling VIDDEC3_control XDM_FLUSH mpeg2_dynParams %p mpeg2_status %p", mpeg2_dynParams, mpeg2_status); | ||
1196 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) mpeg2_dynParams, (VIDDEC3_Status *) mpeg2_status); | ||
1197 | break; | ||
1198 | #endif | ||
1199 | } | ||
1200 | |||
1201 | /* We have sent the XDM_FLUSH, call VIDDEC3_process until we get | ||
1202 | * an error of XDM_EFAIL which tells us there are no more buffers | ||
1203 | * at codec level. | ||
1204 | */ | ||
1205 | |||
1206 | inArgs->inputID = 0; | ||
1207 | inArgs->numBytes = 0; | ||
1208 | inBufs->descs[0].buf = NULL; | ||
1209 | inBufs->descs[0].bufSize.bytes = 0; | ||
1210 | outBufs->numBufs = 0; | ||
1211 | outBufs->descs[0].buf = NULL; | ||
1212 | outBufs->descs[1].buf = NULL; | ||
1213 | if( buf ) { | ||
1214 | output_release(buf); | ||
1215 | } | ||
1216 | outBufsInUse = 0; | ||
1217 | |||
1218 | |||
1219 | } else { | ||
1220 | /* end of input.. */ | ||
1221 | inBufs->numBufs = 0; | ||
1222 | eof = 1; | ||
1223 | |||
1224 | switch( codec_switch ) { | ||
1225 | case DCE_TEST_H264 : | ||
1226 | DEBUG("Calling VIDDEC3_control XDM_FLUSH h264_dynParams %p h264_status %p", h264_dynParams, h264_status); | ||
1227 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) h264_dynParams, (VIDDEC3_Status *) h264_status); | ||
1228 | break; | ||
1229 | case DCE_TEST_MPEG4 : | ||
1230 | DEBUG("Calling VIDDEC3_control XDM_FLUSH mpeg4_dynParams %p mpeg4_status %p", mpeg4_dynParams, mpeg4_status); | ||
1231 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) mpeg4_dynParams, (VIDDEC3_Status *) mpeg4_status); | ||
1232 | break; | ||
1233 | case DCE_TEST_VC1SMP : | ||
1234 | case DCE_TEST_VC1AP : | ||
1235 | DEBUG("Calling VIDDEC3_control XDM_FLUSH vc1_dynParams %p vc1_status %p", vc1_dynParams, vc1_status); | ||
1236 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) vc1_dynParams, (VIDDEC3_Status *) vc1_status); | ||
1237 | break; | ||
1238 | case DCE_TEST_MJPEG : | ||
1239 | DEBUG("Calling VIDDEC3_control XDM_FLUSH mjpeg_dynParams %p mjpeg_status %p", mjpeg_dynParams, mjpeg_status); | ||
1240 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) mjpeg_dynParams, (VIDDEC3_Status *) mjpeg_status); | ||
1241 | break; | ||
1242 | #ifdef ENABLE_MPEG2 | ||
1243 | case DCE_TEST_MPEG2 : | ||
1244 | DEBUG("Calling VIDDEC3_control XDM_FLUSH mpeg2_dynParams %p mpeg2_status %p", mpeg2_dynParams, mpeg2_status); | ||
1245 | err = VIDDEC3_control(codec, XDM_FLUSH, (VIDDEC3_DynamicParams *) mpeg2_dynParams, (VIDDEC3_Status *) mpeg2_status); | ||
1246 | break; | ||
1247 | #endif | ||
1248 | } | ||
1249 | |||
1250 | /* We have sent the XDM_FLUSH, call VIDDEC3_process until we get | ||
1251 | * an error of XDM_EFAIL which tells us there are no more buffers | ||
1252 | * at codec level. | ||
1253 | */ | ||
1254 | |||
1255 | inArgs->inputID = 0; | ||
1256 | inArgs->numBytes = 0; | ||
1257 | inBufs->numBufs = 0; | ||
1258 | inBufs->descs[0].buf = NULL; | ||
1259 | inBufs->descs[0].bufSize.bytes = 0; | ||
1260 | outBufs->numBufs = 0; | ||
1261 | outBufs->descs[0].buf = NULL; | ||
1262 | outBufs->descs[1].buf = NULL; | ||
1263 | if( buf ) { | ||
1264 | output_release(buf); | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | #ifdef DUMPINPUTDATA | ||
1269 | DEBUG("input data dump inArgs->numBytes[%d] inputDump[%p]", inArgs->numBytes, inputDump); | ||
1270 | |||
1271 | //Dump the file | ||
1272 | if( inputDump == NULL ) { | ||
1273 | inputDump = fopen("/tmp/inputdump.h264", "ab"); | ||
1274 | DEBUG("input data dump file open %p errno %d", inputDump, errno); | ||
1275 | if( inputDump == NULL ) { | ||
1276 | DEBUG("Opening input Dump /tmp/inputdump.h264 file FAILED"); | ||
1277 | } | ||
1278 | } | ||
1279 | DEBUG("input data dump file open %p Successful", inputDump); | ||
1280 | |||
1281 | fwrite(input, sizeof(char), inArgs->numBytes, inputDump); | ||
1282 | DEBUG("Dumping input file with size = %d ", inArgs->numBytes); | ||
1283 | fflush(inputDump); | ||
1284 | fclose(inputDump); | ||
1285 | inputDump = NULL; | ||
1286 | #endif | ||
1287 | |||
1288 | int iters = 0; | ||
1289 | |||
1290 | do { | ||
1291 | DEBUG("Calling VIDDEC3_process inArgs->inputID=%x inBufs->descs[0].buf %p inBufs->descs.bufSize %d input %p", | ||
1292 | inArgs->inputID, inBufs->descs[0].buf, (int) inBufs->descs[0].bufSize.bytes, input); | ||
1293 | #ifdef PROFILE_TIME | ||
1294 | codec_process_time = mark_microsecond(NULL); | ||
1295 | #endif | ||
1296 | err = VIDDEC3_process(codec, inBufs, outBufs, inArgs, outArgs); | ||
1297 | #ifdef PROFILE_TIME | ||
1298 | INFO("processed returned in: %llu us", (uint64_t) mark_microsecond(&codec_process_time)); | ||
1299 | #endif | ||
1300 | if( err ) { | ||
1301 | if( XDM_ISFATALERROR(outArgs->extendedError)) { | ||
1302 | ERROR("process returned error: %d\n", err); | ||
1303 | ERROR("extendedError: %08x", outArgs->extendedError); | ||
1304 | goto shutdown; | ||
1305 | } else if( eof ) { | ||
1306 | /* | ||
1307 | * Flush has been ordered, processing the returned output from codec. | ||
1308 | * For H.264, bit 18 - IH264VDEC_ERR_STREAM_END indicates flush is completed. | ||
1309 | * For MPEG4, bit 24 - IMPEG4VDEC_ERR_STREAM_END indicates flush is completed. | ||
1310 | * Only return XDM_EFAIL, when those bit are set. | ||
1311 | */ | ||
1312 | ERROR("Codec_process returned err=%d, extendedError=%08x", err, outArgs->extendedError); | ||
1313 | err = XDM_EFAIL; | ||
1314 | |||
1315 | if((!(((outArgs->extendedError) >> 24) & 0x1)) && | ||
1316 | ((ivahd_decode_type == 2 /*IVAHD_MP4V_DECODE*/) || | ||
1317 | (ivahd_decode_type == 3 /*IVAHD_S263_DECODE*/))) { | ||
1318 | err = XDM_EOK; | ||
1319 | } | ||
1320 | |||
1321 | if((!(((outArgs->extendedError) >> 18) & 0x1)) && | ||
1322 | ((ivahd_decode_type == 1 /*IVAHD_H264_DECODE*/) || | ||
1323 | (ivahd_decode_type == 0 /*IVAHD_AVC1_DECODE*/))) { | ||
1324 | err = XDM_EOK; | ||
1325 | } | ||
1326 | |||
1327 | if( err == XDM_EFAIL ) { | ||
1328 | DEBUG("-------------------- Flush completed------------------------"); | ||
1329 | } | ||
1330 | } else { | ||
1331 | DEBUG("Non-fatal err=%d, extendedError=%08x", err, outArgs->extendedError); | ||
1332 | err = XDM_EOK; | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | /* | ||
1337 | * Handling of output data from codec | ||
1338 | */ | ||
1339 | if( tiler ) { | ||
1340 | for( i = 0; outArgs->outputID[i]; i++ ) { | ||
1341 | /* calculate offset to region of interest */ | ||
1342 | XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion); | ||
1343 | |||
1344 | int yoff = (r->topLeft.y * stride) + r->topLeft.x; | ||
1345 | int uvoff = (r->topLeft.y * stride / 2) + (stride * padded_height) + r->topLeft.x; | ||
1346 | |||
1347 | /* get the output buffer and write it to file */ | ||
1348 | buf = (OutputBuffer *)outArgs->outputID[i]; | ||
1349 | DEBUG("pop: %d (%p)", out_cnt, buf); | ||
1350 | |||
1351 | if( out_cnt < 30 ) { // write first 30 frames to output file out_cnt < 300 | ||
1352 | write_output(out_pattern, out_cnt++, buf->buf + yoff, | ||
1353 | buf->buf + uvoff, stride); | ||
1354 | } else { | ||
1355 | out_cnt++; | ||
1356 | } | ||
1357 | } | ||
1358 | } else { | ||
1359 | for( i = 0; outArgs->outputID[i]; i++ ) { | ||
1360 | /* calculate offset to region of interest */ | ||
1361 | XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion); | ||
1362 | |||
1363 | int yoff = (r->topLeft.y * padded_width) + r->topLeft.x; | ||
1364 | int uvoff = (r->topLeft.y * padded_width / 2) + (padded_height * padded_width) + r->topLeft.x; | ||
1365 | |||
1366 | /* get the output buffer and write it to file */ | ||
1367 | buf = (OutputBuffer *)outArgs->outputID[i]; | ||
1368 | DEBUG("pop: %d (%p)", out_cnt, buf); | ||
1369 | |||
1370 | if( out_cnt < 300 ) { // write first 300 frames to output file | ||
1371 | write_output(out_pattern, out_cnt++, buf->buf + yoff, | ||
1372 | buf->buf + uvoff, padded_width); | ||
1373 | } else { | ||
1374 | out_cnt++; | ||
1375 | } | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | for( i = 0; outArgs->freeBufID[i]; i++ ) { | ||
1380 | DEBUG("freeBufID[%d] = %d", i, outArgs->freeBufID[i]); | ||
1381 | buf = (OutputBuffer *)outArgs->freeBufID[i]; | ||
1382 | output_release(buf); | ||
1383 | } | ||
1384 | |||
1385 | if( outArgs->outBufsInUseFlag ) { | ||
1386 | outBufsInUse = TRUE; | ||
1387 | DEBUG("outBufsInUseFlag is SET. Not sending a new output buffer to codec on the next Codec_process "); | ||
1388 | } else { | ||
1389 | outBufsInUse = FALSE; | ||
1390 | } | ||
1391 | |||
1392 | ++iters; // Guard for infinite VIDDEC3_PROCESS loop when codec never return XDM_EFAIL | ||
1393 | } while( eof && (err != XDM_EFAIL) && (iters < 100)); // Multiple VIDDEC3_process when eof until err == XDM_EFAIL | ||
1394 | |||
1395 | } | ||
1396 | |||
1397 | shutdown: | ||
1398 | |||
1399 | printf("\nDeleting codec...\n"); | ||
1400 | VIDDEC3_delete(codec); | ||
1401 | |||
1402 | out: | ||
1403 | if( engine ) { | ||
1404 | Engine_close(engine); | ||
1405 | } | ||
1406 | if( params ) { | ||
1407 | dce_free(params); | ||
1408 | } | ||
1409 | if( dynParams ) { | ||
1410 | dce_free(dynParams); | ||
1411 | } | ||
1412 | if( status ) { | ||
1413 | dce_free(status); | ||
1414 | } | ||
1415 | if( inBufs ) { | ||
1416 | dce_free(inBufs); | ||
1417 | } | ||
1418 | if( outBufs ) { | ||
1419 | dce_free(outBufs); | ||
1420 | } | ||
1421 | if( inArgs ) { | ||
1422 | dce_free(inArgs); | ||
1423 | } | ||
1424 | if( outArgs ) { | ||
1425 | dce_free(outArgs); | ||
1426 | } | ||
1427 | if( input ) { | ||
1428 | MemMgr_Free(input); | ||
1429 | } | ||
1430 | |||
1431 | output_free(); | ||
1432 | |||
1433 | printf("DCE test completed...\n"); | ||
1434 | |||
1435 | return (0); | ||
1436 | } | ||
1437 | |||
diff --git a/test_qnx/dce_test.use b/test_qnx/dce_test.use new file mode 100644 index 0000000..413d849 --- /dev/null +++ b/test_qnx/dce_test.use | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * $QNXLicenseC: | ||
3 | */ | ||
4 | |||
5 | |||
6 | %C dce test application to test libdce | ||
7 | |||
8 | Syntax: | ||
9 | %C [options] | ||
10 | Options: | ||
11 | -h Print out the help information | ||
12 | |||
13 | Examples: | ||
14 | 1. decoding h.264 | ||
15 | dce_test width height framesize inpattern outpattern codec tiler/nontiler | ||
16 | dce_test 320 240 framesize.txt inputfile.h264 outputfile.yuv h264 tiler | ||
17 | |||
18 | 2. decoding mpeg4 | ||
19 | dce_test width height framesize inpattern outpattern codec tiler/nontiler | ||
20 | dce_test 640 480 framesize.txt inputfile.m4v outputfile.yuv mpeg4 nontiler | ||
21 | |||
22 | 3. decoding vc1ap | ||
23 | dce_test width height framesize inpattern outpattern codec tiler/nontiler | ||
24 | dce_test 720 480 framesize.txt inputfile.vc1 outputfile.yuv vc1ap tiler | ||
25 | |||
26 | 4. decoding vc1smp | ||
27 | dce_test width height framesize inpattern outpattern codec tiler/nontiler | ||
28 | dce_test 320 240 framesize.txt inputfile.vc1 outputfile.yuv vc1smp nontiler | ||
29 | |||
30 | 5. decoding mjpeg | ||
31 | dce_test width height framesize inpattern outpattern codec tiler/nontiler | ||
32 | dce_test 1280 720 framesize.txt inputfile.bin outputfile.yuv mjpeg tiler | ||
33 | |||
34 | 6. decoding mpeg2 | ||
35 | dce_test width height framesize inpattern outpattern codec tiler/nontiler | ||
36 | dce_test 1920 1088 framesize.txt inputfile.bin outputfile.yuv mpeg2 nontiler | ||
37 | |||
38 | Currently supported codecs: h264, mpeg4, vc1ap, vc1smp, mjpeg, mpeg2 | ||