/*
 *  ======== call ========
 */
static VISA_Status call(VISA_Handle visaHandle, VISA_Msg visaMsg)
{
    _VIDTRANSCODE_Msg *msg  = (_VIDTRANSCODE_Msg *)visaMsg;
    VIDTRANSCODE_Handle handle = (VIDTRANSCODE_Handle)visaHandle;
    Int i;
    XDM1_BufDesc inBufs;
    XDM_BufDesc outBufs;
    IVIDTRANSCODE_OutArgs *pOutArgs;
    IVIDTRANSCODE_Status *pStatus;
    Int numBufs;

    /* perform the requested VIDTRANSCODE operation by parsing message. */
    switch (msg->visa.cmd) {

        case _VIDTRANSCODE_CPROCESS: {
            /* unmarshal inBufs and outBufs */
            inBufs           = msg->cmd.process.inBufs;

            outBufs.bufs     = msg->cmd.process.outBufs;
            outBufs.numBufs  = msg->cmd.process.numOutBufs;
            outBufs.bufSizes = msg->cmd.process.outBufSizes;

            if (SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB) {
                /* invalidate cache for all input buffers */
                for (i = 0, numBufs = 0; 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; i < XDM_MAX_IO_BUFFERS; i++) {
                    if (outBufs.bufs[i] != NULL) {
                        /* valid member of sparse array, manage it */
                        Memory_cacheInv(outBufs.bufs[i], outBufs.bufSizes[i]);

                        if (++numBufs == outBufs.numBufs) {
                            break;
                        }
                    }
                }
            }

            /* unmarshall outArgs based on the "size" of inArgs */
            pOutArgs = (IVIDTRANSCODE_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 = VIDTRANSCODE_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 encoded buffers  */
                for (i = 0; i < IVIDTRANSCODE_MAXOUTSTREAMS; i++) {
                    if ((pOutArgs->outputID[0] != 0) &&
                            (pOutArgs->encodedBuf[i].buf != NULL) &&
                            XDM_ISACCESSMODE_WRITE(pOutArgs->encodedBuf[i].accessMask)) {

                        Memory_cacheWb(pOutArgs->encodedBuf[i].buf,
                                pOutArgs->encodedBuf[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(
                         *         pOutArgs.encodedBuf[i].accessMask);
                         */
                    }
                }
            }

            /*
             * 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 _VIDTRANSCODE_CCONTROL: {
            /* unmarshall status based on the "size" of params */
            pStatus =
                (IVIDTRANSCODE_Status *)((UInt)(&(msg->cmd.control.dynParams)) +
                msg->cmd.control.dynParams.size);

            /* invalidate data buffer */
            if (pStatus->data.buf != NULL) {
                Memory_cacheInv(pStatus->data.buf, pStatus->data.bufSize);
            }

            msg->visa.status = VIDTRANSCODE_control(handle, msg->cmd.control.id,
                &(msg->cmd.control.dynParams), pStatus);

            /* writeback data buffer */
            if ((pStatus->data.buf != NULL) &&
                XDM_ISACCESSMODE_WRITE(pStatus->data.accessMask)) {

                Memory_cacheWb(pStatus->data.buf, pStatus->data.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.accessMask);
                 */
            }

            break;
        }

        default: {
            msg->visa.status = VISA_EFAIL;

            break;
        }
    }
    return (VISA_EOK);
}
Ejemplo n.º 2
0
static int do_transcodeFrame(CodecEngine* _ce,
                             const void* _srcFramePtr, size_t _srcFrameSize,
                             void* _dstFramePtr, size_t _dstFrameSize, size_t* _dstFrameUsed)
{
  if (_ce->m_srcBuffer == NULL || _ce->m_dstBuffer == NULL)
    return ENOTCONN;
  if (_srcFramePtr == NULL || _dstFramePtr == NULL)
    return EINVAL;
  if (_srcFrameSize > _ce->m_srcBufferSize || _dstFrameSize > _ce->m_dstBufferSize)
    return ENOSPC;


  VIDTRANSCODE_InArgs tcInArgs;
  memset(&tcInArgs, 0, sizeof(tcInArgs));
  tcInArgs.size = sizeof(tcInArgs);
  tcInArgs.numBytes = _srcFrameSize;
  tcInArgs.inputID = 1; // must be non-zero, otherwise caching issues appear

  VIDTRANSCODE_OutArgs tcOutArgs;
  memset(&tcOutArgs,    0, sizeof(tcOutArgs));
  tcOutArgs.size = sizeof(tcOutArgs);

  XDM1_BufDesc tcInBufDesc;
  memset(&tcInBufDesc,  0, sizeof(tcInBufDesc));
  tcInBufDesc.numBufs = 1;
  tcInBufDesc.descs[0].buf = _ce->m_srcBuffer;
  tcInBufDesc.descs[0].bufSize = _srcFrameSize;

  XDM_BufDesc tcOutBufDesc;
  memset(&tcOutBufDesc, 0, sizeof(tcOutBufDesc));
  XDAS_Int8* tcOutBufDesc_bufs[1];
  XDAS_Int32 tcOutBufDesc_bufSizes[1];
  tcOutBufDesc.numBufs = 1;
  tcOutBufDesc.bufs = tcOutBufDesc_bufs;
  tcOutBufDesc.bufs[0] = _ce->m_dstBuffer;
  tcOutBufDesc.bufSizes = tcOutBufDesc_bufSizes;
  tcOutBufDesc.bufSizes[0] = _dstFrameSize;

  memcpy(_ce->m_srcBuffer, _srcFramePtr, _srcFrameSize);

  Memory_cacheWbInv(_ce->m_srcBuffer, _ce->m_srcBufferSize); // invalidate and flush *whole* cache, not only written portion, just in case
  Memory_cacheInv(_ce->m_dstBuffer, _ce->m_dstBufferSize); // invalidate *whole* cache, not only expected portion, just in case

  XDAS_Int32 processResult = VIDTRANSCODE_process(_ce->m_vidtranscodeHandle, &tcInBufDesc, &tcOutBufDesc, &tcInArgs, &tcOutArgs);
  if (processResult != IVIDTRANSCODE_EOK)
  {
    fprintf(stderr, "VIDTRANSCODE_process(%zu -> %zu) failed: %"PRIi32"/%"PRIi32"\n",
            _srcFrameSize, _dstFrameSize, processResult, tcOutArgs.extendedError);
    return EILSEQ;
  }

#warning Remove me after a while if everything is fine
#if 0 // does not seems to be needed according to notes in CE skeletons (Wb is done by DSP side, not ARM)
  if (XDM_ISACCESSMODE_WRITE(tcOutArgs.encodedBuf[0].accessMask))
    Memory_cacheWb(_ce->m_dstBuffer, _ce->m_dstBufferSize);
#endif

  if (tcOutArgs.encodedBuf[0].bufSize > _dstFrameSize)
  {
    *_dstFrameUsed = _dstFrameSize;
    fprintf(stderr, "VIDTRANSCODE_process(%zu -> %zu) returned too large buffer %zu, truncated\n",
            _srcFrameSize, _dstFrameSize, *_dstFrameUsed);
  }
  else if (tcOutArgs.encodedBuf[0].bufSize < 0)
  {
    *_dstFrameUsed = 0;
    fprintf(stderr, "VIDTRANSCODE_process(%zu -> %zu) returned negative buffer size\n",
            _srcFrameSize, _dstFrameSize);
  }
  else
    *_dstFrameUsed = tcOutArgs.encodedBuf[0].bufSize;

  memcpy(_dstFramePtr, _ce->m_dstBuffer, *_dstFrameUsed);

  return 0;
}