/****************************************************************************** * 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; }
/****************************************************************************** * 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; }
Void *writerThrFxn(Void *arg) { WriterEnv *envp = (WriterEnv *) arg; Void *status = THREAD_SUCCESS; FILE *outFile = NULL; Buffer_Attrs bAttrs = Buffer_Attrs_DEFAULT; BufTab_Handle hBufTab = NULL; Buffer_Handle hOutBuf; Int bufIdx; /* Initialization */ /* Open the output video file */ outFile = fopen(envp->videoFile, "w"); if (outFile == NULL) { ERR("Failed to open %s for writing\n", envp->videoFile); cleanup(THREAD_FAILURE); } /* Create buftab for video thread */ hBufTab = BufTab_create(NUM_WRITER_BUFS, envp->outBufSize, &bAttrs); if (hBufTab == NULL) { ERR("Failed to allocate contiguous buffers\n"); cleanup(THREAD_FAILURE); } /* Send all buffers to the video thread to be filled with encoded data */ for (bufIdx = 0; bufIdx < NUM_WRITER_BUFS; bufIdx++) { if (Fifo_put(envp->hWriterOutFifo, BufTab_getBuf(hBufTab, bufIdx)) < 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(1) { /* Get an encoded buffer from the video thread */ if (Fifo_get(envp->hWriterInFifo, &hOutBuf) < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } if (Buffer_getNumBytesUsed(hOutBuf)) { if (fwrite(Buffer_getUserPtr(hOutBuf), Buffer_getNumBytesUsed(hOutBuf), 1, outFile) != 1) { ERR("Error writing the encoded data to video file\n"); cleanup(THREAD_FAILURE); } } else { printf("Warning, writer received 0 byte encoded frame\n"); } /* Return buffer to capture thread */ if (Fifo_put(envp->hWriterOutFifo, hOutBuf) < 0) { ERR("Failed to send buffer to display thread\n"); cleanup(THREAD_FAILURE); } } cleanup: /* Make sure the other threads aren't waiting for us */ Rendezvous_force(envp->hRendezvousInit); Pause_off(envp->hPauseProcess); /* Meet up with other threads before cleaning up */ Rendezvous_meet(envp->hRendezvousCleanup); /* Clean up the thread before exiting */ if (outFile) { fclose(outFile); } if (hBufTab) { BufTab_delete(hBufTab); } return status; }
Void *deiThrFxn(Void *arg) { DeiEnv *envp = (DeiEnv *) arg; Void *status = THREAD_SUCCESS; Uint32 sysRegBase = 0; VIDENC1_Handle hDei = NULL; IDEI_Params deiParams; Uint16 frame_width = 0, frame_height = 0; Uint16 threshold_low = 0, threshold_high = 0; IVIDEO1_BufDescIn inBufDesc; XDM_BufDesc outBufDesc; XDAS_Int8 *outbufs[2]; XDAS_Int32 outBufSizeArray[2]; VIDENC1_InArgs inArgs; IDEI_OutArgs outArgs; Uint32 bufferSize; CMEM_AllocParams cmemPrm; Uint32 prevBufAddr, outBufAddr; Buffer_Handle cBuf, dBuf; Int ret = 0; int fd = -1; dm365mmap_params_t dm365mmap_params; pthread_mutex_t Dmai_DM365dmaLock = PTHREAD_MUTEX_INITIALIZER; /* ▼▼▼▼▼ Initialization ▼▼▼▼▼ */ DM365MM_init(); printf("\n"); /* dm365mm issue */ sysRegBase = DM365MM_mmap(0x01C40000, 0x4000); CMEM_init(); cmemPrm.type = CMEM_HEAP; cmemPrm.flags = CMEM_NONCACHED; cmemPrm.alignment = 32; prevBufAddr = (Uint32)CMEM_alloc(IN_OUT_BUF_SIZE, &cmemPrm); outBufAddr = (Uint32)CMEM_alloc(IN_OUT_BUF_SIZE, &cmemPrm); frame_width = 720; frame_height = 576; threshold_low = 16; threshold_high = 20; /* Create DEI instance */ deiParams.videncParams.size = sizeof(IDEI_Params); deiParams.frameHeight = frame_height; deiParams.frameWidth = frame_width; deiParams.inLineOffset = frame_width; deiParams.outLineOffset = (frame_width - 8); deiParams.threshold_low = threshold_low; deiParams.threshold_high = threshold_high; deiParams.inputFormat = XDM_YUV_422ILE; deiParams.outputFormat = XDM_YUV_420SP; deiParams.q_num = 1; deiParams.askIMCOPRes = 0; deiParams.sysBaseAddr = sysRegBase; hDei = VIDENC1_create(envp->hEngine, "dei", (VIDENC1_Params *)&deiParams); if(hDei == NULL) { ERR("DEI alg creation failed\n"); cleanup(THREAD_FAILURE); } fd = open("/dev/dm365mmap", O_RDWR | O_SYNC); Rendezvous_meet(envp->hRendezvousInit); /* ▲▲▲▲▲ Initialization ▲▲▲▲▲ */ while (1) { if (Fifo_get(envp->hFromCaptureFifo, &cBuf) < 0) { ERR("Failed to get buffer from capture thread\n"); cleanup(THREAD_FAILURE); } if (Fifo_get(envp->hFromDisplayFifo, &dBuf) < 0) { ERR("Failed to get buffer from display thread\n"); cleanup(THREAD_FAILURE); } inBufDesc.numBufs = 4; bufferSize = (frame_width * frame_height); inBufDesc.bufDesc[0].bufSize = bufferSize; inBufDesc.bufDesc[0].buf = (XDAS_Int8 *)Buffer_getUserPtr(cBuf); inBufDesc.bufDesc[0].accessMask = 0; inBufDesc.bufDesc[1].bufSize = bufferSize; inBufDesc.bufDesc[1].buf = (XDAS_Int8 *)(Buffer_getUserPtr(cBuf) + bufferSize); inBufDesc.bufDesc[1].accessMask = 0; inBufDesc.bufDesc[2].bufSize = bufferSize; inBufDesc.bufDesc[2].buf = (XDAS_Int8 *)prevBufAddr; inBufDesc.bufDesc[2].accessMask = 0; inBufDesc.bufDesc[3].bufSize = bufferSize; inBufDesc.bufDesc[3].buf = (XDAS_Int8 *)(prevBufAddr + bufferSize); inBufDesc.bufDesc[3].accessMask = 0; /* Output buffers */ outBufDesc.numBufs = 2; outbufs[0] = (XDAS_Int8*)outBufAddr; outbufs[1] = (XDAS_Int8*)(outBufAddr + bufferSize); outBufSizeArray[0] = bufferSize; outBufSizeArray[1] = bufferSize / 2; outBufDesc.bufSizes = outBufSizeArray; outBufDesc.bufs = outbufs; inArgs.size = sizeof(VIDENC1_InArgs); outArgs.videncOutArgs.size = sizeof(IDEI_OutArgs); ret = VIDENC1_process((VIDENC1_Handle)hDei, &inBufDesc, &outBufDesc, &inArgs, (IVIDENC1_OutArgs *)&outArgs); if (ret != VIDENC1_EOK) { ERR("DEI process failed\n"); cleanup(THREAD_FAILURE); } dm365mmap_params.src = CMEM_getPhys(outbufs[0]); dm365mmap_params.srcmode = 0; dm365mmap_params.dst = Buffer_getPhysicalPtr(dBuf); dm365mmap_params.dstmode = 0; dm365mmap_params.srcbidx = 712; dm365mmap_params.dstbidx = 704; dm365mmap_params.acnt = 704; dm365mmap_params.bcnt = 576; dm365mmap_params.ccnt = 1; dm365mmap_params.bcntrld = dm365mmap_params.bcnt; dm365mmap_params.syncmode = 1; pthread_mutex_lock(&Dmai_DM365dmaLock); if (ioctl(fd, DM365MMAP_IOCMEMCPY, &dm365mmap_params) == -1) { ERR("memcpy: Failed to do memcpy\n"); cleanup(THREAD_FAILURE); } pthread_mutex_unlock(&Dmai_DM365dmaLock); dm365mmap_params.src = CMEM_getPhys(outbufs[1]); dm365mmap_params.srcmode = 0; dm365mmap_params.dst = Buffer_getPhysicalPtr(dBuf) + (Buffer_getSize(dBuf) * 2 / 3); dm365mmap_params.dstmode = 0; dm365mmap_params.srcbidx = 712; dm365mmap_params.dstbidx = 704; dm365mmap_params.acnt = 712; dm365mmap_params.bcnt = 570 / 2; dm365mmap_params.ccnt = 1; dm365mmap_params.bcntrld = dm365mmap_params.bcnt; dm365mmap_params.syncmode = 1; pthread_mutex_lock(&Dmai_DM365dmaLock); if (ioctl(fd, DM365MMAP_IOCMEMCPY, &dm365mmap_params) == -1) { ERR("memcpy: Failed to do memcpy\n"); cleanup(THREAD_FAILURE); } pthread_mutex_unlock(&Dmai_DM365dmaLock); Buffer_setNumBytesUsed(dBuf, 704 * 576 * 3 / 2); dm365mmap_params.src = Buffer_getPhysicalPtr(cBuf); dm365mmap_params.srcmode = 0; dm365mmap_params.dst = prevBufAddr; dm365mmap_params.dstmode = 0; dm365mmap_params.srcbidx = 1440; dm365mmap_params.dstbidx = 1440; dm365mmap_params.acnt = 1440; dm365mmap_params.bcnt = 576; dm365mmap_params.ccnt = 1; dm365mmap_params.bcntrld = dm365mmap_params.bcnt; dm365mmap_params.syncmode = 1; pthread_mutex_lock(&Dmai_DM365dmaLock); if (ioctl(fd, DM365MMAP_IOCMEMCPY, &dm365mmap_params) == -1) { ERR("memcpy: Failed to do memcpy\n"); cleanup(THREAD_FAILURE); } pthread_mutex_unlock(&Dmai_DM365dmaLock); /* Send buffer to display thread */ if (Fifo_put(envp->hToDisplayFifo, dBuf) < 0) { ERR("Failed to send buffer to dei thread\n"); cleanup(THREAD_FAILURE); } /* Send buffer to display thread */ if (Fifo_put(envp->hToCaptureFifo, cBuf) < 0) { ERR("Failed to send buffer to dei thread\n"); cleanup(THREAD_FAILURE); } } cleanup: Rendezvous_force(envp->hRendezvousInit); Rendezvous_meet(envp->hRendezvousCleanup); /* Delete DEI ALG instance */ VIDENC1_delete(hDei); DM365MM_ummap(sysRegBase,0x4000); DM365MM_exit(); if (fd > 0) { close(fd); } return status; }
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; }