diff options
author | Saurabh Bipin Chandra | 2013-04-22 11:42:19 -0500 |
---|---|---|
committer | Saurabh Bipin Chandra | 2013-04-26 09:14:28 -0500 |
commit | 6647d1f16d70b9d867ce5b7aef92705939aa5975 (patch) | |
tree | 73b154f99e7ceff809c8a98be6489e4ee11d0877 | |
download | hardware-ti-libdce-6647d1f16d70b9d867ce5b7aef92705939aa5975.tar.gz hardware-ti-libdce-6647d1f16d70b9d867ce5b7aef92705939aa5975.tar.xz hardware-ti-libdce-6647d1f16d70b9d867ce5b7aef92705939aa5975.zip |
[libDCE] Add IPC 3.x Adapted code to Repository
This patch adds libdce code to the repository.
LibDCE has been adapted to use the MmRpc layer
of IPC 3.x. This version of LibDCE is expected to
work on QNX.
Patchset 2 adds/modifies:
1. Removes Tiler 2D allocation/free for now.
2. Corrects memplugin_free() for Tiler 1D.
3. Modifies dce_test app to dump output till 30 frames.
4. Renamed dce.h to libdce.h.
5. Corrected header files across all files.
6. Build configuration for QNX
7. Removes build warnings.
8. Add README for Build instructions
9. Takes care of comments of Buddy and Pradeep.
Patchset 3 adds/modifies:
1. Reduced Stack usage of each function.
2. Add ptr check in memplugin and remove from libdce.
3. Add DCE_Assert macros.
4. Add DCE_error_status enum.
5. Comments Cleanup
6. Make some functions static.
7. process() cleanup including removing reply_buf.
8. Add else if (for codec_type == Encoder type)
9. Converted Macros to Inline functions.
10.Converted init and deinit to dce_init and dce_deinit functions.
11. Removed dce_init() and dce_deinit() declarations
Patchset 4 adds/modifies:
1. Assert Input function arguments.
2. Correct copyright year.
3. Correct memplugin_free for Shared memory.
4. Create dce_priv.h and move trace and assert macros to the header.
5. Redeclare mem_type enum and add mem_error_status enum in
memplugin.h and make corresponding changes.
6. Add asserts in memplugin.
Intention of some of the changes above is to move towards
delinking Libdce and Memplugin.
Patchset 5:
1. Missed to add dce_priv.h file.
Patchset 6:
1. Take care Pradeep's comment.
Change-Id: I6e5e37b7088362e7bad66200fc3454bb828e0eff
Signed-off-by: Saurabh Bipin Chandra <a0131926@ti.com>
-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 | ||