/****************************************************************************** * gst_tiprepencbuf_convert_gst_to_dmai * This function convert gstreamer buffer into DMAI graphics buffer. *****************************************************************************/ static Buffer_Handle gst_tiprepencbuf_convert_gst_to_dmai(GstTIPrepEncBuf * prepencbuf, GstBuffer * buf, gboolean reference) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Buffer_Handle hBuf = NULL; gfxAttrs.bAttrs.reference = reference; gfxAttrs.dim.width = prepencbuf->srcWidth; gfxAttrs.dim.height = prepencbuf->srcHeight; gfxAttrs.colorSpace = prepencbuf->srcColorSpace; gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(gfxAttrs.dim.width, prepencbuf->srcColorSpace); hBuf = Buffer_create(GST_BUFFER_SIZE(buf), BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBuf == NULL) { GST_ERROR("failed to create buffer\n"); return NULL; } Buffer_setUserPtr(hBuf, (Int8 *) GST_BUFFER_DATA(buf)); Buffer_setNumBytesUsed(hBuf, GST_BUFFER_SIZE(buf)); return hBuf; }
static gboolean alloc_bufTab(GstTICaptureSrc *src) { BufferGfx_Attrs gfx = BufferGfx_Attrs_DEFAULT; int size; gfx.dim.width = src->width; gfx.dim.height = src->height; gfx.colorSpace = src->cAttrs.colorSpace; gfx.dim.lineLength = BufferGfx_calcLineLength(src->width, gfx.colorSpace); #if defined(Platform_dm365) || defined(Platform_dm368) gfx.dim.lineLength = Dmai_roundUp(gfx.dim.lineLength, 32); #endif size = gst_ti_calc_buffer_size(gfx.dim.width, gfx.dim.height, gfx.dim.lineLength, gfx.colorSpace); GST_INFO( "bufsize: %d %ldx%ld linesize %ld", size, gfx.dim.width, gfx.dim.height, gfx.dim.lineLength ); gfx.bAttrs.useMask = gst_tidmaibuffer_VIDEOSRC_FREE; src->cAttrs.numBufs = src->numbufs; src->hBufTab = gst_tidmaibuftab_new(src->cAttrs.numBufs, size, BufferGfx_getBufferAttrs(&gfx)); gst_tidmaibuftab_set_blocking(src->hBufTab, FALSE); return TRUE; }
/****************************************************************************** * Buffer_clone ******************************************************************************/ Buffer_Handle Buffer_clone(Buffer_Handle hBuf) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Buffer_Handle hNewBuf; Buffer_getAttrs(hBuf, BufferGfx_getBufferAttrs(&gfxAttrs)); hNewBuf = Buffer_create(hBuf->origState.numBytes, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hNewBuf == NULL) { Dmai_err0("Failed to create new Buffer while cloning\n"); return NULL; } return hNewBuf; }
/****************************************************************************** * captureThrFxn ******************************************************************************/ Void *captureThrFxn(Void *arg) { CaptureEnv *envp = (CaptureEnv *) arg; Void *status = THREAD_SUCCESS; Capture_Attrs cAttrs = Capture_Attrs_DM365_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Capture_Handle hCapture = NULL; BufTab_Handle hBufTab = NULL; BufferGfx_Dimensions dim; Buffer_Handle hDstBuf, hCapBuf; Int32 width, height, bufSize; Int fifoRet; ColorSpace_Type colorSpace = ColorSpace_YUV420PSEMI; /* Create capture device driver instance */ cAttrs.numBufs = NUM_CAPTURE_BUFS; cAttrs.videoInput = envp->videoInput; cAttrs.videoStd = envp->videoStd; cAttrs.colorSpace = colorSpace; if (VideoStd_getResolution(envp->videoStd, &width, &height) < 0) { ERR("Failed to calculate resolution of video standard\n"); cleanup(THREAD_FAILURE); } if (envp->imageWidth > 0 && envp->imageHeight > 0) { if (width < envp->imageWidth && height < envp->imageHeight) { ERR("User resolution (%ldx%ld) larger than detected (%ldx%ld)\n", envp->imageWidth, envp->imageHeight, width, height); cleanup(THREAD_FAILURE); } /* * Capture driver provides 32-byte aligned data. We 32-byte align the * capture and video buffers to perform zero copy encoding. */ envp->imageWidth = Dmai_roundUp(envp->imageWidth, 32); } else { /* Resolution was not set on command line. Set to defaults. */ envp->imageHeight = height; /* * Capture driver provides 32-byte aligned data. We 32-byte align the * capture and video buffers to perform zero copy encoding. */ envp->imageWidth = Dmai_roundUp(width, 32); } Dmai_clear(dim); dim.width = envp->imageWidth; dim.height = envp->imageHeight; dim.lineLength = Dmai_roundUp(dim.width, 32); if (colorSpace == ColorSpace_YUV420PSEMI) { bufSize = dim.lineLength * dim.height * 3 / 2; } else { bufSize = dim.lineLength * dim.height * 2; } gfxAttrs.dim = dim; /* Report the video standard and image size back to the main thread */ Rendezvous_meet(envp->hRendezvousCapStd); gfxAttrs.colorSpace = colorSpace; hBufTab = BufTab_create(NUM_CAPTURE_BUFS, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBufTab == NULL) { ERR("Failed to create buftab\n"); cleanup(THREAD_FAILURE); } if ((envp->videoStd == VideoStd_720P_60) && (!envp->passThrough)) { cAttrs.videoStd = VideoStd_720P_30; } else { cAttrs.videoStd = envp->videoStd; } cAttrs.colorSpace = colorSpace; cAttrs.captureDimension = &dim; cAttrs.numBufs = NUM_CAPTURE_BUFS; hCapture = Capture_create(hBufTab, &cAttrs); if (hCapture == NULL) { ERR("Failed to create capture device\n"); cleanup(THREAD_FAILURE); } /* Get a buffer from the video thread */ fifoRet = Fifo_get(envp->hInFifo, &hDstBuf); if (fifoRet < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } if (fifoRet == Dmai_EFLUSH) { cleanup(THREAD_SUCCESS); } /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvousInit); while (!gblGetQuit()) { /* Get a buffer from the capture driver to encode */ if (Capture_get(hCapture, &hCapBuf) < 0) { ERR("Failed to get capture buffer\n"); cleanup(THREAD_FAILURE); } /* Send captured buffer to video thread for encoding */ if (Fifo_put(envp->hOutFifo, hCapBuf) < 0) { ERR("Failed to send buffer to video thread\n"); cleanup(THREAD_FAILURE); } /* Pause processing? */ Pause_test(envp->hPauseProcess); /* Get a buffer from the video thread */ fifoRet = Fifo_get(envp->hInFifo, &hDstBuf); if (fifoRet < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } /* Did the video thread flush the fifo? */ if (fifoRet == Dmai_EFLUSH) { cleanup(THREAD_SUCCESS); } /* Return a buffer to the capture driver */ if (Capture_put(hCapture, hDstBuf) < 0) { ERR("Failed to put capture buffer\n"); cleanup(THREAD_FAILURE); } } cleanup: /* Make sure the other threads aren't waiting for us */ Rendezvous_force(envp->hRendezvousCapStd); Rendezvous_force(envp->hRendezvousInit); Pause_off(envp->hPauseProcess); Fifo_flush(envp->hOutFifo); /* Meet up with other threads before cleaning up */ Rendezvous_meet(envp->hRendezvousCleanup); if (hCapture) { Capture_delete(hCapture); } /* Clean up the thread before exiting */ if (hBufTab) { BufTab_delete(hBufTab); } return status; }
/****************************************************************************** * displayThrFxn ******************************************************************************/ Void *displayThrFxn(Void *arg) { DisplayEnv *envp = (DisplayEnv *) arg; Display_Attrs dAttrs = Display_Attrs_DM365_VID_DEFAULT; Display_Handle hDisplay = NULL; Framecopy_Handle hFc = NULL; Void *status = THREAD_SUCCESS; Uns frameCnt = 0; BufferGfx_Dimensions srcDim; Buffer_Handle hSrcBuf, hDstBuf; Int fifoRet; ColorSpace_Type colorSpace = ColorSpace_YUV420PSEMI; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; BufTab_Handle hBufTab = NULL; Int32 bufSize; Time_Attrs tAttrs = Time_Attrs_DEFAULT; Time_Handle hTime = NULL; Int32 time, waitTime; Int bufCnt = 1; hTime = Time_create(&tAttrs); if (hTime == NULL) { ERR("Failed to create Time object\n"); cleanup(THREAD_FAILURE); } if(Time_reset(hTime) != Dmai_EOK) { ERR("Failed to reset timer\n"); cleanup(THREAD_FAILURE); } /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvousInit); while (!gblGetQuit()) { /* Pause processing? */ Pause_test(envp->hPauseProcess); /* Pause for priming? */ Pause_test(envp->hPausePrime); /* Get decoded video frame */ fifoRet = Fifo_get(envp->hInFifo, &hSrcBuf); if (fifoRet < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } /* Did the video thread flush the fifo? */ if (fifoRet == Dmai_EFLUSH) { cleanup(THREAD_SUCCESS); } BufferGfx_getDimensions(hSrcBuf, &srcDim); /* Prime the display driver with the first NUM_DISPLAY_BUFS buffers */ if (bufCnt <= NUM_DISPLAY_BUFS) { if (bufCnt == 1) { // Create the Display at the first frame gfxAttrs.dim.width = srcDim.width; gfxAttrs.dim.height = srcDim.height; gfxAttrs.dim.lineLength = srcDim.lineLength; gfxAttrs.dim.x = srcDim.x; gfxAttrs.dim.y = srcDim.y; if (colorSpace == ColorSpace_YUV420PSEMI) { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 3 / 2; } else { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 2; } /* Create a table of buffers to use with the device drivers */ gfxAttrs.colorSpace = colorSpace; hBufTab = BufTab_create(NUM_DISPLAY_BUFS, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBufTab == NULL) { ERR("Failed to create buftab\n"); cleanup(THREAD_FAILURE); } /* Create the display device instance */ dAttrs.delayStreamon = TRUE; dAttrs.numBufs = NUM_DISPLAY_BUFS; dAttrs.videoStd = envp->videoStd; /* * Round down the width to a multiple of 32 as required by * display driver. Otherwise, the driver would internally round * up the width, resulting in the codec padding showing up * on the display when the image width is not a multiple of 32. */ dAttrs.width = ((gfxAttrs.dim.width & 0x1f) ? (gfxAttrs.dim.width & ~(0x1f)) : gfxAttrs.dim.width); dAttrs.height = gfxAttrs.dim.height; dAttrs.videoOutput = envp->displayOutput; dAttrs.colorSpace = colorSpace; hDisplay = Display_create(hBufTab, &dAttrs); if (hDisplay == NULL) { ERR("Failed to create display device\n"); cleanup(THREAD_FAILURE); } } bufCnt++; } else { /* Get a buffer from the display device driver */ if (Display_get(hDisplay, &hDstBuf) < 0) { ERR("Failed to get display buffer\n"); cleanup(THREAD_FAILURE); } /* Send buffer back to the video thread */ if (Fifo_put(envp->hOutFifo, hDstBuf) < 0) { ERR("Failed to send buffer to video thread\n"); cleanup(THREAD_FAILURE); } } if (envp->videoStd == VideoStd_720P_60) { if (Time_delta(hTime, (UInt32*)&time) < 0) { ERR("Failed to get timer delta\n"); cleanup(THREAD_FAILURE); } waitTime = DISPLAYLOOPLATENCY - time; if(waitTime > 0) { usleep(waitTime); } if(Time_reset(hTime) != Dmai_EOK) { ERR("Failed to reset timer\n"); cleanup(THREAD_FAILURE); } } /* Incremement statistics for the user interface */ gblIncFrames(); /* Give a filled buffer back to the display device driver */ if (Display_put(hDisplay, hSrcBuf) < 0) { ERR("Failed to put display buffer\n"); cleanup(THREAD_FAILURE); } frameCnt++; } cleanup: /* Make sure the other threads aren't waiting for us */ Rendezvous_force(envp->hRendezvousInit); Pause_off(envp->hPauseProcess); Pause_off(envp->hPausePrime); Fifo_flush(envp->hOutFifo); /* Meet up with other threads before cleaning up */ Rendezvous_meet(envp->hRendezvousCleanup); /* Clean up the thread before exiting */ if (hFc) { Framecopy_delete(hFc); } if (hDisplay) { Display_delete(hDisplay); } /* Clean up the thread before exiting */ if (hBufTab) { BufTab_delete(hBufTab); } if(hTime) { Time_delete(hTime); } return status; }
/****************************************************************************** * appMain ******************************************************************************/ Int appMain(Args * args) { VIDENC1_Params params = Venc1_Params_DEFAULT; VIDENC1_DynamicParams dynParams = Venc1_DynamicParams_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Buffer_Attrs bAttrs = Buffer_Attrs_DEFAULT; Time_Attrs tAttrs = Time_Attrs_DEFAULT; Venc1_Handle hVe1 = NULL; FILE *outFile = NULL; FILE *reconFile = NULL; FILE *inFile = NULL; Engine_Handle hEngine = NULL; Time_Handle hTime = NULL; Bool flushed = FALSE; Bool mustExit = FALSE; BufTab_Handle hBufTab = NULL; Buffer_Handle hOutBuf = NULL; Buffer_Handle hFreeBuf = NULL; Buffer_Handle hInBuf = NULL; Buffer_Handle hReconBuf = NULL; Int numFrame = 0; Int flushCntr = 1; Int bufIdx; Int inBufSize, outBufSize; Cpu_Device device; Int numBufs; ColorSpace_Type colorSpace; UInt32 time; Int ret = Dmai_EOK; printf("Starting application...\n"); /* Initialize the codec engine run time */ CERuntime_init(); /* Initialize DMAI */ Dmai_init(); /* Determine which device the application is running on */ if (Cpu_getDevice(NULL, &device) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to determine target board\n"); goto cleanup; } if (args->benchmark) { hTime = Time_create(&tAttrs); if (hTime == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create Time object\n"); goto cleanup; } } /* Open the input file with raw yuv data */ inFile = fopen(args->inFile, "rb"); if (inFile == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open input file %s\n", args->inFile); goto cleanup; } /* Using a larger vbuf to enhance performance of file i/o */ if (setvbuf(inFile, vbufferIn, _IOFBF, sizeof(vbufferIn)) != 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to setvbuf on input file descriptor\n"); goto cleanup; } /* Open the output file where to put encoded data */ outFile = fopen(args->outFile, "wb"); if (outFile == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open output file %s\n", args->outFile); goto cleanup; } /* Using a larger vbuf to enhance performance of file i/o */ if (setvbuf(outFile, vbufferOut, _IOFBF, sizeof(vbufferOut)) != 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to setvbuf on output file descriptor\n"); goto cleanup; } /* Open the output file where to put reconstructed frames */ if (args->writeReconFrames) { reconFile = fopen(args->reconFile, "wb"); if (reconFile == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open output file %s\n", args->reconFile); goto cleanup; } /* Using a larger vbuf to enhance performance of file i/o */ if (setvbuf(reconFile, vbufferRecon, _IOFBF, sizeof(vbufferRecon)) != 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to setvbuf on output file descriptor\n"); goto cleanup; } } /* Open the codec engine */ hEngine = Engine_open(args->engineName, NULL, NULL); if (hEngine == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open codec engine: %s\n", args->engineName); goto cleanup; } /* Set up codec parameters depending on bit rate */ if (args->bitRate < 0) { /* Variable bit rate */ params.rateControlPreset = IVIDEO_NONE; /* * If variable bit rate use a bogus bit rate value (> 0) * since it will be ignored. */ params.maxBitRate = 2000000; } else { /* Constant bit rate */ params.rateControlPreset = IVIDEO_LOW_DELAY; params.maxBitRate = args->bitRate; } /* Set up codec parameters depending on device */ switch (device) { case Cpu_Device_DM6467: params.inputChromaFormat = XDM_YUV_420SP; params.reconChromaFormat = XDM_CHROMA_NA; break; case Cpu_Device_DM355: params.inputChromaFormat = XDM_YUV_422ILE; params.reconChromaFormat = XDM_YUV_420P; break; case Cpu_Device_DM365: case Cpu_Device_DM368: params.inputChromaFormat = XDM_YUV_420SP; params.reconChromaFormat = XDM_YUV_420SP; break; case Cpu_Device_DM3730: params.rateControlPreset = IVIDEO_STORAGE; params.inputChromaFormat = XDM_YUV_422ILE; break; default: params.inputChromaFormat = XDM_YUV_422ILE; break; } params.maxWidth = args->width; params.maxHeight = args->height; /* Workaround for SDOCM00068944: h264fhdvenc fails to create codec when params.dataEndianness is set as XDM_BYTE */ if(device == Cpu_Device_DM6467) { if (!strcmp(args->codecName, "h264fhdvenc")) { params.dataEndianness = XDM_LE_32; } } params.maxInterFrameInterval = 1; dynParams.targetBitRate = params.maxBitRate; dynParams.inputWidth = params.maxWidth; dynParams.inputHeight = params.maxHeight; /* Create the video encoder */ hVe1 = Venc1_create(hEngine, args->codecName, ¶ms, &dynParams); if (hVe1 == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create video encoder: %s\n", args->codecName); goto cleanup; } /* Ask the codec how much input data it needs */ inBufSize = Venc1_getInBufSize(hVe1); /* Ask the codec how much space it needs for output data */ outBufSize = Venc1_getOutBufSize(hVe1); /* Which color space to use in the graphics buffers depends on the device */ colorSpace = ((device == Cpu_Device_DM6467)|| (device == Cpu_Device_DM365) || (device == Cpu_Device_DM368)) ? ColorSpace_YUV420PSEMI : ColorSpace_UYVY; /* Align buffers to cache line boundary */ gfxAttrs.bAttrs.memParams.align = bAttrs.memParams.align = BUFSIZEALIGN; /* Use cached buffers if requested */ if (args->cache) { gfxAttrs.bAttrs.memParams.flags = bAttrs.memParams.flags = Memory_CACHED; } gfxAttrs.dim.width = args->width; gfxAttrs.dim.height = args->height; if ((device == Cpu_Device_DM6467) || (device == Cpu_Device_DM365) || (device == Cpu_Device_DM368)) { gfxAttrs.dim.height = Dmai_roundUp(gfxAttrs.dim.height, CODECHEIGHTALIGN); } gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(args->width, colorSpace); gfxAttrs.colorSpace = colorSpace; if (inBufSize < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to calculate buffer attributes\n"); goto cleanup; } /* Number of input buffers required */ if(params.maxInterFrameInterval>1) { /* B frame support */ numBufs = params.maxInterFrameInterval; } else { numBufs = 1; } /* Create a table of input buffers of the size requested by the codec */ hBufTab = BufTab_create(numBufs, Dmai_roundUp(inBufSize, BUFSIZEALIGN), BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBufTab == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to allocate contiguous buffers\n"); goto cleanup; } /* Set input buffer table */ Venc1_setBufTab(hVe1, hBufTab); /* Create the reconstructed frame buffer for raw yuv data */ if (args->writeReconFrames) { hReconBuf = Buffer_create(Dmai_roundUp(inBufSize, BUFSIZEALIGN), BufferGfx_getBufferAttrs(&gfxAttrs)); if (hReconBuf == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to allocate contiguous buffer\n"); goto cleanup; } } /* Create the output buffer for encoded video data */ hOutBuf = Buffer_create(Dmai_roundUp(outBufSize, BUFSIZEALIGN), &bAttrs); if (hOutBuf == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create contiguous buffer\n"); goto cleanup; } while (1) { /* Get a buffer for input */ hInBuf = BufTab_getFreeBuf(hBufTab); if (hInBuf == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get a free contiguous buffer from BufTab\n"); BufTab_print(hBufTab); goto cleanup; } if (args->benchmark) { if (Time_reset(hTime) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to reset timer\n"); goto cleanup; } } /* Read a yuv input frame */ printf("\n Frame %d: ", numFrame); if ((device == Cpu_Device_DM6467)|| (device == Cpu_Device_DM365) || (device == Cpu_Device_DM368)) { if(args->sp) { if (readFrame420SP(hInBuf, inFile, args->height) < 0) { ret = Dmai_EFAIL; goto cleanup; } } else { if (readFrame420P(hInBuf, inFile, args->height) < 0) { ret = Dmai_EFAIL; goto cleanup; } } } else { if (readFrameUYVY(hInBuf, inFile) < 0) { ret = Dmai_EFAIL; mustExit = TRUE; } } if (++numFrame == args->numFrames||mustExit == TRUE) { if(!(params.maxInterFrameInterval>1)) { /* No B-frame support */ printf("... exiting \n"); goto cleanup; } /* * When encoding a stream with B-frames, ending the processing * requires to free the buffer held by the encoder. This is done by * flushing the encoder and performing a last process() call * with a dummy input buffer. */ printf("\n... exiting with flush (B-frame stream) \n"); flushCntr = params.maxInterFrameInterval-1; flushed = TRUE; Venc1_flush(hVe1); } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Read time: %uus\n", (Uns)time); } /* * Following flushing loop will iterate more than one time only * when the encoder completes processing by flushing the frames * held by the encoder. All flushed frames will be encoded as P * or I frames. */ for(bufIdx = 0; bufIdx < flushCntr; bufIdx++) { if (args->cache) { /* * To meet xDAIS DMA Rule 7, when input buffers are cached, we * must writeback the cache into physical memory. Also, per DMA * Rule 7, we must invalidate the output buffer from * cache before providing it to any xDAIS algorithm. */ Memory_cacheWbInv(Buffer_getUserPtr(hInBuf), Buffer_getSize(hInBuf)); /* Per DMA Rule 7, our output buffer cache lines must be cleaned */ Memory_cacheInv(Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Pre-process cache maintenance: %uus \n", (Uns) time); } } /* Make sure the whole buffer is used for input */ BufferGfx_resetDimensions(hInBuf); /* Encode the video buffer */ if (Venc1_process(hVe1, hInBuf, hOutBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to encode video buffer\n"); goto cleanup; } /* if encoder generated output content, free released buffer */ if (Buffer_getNumBytesUsed(hOutBuf)>0) { /* Get free buffer */ hFreeBuf = Venc1_getFreeBuf(hVe1); /* Free buffer */ BufTab_freeBuf(hFreeBuf); } /* if encoder did not generate output content */ else { /* if non B frame sequence */ /* encoder skipped frame probably exceeding target bitrate */ if (params.maxInterFrameInterval<=1) { /* free buffer */ printf(" Encoder generated 0 size frame\n"); BufTab_freeBuf(hInBuf); } } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get encode time\n"); goto cleanup; } printf("[%d] Encode: %uus\n", numFrame, (Uns)time); } if (args->cache) { /* Writeback the outBuf. */ Memory_cacheWb(Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Post-process cache write back: %uus \n", (Uns) time); } } /* Write the encoded frame to the file system */ if (Buffer_getNumBytesUsed(hOutBuf)) { if (fwrite(Buffer_getUserPtr(hOutBuf), Buffer_getNumBytesUsed(hOutBuf), 1, outFile) != 1) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to write encoded video data to file\n"); goto cleanup; } } /* Write the reconstructed frame to the file system */ if (args->writeReconFrames) { processReconData(Venc1_getReconBufs(hVe1), hInBuf, hReconBuf); if (Buffer_getNumBytesUsed(hReconBuf)) { if (fwrite(Buffer_getUserPtr(hReconBuf), Buffer_getNumBytesUsed(hReconBuf), 1, reconFile) != 1) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to write reconstructed frame to file\n"); goto cleanup; } } } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; printf("Failed to get timer delta\n"); goto cleanup; } printf("File write time: %uus\n", (Uns)time); if (Time_total(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer total\n"); goto cleanup; } printf("Total: %uus\n", (Uns)time); } } /* If the codec flushing completed, exit main thread */ if (flushed) { /* Free dummy input buffer used for flushing process() calls */ printf("freeing dummy input buffer ... \n"); BufTab_freeBuf(hInBuf); break; } } cleanup: /* Clean up the application */ if (hOutBuf) { Buffer_delete(hOutBuf); } if (hReconBuf) { Buffer_delete(hReconBuf); } if (hVe1) { Venc1_delete(hVe1); } if (hBufTab) { BufTab_delete(hBufTab); } if (hEngine) { Engine_close(hEngine); } if (inFile) { fclose(inFile); } if (outFile) { fclose(outFile); } if (reconFile) { fclose(reconFile); } if (hTime) { Time_delete(hTime); } printf("End of application.\n"); if (ret == Dmai_EFAIL) return 1; else return 0; }
/****************************************************************************** * captureThrFxn ******************************************************************************/ Void *captureThrFxn(Void *arg) { CaptureEnv *envp = (CaptureEnv *) arg; Void *status = THREAD_SUCCESS; Capture_Attrs cAttrs = Capture_Attrs_DM365_DEFAULT; Display_Attrs dAttrs = Display_Attrs_DM365_VID_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Capture_Handle hCapture = NULL; Display_Handle hDisplay = NULL; BufTab_Handle hBufTab = NULL; BufTab_Handle hDispBufTab = NULL; BufTab_Handle hFifoBufTab = NULL; Buffer_Handle hDstBuf, hCapBuf, hDisBuf, hBuf; BufferGfx_Dimensions capDim; VideoStd_Type videoStd; Int32 width, height, bufSize; Int fifoRet; ColorSpace_Type colorSpace = ColorSpace_YUV420PSEMI; Int bufIdx; Int numCapBufs; /* Create capture device driver instance */ cAttrs.numBufs = NUM_CAPTURE_BUFS; cAttrs.videoInput = envp->videoInput; cAttrs.videoStd = envp->videoStd; cAttrs.colorSpace = colorSpace; videoStd = envp->videoStd; /* We only support D1, 720P and 1080P input */ if (videoStd != VideoStd_D1_NTSC && videoStd != VideoStd_D1_PAL && videoStd != VideoStd_720P_60 && videoStd != VideoStd_720P_50 && videoStd != VideoStd_1080I_30) { ERR("Need D1/720P/1080P input to this demo\n"); cleanup(THREAD_FAILURE); } if (envp->imageWidth > 0 && envp->imageHeight > 0) { if (VideoStd_getResolution(videoStd, &width, &height) < 0) { ERR("Failed to calculate resolution of video standard\n"); cleanup(THREAD_FAILURE); } if (width < envp->imageWidth && height < envp->imageHeight) { ERR("User resolution (%ldx%ld) larger than detected (%ldx%ld)\n", envp->imageWidth, envp->imageHeight, width, height); cleanup(THREAD_FAILURE); } /* * Capture driver provides 32 byte aligned data. We 32 byte align the * capture and video buffers to perform zero copy encoding. */ envp->imageWidth = Dmai_roundUp(envp->imageWidth,32); capDim.x = 0; capDim.y = 0; capDim.height = envp->imageHeight; capDim.width = envp->imageWidth; capDim.lineLength = BufferGfx_calcLineLength(capDim.width, colorSpace); } else { /* Calculate the dimensions of a video standard given a color space */ if (BufferGfx_calcDimensions(videoStd, colorSpace, &capDim) < 0) { ERR("Failed to calculate Buffer dimensions\n"); cleanup(THREAD_FAILURE); } /* * Capture driver provides 32 byte aligned data. We 32 byte align the * capture and video buffers to perform zero copy encoding. */ capDim.width = Dmai_roundUp(capDim.width,32); envp->imageWidth = capDim.width; envp->imageHeight = capDim.height; } numCapBufs = NUM_CAPTURE_BUFS; gfxAttrs.dim.height = capDim.height; gfxAttrs.dim.width = capDim.width; gfxAttrs.dim.lineLength = Dmai_roundUp(BufferGfx_calcLineLength(gfxAttrs.dim.width, colorSpace), 32); gfxAttrs.dim.x = 0; gfxAttrs.dim.y = 0; if (colorSpace == ColorSpace_YUV420PSEMI) { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 3 / 2; } else { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 2; } /* Create a table of buffers to use with the capture driver */ gfxAttrs.colorSpace = colorSpace; hBufTab = BufTab_create(numCapBufs, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBufTab == NULL) { ERR("Failed to create buftab\n"); cleanup(THREAD_FAILURE); } /* Create a table of buffers to use to prime Fifo to video thread */ hFifoBufTab = BufTab_create(VIDEO_PIPE_SIZE, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hFifoBufTab == NULL) { ERR("Failed to create buftab\n"); cleanup(THREAD_FAILURE); } /* Update global data for user interface */ gblSetImageWidth(envp->imageWidth); gblSetImageHeight(envp->imageHeight); /* Report the video standard and image size back to the main thread */ Rendezvous_meet(envp->hRendezvousCapStd); /* Capture at half frame rate if using COMPONENT input at 720P */ if ((envp->videoStd == VideoStd_720P_60) && (envp->videoInput == Capture_Input_COMPONENT)) { cAttrs.videoStd = VideoStd_720P_30; } else { cAttrs.videoStd = envp->videoStd; } /*If its component input and video std is 1080I_30 then make it 1080I_60.*/ if (cAttrs.videoStd == VideoStd_1080I_30 && cAttrs.videoInput == Capture_Input_COMPONENT) { cAttrs.videoStd = VideoStd_1080I_60; } cAttrs.numBufs = NUM_CAPTURE_BUFS; cAttrs.colorSpace = colorSpace; cAttrs.captureDimension = &gfxAttrs.dim; /* Create the capture device driver instance */ hCapture = Capture_create(hBufTab, &cAttrs); if (hCapture == NULL) { ERR("Failed to create capture device. Is video input connected?\n"); cleanup(THREAD_FAILURE); } /* Create a table of buffers to use with the display driver */ hDispBufTab = BufTab_create(NUM_DISPLAY_BUFS, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hDispBufTab == NULL) { ERR("Failed to create buftab\n"); cleanup(THREAD_FAILURE); } /* Create display device driver instance if preview is needed */ if (!envp->previewDisabled) { dAttrs.videoStd = envp->videoStd; if ( (dAttrs.videoStd == VideoStd_CIF) || (dAttrs.videoStd == VideoStd_SIF_NTSC) || (dAttrs.videoStd == VideoStd_SIF_PAL) || (dAttrs.videoStd == VideoStd_VGA) || (dAttrs.videoStd == VideoStd_D1_NTSC) || (dAttrs.videoStd == VideoStd_D1_PAL) ) { dAttrs.videoOutput = Display_Output_COMPOSITE; } else { dAttrs.videoOutput = Display_Output_COMPONENT; } dAttrs.numBufs = NUM_DISPLAY_BUFS; dAttrs.colorSpace = colorSpace; dAttrs.width = capDim.width; dAttrs.height = capDim.height; hDisplay = Display_create(hDispBufTab, &dAttrs); if (hDisplay == NULL) { ERR("Failed to create display device\n"); cleanup(THREAD_FAILURE); } } for (bufIdx = 0; bufIdx < VIDEO_PIPE_SIZE; bufIdx++) { /* Queue the video buffers for main thread processing */ hBuf = BufTab_getFreeBuf(hFifoBufTab); if (hBuf == NULL) { ERR("Failed to fill video pipeline\n"); cleanup(THREAD_FAILURE); } /* Fill with black the buffer */ CapBuf_blackFill(hBuf); /* Send buffer to video thread for encoding */ if (Fifo_put(envp->hOutFifo, hBuf) < 0) { ERR("Failed to send buffer to display thread\n"); cleanup(THREAD_FAILURE); } } /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvousInit); while (!gblGetQuit()) { /* Pause processing? */ Pause_test(envp->hPauseProcess); /* Capture a frame */ if (Capture_get(hCapture, &hCapBuf) < 0) { ERR("Failed to get capture buffer\n"); cleanup(THREAD_FAILURE); } /* Get a buffer from the display device */ if ((!envp->previewDisabled) && (Display_get(hDisplay, &hDisBuf) < 0)) { ERR("Failed to get display buffer\n"); cleanup(THREAD_FAILURE); } /* Send buffer to video thread for encoding */ if (Fifo_put(envp->hOutFifo, hCapBuf) < 0) { ERR("Failed to send buffer to display thread\n"); cleanup(THREAD_FAILURE); } /* Get a buffer from the video thread */ fifoRet = Fifo_get(envp->hInFifo, &hDstBuf); if (fifoRet < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } /* Did the video thread flush the fifo? */ if (fifoRet == Dmai_EFLUSH) { cleanup(THREAD_SUCCESS); } if (!envp->previewDisabled) { /* Release buffer to the display device driver */ if (Display_put(hDisplay, hDstBuf) < 0) { ERR("Failed to put display buffer\n"); cleanup(THREAD_FAILURE); } } if (envp->previewDisabled) { /* Return the processed buffer to the capture driver */ if (Capture_put(hCapture, hDstBuf) < 0) { ERR("Failed to put capture buffer\n"); cleanup(THREAD_FAILURE); } } else { /* Return the displayed buffer to the capture driver */ if (Capture_put(hCapture, hDisBuf) < 0) { ERR("Failed to put capture buffer\n"); cleanup(THREAD_FAILURE); } } /* Increment statistics for the user interface */ gblIncFrames(); } cleanup: /* Make sure the other threads aren't waiting for us */ Rendezvous_force(envp->hRendezvousCapStd); Rendezvous_force(envp->hRendezvousInit); Pause_off(envp->hPauseProcess); Fifo_flush(envp->hOutFifo); /* Meet up with other threads before cleaning up */ Rendezvous_meet(envp->hRendezvousCleanup); if (hDisplay) { Display_delete(hDisplay); } if (hCapture) { Capture_delete(hCapture); } /* Clean up the thread before exiting */ if (hBufTab) { BufTab_delete(hBufTab); } if (hFifoBufTab) { BufTab_delete(hFifoBufTab); } if (hDispBufTab) { BufTab_delete(hDispBufTab); } return status; }
/****************************************************************************** * Display_fbdev_create ******************************************************************************/ Display_Handle Display_fbdev_create(BufTab_Handle hBufTab, Display_Attrs *attrs) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; struct fb_var_screeninfo varInfo; struct fb_fix_screeninfo fixInfo; Int displaySize; Int bufIdx; Int8 *virtPtr; Int32 physPtr; Int32 height, width; Display_Handle hDisplay; Buffer_Handle hBuf; if (attrs == NULL) { Dmai_err0("Must supply valid attrs\n"); return NULL; } if (hBufTab != NULL) { Dmai_err0("FBdev display does not accept user allocated buffers\n"); return NULL; } hDisplay = calloc(1, sizeof(Display_Object)); if (hDisplay == NULL) { Dmai_err0("Failed to allocate space for Display Object\n"); return NULL; } /* Open video display device */ hDisplay->fd = open(attrs->displayDevice, O_RDWR); if (hDisplay->fd == -1) { Dmai_err2("Failed to open fb device %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } /* Get fixed screen info */ if (ioctl(hDisplay->fd, FBIOGET_FSCREENINFO, &fixInfo) == -1) { Dmai_err2("Failed FBIOGET_FSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } /* Get virtual screen info */ if (ioctl(hDisplay->fd, FBIOGET_VSCREENINFO, &varInfo) == -1) { Dmai_err2("Failed FBIOGET_VSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } Dmai_dbg5("Found width=%d height=%d, yres_virtual=%d,xres_virtual=%d," " line_length=%d\n", varInfo.xres, varInfo.yres, varInfo.yres_virtual,varInfo.xres_virtual, fixInfo.line_length); /* Save current virtual screen info. */ memcpy(&hDisplay->origVarInfo, &varInfo, sizeof(struct fb_var_screeninfo)); /* If video standard is set to auto then use current height and width */ if (attrs->videoStd == VideoStd_AUTO) { width = varInfo.xres; height = varInfo.yres; } /* If video standard is not set then use the height/width passed from * attribute. */ else if (attrs->videoStd == -1) { width = attrs->width; height = attrs->height; } /* calulcate height/width from video standard */ else { VideoStd_getResolution(attrs->videoStd, &width, &height); } if (attrs->width > 0) { width = attrs->width; } if (attrs->height > 0) { height = attrs->height; } if (width > varInfo.xres) { width = varInfo.xres; } if (height > varInfo.yres) { height = varInfo.yres; } varInfo.xoffset = 0; varInfo.yoffset = 0; varInfo.xres = width; varInfo.yres = height; varInfo.xres_virtual = width; varInfo.yres_virtual = varInfo.yres * attrs->numBufs; /* Set video display format */ Dmai_dbg4("Setting width=%d height=%d, yres_virtual=%d," " xres_virtual=%d\n", varInfo.xres, varInfo.yres, varInfo.yres_virtual, varInfo.xres_virtual); if (ioctl(hDisplay->fd, FBIOPUT_VSCREENINFO, &varInfo) == -1) { Dmai_err2("Failed FBIOPUT_VSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } if (ioctl(hDisplay->fd, FBIOGET_FSCREENINFO, &fixInfo) == -1) { Dmai_err2("Failed FBIOGET_FSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } Dmai_dbg5("New width=%d, height=%d, yres_virtual=%d,xres_virtual=%d, " "line_length=%d\n", varInfo.xres, varInfo.yres, varInfo.yres_virtual, varInfo.xres_virtual, fixInfo.line_length); gfxAttrs.dim.width = varInfo.xres; gfxAttrs.colorSpace = attrs->colorSpace; gfxAttrs.dim.height = varInfo.yres; gfxAttrs.dim.lineLength = fixInfo.line_length; gfxAttrs.bAttrs.reference = TRUE; displaySize = fixInfo.line_length * varInfo.yres; hBufTab = BufTab_create(attrs->numBufs, displaySize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBufTab == NULL) { Dmai_err0("Failed to allocate BufTab for display buffers\n"); cleanup(hDisplay); return NULL; } hBuf = BufTab_getBuf(hBufTab, 0); Buffer_setNumBytesUsed(hBuf, varInfo.xres * varInfo.yres * varInfo.bits_per_pixel / 8); virtPtr = (Int8 *) mmap (NULL, displaySize * attrs->numBufs, PROT_READ | PROT_WRITE, MAP_SHARED, hDisplay->fd, 0); if (virtPtr == MAP_FAILED) { Dmai_err2("Failed mmap on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } if (Buffer_setUserPtr(hBuf, virtPtr) < 0) { cleanup(hDisplay); return NULL; } _Dmai_blackFill(hBuf); Dmai_dbg3("Display buffer %d mapped to %#lx has physical address %#lx\n", 0, (Int32) virtPtr, physPtr); for (bufIdx=1; bufIdx < attrs->numBufs; bufIdx++) { hBuf = BufTab_getBuf(hBufTab, bufIdx); Buffer_setNumBytesUsed(hBuf, varInfo.xres * varInfo.yres * varInfo.bits_per_pixel / 8); virtPtr = virtPtr + displaySize; Buffer_setUserPtr(hBuf, virtPtr); _Dmai_blackFill(hBuf); Dmai_dbg3("Display buffer %d mapped to %#lx, physical address %#lx\n", bufIdx, (unsigned long) virtPtr, physPtr); } hDisplay->hBufTab = hBufTab; hDisplay->displayIdx = 0; hDisplay->workingIdx = attrs->numBufs > 1 ? 1 : 0; hDisplay->displayStd = Display_Std_FBDEV; if (setDisplayBuffer(hDisplay, hDisplay->displayIdx) < 0) { cleanup(hDisplay); return NULL; } return hDisplay; }
/****************************************************************************** * appMain ******************************************************************************/ Void appMain(Args * args) { VIDENC_Params params = Venc_Params_DEFAULT; VIDENC_DynamicParams dynParams = Venc_DynamicParams_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Buffer_Attrs bAttrs = Buffer_Attrs_DEFAULT; Time_Attrs tAttrs = Time_Attrs_DEFAULT; Venc_Handle hVe = NULL; FILE *outFile = NULL; FILE *inFile = NULL; Engine_Handle hEngine = NULL; Time_Handle hTime = NULL; Int numFrame = 0; Buffer_Handle hOutBuf = NULL; Buffer_Handle hInBuf = NULL; ColorSpace_Type colorSpace; UInt32 time; printf("Starting application...\n"); /* Initialize the codec engine run time */ CERuntime_init(); /* Initialize DMAI */ Dmai_init(); if (args->benchmark) { hTime = Time_create(&tAttrs); if (hTime == NULL) { printf("Failed to create Time object\n"); goto cleanup; } } /* Open input file */ inFile = fopen(args->inFile, "rb"); if (inFile == NULL) { printf("Failed to open input file %s\n", args->inFile); goto cleanup; } /* Using a larger vbuf to enhance performance of file i/o */ if (setvbuf(inFile, vbufferIn, _IOFBF, sizeof(vbufferIn)) != 0) { printf("Failed to setvbuf on input file descriptor\n"); goto cleanup; } /* Open output file */ outFile = fopen(args->outFile, "wb"); if (outFile == NULL) { printf("Failed to open output file %s\n", args->outFile); goto cleanup; } /* Using a larger vbuf to enhance performance of file i/o */ if (setvbuf(outFile, vbufferOut, _IOFBF, sizeof(vbufferOut)) != 0) { printf("Failed to setvbuf on output file descriptor\n"); goto cleanup; } /* Open the codec engine */ hEngine = Engine_open(args->engineName, NULL, NULL); if (hEngine == NULL) { printf("Failed to open codec engine: %s\n", args->engineName); goto cleanup; } params.maxWidth = args->width; params.maxHeight = args->height; /* Set up codec parameters depending on bit rate */ if (args->bitRate < 0) { /* Variable bit rate */ params.rateControlPreset = IVIDEO_NONE; /* * If variable bit rate use a bogus bit rate value (> 0) * since it will be ignored. */ params.maxBitRate = 2000000; } else { /* Constant bit rate */ params.rateControlPreset = IVIDEO_LOW_DELAY; params.maxBitRate = args->bitRate; } params.inputChromaFormat = XDM_YUV_422ILE; dynParams.targetBitRate = params.maxBitRate; dynParams.inputWidth = params.maxWidth; dynParams.inputHeight = params.maxHeight; /* Create the video encoder */ hVe = Venc_create(hEngine, args->codecName, ¶ms, &dynParams); if (hVe == NULL) { printf("Failed to create video encoder: %s\n", args->codecName); goto cleanup; } /* Only the UYVY colorspace is supported in this application */ colorSpace = ColorSpace_UYVY; /* Align buffers to cache line boundary */ gfxAttrs.bAttrs.memParams.align = bAttrs.memParams.align = BUFSIZEALIGN; /* Use cached buffers if requested */ if (args->cache) { gfxAttrs.bAttrs.memParams.flags = bAttrs.memParams.flags = Memory_CACHED; } /* Calculate the buffer attributes */ gfxAttrs.dim.width = args->width; gfxAttrs.dim.height = args->height; gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(args->width, colorSpace); gfxAttrs.colorSpace = colorSpace; /* Create input buffer */ hInBuf = Buffer_create(Dmai_roundUp(Venc_getInBufSize(hVe), BUFSIZEALIGN), BufferGfx_getBufferAttrs(&gfxAttrs)); if (hInBuf == NULL) { printf("Failed to allocate contiguous buffer\n"); goto cleanup; } /* Create output buffer */ hOutBuf = Buffer_create(Dmai_roundUp(Venc_getOutBufSize(hVe), BUFSIZEALIGN), &bAttrs); if (hOutBuf == NULL) { printf("Failed to create contiguous buffer\n"); goto cleanup; } while (numFrame++ < args->numFrames) { /* Read a yuv input frame */ printf("Frame %d: ", numFrame); if (readFrameUYVY(hInBuf, inFile) < 0) { goto cleanup; } if (args->benchmark) { if (Time_reset(hTime) < 0) { printf("Failed to reset timer\n"); goto cleanup; } } if (args->cache) { /* * To meet xDAIS DMA Rule 7, when input buffers are cached, we * must writeback the cache into physical memory. Also, per DMA * Rule 7, we must invalidate the output buffer from * cache before providing it to any xDAIS algorithm. */ Memory_cacheWbInv(Buffer_getUserPtr(hInBuf), Buffer_getSize(hInBuf)); /* Per DMA Rule 7, our output buffer cache lines must be cleaned */ Memory_cacheInv(Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { printf("Failed to get timer delta\n"); goto cleanup; } printf("Pre-process cache maintenance: %uus \n", (Uns) time); } } /* Encode the video buffer */ if (Venc_process(hVe, hInBuf, hOutBuf) < 0) { printf("Failed to encode video buffer\n"); goto cleanup; } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { printf("Failed to get encode time\n"); goto cleanup; } printf("[%d] Encode: %uus\n", numFrame, (Uns)time); } if (args->cache) { /* Writeback the outBuf. */ Memory_cacheWb(Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { printf("Failed to get timer delta\n"); goto cleanup; } printf("Post-process cache write back: %uus \n", (Uns) time); } } /* Write the encoded frame to the file system */ if (Buffer_getNumBytesUsed(hOutBuf)) { if (fwrite(Buffer_getUserPtr(hOutBuf), Buffer_getNumBytesUsed(hOutBuf), 1, outFile) != 1) { printf("Failed to write encoded video data to file\n"); goto cleanup; } } if (args->benchmark) { if (Time_total(hTime, &time) < 0) { printf("Failed to get timer total\n"); goto cleanup; } printf("Total: %uus\n", (unsigned int)time); } } cleanup: /* Clean up the application */ if (hOutBuf) { Buffer_delete(hOutBuf); } if (hInBuf) { Buffer_delete(hInBuf); } if (hVe) { Venc_delete(hVe); } if (hEngine) { Engine_close(hEngine); } if (inFile) { fclose(inFile); } if (outFile) { fclose(outFile); } if (hTime) { Time_delete(hTime); } printf("End of application.\n"); return; }
/****************************************************************************** * _Dmai_v4l2DriverAlloc ******************************************************************************/ Int _Dmai_v4l2DriverAlloc(Int fd, Int numBufs, enum v4l2_buf_type type, struct _VideoBufDesc **bufDescsPtr, BufTab_Handle *hBufTabPtr, Int topOffset, ColorSpace_Type colorSpace) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; struct v4l2_requestbuffers req; struct v4l2_format fmt; _VideoBufDesc *bufDesc; Buffer_Handle hBuf; Int bufIdx; Int8 *virtPtr; Dmai_clear(fmt); fmt.type = type; if (ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) { Dmai_err1("VIDIOC_G_FMT failed (%s)\n", strerror(errno)); return Dmai_EFAIL; } Dmai_clear(req); req.count = numBufs; req.type = type; req.memory = V4L2_MEMORY_MMAP; /* Allocate buffers in the capture device driver */ if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { Dmai_err1("VIDIOC_REQBUFS failed (%s)\n", strerror(errno)); return Dmai_ENOMEM; } if (req.count < numBufs || !req.count) { Dmai_err0("Insufficient device driver buffer memory\n"); return Dmai_ENOMEM; } /* Allocate space for buffer descriptors */ *bufDescsPtr = calloc(numBufs, sizeof(_VideoBufDesc)); if (*bufDescsPtr == NULL) { Dmai_err0("Failed to allocate space for buffer descriptors\n"); return Dmai_ENOMEM; } gfxAttrs.dim.width = fmt.fmt.pix.width; gfxAttrs.dim.height = fmt.fmt.pix.height; gfxAttrs.dim.lineLength = fmt.fmt.pix.bytesperline; gfxAttrs.colorSpace = colorSpace; gfxAttrs.bAttrs.reference = TRUE; *hBufTabPtr = BufTab_create(numBufs, fmt.fmt.pix.sizeimage, BufferGfx_getBufferAttrs(&gfxAttrs)); if (*hBufTabPtr == NULL) { return Dmai_ENOMEM; } for (bufIdx = 0; bufIdx < numBufs; bufIdx++) { bufDesc = &(*bufDescsPtr)[bufIdx]; /* Ask for information about the driver buffer */ Dmai_clear(bufDesc->v4l2buf); bufDesc->v4l2buf.type = type; bufDesc->v4l2buf.memory = V4L2_MEMORY_MMAP; bufDesc->v4l2buf.index = bufIdx; if (ioctl(fd, VIDIOC_QUERYBUF, &bufDesc->v4l2buf) == -1) { Dmai_err1("Failed VIDIOC_QUERYBUF (%s)\n", strerror(errno)); return Dmai_EFAIL; } /* Map the driver buffer to user space */ virtPtr = mmap(NULL, bufDesc->v4l2buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bufDesc->v4l2buf.m.offset) + topOffset; if (virtPtr == MAP_FAILED) { Dmai_err1("Failed to mmap buffer (%s)\n", strerror(errno)); return Dmai_EFAIL; } /* Initialize the Buffer with driver buffer information */ hBuf = BufTab_getBuf(*hBufTabPtr, bufIdx); Buffer_setNumBytesUsed(hBuf, fmt.fmt.pix.bytesperline * fmt.fmt.pix.height); Buffer_setUseMask(hBuf, gfxAttrs.bAttrs.useMask); Buffer_setUserPtr(hBuf, virtPtr); /* Initialize buffer to black */ _Dmai_blackFill(hBuf); Dmai_dbg3("Driver buffer %d mapped to %#x has physical address " "%#lx\n", bufIdx, (Int) virtPtr, Buffer_getPhysicalPtr(hBuf)); bufDesc->hBuf = hBuf; /* Queue buffer in device driver */ if (ioctl(fd, VIDIOC_QBUF, &bufDesc->v4l2buf) == -1) { Dmai_err1("VIODIOC_QBUF failed (%s)\n", strerror(errno)); return Dmai_EFAIL; } } return Dmai_EOK; }
/****************************************************************************** * appMain ******************************************************************************/ Int appMain(Args * args) { Framecopy_Attrs fcAttrs = Framecopy_Attrs_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Smooth_Attrs smAttrs = Smooth_Attrs_DEFAULT; Time_Attrs tAttrs = Time_Attrs_DEFAULT; BufTab_Handle hCapBufTab = NULL; BufTab_Handle hDisBufTab = NULL; Display_Handle hDisplay = NULL; Capture_Handle hCapture = NULL; Framecopy_Handle hFc = NULL; Smooth_Handle hSmooth = NULL; Time_Handle hTime = NULL; Int numFrame = 0; Display_Attrs dAttrs; Capture_Attrs cAttrs; Buffer_Handle cBuf, dBuf; Cpu_Device device; Int bufIdx; UInt32 time; BufferGfx_Dimensions dim; Int32 bufSize; Int ret = Dmai_EOK; /* Initialize DMAI */ Dmai_init(); if (args->benchmark) { hTime = Time_create(&tAttrs); if (hTime == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create Time object\n"); goto cleanup; } } /* Determine which device the application is running on */ if (Cpu_getDevice(NULL, &device) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to determine target board\n"); goto cleanup; } /* Set the display and capture attributes depending on device */ switch (device) { case Cpu_Device_DM6467: dAttrs = Display_Attrs_DM6467_VID_DEFAULT; cAttrs = Capture_Attrs_DM6467_DEFAULT; break; case Cpu_Device_DM365: case Cpu_Device_DM368: dAttrs = Display_Attrs_DM365_VID_DEFAULT; cAttrs = Capture_Attrs_DM365_DEFAULT; dAttrs.colorSpace = ColorSpace_YUV420PSEMI; cAttrs.colorSpace = dAttrs.colorSpace; break; case Cpu_Device_OMAPL138: dAttrs = Display_Attrs_OMAPL138_VID_DEFAULT; cAttrs = Capture_Attrs_OMAPL138_DEFAULT; break; case Cpu_Device_OMAP3530: case Cpu_Device_DM3730: dAttrs = Display_Attrs_O3530_VID_DEFAULT; cAttrs = Capture_Attrs_OMAP3530_DEFAULT; dAttrs.colorSpace = cAttrs.colorSpace = ColorSpace_UYVY; dAttrs.rotation = 270; break; default: dAttrs = Display_Attrs_DM6446_DM355_VID_DEFAULT; cAttrs = Capture_Attrs_DM6446_DM355_DEFAULT; break; } if (args->displayStd != -1) { dAttrs.displayStd = args->displayStd; } if (args->displayDevice) { dAttrs.displayDevice = args->displayDevice; } if (args->displayNumBufs != -1) { dAttrs.numBufs = args->displayNumBufs; } /* Enable cropping in capture driver if selected */ if (args->width != -1 && args->height != -1 && args->crop) { cAttrs.cropX = args->xIn; cAttrs.cropY = args->yIn; cAttrs.cropWidth = args->width; cAttrs.cropHeight = args->height; } cAttrs.videoInput = args->videoInput; if (Capture_detectVideoStd(NULL, &cAttrs.videoStd, &cAttrs) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to detect capture video standard\n"); goto cleanup; } /* The color space of the capture buffers depend on the device */ gfxAttrs.colorSpace = cAttrs.colorSpace; if (VideoStd_getResolution(cAttrs.videoStd, &gfxAttrs.dim.width, &gfxAttrs.dim.height) < 0) { goto cleanup; } gfxAttrs.dim.lineLength = Dmai_roundUp(BufferGfx_calcLineLength(gfxAttrs.dim.width, gfxAttrs.colorSpace), 32); gfxAttrs.dim.x = 0; gfxAttrs.dim.y = 0; if (gfxAttrs.colorSpace == ColorSpace_YUV422PSEMI) { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 2; } else if (gfxAttrs.colorSpace == ColorSpace_YUV420PSEMI) { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 3 / 2; } else { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height; } if (args->captureUalloc) { /* Create a table of video buffers to use with the capture device */ hCapBufTab = BufTab_create(cAttrs.numBufs, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hCapBufTab == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to allocate contiguous buffers\n"); goto cleanup; } } /* Create the capture device driver instance */ hCapture = Capture_create(hCapBufTab, &cAttrs); if (hCapture == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create capture device\n"); goto cleanup; } /* Create the display device driver instance */ dAttrs.videoStd = Capture_getVideoStd(hCapture); dAttrs.videoOutput = args->videoOutput; if (args->displayUalloc) { /* Create a table of video buffers to use with the display device */ hDisBufTab = BufTab_create(dAttrs.numBufs, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hDisBufTab == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to allocate contiguous buffers\n"); goto cleanup; } } hDisplay = Display_create(hDisBufTab, &dAttrs); if (hDisplay == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create display device\n"); goto cleanup; } if (args->smooth) { /* Create the smooth job */ hSmooth = Smooth_create(&smAttrs); if (hSmooth == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create smooth job\n"); } } else { /* Create the frame copy job */ fcAttrs.accel = args->accel; hFc = Framecopy_create(&fcAttrs); if (hFc == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create frame copy job\n"); goto cleanup; } } /* * If cropping is not used, alter the dimensions of the captured * buffers and position the smaller image inside the full screen. */ if (args->width != -1 && args->height != -1 && !args->crop) { for (bufIdx = 0; bufIdx < BufTab_getNumBufs(Capture_getBufTab(hCapture)); bufIdx++) { cBuf = BufTab_getBuf(Capture_getBufTab(hCapture), bufIdx); BufferGfx_getDimensions(cBuf, &dim); dim.width = args->width; dim.height = args->height; dim.x = args->xIn; dim.y = args->yIn; if (BufferGfx_setDimensions(cBuf, &dim) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Input resolution does not fit in capture frame\n"); goto cleanup; } } } /* * Alter the dimensions of the display buffers and position * the smaller image inside the full screen. */ if (args->width != -1 && args->height != -1) { for (bufIdx = 0; bufIdx < BufTab_getNumBufs(Display_getBufTab(hDisplay)); bufIdx++) { dBuf = BufTab_getBuf(Display_getBufTab(hDisplay), bufIdx); BufferGfx_getDimensions(dBuf, &dim); dim.width = args->width; dim.height = args->height; dim.x = args->xOut; dim.y = args->yOut; if (BufferGfx_setDimensions(dBuf, &dim) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Output resolution does not fit in display frame\n"); goto cleanup; } } } if (args->smooth) { if (Smooth_config(hSmooth, BufTab_getBuf(Capture_getBufTab(hCapture), 0), BufTab_getBuf(Display_getBufTab(hDisplay), 0)) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to configure smooth job\n"); goto cleanup; } } else { /* Configure the frame copy job */ if (Framecopy_config(hFc, BufTab_getBuf(Capture_getBufTab(hCapture), 0), BufTab_getBuf(Display_getBufTab(hDisplay), 0)) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to configure frame copy job\n"); goto cleanup; } } while (numFrame++ < args->numFrames || args->numFrames == 0) { if (args->benchmark) { if (Time_reset(hTime) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to reset timer\n"); goto cleanup; } } /* Get a captured frame from the capture device */ if (Capture_get(hCapture, &cBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get capture buffer\n"); goto cleanup; } /* Get a frame from the display device to be filled with data */ if (Display_get(hDisplay, &dBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get display buffer\n"); goto cleanup; } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } } if (args->smooth) { /* * Remove interlacing artifacts from the captured buffer and * store the result in the display buffer. */ if (Smooth_execute(hSmooth, cBuf, dBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to execute smooth job\n"); goto cleanup; } } else { /* Copy the captured buffer to the display buffer */ if (Framecopy_execute(hFc, cBuf, dBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to execute frame copy job\n"); goto cleanup; } } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Smooth / Framecopy: %uus ", (Uns) time); } /* Give captured buffer back to the capture device driver */ if (Capture_put(hCapture, cBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to put capture buffer\n"); goto cleanup; } /* Send filled buffer to display device driver to be displayed */ if (Display_put(hDisplay, dBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to put display buffer\n"); goto cleanup; } if (args->benchmark) { if (Time_total(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer total\n"); goto cleanup; } printf("Frame time: %uus\n", (Uns) time); } } cleanup: /* Clean up the application */ if (hSmooth) { Smooth_delete(hSmooth); } if (hFc) { Framecopy_delete(hFc); } if (hCapture) { Capture_delete(hCapture); } if (hDisplay) { Display_delete(hDisplay); } if (hTime) { Time_delete(hTime); } if (hCapBufTab) { BufTab_delete(hCapBufTab); } if (hDisBufTab) { BufTab_delete(hDisBufTab); } if (ret == Dmai_EFAIL) return 1; else return 0; }
/****************************************************************************** * appMain ******************************************************************************/ Int appMain(Args * args) { IMGDEC1_Params params = Idec1_Params_DEFAULT; IMGDEC1_DynamicParams dynParams = Idec1_DynamicParams_DEFAULT; Buffer_Attrs bAttrs = Buffer_Attrs_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Time_Attrs tAttrs = Time_Attrs_DEFAULT; Idec1_Handle hId = NULL; Engine_Handle hEngine = NULL; Time_Handle hTime = NULL; Buffer_Handle hInBuf = NULL; Buffer_Handle hOutBuf = NULL; FILE *outFile = NULL; FILE *inFile = NULL; Int numBytes = 0; Int ret = Dmai_EOK; Cpu_Device device; UInt32 time; printf("Starting application...\n"); if (args->benchmark) { hTime = Time_create(&tAttrs); if (hTime == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create Time object\n"); goto cleanup; } } /* Initialize the codec engine run time */ CERuntime_init(); /* Initialize DMAI */ Dmai_init(); /* Determine which device the application is running on */ if (Cpu_getDevice(NULL, &device) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to determine target board\n"); goto cleanup; } /* Open input file */ inFile = fopen(args->inFile, "rb"); if (inFile == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open file %s\n", args->inFile); goto cleanup; } /* Open output file */ outFile = fopen(args->outFile, "wb"); if (outFile == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create output file %s\n", args->outFile); goto cleanup; } /* Using a larger vbuf to enhance performance of file i/o */ if (setvbuf(outFile, vbuffer, _IOFBF, sizeof(vbuffer)) != 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to setvbuf on file descriptor\n"); goto cleanup; } /* Open the codec engine */ hEngine = Engine_open(args->engineName, NULL, NULL); if (hEngine == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open codec engine %s\n", args->engineName); goto cleanup; } /* * Set output color format to UYVY or Planar output. * Here XDM_DEFUALT sets the output planar format to * the planar fromat of the encoded image. * */ switch (args->oColorSpace) { case ColorSpace_UYVY: params.forceChromaFormat = XDM_YUV_422ILE; break; case ColorSpace_NOTSET: params.forceChromaFormat = XDM_CHROMAFORMAT_DEFAULT; break; case ColorSpace_YUV444P: params.forceChromaFormat = XDM_YUV_444P; break; case ColorSpace_YUV422P: params.forceChromaFormat = XDM_YUV_422P; break; case ColorSpace_YUV420P: params.forceChromaFormat = XDM_YUV_420P; break; case ColorSpace_YUV420PSEMI: params.forceChromaFormat = XDM_YUV_420SP; break; case ColorSpace_GRAY: params.forceChromaFormat = ColorSpace_GRAY; break; default: ret = Dmai_EFAIL; fprintf(stderr,"Unsupported output color space %d.\n", args->oColorSpace); goto cleanup; } if ((device == Cpu_Device_DM365) || (device == Cpu_Device_DM368)) { params.maxHeight = VideoStd_720P_HEIGHT; params.maxWidth = VideoStd_720P_WIDTH; } if (device == Cpu_Device_DM6467) { params.maxHeight = VideoStd_720P_HEIGHT; params.maxWidth = VideoStd_720P_WIDTH; } /* Create the image decoder */ hId = Idec1_create(hEngine, args->codecName, ¶ms, &dynParams); if (hId == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create image decoder: %s\n", args->codecName); goto cleanup; } /* Align buffers to cache line boundary */ gfxAttrs.bAttrs.memParams.align = bAttrs.memParams.align = BUFSIZEALIGN; /* Use cached buffers if requested */ if (args->cache) { gfxAttrs.bAttrs.memParams.flags = bAttrs.memParams.flags = Memory_CACHED; } gfxAttrs.colorSpace = args->oColorSpace; gfxAttrs.dim.width = params.maxWidth; gfxAttrs.dim.height = params.maxHeight; gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(params.maxWidth, gfxAttrs.colorSpace); /* Create an output buffer for decoded data */ hOutBuf = Buffer_create( Dmai_roundUp(Idec1_getOutBufSize(hId), BUFSIZEALIGN), BufferGfx_getBufferAttrs(&gfxAttrs)); if (hOutBuf == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create contiguous buffers\n"); goto cleanup; } /* Create an input buffer for encoded data */ hInBuf = Buffer_create(Dmai_roundUp(Idec1_getInBufSize(hId), BUFSIZEALIGN), &bAttrs); if (hInBuf == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to create contiguous buffers\n"); goto cleanup; } /* Read encoded image data */ numBytes = fread(Buffer_getUserPtr(hInBuf), 1, Idec1_getInBufSize(hId), inFile); Buffer_setNumBytesUsed(hInBuf, numBytes); if (args->benchmark) { if (Time_reset(hTime) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to reset timer\n"); goto cleanup; } } if (args->cache) { /* * To meet xDAIS DMA Rule 7, when input buffers are cached, we * must writeback the cache into physical memory. Also, per DMA * Rule 7, we must invalidate the output buffer from * cache before providing it to any xDAIS algorithm. */ Memory_cacheWbInv(Buffer_getUserPtr(hInBuf), Buffer_getSize(hInBuf)); /* Per DMA Rule 7, our output buffer cache lines must be cleaned */ Memory_cacheInv(Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Pre-process cache maintenance: %uus \n", (Uns) time); } } printf("Decoding image...\n"); /* Decode the image frame */ ret = Idec1_process(hId, hInBuf, hOutBuf); if (ret < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to decode image buffer\n"); goto cleanup; } if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Frame - Decode: %uus \n", (unsigned int)time); } if (args->cache) { /* Writeback the outBuf. */ Memory_cacheWb(Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); if (args->benchmark) { if (Time_delta(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer delta\n"); goto cleanup; } printf("Post-process cache write back: %uus ", (Uns) time); } } /* Write decoded image to a file */ if (BufferGfx_getColorSpace(hOutBuf) == ColorSpace_UYVY){ if (writeFrameUYVY(hOutBuf, outFile) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to write image to file\n"); goto cleanup; } } else if (BufferGfx_getColorSpace(hOutBuf) == ColorSpace_YUV420PSEMI) { if (writeFrameSemiPlanar(hOutBuf, outFile) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to write image to file\n"); goto cleanup; } } else if (BufferGfx_getColorSpace(hOutBuf) == ColorSpace_YUV420P || ColorSpace_YUV422P || ColorSpace_YUV444P || ColorSpace_GRAY){ /* For XDM_GRAY ignoring the color planes */ if (args->oColorSpace == ColorSpace_GRAY){ BufferGfx_setColorSpace (hOutBuf, ColorSpace_GRAY); } if (writeFramePlanar(hOutBuf, outFile) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to write image to file\n"); goto cleanup; } } else { ret = Dmai_EFAIL; fprintf(stderr,"Invalid output colorspace.\n"); goto cleanup; } if (args->benchmark) { if (Time_total(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer total\n"); goto cleanup; } printf("Total: %uus\n", (unsigned int)time); } cleanup: /* Clean up the application */ if (hId) { Idec1_delete(hId); } if (hInBuf) { Buffer_delete(hInBuf); } if (hOutBuf) { Buffer_delete(hOutBuf); } if (hEngine) { Engine_close(hEngine); } if (hTime) { Time_delete(hTime); } if (inFile) { fclose(inFile); } if (outFile) { fclose(outFile); } printf("End of application.\n"); if (ret == Dmai_EFAIL) return 1; else return 0; }
/****************************************************************************** * gst_tiprepencbuf_set_caps *****************************************************************************/ static gboolean gst_tiprepencbuf_set_caps(GstBaseTransform * trans, GstCaps * in, GstCaps * out) { GstTIPrepEncBuf *prepencbuf = GST_TIPREPENCBUF(trans); BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; gboolean ret = FALSE; guint32 fourcc; guint outBufSize; GST_LOG("begin set caps\n"); /* parse input cap */ if (!gst_tiprepencbuf_parse_caps(in, &prepencbuf->srcWidth, &prepencbuf->srcHeight, &fourcc)) { GST_ELEMENT_ERROR(prepencbuf, RESOURCE, FAILED, ("failed to get input resolution\n"), (NULL)); goto exit; } GST_LOG("input fourcc %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS(fourcc)); /* map fourcc with its corresponding dmai colorspace type */ prepencbuf->srcColorSpace = gst_tiprepencbuf_get_colorSpace(fourcc); /* parse output cap */ if (!gst_tiprepencbuf_parse_caps(out, &prepencbuf->dstWidth, &prepencbuf->dstHeight, &fourcc)) { GST_ELEMENT_ERROR(prepencbuf, RESOURCE, FAILED, ("failed to get output resolution\n"), (NULL)); goto exit; } GST_LOG("output fourcc %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS(fourcc)); /* map fourcc with its corresponding dmai colorspace type */ prepencbuf->dstColorSpace = gst_tiprepencbuf_get_colorSpace(fourcc); /* calculate output buffer size */ outBufSize = gst_ti_calc_buffer_size(prepencbuf->dstWidth, prepencbuf->dstHeight, 0, prepencbuf->dstColorSpace); /* allocate output buffer */ gfxAttrs.bAttrs.useMask = gst_tidmaibuffer_GST_FREE; gfxAttrs.colorSpace = prepencbuf->dstColorSpace; gfxAttrs.dim.width = prepencbuf->dstWidth; gfxAttrs.dim.height = prepencbuf->dstHeight; gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(gfxAttrs.dim.width, gfxAttrs.colorSpace); if (prepencbuf->numOutputBufs == 0) { prepencbuf->numOutputBufs = 2; } prepencbuf->hOutBufTab = gst_tidmaibuftab_new(prepencbuf->numOutputBufs, outBufSize, BufferGfx_getBufferAttrs (&gfxAttrs)); if (prepencbuf->hOutBufTab == NULL) { GST_ELEMENT_ERROR(prepencbuf, RESOURCE, NO_SPACE_LEFT, ("failed to create output bufTab\n"), (NULL)); goto exit; } ret = TRUE; exit: GST_LOG("end set caps\n"); return ret; }
/***************************************************************************** * gst_tidmaiaccel_prepare_output_buffer * Function is used to allocate output buffer *****************************************************************************/ static GstFlowReturn gst_tidmaiaccel_prepare_output_buffer (GstBaseTransform *trans, GstBuffer *inBuf, gint size, GstCaps *caps, GstBuffer **outBuf) { GstTIDmaiaccel *dmaiaccel = GST_TIDMAIACCEL(trans); Buffer_Handle hOutBuf; Bool isContiguous = FALSE; UInt32 phys = 0; /* Always check if the buffer is contiguous */ phys = Memory_getBufferPhysicalAddress( GST_BUFFER_DATA(inBuf), GST_BUFFER_SIZE(inBuf), &isContiguous); if (isContiguous && dmaiaccel->width){ GST_DEBUG("Is contiguous video buffer"); Memory_registerContigBuf((UInt32)GST_BUFFER_DATA(inBuf), GST_BUFFER_SIZE(inBuf),phys); /* This is a contiguous buffer, create a dmai buffer transport */ BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; gfxAttrs.bAttrs.reference = TRUE; gfxAttrs.dim.width = dmaiaccel->width; gfxAttrs.dim.height = dmaiaccel->height; gfxAttrs.colorSpace = dmaiaccel->colorSpace; gfxAttrs.dim.lineLength = dmaiaccel->lineLength; hOutBuf = Buffer_create(GST_BUFFER_SIZE(inBuf), &gfxAttrs.bAttrs); BufferGfx_setDimensions(hOutBuf,&gfxAttrs.dim); BufferGfx_setColorSpace(hOutBuf,gfxAttrs.colorSpace); Buffer_setUserPtr(hOutBuf, (Int8*)GST_BUFFER_DATA(inBuf)); Buffer_setNumBytesUsed(hOutBuf, GST_BUFFER_SIZE(inBuf)); *outBuf = gst_tidmaibuffertransport_new(hOutBuf, NULL, NULL, FALSE); gst_buffer_set_data(*outBuf, (guint8*) Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); gst_buffer_copy_metadata(*outBuf,inBuf,GST_BUFFER_COPY_ALL); gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad)); /* We need to grab a reference to the input buffer since we have * a pointer to his buffer */ gst_buffer_ref(inBuf); gst_tidmaibuffertransport_set_release_callback( (GstTIDmaiBufferTransport *)*outBuf, dmaiaccel_release_cb,inBuf); return GST_FLOW_OK; } else { GST_DEBUG("Copying into contiguous video buffer"); /* This is a contiguous buffer, create a dmai buffer transport */ if (!dmaiaccel->bufTabAllocated){ /* Initialize our buffer tab */ BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; gfxAttrs.dim.width = dmaiaccel->width; gfxAttrs.dim.height = dmaiaccel->height; gfxAttrs.colorSpace = dmaiaccel->colorSpace; gfxAttrs.dim.lineLength = dmaiaccel->lineLength; dmaiaccel->hOutBufTab = BufTab_create(2, GST_BUFFER_SIZE(inBuf), BufferGfx_getBufferAttrs(&gfxAttrs)); pthread_mutex_init(&dmaiaccel->bufTabMutex, NULL); pthread_cond_init(&dmaiaccel->bufTabCond, NULL); if (dmaiaccel->hOutBufTab == NULL) { GST_ELEMENT_ERROR(dmaiaccel,RESOURCE,NO_SPACE_LEFT,(NULL), ("failed to create output buffer tab")); return GST_FLOW_ERROR; } dmaiaccel->bufTabAllocated = TRUE; } pthread_mutex_lock(&dmaiaccel->bufTabMutex); hOutBuf = BufTab_getFreeBuf(dmaiaccel->hOutBufTab); if (hOutBuf == NULL) { GST_INFO("Failed to get free buffer, waiting on bufTab\n"); pthread_cond_wait(&dmaiaccel->bufTabCond, &dmaiaccel->bufTabMutex); hOutBuf = BufTab_getFreeBuf(dmaiaccel->hOutBufTab); if (hOutBuf == NULL) { GST_ELEMENT_ERROR(dmaiaccel,RESOURCE,NO_SPACE_LEFT,(NULL), ("failed to get a free contiguous buffer from BufTab")); pthread_mutex_unlock(&dmaiaccel->bufTabMutex); return GST_FLOW_ERROR; } } pthread_mutex_unlock(&dmaiaccel->bufTabMutex); memcpy(Buffer_getUserPtr(hOutBuf),GST_BUFFER_DATA(inBuf), GST_BUFFER_SIZE(inBuf)); Buffer_setNumBytesUsed(hOutBuf, GST_BUFFER_SIZE(inBuf)); *outBuf = gst_tidmaibuffertransport_new(hOutBuf, &dmaiaccel->bufTabMutex, &dmaiaccel->bufTabCond, FALSE); gst_buffer_set_data(*outBuf, (guint8*) Buffer_getUserPtr(hOutBuf), Buffer_getSize(hOutBuf)); gst_buffer_copy_metadata(*outBuf,inBuf,GST_BUFFER_COPY_ALL); gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad)); return GST_FLOW_OK; } }
/******************************************************************************* * gst_tidmaivideosink_render *******************************************************************************/ static GstFlowReturn gst_tidmaivideosink_render(GstBaseSink * bsink, GstBuffer * buf) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Buffer_Handle hDispBuf = NULL; Buffer_Handle inBuf = NULL; BufferGfx_Dimensions inDimSave; GstTIDmaiVideoSink *sink = GST_TIDMAIVIDEOSINK_CAST(bsink); GST_DEBUG("Begin, buffer %p",buf); /* The base sink send us the first buffer twice, so we avoid processing * it again, since the Display_put may fail on this case when using * pad_allocation */ if (sink->prerolledBuffer == buf){ GST_DEBUG("Not displaying previously pre-rolled buffer"); sink->prerolledBuffer = NULL; return GST_FLOW_OK; } sink->prerolledBuffer = NULL; /* If the input buffer is non dmai buffer, then allocate dmai buffer and * copy input buffer in dmai buffer using memcpy routine. */ if (GST_IS_TIDMAIBUFFERTRANSPORT(buf)) { inBuf = GST_TIDMAIBUFFERTRANSPORT_DMAIBUF(buf); } else { /* allocate DMAI buffer */ if (sink->tempDmaiBuf == NULL) { GST_DEBUG("Input buffer is non-dmai, allocating new buffer"); gfxAttrs.dim.width = sink->width; gfxAttrs.dim.height = sink->height; gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(sink->width, sink->colorSpace); gfxAttrs.colorSpace = sink->colorSpace; sink->tempDmaiBuf = Buffer_create(GST_BUFFER_SIZE(buf), BufferGfx_getBufferAttrs(&gfxAttrs)); if (sink->tempDmaiBuf == NULL) { GST_ELEMENT_ERROR(sink,STREAM,FAILED,(NULL), ("Failed to allocate memory for the input buffer")); return GST_FLOW_UNEXPECTED; } } inBuf = sink->tempDmaiBuf; memcpy(Buffer_getUserPtr(inBuf), buf->data, buf->size); } if (Buffer_getBufTab(inBuf) == Display_getBufTab(sink->hDisplay)) { GST_DEBUG("Flipping pad allocated buffer"); /* We got a buffer that is already on video memory, just flip it */ hDispBuf = inBuf; if (sink->numAllocatedBuffers) sink->numAllocatedBuffers--; sink->allocatedBuffers[Buffer_getId(inBuf)] = NULL; if (buf == sink->lastAllocatedBuffer){ sink->lastAllocatedBuffer = NULL; } } else { /* Check if we can allocate a new buffer, otherwise we may need * to drop the buffer */ BufferGfx_getDimensions(inBuf, &inDimSave); if ((sink->numAllocatedBuffers >= (BufTab_getNumBufs(Display_getBufTab(sink->hDisplay)) - 1)) && (sink->numUnusedBuffers == 0)){ GST_ELEMENT_WARNING(sink,RESOURCE,NO_SPACE_LEFT,(NULL), ("Dropping incoming buffers because no display buffer" " available")); return GST_FLOW_OK; } else { GST_DEBUG("Obtaining display buffer"); hDispBuf = gst_tidmaivideosink_get_display_buffer(sink,inBuf); if (!hDispBuf){ return GST_FLOW_UNEXPECTED; } } if (Framecopy_config(sink->hFc, inBuf, hDispBuf) < 0) { GST_ELEMENT_ERROR(sink,STREAM,FAILED,(NULL), ("Failed to configure the frame copy")); return GST_FLOW_UNEXPECTED; } if (Framecopy_execute(sink->hFc, inBuf, hDispBuf) < 0) { GST_ELEMENT_ERROR(sink,STREAM,FAILED,(NULL), ("Failed to execute the frame copy")); return GST_FLOW_UNEXPECTED; } BufferGfx_resetDimensions(hDispBuf); BufferGfx_setDimensions(inBuf, &inDimSave); } /* Send filled buffer to display device driver to be displayed */ if (Display_put(sink->hDisplay, hDispBuf) < 0) { GST_ELEMENT_ERROR(sink,STREAM,FAILED,(NULL), ("Failed to put the buffer on display")); return GST_FLOW_UNEXPECTED; } GST_DEBUG("Finish"); return GST_FLOW_OK; }
/****************************************************************************** * appMain ******************************************************************************/ Int appMain(Args * args) { Time_Attrs tAttrs = Time_Attrs_DEFAULT; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Display_Handle hDisplay = NULL; Time_Handle hTime = NULL; BufTab_Handle hDisBufTab= NULL; Int numFrame = 0; Display_Attrs dAttrs; Buffer_Handle hDispBuf; Int y, x, pos, color; Cpu_Device device; UInt32 time; Int32 bufSize; BufferGfx_Dimensions dim; Int ret = Dmai_EOK; /* Initialize DMAI */ Dmai_init(); if (args->benchmark) { hTime = Time_create(&tAttrs); if (hTime == NULL) { ret = Dmai_EFAIL; fprintf(stderr, "Failed to create Time object\n"); goto cleanup; } } /* Determine which device the application is running on */ if (Cpu_getDevice(NULL, &device) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to determine target board\n"); goto cleanup; } switch (device) { case Cpu_Device_DM6467: dAttrs = Display_Attrs_DM6467_VID_DEFAULT; break; case Cpu_Device_OMAP3530: case Cpu_Device_DM3730: dAttrs = Display_Attrs_O3530_VID_DEFAULT; break; case Cpu_Device_OMAPL138: dAttrs = Display_Attrs_OMAPL138_OSD_DEFAULT; break; case Cpu_Device_DM365: case Cpu_Device_DM368: dAttrs = Display_Attrs_DM365_VID_DEFAULT; break; case Cpu_Device_OMAPL137: dAttrs = Display_Attrs_OMAPL137_OSD_DEFAULT; break; default: dAttrs = Display_Attrs_DM6446_DM355_VID_DEFAULT; break; } if (args->displayUalloc) { gfxAttrs.colorSpace = dAttrs.colorSpace; if (VideoStd_getResolution(args->videoStd, &gfxAttrs.dim.width, &gfxAttrs.dim.height) < 0) { goto cleanup; } gfxAttrs.dim.lineLength = Dmai_roundUp(BufferGfx_calcLineLength(gfxAttrs.dim.width, gfxAttrs.colorSpace), 32); gfxAttrs.dim.x = 0; gfxAttrs.dim.y = 0; if (gfxAttrs.colorSpace == ColorSpace_YUV422PSEMI) { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 2; } else if (gfxAttrs.colorSpace == ColorSpace_YUV420PSEMI) { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 3 / 2; } else { bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height; } if (bufSize < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to calculated size for display buffers\n"); goto cleanup; } /* Create a table of video buffers to use with the display device */ hDisBufTab = BufTab_create(dAttrs.numBufs, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hDisBufTab == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to allocate contiguous buffers\n"); goto cleanup; } } /* Create the video display */ dAttrs.videoStd = args->videoStd; dAttrs.videoOutput = args->videoOutput; hDisplay = Display_create(hDisBufTab, &dAttrs); if (hDisplay == NULL) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to open display device\n"); goto cleanup; } x = color = 0; while (numFrame++ < args->numFrames) { if (args->benchmark) { if (Time_reset(hTime) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to reset timer\n"); goto cleanup; } } /* Get a buffer from the display driver */ if (Display_get(hDisplay, &hDispBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get display buffer\n"); goto cleanup; } /* Retrieve the dimensions of the display buffer */ BufferGfx_getDimensions(hDispBuf, &dim); printf("Display size %dx%d pitch %d x = %d color %d\n", (Int) dim.width, (Int) dim.height, (Int) dim.lineLength, x, color); /* Draw a vertical bar of a color */ for (y = 0; y < dim.height; y++) { pos = y * dim.lineLength + x * 2; memset(Buffer_getUserPtr(hDispBuf) + pos, color, 2); } x = (x + 1) % dim.width; color = (color + 1) % 0xff; /* Give the display buffer back to be displayed */ if (Display_put(hDisplay, hDispBuf) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to put display buffer\n"); goto cleanup; } if (args->benchmark) { if (Time_total(hTime, &time) < 0) { ret = Dmai_EFAIL; fprintf(stderr,"Failed to get timer total\n"); goto cleanup; } printf("[%d] Frame time: %uus\n", numFrame, (Uns) time); } } cleanup: /* Clean up the application */ if (hDisplay) { Display_delete(hDisplay); } if (hDisBufTab) { BufTab_delete(hDisBufTab); } if (hTime) { Time_delete(hTime); } if (ret == Dmai_EFAIL) return 1; else return 0; }
Void *videoThrFxn(Void *arg) { VideoEnv *envp = (VideoEnv *) arg; Venc1_Handle hVe1 = NULL; VIDENC1_Params params = Venc1_Params_DEFAULT; VIDENC1_DynamicParams dynParams = Venc1_DynamicParams_DEFAULT; IH264VENC_Params h264Params = IH264VENC_PARAMS; IH264VENC_DynamicParams h264DynParams = H264VENC_TI_IH264VENC_DYNAMICPARAMS; VUIParamBuffer VUI_Buffer = H264VENC_TI_VUIPARAMBUFFER; BufTab_Handle hVidBufTab = NULL; Buffer_Handle hVInBuf, hWOutBuf; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; ColorSpace_Type colorSpace = ColorSpace_YUV420PSEMI; Int bufSize = 0; Void *status = THREAD_SUCCESS; /* Initialization */ params.maxWidth = envp->imageWidth; params.maxHeight = envp->imageHeight; params.inputChromaFormat = XDM_YUV_420SP; params.reconChromaFormat = XDM_YUV_420SP; params.maxFrameRate = envp->videoFrameRate; params.encodingPreset = XDM_USER_DEFINED; params.rateControlPreset = IVIDEO_USER_DEFINED; params.maxBitRate = 10000000; dynParams.targetBitRate = envp->videoBitRate*0.9; dynParams.inputWidth = envp->imageWidth; dynParams.captureWidth = Dmai_roundUp(BufferGfx_calcLineLength(envp->imageWidth, colorSpace), 32); dynParams.inputHeight = envp->imageHeight; dynParams.refFrameRate = params.maxFrameRate; dynParams.targetFrameRate = params.maxFrameRate; dynParams.intraFrameInterval = 0; dynParams.interFrameInterval = 0; h264Params.videncParams = params; h264Params.videncParams.size = sizeof(IH264VENC_Params); h264Params.encQuality = 1; h264Params.enableDDRbuff = 1; /* Uses DDR instead of VICP buffers */ h264Params.enableARM926Tcm = 0; h264Params.enableVUIparams = (0x1 << 1); h264Params.videncParams.inputContentType = IVIDEO_PROGRESSIVE; h264DynParams.videncDynamicParams = dynParams; h264DynParams.videncDynamicParams.size = sizeof(IH264VENC_DynamicParams); h264DynParams.VUI_Buffer = &VUI_Buffer; h264DynParams.VUI_Buffer->aspectRatioInfoPresentFlag = 1; h264DynParams.VUI_Buffer->overscanInfoPresentFlag = 0; h264DynParams.VUI_Buffer->videoSignalTypePresentFlag = 0; h264DynParams.VUI_Buffer->timingInfoPresentFlag = 1; h264DynParams.VUI_Buffer->numUnitsInTicks = 1; h264DynParams.VUI_Buffer->timeScale = params.maxFrameRate / 1000; h264DynParams.VUI_Buffer->fixedFrameRateFlag = 1; h264DynParams.VUI_Buffer->nalHrdParameterspresentFlag = 1; h264DynParams.VUI_Buffer->picStructPresentFlag = 1; h264DynParams.idrFrameInterval = 15; hVe1 = Venc1_create(envp->hEngine, envp->videoEncoder, (IVIDENC1_Params *) &h264Params, (IVIDENC1_DynamicParams *) &h264DynParams); if (hVe1 == NULL) { ERR("Failed to create video encoder: %s\n", envp->videoEncoder); cleanup(THREAD_FAILURE); } /* Store the output buffer size in the environment */ envp->outBufSize = Venc1_getOutBufSize(hVe1); /* Signal that the codec is created and output buffer size available */ Rendezvous_meet(envp->hRendezvousWriter); /* Video BufTab create */ BufferGfx_calcDimensions(VideoStd_D1_PAL, colorSpace, &gfxAttrs.dim); gfxAttrs.dim.width = 704; gfxAttrs.dim.height = 576; gfxAttrs.dim.lineLength = Dmai_roundUp(BufferGfx_calcLineLength(gfxAttrs.dim.width, colorSpace), 32); gfxAttrs.colorSpace = colorSpace; bufSize = gfxAttrs.dim.lineLength * gfxAttrs.dim.height * 3 / 2; hVidBufTab = BufTab_create(NUM_VIDEO_BUFS, bufSize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hVidBufTab == NULL) { ERR("Failed to create video buftab\n"); cleanup(THREAD_FAILURE); } /* Set input buffer table */ Venc1_setBufTab(hVe1, hVidBufTab); /* Send video buffers to DEI */ Int nBufId = 0; for (nBufId = 0; nBufId < NUM_VIDEO_BUFS; nBufId++) { hVInBuf = BufTab_getBuf(hVidBufTab, nBufId); if (Fifo_put(envp->hVideoOutFifo, hVInBuf) < 0) { ERR("Failed to send buffer to dei thread\n"); cleanup(THREAD_FAILURE); } } /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvousInit); while(1) { /* Get buffer from DEI thread */ if(Fifo_get(envp->hVideoInFifo, &hVInBuf) < 0) { ERR("Failed to get buffer from dei thread\n"); cleanup(THREAD_FAILURE); } /* Get buffer from Writer thread */ if(Fifo_get(envp->hWriterOutFifo, &hWOutBuf) < 0) { ERR("Failed to get buffer from writer thread\n"); cleanup(THREAD_FAILURE); } /* Make sure the whole buffer is used for input */ BufferGfx_resetDimensions(hVInBuf); /* Encode */ if (Venc1_process(hVe1, hVInBuf, hWOutBuf) < 0) { ERR("Failed to encode video buffer\n"); cleanup(THREAD_FAILURE); } /* Put buffer to dei thread */ if (Fifo_put(envp->hVideoOutFifo, hVInBuf) < 0) { ERR("Failed to send buffer to dei thread\n"); cleanup(THREAD_FAILURE); } /* Put buffer to writer thread */ if (Fifo_put(envp->hWriterInFifo, hWOutBuf) < 0) { ERR("Failed to send buffer to dei thread\n"); cleanup(THREAD_FAILURE); } } cleanup: /* Make sure the other threads aren't waiting for us */ Rendezvous_force(envp->hRendezvousInit); Rendezvous_force(envp->hRendezvousWriter); /* Make sure the other threads aren't waiting for init to complete */ Rendezvous_meet(envp->hRendezvousCleanup); if (hVidBufTab) { BufTab_delete(hVidBufTab); } if (hVe1) { Venc1_delete(hVe1); } return status; }