static gint
codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush)
{
  gint err;
  GstClockTime t;
  GstBuffer *outbuf = NULL;
  gint i;

  self->outArgs->outputID[0] = 0;
  self->outArgs->freeBufID[0] = 0;

  t = gst_util_get_timestamp ();
  err = VIDDEC3_process (self->codec,
      self->inBufs, self->outBufs, self->inArgs, self->outArgs);
  GST_INFO_OBJECT (self, "%10dns", (gint) (gst_util_get_timestamp () - t));

  if (err) {
    GST_WARNING_OBJECT (self, "err=%d, extendedError=%08x",
        err, self->outArgs->extendedError);

    err = VIDDEC3_control (self->codec, XDM_GETSTATUS,
        self->dynParams, self->status);

    GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
        err, self->status->extendedError);

    if (XDM_ISFATALERROR (self->outArgs->extendedError) || flush) {
      /* we are processing for display and it is a non-fatal error, so lets
       * try to recover.. otherwise return the error
       */
      err = XDM_EFAIL;
    }
  }

  for (i = 0; self->outArgs->outputID[i]; i++) {
    if (G_UNLIKELY (self->first_out_buffer) && send) {
      /* send region of interest to sink on first buffer: */
      XDM_Rect *r = &(self->outArgs->displayBufs.bufDesc[0].activeFrameRegion);

      GST_DEBUG_OBJECT (self, "setting crop to %d, %d, %d, %d",
          r->topLeft.x, r->topLeft.y, r->bottomRight.x, r->bottomRight.y);

      gst_pad_push_event (self->srcpad,
          gst_event_new_crop (r->topLeft.y, r->topLeft.x,
              r->bottomRight.x - r->topLeft.x,
              r->bottomRight.y - r->topLeft.y));

      self->first_out_buffer = FALSE;
    }

    outbuf = codec_get_outbuf (self, self->outArgs->outputID[i]);
    if (send) {
      if (GST_IS_DUCATIBUFFER (outbuf)) {
        outbuf = gst_ducati_buffer_get (GST_DUCATIBUFFER (outbuf));
      }
      GST_DEBUG_OBJECT (self, "got buffer: %d %p (%" GST_TIME_FORMAT ")",
          i, outbuf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
      gst_pad_push (self->srcpad, outbuf);
    } else {
      GST_DEBUG_OBJECT (self, "free buffer: %d %p", i, outbuf);
      gst_buffer_unref (outbuf);
    }
  }

  for (i = 0; self->outArgs->freeBufID[i]; i++) {
    codec_unlock_outbuf (self, self->outArgs->freeBufID[i]);
  }

  return err;
}
Beispiel #2
0
/*
 *  ======== call ========
 */
static VISA_Status call(VISA_Handle visaHandle, VISA_Msg visaMsg)
{
    _VIDDEC3_Msg *msg  = (_VIDDEC3_Msg *)visaMsg;
    VIDDEC3_Handle handle = (VIDDEC3_Handle)visaHandle;
    Int i;
    XDM2_BufDesc inBufs;
    XDM2_BufDesc outBufs;
    IVIDDEC3_OutArgs *pOutArgs;
    IVIDDEC3_Status *pStatus;
    IVIDDEC3_CodecClassConfig *codecClassConfig;
    Int numBufs;
    Bool success;

    /* get stub/skeleton config data; can be NULL (for old codecs) */
    codecClassConfig =
            (IVIDDEC3_CodecClassConfig *)VISA_getCodecClassConfig(visaHandle);

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

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

            /* 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,
                     * invalidate it unless user configured it not to
                     */
                    if (codecClassConfig != NULL &&
                        codecClassConfig->manageInBufsCache[i] == FALSE) {
                       /* do nothing, i.e. don't invalidate */
                    } else {
                        if (inBufs.descs[i].memType == XDM_MEMTYPE_RAW) {
                            Memory_cacheInv(inBufs.descs[i].buf,
                                    inBufs.descs[i].bufSize.bytes);
                        } else {
                            /* TODO:H are tiled buffers cacheable? */
                        }
                    }

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

            /* invalidate cache for all output buffers */
            for (i = 0, numBufs = 0; i < XDM_MAX_IO_BUFFERS; i++) {
                if (outBufs.descs[i].buf != NULL) {
                    /* valid member of sparse array,
                     * invalidate it unless user configured it not to
                     */
                    if (codecClassConfig != NULL &&
                        codecClassConfig->manageOutBufsCache[i] == FALSE) {
                       /* do nothing, i.e. don't invalidate */
                    } else {
                        if (outBufs.descs[i].memType == XDM_MEMTYPE_RAW) {
                            Memory_cacheInv(outBufs.descs[i].buf,
                                    outBufs.descs[i].bufSize.bytes);
                        } else {
                            /* TODO:H are tiled buffers cacheable? */
                        }
                    }

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

            /* unmarshall outArgs based on the "size" of inArgs */
            pOutArgs = (IVIDDEC3_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) +
                msg->cmd.process.inArgs.size);

            /*
             * Note, there's no need to invalidate cache for
             * pOutArgs->decodedBuf bufs nor pOutArgs->displayBufs
             * bufs as the app doesn't provide OUT buffers to the
             * algorithm via these fields.
             */

            /* make the process call */
            msg->visa.status = VIDDEC3_process(handle,
                &inBufs, &outBufs, &(msg->cmd.process.inArgs), pOutArgs);

            /*
             * We probably should only be doing this if msg->visa.status
             * is IVIDDEC3_EOK or _EFAIL and .extendedError is non-fatal.
             */

            /*
             * Writeback cache for all output buffers:
             *   - .decodedBufs
             *   - .displayBufs
             */
            /*
             * ======== .decodedBufs ========
             */

            success = writebackVideo2BufDesc(&pOutArgs->decodedBufs);
            if (!success) {
                return (VISA_EFAIL);
            }

            /*
             * ======== .displayBufs ========
             */

            /* identify which mode the displayBufs are returned as */
            if (pOutArgs->displayBufsMode == IVIDDEC3_DISPLAYBUFS_EMBEDDED) {

                /* the display buffers are embedded in the outArgs struct */
                for (i = 0; (pOutArgs->outputID[i] != 0) &&
                        (i < IVIDEO2_MAX_IO_BUFFERS); i++) {

                    success = writebackVideo2BufDesc(
                            &(pOutArgs->displayBufs.bufDesc[i]));

                    if (!success) {
                        return (VISA_EFAIL);
                    }
                }
            }
            else {
                /* the display buffers are pointed to in the outArgs struct */
                for (i = 0; (pOutArgs->outputID[i] != 0) &&
                        (i < IVIDEO2_MAX_IO_BUFFERS); i++) {

                    success = writebackVideo2BufDesc(
                            pOutArgs->displayBufs.pBufDesc[i]);

                    if (!success) {
                        return (VISA_EFAIL);
                    }
                }
            }

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

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

            msg->visa.status = VIDDEC3_control(handle, msg->cmd.control.id,
                &(msg->cmd.control.params), 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);
}