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; }
/* * ======== 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); }