/* * ======== analyze ======== */ static Void analyze(VIDANALYTICS_Handle analyzer, FILE *in, FILE *out) { Int n; Int32 result; VIDANALYTICS_InArgs inArgs; VIDANALYTICS_OutArgs outArgs; VIDANALYTICS_DynamicParams dynParams; VIDANALYTICS_Status status; XDM1_BufDesc inBufDesc; XDM1_BufDesc outBufDesc; /* clear and initialize the buffer descriptors */ inBufDesc.numBufs = outBufDesc.numBufs = 1; inBufDesc.descs[0].bufSize = outBufDesc.descs[0].bufSize = NSAMPLES; inBufDesc.descs[0].buf = inBuf; outBufDesc.descs[0].buf = outBuf; /* initialize all "sized" fields */ inArgs.size = sizeof(inArgs); outArgs.size = sizeof(outArgs); dynParams.size = sizeof(dynParams); status.size = sizeof(status); /* if the codecs support it, dump their versions */ status.data.numBufs = 1; status.data.descs[0].buf = versionBuf; status.data.descs[0].bufSize = MAXVERSIONSIZE; result = VIDANALYTICS_control(analyzer, XDM_GETVERSION, &dynParams, &status); GT_1trace(curMask, GT_1CLASS, "Analyzer version: %s\n", (result == VIDANALYTICS_EOK ? ((char *)status.data.descs[0].buf) : "[unknown]")); /* * This app expects the analyzer to accept 1 buf in and provide 1 buf out, * and the buf sizes of the in and out buffer must be able to handle * NSAMPLES bytes of data. */ status.data.numBufs = 0; status.data.descs[0].buf = NULL; result = VIDANALYTICS_control(analyzer, XDM_GETBUFINFO, &dynParams, &status); if (result != VIDANALYTICS_EOK) { /* failure, report error and exit */ GT_1trace(curMask, GT_7CLASS, "VIDANALYTICS control status = %ld\n", status); return; } /* Validate this analyzer will meet our buffer requirements */ if ((inBufDesc.numBufs < status.bufInfo.minNumInBufs) || (IFRAMESIZE < status.bufInfo.minInBufSize[0]) || (outBufDesc.numBufs < status.bufInfo.minNumOutBufs) || (OFRAMESIZE < status.bufInfo.minOutBufSize[0])) { /* failure, report error and exit */ GT_0trace(curMask, GT_7CLASS, "Error: analyzer codec feature conflict\n"); return; } /* * Read complete frames from in, analyze, and write to out. */ for (n = 0; fread(inBuf, IFRAMESIZE, 1, in) == 1; n++) { #ifdef CACHE_ENABLED #ifdef xdc_target__isaCompatible_64P /* * fread() on this processor is implemented using CCS's stdio, which * is known to write into the cache, not physical memory. To meet * xDAIS DMA Rule 7, we must writeback the cache into physical * memory. Also, per DMA Rule 7, we must invalidate the buffer's * cache before providing it to any xDAIS algorithm. */ Memory_cacheWbInv(inBuf, IFRAMESIZE); #else #error Unvalidated config - add appropriate fread-related cache maintenance #endif /* Per DMA Rule 7, our output buffer cache lines must be cleaned */ Memory_cacheInv(outBuf, OFRAMESIZE); #endif GT_1trace(curMask, GT_1CLASS, "App-> Processing frame %d...\n", n); /* * Analyze the frame. */ result = VIDANALYTICS_process(analyzer, &inBufDesc, &outBufDesc, &inArgs, &outArgs); GT_2trace(curMask, GT_2CLASS, "App-> Analyzer frame %d process returned - 0x%x)\n", n, result); if (result != VIDANALYTICS_EOK) { GT_3trace(curMask, GT_7CLASS, "App-> Analyzer frame %d processing FAILED, result = 0x%x, " "extendedError = 0x%x\n", n, result, outArgs.extendedError); break; } #ifdef CACHE_ENABLED /* * Conditionally writeback the analyzed buf from the previous * call. */ if (XDM_ISACCESSMODE_WRITE(outBufDesc.descs[0].accessMask)) { Memory_cacheWb(outBuf, OFRAMESIZE); } #endif /* write to file */ fwrite(outBufDesc.descs[0].buf, OFRAMESIZE, 1, out); } GT_1trace(curMask, GT_1CLASS, "%d frames analyzed\n", n); }
/* * ======== call ======== */ static VISA_Status call(VISA_Handle visaHandle, VISA_Msg visaMsg) { _VIDANALYTICS_Msg *msg = (_VIDANALYTICS_Msg *)visaMsg; VIDANALYTICS_Handle handle = (VIDANALYTICS_Handle)visaHandle; Int i; XDM1_BufDesc inBufs; XDM1_BufDesc outBufs; IVIDANALYTICS_OutArgs *pOutArgs; IVIDANALYTICS_Status *pStatus; Int numBufs; /* perform the requested VIDANALYTICS operation by parsing message. */ switch (msg->visa.cmd) { case _VIDANALYTICS_CPROCESS: { /* unmarshal inBufs and outBufs */ inBufs = msg->cmd.process.inBufs; outBufs = msg->cmd.process.outBufs; if (SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB) { /* invalidate cache for all input buffers */ for (i = 0, numBufs = 0; (numBufs < inBufs.numBufs) && (i < XDM_MAX_IO_BUFFERS); i++) { if (inBufs.descs[i].buf != NULL) { /* valid member of sparse array, manage it */ Memory_cacheInv(inBufs.descs[i].buf, inBufs.descs[i].bufSize); if (++numBufs == inBufs.numBufs) { break; } } } /* invalidate cache for all output buffers */ for (i = 0, numBufs = 0; (numBufs < outBufs.numBufs) && (i < XDM_MAX_IO_BUFFERS); i++) { if (outBufs.descs[i].buf != NULL) { /* valid member of sparse array, manage it */ Memory_cacheInv(outBufs.descs[i].buf, outBufs.descs[i].bufSize); if (++numBufs == outBufs.numBufs) { break; } } } } /* SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB */ /* unmarshall outArgs based on the "size" of inArgs */ pOutArgs = (IVIDANALYTICS_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) + msg->cmd.process.inArgs.size); /* * Note, there's no need to invalidate cache for * pOutArgs->encodedBuf bufs as they're * not _really_ OUT buffers. Rather they're references to * the _real_ OUT buffers that are provided in outBufs - which * were already invalidated above. */ /* make the process call */ msg->visa.status = VIDANALYTICS_process(handle, &inBufs, &outBufs, &(msg->cmd.process.inArgs), pOutArgs); if (SKEL_cachingPolicy == SKEL_WBINVALL) { Memory_cacheWbInvAll(); } else if (SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB) { /* writeback cache for analysis output buffers */ for (i = 0, numBufs = 0; (numBufs < outBufs.numBufs) && (i < XDM_MAX_IO_BUFFERS); i++) { if ((outBufs.descs[i].buf != NULL) && XDM_ISACCESSMODE_WRITE(outBufs.descs[i].accessMask)) { /* valid member of sparse array, written to via CPU */ Memory_cacheWb(outBufs.descs[i].buf, outBufs.descs[i].bufSize); /* * Since we've cacheWb this buffer, we arguably should * reflect this cache state and clear the WRITE bit in * the .accessMask field. However, we know the stub * doesn't propogate this field to the calling app, so * this extra buffer management detail isn't necessary: * * XDM_CLEARACCESSMODE_WRITE(outBufs.descs[i].accessMask); */ if (++numBufs == outBufs.numBufs) { break; } } } } /* * Note that any changes to individual outBufs[i] values made by * the codec will automatically update msg->cmd.process.outBufs * as we pass the outBufs array by reference. */ break; } case _VIDANALYTICS_CCONTROL: { /* unmarshall status based on the "size" of dynParams */ pStatus = (IVIDANALYTICS_Status *)((UInt)(&(msg->cmd.control.dynParams)) + msg->cmd.control.dynParams.size); /* invalidate data buffers */ for (i = 0, numBufs = 0; (numBufs < pStatus->data.numBufs) && (i < XDM_MAX_IO_BUFFERS); i++) { if (pStatus->data.descs[i].buf != NULL) { /* valid member of sparse array, manage it */ Memory_cacheInv(pStatus->data.descs[i].buf, pStatus->data.descs[i].bufSize); if (++numBufs == pStatus->data.numBufs) { break; } } } msg->visa.status = VIDANALYTICS_control(handle, msg->cmd.control.id, &(msg->cmd.control.dynParams), pStatus); /* writeback data buffers */ for (i = 0, numBufs = 0; (numBufs < pStatus->data.numBufs) && (i < XDM_MAX_IO_BUFFERS); i++) { if ((pStatus->data.descs[i].buf != NULL) && XDM_ISACCESSMODE_WRITE(pStatus->data.descs[i].accessMask)) { /* valid member of sparse array, manage it */ Memory_cacheWb(pStatus->data.descs[i].buf, pStatus->data.descs[i].bufSize); /* * Since we've cacheWb this buffer, we arguably should * reflect this cache state and clear the WRITE bit in * the .accessMask field. However, we know the stub * doesn't propogate this field to the calling app, so * this extra buffer management detail isn't necessary: * * XDM_CLEARACCESSMODE_WRITE( * pStatus->data.descs[i].accessMask); */ if (++numBufs == pStatus->data.numBufs) { break; } } } break; } default: { msg->visa.status = VISA_EFAIL; break; } } return (VISA_EOK); }