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 * ======== viddec3_stubs.c ========
35 * This file contains an implemenation of the IVIDDEC3 interface for the
36 * video decoder class of algorithms.
37 *
38 * These functions are the "client-side" of a "remote" implementation.
39 *
40 */
42 /* This define must precede inclusion of any xdc header files */
43 #define Registry_CURDESC ti_sdo_ce_video3_viddec3_desc
45 #include <xdc/std.h>
46 #include <xdc/runtime/Assert.h>
47 #include <xdc/runtime/Diags.h>
48 #include <xdc/runtime/Log.h>
49 #include <xdc/runtime/Registry.h>
51 #include <ti/sdo/ce/visa.h>
52 #include <ti/xdais/dm/ividdec3.h>
53 #include <ti/sdo/ce/osal/Memory.h>
55 #include <string.h> /* for memcpy and memset. */
57 #include <ti/sdo/ce/utils/xdm/XdmUtils.h>
59 #include "viddec3.h"
60 #include "_viddec3.h"
62 extern Registry_Desc ti_sdo_ce_video3_viddec3_desc;
65 static XDAS_Int32 process(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
66 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs);
67 static XDAS_Int32 processAsync(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
68 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs);
69 static XDAS_Int32 processWait(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
70 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs,
71 UInt timeout);
72 static XDAS_Int32 control(IVIDDEC3_Handle h, IVIDDEC3_Cmd id,
73 IVIDDEC3_DynamicParams *params, IVIDDEC3_Status *status);
74 static XDAS_Int32 marshallMsg(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
75 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs,
76 _VIDDEC3_Msg **pmsg);
77 static XDAS_Int32 unmarshallMsg(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
78 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs,
79 _VIDDEC3_Msg *msg, XDAS_Int32 retVal);
80 static Bool p2vVideo2BufDesc(IVIDEO2_BufDesc *pBufDesc);
82 IVIDDEC3_Fxns VIDDEC3_STUBS = {
83 {&VIDDEC3_STUBS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
84 process, control,
85 };
88 /*
89 * ======== marshallMsg ========
90 */
91 static XDAS_Int32 marshallMsg(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
92 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs,
93 _VIDDEC3_Msg **pmsg)
94 {
95 XDAS_Int32 retVal = IVIDDEC3_EOK;
96 VISA_Handle visa = (VISA_Handle)h;
97 _VIDDEC3_Msg *msg;
98 Int i;
99 IVIDDEC3_OutArgs *pMsgOutArgs;
100 Int numBufs;
101 Int payloadSize;
103 /*
104 * Validate arguments. Do we want to do this _every_ time, or just in
105 * checked builds?
106 */
107 if ((inArgs == NULL) || (inArgs->size < sizeof(IVIDDEC3_InArgs)) ||
108 (outArgs == NULL) || (outArgs->size < sizeof(IVIDDEC3_OutArgs))) {
110 /* invalid args, could even assert here, it's a spec violation. */
111 return (IVIDDEC3_EFAIL);
112 }
114 /*
115 * Initialize extendedError to zero so we don't return something
116 * uninitialized in extendedError.
117 */
118 outArgs->extendedError = 0;
120 if (pmsg == NULL) {
121 return (IVIDDEC3_EFAIL);
122 }
124 /* make sure it'll all fit! */
125 payloadSize = sizeof(VISA_MsgHeader) + sizeof(*inBufs) + sizeof(*outBufs) +
126 inArgs->size + outArgs->size;
128 if (payloadSize > VISA_getMaxMsgSize(visa)) {
129 /* Can't handle these large extended args. */
130 Log_print2(Diags_USER6,
131 "[+6] process> invalid arguments - too big (0x%x > 0x%x). "
132 "Validate .size fields", payloadSize,
133 VISA_getMaxMsgSize(visa));
135 return (IVIDDEC3_EUNSUPPORTED);
136 }
138 /* get a message appropriate for this algorithm */
139 if ((msg = (_VIDDEC3_Msg *)VISA_allocMsg(visa)) == NULL) {
140 return (IVIDDEC3_EFAIL);
141 }
143 /* zero out msg->cmd (not msg->visa!) */
144 memset(&(msg->cmd), 0, sizeof(msg->cmd));
146 /*
147 * Marshall the command: copy the client-passed arguments into flattened
148 * message data structures, converting every pointer address to alg.
149 * data buffer into physical address.
150 */
152 /* First specify the processing command that the skeleton should do */
153 msg->visa.cmd = _VIDDEC3_CPROCESS;
155 /* commentary follows for marshalling the inBufs argument: */
157 /* 1) initialize the whole inBufs struct */
158 msg->cmd.process.inBufs = *inBufs;
160 /* 2) translate pointers present in the inBufs */
161 for (i = 0, numBufs = 0;
162 ((numBufs < inBufs->numBufs) && (i < XDM_MAX_IO_BUFFERS)); i++) {
163 if (inBufs->descs[i].buf != NULL) {
165 /* valid member of sparse array, convert it */
166 msg->cmd.process.inBufs.descs[i].buf = (XDAS_Int8 *)
167 Memory_getBufferPhysicalAddress(inBufs->descs[i].buf,
168 inBufs->descs[i].bufSize.bytes, NULL);
170 if (msg->cmd.process.inBufs.descs[i].buf == NULL) {
171 retVal = IVIDDEC3_EFAIL;
172 goto exit;
173 }
175 /* Clear .accessMask; the local processor won't access this buf */
176 inBufs->descs[i].accessMask = 0;
178 /* found, and handled, another buffer. */
179 numBufs++;
180 }
181 else {
182 /* empty member of sparse array, no conversion needed. */
183 msg->cmd.process.inBufs.descs[i].bufSize.bytes = 0;
184 msg->cmd.process.inBufs.descs[i].buf = NULL;
185 }
186 }
188 if (VISA_isChecked()) {
189 /* check that we found inBufs->numBufs pointers in inBufs->bufs[] */
190 Assert_isTrue(inBufs->numBufs == numBufs, (Assert_Id)NULL);
191 }
193 /* we're done (with inBufs). Because msg->cmd.process is non-cacheable
194 * and contiguous (it has been allocated by MSGQ), we don't have to do
195 * anything else.
196 */
198 /* translate outBufs. */
199 msg->cmd.process.outBufs.numBufs = outBufs->numBufs;
201 for (i = 0, numBufs = 0; i < XDM_MAX_IO_BUFFERS; i++) {
202 if (outBufs->descs[i].buf != NULL) {
203 /* initialize the buf desc, then translate the addr if needed */
204 msg->cmd.process.outBufs.descs[i] = outBufs->descs[i];
206 /* valid member of sparse array, convert it */
207 if (outBufs->descs[i].memType == XDM_MEMTYPE_RAW) {
208 msg->cmd.process.outBufs.descs[i].buf = (XDAS_Int8 *)
209 Memory_getBufferPhysicalAddress(outBufs->descs[i].buf,
210 outBufs->descs[i].bufSize.bytes, NULL);
211 }
212 else {
213 /* Does tiled memory need to be tranlated?!? */
214 Log_print1(Diags_USER4,
215 "[+4] Tiled memory buffer detected (0x%x), no addr "
216 "translation", (IArg)outBufs->descs[i].buf);
217 }
219 if (msg->cmd.process.outBufs.descs[i].buf == NULL) {
220 /* TODO:M - should add at least a trace statement when trace
221 * is supported. Another good idea is to return something
222 * more clear than EFAIL.
223 */
224 retVal = IVIDDEC3_EFAIL;
225 goto exit;
226 }
228 /* found, and handled, another buffer. See if it's the last one */
229 if (++numBufs == outBufs->numBufs) {
230 break;
231 }
232 }
233 else {
234 /* empty member of sparse array, no conversion needed */
235 msg->cmd.process.outBufs.descs[i].bufSize.bytes = 0;
236 msg->cmd.process.outBufs.descs[i].buf = NULL;
237 }
238 }
240 if (VISA_isChecked()) {
241 /* check that we found outBufs->numBufs pointers in outBufs->bufs[] */
242 Assert_isTrue(outBufs->numBufs == numBufs, (Assert_Id)NULL);
243 }
245 /* inArgs has no pointers so simply memcpy "size" bytes into the msg */
246 memcpy(&(msg->cmd.process.inArgs), inArgs, inArgs->size);
248 /* point at outArgs and set the "size" */
249 pMsgOutArgs = (IVIDDEC3_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) +
250 inArgs->size);
252 /* set the size field - the rest is filled in by the codec */
253 pMsgOutArgs->size = outArgs->size;
255 *pmsg = msg;
257 return (retVal);
259 exit:
260 VISA_freeMsg(visa, (VISA_Msg)msg);
262 return (retVal);
263 }
265 /*
266 * ======== unmarshallMsg ========
267 */
268 static XDAS_Int32 unmarshallMsg(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
269 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs,
270 _VIDDEC3_Msg *msg, XDAS_Int32 retVal)
271 {
272 VISA_Handle visa = (VISA_Handle)h;
273 Int i;
274 IVIDDEC3_OutArgs *pMsgOutArgs;
275 Int numBufs;
276 Bool success;
278 /*
279 * Do a wholesale replace of skeleton returned structure.
280 * Pointer conversion of fields in outArgs is done below (only
281 * in the case of a successful return value).
282 */
283 pMsgOutArgs = (IVIDDEC3_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) +
284 inArgs->size);
286 if (VISA_isChecked()) {
287 /* ensure the codec didn't change outArgs->size */
288 Assert_isTrue(pMsgOutArgs->size == outArgs->size, (Assert_Id)NULL);
289 }
291 memcpy(outArgs, pMsgOutArgs, outArgs->size);
293 /* if VISA_call was successful, unmarshall the necessary buffers. */
294 if (retVal == IVIDDEC3_EOK) {
295 /* unmarshall the output data in outBufs and outArgs. */
297 if (VISA_isChecked()) {
298 /* ensure the codec didn't send back "too many" buffers */
299 Assert_isTrue(
300 msg->cmd.process.outBufs.numBufs < XDM_MAX_IO_BUFFERS,
301 (Assert_Id)NULL);
302 }
304 /* The outBufs may have changed (right?), so init the outBufs struct. */
305 *outBufs = msg->cmd.process.outBufs;
307 for (i = 0, numBufs = 0;
308 ((numBufs < outBufs->numBufs) && (i < XDM_MAX_IO_BUFFERS)); i++) {
310 if (outBufs->descs[i].buf != NULL) {
311 /* valid member of sparse array, convert it */
312 if (outBufs->descs[i].memType == XDM_MEMTYPE_RAW) {
313 outBufs->descs[i].buf = (XDAS_Int8 *)
314 Memory_getBufferVirtualAddress(
315 (UInt32)outBufs->descs[i].buf,
316 outBufs->descs[i].bufSize.bytes);
317 }
318 else {
319 /* Does tiled memory need to be translated?!? */
320 Log_print1(Diags_USER4,
321 "Tiled memory buffer detected (0x%x), no addr "
322 "translation", (IArg)outBufs->descs[i].buf);
323 }
325 if (outBufs->descs[i].buf == NULL) {
326 /* TODO:L - return something more clear than EFAIL? */
327 Log_print1(Diags_USER7,
328 "[+7] ERROR> address translation of "
329 "outBufs->descs[0x%x].buf failed", i);
331 retVal = IVIDDEC3_EFAIL;
332 goto exit;
333 }
335 /* found, and handled, another buffer. */
336 numBufs++;
337 }
338 else {
339 /* empty member of sparse array, no conversion needed */
340 outBufs->descs[i].bufSize.bytes = 0;
341 outBufs->descs[i].buf = NULL;
342 }
343 }
345 }
347 /*
348 * Note that buffers can also be returned if IVIDDEC_EFAIL is returned
349 * with a non-fatal .extendedError in displayBufs[] and decodedBufs.
350 */
352 /* address translate the decoded buffers if non-fatal error */
353 if ((retVal == IVIDDEC3_EOK) ||
354 (!(XDM_ISFATALERROR(outArgs->decodedBufs.extendedError)))) {
356 success = p2vVideo2BufDesc(&(outArgs->decodedBufs));
357 if (!success) {
358 retVal = IVIDDEC3_EFAIL;
359 goto exit;
360 }
361 }
363 if (outArgs->displayBufsMode == IVIDDEC3_DISPLAYBUFS_EMBEDDED) {
365 /* the display buffers are embedded in the outArgs struct */
366 for (i = 0; (outArgs->outputID[i] != 0) && (i < IVIDEO2_MAX_IO_BUFFERS);
367 i++) {
369 if ((retVal == IVIDDEC3_EOK) ||
370 (!(XDM_ISFATALERROR(outArgs->
371 displayBufs.bufDesc[i].extendedError)))) {
372 success = p2vVideo2BufDesc(&(outArgs->displayBufs.bufDesc[i]));
374 if (!success) {
375 retVal = IVIDDEC3_EFAIL;
376 goto exit;
377 }
378 }
379 }
380 }
381 else {
382 /* the display buffers are pointed to in the outArgs struct */
383 for (i = 0; (outArgs->outputID[i] != 0) && (i < IVIDEO2_MAX_IO_BUFFERS);
384 i++) {
386 success = p2vVideo2BufDesc(outArgs->displayBufs.pBufDesc[i]);
388 if (!success) {
389 return (VISA_EFAIL);
390 }
391 }
392 }
394 /* Note that we did *nothing* with inBufs nor inArgs. This should be ok. */
396 exit:
397 VISA_freeMsg(visa, (VISA_Msg)msg);
399 return (retVal);
400 }
402 /*
403 * ======== process ========
404 * This is the sync stub implementation for the process method
405 */
406 static XDAS_Int32 process(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
407 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs)
408 {
409 XDAS_Int32 retVal;
410 _VIDDEC3_Msg *msg;
411 VISA_Handle visa = (VISA_Handle)h;
413 retVal = marshallMsg(h, inBufs, outBufs, inArgs, outArgs, &msg);
414 if (retVal != IVIDDEC3_EOK) {
415 return (retVal);
416 }
418 /* send the message to the skeleton and wait for completion */
419 retVal = VISA_call(visa, (VISA_Msg *)&msg);
421 /* Regardless of return value, unmarshall outArgs. */
422 retVal = unmarshallMsg(h, inBufs, outBufs, inArgs, outArgs, msg, retVal);
424 return (retVal);
425 }
427 /*
428 * ======== processAsync ========
429 * This is the async stub implementation for the process method
430 */
431 static XDAS_Int32 processAsync(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
432 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs)
433 {
434 XDAS_Int32 retVal;
435 _VIDDEC3_Msg *msg;
436 VISA_Handle visa = (VISA_Handle)h;
438 retVal = marshallMsg(h, inBufs, outBufs, inArgs, outArgs, &msg);
439 if (retVal != IVIDDEC3_EOK) {
440 return (retVal);
441 }
443 /* send the message to the skeleton without waiting for completion */
444 retVal = VISA_callAsync(visa, (VISA_Msg *)&msg);
446 return (retVal);
447 }
449 /*
450 * ======== processWait ========
451 */
452 static XDAS_Int32 processWait(IVIDDEC3_Handle h, XDM2_BufDesc *inBufs,
453 XDM2_BufDesc *outBufs, IVIDDEC3_InArgs *inArgs, IVIDDEC3_OutArgs *outArgs,
454 UInt timeout)
455 {
456 XDAS_Int32 retVal;
457 _VIDDEC3_Msg *msg;
458 VISA_Handle visa = (VISA_Handle)h;
460 Assert_isTrue(!VISA_isLocal(visa), (Assert_Id)NULL);
462 /* wait for completion of "last" message */
463 retVal = VISA_wait(visa, (VISA_Msg *)&msg, timeout);
465 /* Unmarshall outArgs if there is a msg to unmarshall. */
466 if (msg != NULL) {
467 Assert_isTrue(msg->visa.cmd == _VIDDEC3_CPROCESS, (Assert_Id)NULL);
469 retVal = unmarshallMsg(h, inBufs, outBufs, inArgs, outArgs, msg,
470 retVal);
471 }
473 return (retVal);
474 }
476 /*
477 * ======== control ========
478 * This is the stub-implementation for the control method
479 */
480 static XDAS_Int32 control(IVIDDEC3_Handle h, IVIDDEC3_Cmd id,
481 IVIDDEC3_DynamicParams *params, IVIDDEC3_Status *status)
482 {
483 XDAS_Int32 retVal;
484 VISA_Handle visa = (VISA_Handle)h;
485 _VIDDEC3_Msg *msg;
486 IVIDDEC3_Status *pMsgStatus;
487 XDAS_Int8 *virtAddr = NULL;
488 Int payloadSize;
490 /*
491 * Validate arguments. Do we want to do this _every_ time, or just in
492 * checked builds?
493 */
494 if ((params == NULL) || (params->size < sizeof(IVIDDEC3_DynamicParams)) ||
495 (status == NULL) || (status->size < sizeof(IVIDDEC3_Status))) {
497 /* invalid args, could even assert here, it's a spec violation. */
498 return (IVIDDEC3_EFAIL);
499 }
501 /*
502 * Initialize extendedError to zero so we don't return something
503 * uninitialized in extendedError.
504 */
505 status->extendedError = 0;
507 /* make sure it'll all fit! */
508 payloadSize = sizeof(VISA_MsgHeader) + sizeof(id) + params->size +
509 status->size;
511 if (payloadSize > VISA_getMaxMsgSize(visa)) {
512 /* Can't handle these large extended args. */
513 Log_print2(Diags_USER6,
514 "[+6] control> invalid arguments - too big (0x%x > 0x%x). "
515 "Validate .size fields", payloadSize,
516 VISA_getMaxMsgSize(visa));
518 return (IVIDDEC3_EUNSUPPORTED);
519 }
521 /* get a message appropriate for this algorithm */
522 if ((msg = (_VIDDEC3_Msg *)VISA_allocMsg(visa)) == NULL) {
523 return (IVIDDEC3_EFAIL);
524 }
526 /* marshall the command */
527 msg->visa.cmd = _VIDDEC3_CCONTROL;
529 msg->cmd.control.id = id;
531 /* params has no pointers so simply memcpy "size" bytes into the msg */
532 memcpy(&(msg->cmd.control.params), params, params->size);
534 /* unmarshall status based on the "size" of params */
535 pMsgStatus = (IVIDDEC3_Status *)((UInt)(&(msg->cmd.control.params)) +
536 params->size);
538 /*
539 * Initialize the .size and .data fields - the rest are filled in by
540 * the codec.
541 */
542 pMsgStatus->size = status->size;
544 if (status->data.buf != NULL) {
545 pMsgStatus->data.bufSize = status->data.bufSize;
547 /* save it for later */
548 virtAddr = status->data.buf;
550 pMsgStatus->data.buf = (XDAS_Int8 *)
551 Memory_getBufferPhysicalAddress(status->data.buf,
552 status->data.bufSize, NULL);
554 if (pMsgStatus->data.buf == NULL) {
555 retVal = IVIDDEC3_EFAIL;
556 goto exit;
557 }
558 }
559 else {
560 /* Place null into the msg so the skel knows it's invalid */
561 pMsgStatus->data.buf = NULL;
562 }
564 /* send the message to the skeleton and wait for completion */
565 retVal = VISA_call(visa, (VISA_Msg *)&msg);
567 /* ensure we get CCONTROL msg (ensure async CPROCESS pipeline drained) */
568 Assert_isTrue(msg->visa.cmd == _VIDDEC3_CCONTROL, (Assert_Id)NULL);
570 /* unmarshall status */
571 pMsgStatus = (IVIDDEC3_Status *)((UInt)(&(msg->cmd.control.params)) +
572 params->size);
574 if (VISA_isChecked()) {
575 /* ensure codec didn't modify status->size */
576 Assert_isTrue(pMsgStatus->size == status->size, (Assert_Id)NULL);
578 /*
579 * TODO:L Should we also check that pMsgStatus->data.buf is the same
580 * after the call as before?
581 */
582 }
584 memcpy(status, pMsgStatus, status->size);
586 /*
587 * And finally, restore status->data.buf to its original value. Note that
588 * this works even when status->data.buf was NULL because virtAddr is
589 * initialized to NULL.
590 *
591 * While potentially more confusing, this is just as correct as
592 * (and faster than!) calling Memory_getVirtualBuffer().
593 */
594 status->data.buf = virtAddr;
596 /* Clear .accessMask; the local processor didn't access the buffer */
597 status->data.accessMask = 0;
599 exit:
600 VISA_freeMsg(visa, (VISA_Msg)msg);
602 return (retVal);
603 }
605 /*
606 * ======== VIDDEC3_processAsync ========
607 */
608 XDAS_Int32 VIDDEC3_processAsync(VIDDEC3_Handle handle, XDM2_BufDesc *inBufs,
609 XDM2_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs)
610 {
611 XDAS_Int32 retVal = VIDDEC3_EFAIL;
613 /*
614 * Note, we do this because someday we may allow dynamically changing
615 * the global 'VISA_isChecked()' value on the fly. If we allow that,
616 * we need to ensure the value stays consistent in the context of this call.
617 */
618 Bool checked = VISA_isChecked();
620 Log_print5(Diags_ENTRY, "[+E] VIDDEC3_processAsync> "
621 "Enter (handle=0x%x, inBufs=0x%x, outBufs=0x%x, inArgs=0x%x, "
622 "outArgs=0x%x)",
623 (IArg)handle, (IArg)inBufs, (IArg)outBufs, (IArg)inArgs,
624 (IArg)outArgs);
626 if (handle) {
627 IVIDDEC3_Handle alg = VISA_getAlgHandle((VISA_Handle)handle);
629 if (alg != NULL) {
630 if (checked) {
631 /* validate inArgs with ranges. */
632 if (inArgs->inputID == 0) {
634 Log_print2(Diags_USER7,
635 "[+7] ERROR> app provided codec (0x%x) with out "
636 "of range inArgs->inputID field (0x%x)",
637 (IArg)alg, inArgs->inputID);
638 }
640 /* Validate inBufs and outBufs. */
641 //todo XdmUtils_validateSparseBufDesc1(inBufs, "inBufs");
642 //todo XdmUtils_validateSparseBufDesc(outBufs, "outBufs");
643 }
645 retVal = processAsync(alg, inBufs, outBufs, inArgs, outArgs);
646 }
647 }
649 Log_print2(Diags_EXIT, "[+X] VIDDEC3_processAsync> "
650 "Exit (handle=0x%x, retVal=0x%x)", (IArg)handle, (IArg)retVal);
652 return (retVal);
653 }
655 /*
656 * ======== VIDDEC3_processWait ========
657 */
658 XDAS_Int32 VIDDEC3_processWait(VIDDEC3_Handle handle, XDM2_BufDesc *inBufs,
659 XDM2_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs,
660 UInt timeout)
661 {
662 XDAS_Int32 retVal = VIDDEC3_EFAIL;
663 VIDDEC3_InArgs refInArgs;
665 /*
666 * Note, we do this because someday we may allow dynamically changing
667 * the global 'VISA_isChecked()' value on the fly. If we allow that,
668 * we need to ensure the value stays consistent in the context of this call.
669 */
670 Bool checked = VISA_isChecked();
672 Log_print5(Diags_ENTRY, "[+E] VIDDEC3_processWait> "
673 "Enter (handle=0x%x, inBufs=0x%x, outBufs=0x%x, inArgs=0x%x, "
674 "outArgs=0x%x)",
675 (IArg)handle, (IArg)inBufs, (IArg)outBufs, (IArg)inArgs,
676 (IArg)outArgs);
678 if (handle) {
679 IVIDDEC3_Handle alg = VISA_getAlgHandle((VISA_Handle)handle);
681 if (alg != NULL) {
682 if (checked) {
683 /*
684 * Make a reference copy of inArgs so we can check that
685 * the codec didn't modify them during process().
686 */
687 refInArgs = *inArgs;
688 }
690 retVal = processWait(alg, inBufs, outBufs, inArgs, outArgs,
691 timeout);
693 if (checked) {
694 /* ensure the codec didn't modify the read-only inArgs */
695 if (memcmp(&refInArgs, inArgs, sizeof(*inArgs)) != 0) {
696 Log_print1(Diags_USER7,
697 "[+7] ERROR> codec (0x%x) modified read-only inArgs "
698 "struct!", (IArg)handle);
699 }
700 }
701 }
702 }
704 Log_print2(Diags_EXIT, "[+X] VIDDEC3_processWait> "
705 "Exit (handle=0x%x, retVal=0x%x)", (IArg)handle, (IArg)retVal);
707 return (retVal);
708 }
710 /*
711 * ======== p2vVideo2BufDesc ========
712 * Translate all phys addrs to virt addrs in an IVIDEO2_BufDesc
713 */
714 static Bool p2vVideo2BufDesc(IVIDEO2_BufDesc *pBufDesc)
715 {
716 Int i;
718 /* Check for a spec violation - probably should be an assert! */
719 if ((pBufDesc->numPlanes >= 3) || (pBufDesc->numMetaPlanes >= 3)) {
720 Log_print3(Diags_USER7,
721 "[+7] ERROR> pBufDesc (0x%x) has invalid .numPlanes (0x%x) "
722 "and/or .numMetaPlanes (0x%x) fields!",
723 (IArg)pBufDesc, pBufDesc->numPlanes, pBufDesc->numMetaPlanes);
724 return (FALSE);
725 }
727 for (i = 0; i < pBufDesc->numPlanes; i++) {
728 if (pBufDesc->planeDesc[i].buf != NULL) {
730 if (pBufDesc->planeDesc[i].memType == XDM_MEMTYPE_RAW) {
731 pBufDesc->planeDesc[i].buf = Memory_getBufferVirtualAddress(
732 (UInt32)pBufDesc->planeDesc[i].buf,
733 pBufDesc->planeDesc[i].bufSize.bytes);
734 } else {
735 /* TODO:H how do we addr translate tiled bufs? */
736 }
738 /* Clear .accessMask; the local processor didn't access this buf. */
739 pBufDesc->planeDesc[i].accessMask = 0;
740 }
741 }
743 for (i = 0; i < pBufDesc->numMetaPlanes; i++) {
744 if (pBufDesc->metadataPlaneDesc[i].buf != NULL) {
746 if (pBufDesc->metadataPlaneDesc[i].memType == XDM_MEMTYPE_RAW) {
747 pBufDesc->metadataPlaneDesc[i].buf =
748 Memory_getBufferVirtualAddress(
749 (UInt32)pBufDesc->metadataPlaneDesc[i].buf,
750 pBufDesc->metadataPlaneDesc[i].bufSize.bytes);
751 } else {
752 /* TODO:H how do we addr translate tiled bufs? */
753 }
755 /* Clear .accessMask; the local processor didn't access this buf. */
756 pBufDesc->metadataPlaneDesc[i].accessMask = 0;
757 }
758 }
759 return (TRUE);
760 }