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 * ======== videnc1.c ========
35 * The XDM IVIDENC1-compliant video encode API's.
36 *
37 * The methods defined here must be independent of whether the underlying
38 * algorithm is executed locally or remotely.
39 *
40 * In fact, these methods must exist on *both* the client and server; the
41 * VIDENC1 skeletons (videnc1_skel.c) call these APIs to create instances on
42 * the remote CPU.
43 */
45 /* This define must precede inclusion of any xdc header files */
46 #define Registry_CURDESC ti_sdo_ce_video1_videnc1_desc
48 #include <xdc/std.h>
49 #include <xdc/runtime/Assert.h>
50 #include <xdc/runtime/Diags.h>
51 #include <xdc/runtime/Log.h>
52 #include <xdc/runtime/Registry.h>
54 #include <string.h> /* for memcmp */
56 #include <ti/sdo/ce/visa.h>
57 #include <ti/sdo/ce/global/CESettings.h>
59 #include <ti/xdais/ialg.h>
60 #include <ti/xdais/dm/ividenc1.h>
62 #include <ti/sdo/ce/utils/xdm/XdmUtils.h>
64 #include "videnc1.h"
65 #include "_videnc1.h"
67 #define MODNAME "ti.sdo.ce.video1.VIDENC1"
69 Registry_Desc ti_sdo_ce_video1_videnc1_desc;
71 static Int regInit = 0; /* Registry_addModule() called */
73 /*
74 * ======== VIDENC1_control ========
75 * This method must be the same for both local and remote invocation;
76 * each call site in the client might be calling different implementations
77 * (one that marshalls & sends and one that simply calls). This API
78 * abstracts *all* video encoders (both high and low complexity
79 * encoders are invoked using this method).
80 */
81 XDAS_Int32 VIDENC1_control(VIDENC1_Handle handle, VIDENC1_Cmd id,
82 VIDENC1_DynamicParams *dynParams, VIDENC1_Status *status)
83 {
84 XDAS_Int32 retVal = VIDENC1_EFAIL;
86 VIDENC1_DynamicParams refDynParams;
87 XDAS_Int32 refStatusSize;
88 XDAS_Int32 refStatusDataBufSize;
90 /*
91 * Note, we assign "VISA_isChecked()" results to a local variable
92 * rather than repeatedly query it throughout this fxn because
93 * someday we may allow dynamically changing the global
94 * 'VISA_isChecked()' value on the fly. If we allow that, we need
95 * to ensure the value stays consistent in the context of this
96 * call.
97 */
98 Bool checked = VISA_isChecked();
100 if (checked) {
101 /* Ensure dynParams and status are non-NULL, per the XDM spec */
103 if ((!(XdmUtils_validateExtendedStruct(dynParams, sizeof(*dynParams),
104 "dynParams"))) || (!(XdmUtils_validateExtendedStruct(status,
105 sizeof(*status), "status")))) {
106 /* for safety, return here before dereferencing and crashing */
107 return (retVal);
108 }
109 }
111 Log_print6(Diags_ENTRY, "[+E] VIDENC1_control> "
112 "Enter (handle=0x%x, id=%d, dynParams=0x%x (size=0x%x), "
113 "status=0x%x (size=0x%x)",
114 (IArg)handle, (IArg)id, (IArg)dynParams, (IArg)(dynParams->size),
115 (IArg)status, (IArg)(status->size));
117 if (handle) {
118 IVIDENC1_Fxns *fxns =
119 (IVIDENC1_Fxns *)VISA_getAlgFxns((VISA_Handle)handle);
120 IVIDENC1_Handle alg = VISA_getAlgHandle((VISA_Handle)handle);
122 if (fxns && (alg != NULL)) {
123 if (checked) {
124 /*
125 * Make a reference copy of dynParams, status->size, and
126 * status->data.bufSize so we can check that the codec
127 * didn't modify these read-only fields during control().
128 */
129 refDynParams = *dynParams;
130 refStatusSize = status->size;
131 refStatusDataBufSize = status->data.bufSize;
132 }
134 //Log_printf(ti_sdo_ce_dvtLog, "%s", (Arg)"VIDENC1:control",
135 // (Arg)handle, (Arg)0);
137 VISA_enter((VISA_Handle)handle);
138 retVal = fxns->control(alg, id, dynParams, status);
139 VISA_exit((VISA_Handle)handle);
141 if (checked) {
142 /* ensure the codec didn't modify the read-only dynParams */
143 if (memcmp(&refDynParams, dynParams, sizeof(*dynParams)) != 0) {
144 Log_print1(Diags_USER7,
145 "[+7] ERROR> codec (0x%x) modified read-only dynParams "
146 "struct!", (IArg)handle);
147 }
149 /* ensure the codec didn't change status->size */
150 if (status->size != refStatusSize) {
151 Log_print1(Diags_USER7,
152 "[+7] ERROR> codec (0x%x) modified read-only status->size "
153 "field!", (IArg)handle);
154 }
156 /* ensure the codec didn't change status->data.bufSize */
157 if (status->data.bufSize != refStatusDataBufSize) {
158 Log_print1(Diags_USER7,
159 "[+7] ERROR> codec (0x%x) modified read-only "
160 "status->data.bufSize field!", (IArg)handle);
161 }
162 }
163 }
164 }
166 Log_print2(Diags_EXIT, "[+X] VIDENC1_control> "
167 "Exit (handle=0x%x, retVal=0x%x)", (IArg)handle, (IArg)retVal);
169 return (retVal);
170 }
173 /*
174 * ======== VIDENC1_create ========
175 */
176 VIDENC1_Handle VIDENC1_create(Engine_Handle engine, String name,
177 IVIDENC1_Params *params)
178 {
179 Registry_Result result;
180 VIDENC1_Handle visa;
182 /* TODO:M Race here! Do we need ATM_Increment in our OSAL? */
183 if (regInit == 0) {
184 /* Register this module for logging */
185 result = Registry_addModule(&ti_sdo_ce_video1_videnc1_desc, MODNAME);
186 Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
188 if (result == Registry_SUCCESS) {
189 /* Set the diags mask to the CE default */
190 CESettings_init();
191 CESettings_setDiags(MODNAME);
192 }
193 regInit = 1;
194 }
196 Log_print3(Diags_ENTRY, "[+E] VIDENC1_create> "
197 "Enter (engine=0x%x, name='%s', params=0x%x)",
198 (IArg)engine, (IArg)name, (IArg)params);
200 visa = VISA_create(engine, name, (IALG_Params *)params,
201 sizeof (_VIDENC1_Msg), VIDENC1_VISATYPE);
203 Log_print1(Diags_EXIT, "[+X] VIDENC1_create> return (0x%x)", (IArg)visa);
205 return (visa);
206 }
209 /*
210 * ======== VIDENC1_delete ========
211 */
212 Void VIDENC1_delete(VIDENC1_Handle handle)
213 {
214 Log_print1(Diags_ENTRY, "[+E] VIDENC1_delete> Enter (handle=0x%x)",
215 (IArg)handle);
217 VISA_delete(handle);
219 Log_print0(Diags_EXIT, "[+X] VIDENC1_delete> return");
220 }
223 /*
224 * ======== VIDENC1_process ========
225 * This method must be the same for both local and remote invocation;
226 * each call site in the client might be calling different implementations
227 * (one that marshalls & sends and one that simply calls). This API
228 * abstracts *all* video encoders (both high and low complexity
229 * encoders are invoked using this method).
230 */
231 XDAS_Int32 VIDENC1_process(VIDENC1_Handle handle, IVIDEO1_BufDescIn *inBufs,
232 XDM_BufDesc *outBufs, IVIDENC1_InArgs *inArgs, IVIDENC1_OutArgs *outArgs)
233 {
234 XDAS_Int32 retVal = VIDENC1_EFAIL;
236 VIDENC1_InArgs refInArgs;
238 /*
239 * Note, we assign "VISA_isChecked()" results to a local variable
240 * rather than repeatedly query it throughout this fxn because
241 * someday we may allow dynamically changing the global
242 * 'VISA_isChecked()' value on the fly. If we allow that, we need
243 * to ensure the value stays consistent in the context of this
244 * call.
245 */
246 Bool checked = VISA_isChecked();
248 if (checked) {
249 /* Ensure inArgs and outArgs are non-NULL, per the XDM spec */
251 if ((!(XdmUtils_validateExtendedStruct(inArgs, sizeof(*inArgs),
252 "inArgs"))) || (!(XdmUtils_validateExtendedStruct(outArgs,
253 sizeof(*outArgs), "outArgs")))) {
254 /* for safety, return here before dereferencing and crashing */
255 return (retVal);
256 }
257 }
259 Log_print5(Diags_ENTRY, "[+E] VIDENC1_process> "
260 "Enter (handle=0x%x, inBufs=0x%x, outBufs=0x%x, inArgs=0x%x, "
261 "outArgs=0x%x)",
262 (IArg)handle, (IArg)inBufs, (IArg)outBufs, (IArg)inArgs,
263 (IArg)outArgs);
265 if (handle) {
266 IVIDENC1_Fxns *fxns =
267 (IVIDENC1_Fxns *)VISA_getAlgFxns((VISA_Handle)handle);
268 IVIDENC1_Handle alg = VISA_getAlgHandle((VISA_Handle)handle);
270 if (fxns && (alg != NULL)) {
271 if (checked) {
272 /* validate inArgs with ranges. */
273 if (inArgs->inputID == 0) {
275 Log_print2(Diags_USER7,
276 "[+7] ERROR> app provided codec (0x%x) with out of range "
277 "inArgs->inputID field (0x%x)",
278 (IArg)alg, (IArg)(inArgs->inputID));
279 }
281 /* Validate inBufs and outBufs. */
282 XdmUtils_validateVideo1BufDescIn(inBufs, "inBufs");
283 XdmUtils_validateSparseBufDesc(outBufs, "outBufs");
285 /*
286 * Make a reference copy of inArgs so we can check that
287 * the codec didn't modify them during process().
288 */
289 refInArgs = *inArgs;
290 }
292 //Log_printf(ti_sdo_ce_dvtLog, "%s", (Arg)"VIDENC1:process",
293 // (Arg)handle, (Arg)0);
295 VISA_enter((VISA_Handle)handle);
296 retVal = fxns->process(alg, inBufs, outBufs, inArgs, outArgs);
297 VISA_exit((VISA_Handle)handle);
299 if (checked) {
300 /* ensure the codec didn't modify the read-only inArgs */
301 if (memcmp(&refInArgs, inArgs, sizeof(*inArgs)) != 0) {
302 Log_print1(Diags_USER7,
303 "[+7] ERROR> codec (0x%x) modified read-only inArgs "
304 "struct!", (IArg)handle);
305 }
306 }
307 }
308 }
310 Log_print2(Diags_EXIT, "[+X] VIDENC1_process> "
311 "Exit (handle=0x%x, retVal=0x%x)", (IArg)handle, (IArg)retVal);
313 return (retVal);
314 }