This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Image processing questions with VPFE & VPBE drivers use

Other Parts Discussed in Thread: TVP5146

Good morning,

I am working with a DM6437,

in the video_preview example of dvsdk_1_01_00_15\example folder we got a basic example with all API calling.

But there are a few things that I do not understand:

- The frameBuffTable got 6 FVID_Frame buffers - That is ok

- There is only one current frameBuffPtr pointer 

- In a moment the following code is used:

FVID_queue(hGioVpfeCcdc, frameBuffTable[0]);

FVID_queue(hGioVpfeCcdc, frameBuffTable[1]);

FVID_queue(hGioVpfeCcdc, frameBuffTable[2]);

FVID_queue(hGioVpbeVid0, frameBuffTable[3]);

FVID_queue(hGioVpbeVid0, frameBuffTable[4]);

FVID_queue(hGioVpbeVid0, frameBuffTable[5]);

So what I understand here is that the VPFE driver will have 3 buffers  to his queue and that the VPBE will have the 3 others buffers to its driver's queue.

In the documentation it is said that each driver's queue has a READY and FREE queue. So when we use a FVID_queue the buffer goes to the READY queue, when it is ready the driver automatically switch it to the FREE queue, and then when we call the FVID_dequeue we can retrieve the captured image.

When a FVID_queue is used, I have read all TI docs and understood that a buffer is put to the READY queue of one of the driver, and if for example we want to retrieve a captured image we have to use a FVID_dequeue. So I actually get why there is only one frameBuffPtr pointer which contains the image retrieved because they don"t need anathor buffer in the example.

- But what I do not understand is what are exactly doing the FVID_exchange API, I mean I read a lot of posts and also the documentation but it is never clear, sometimes it is said that the FVID_exchange function is equivalent to the serial use of a FVID_queue followed by a FVID_dequeue. I wonder how to acutally replace the FVID_exchange lines by only FVID_queue and FVID_deqeue functions to do the same work with the FVID_exchange API.

Then  my challenge is that:

- when the FVID_queue and FVID_dequeue are clear, I want to process one image captured every 3 images captured, that mean that

Phase 1:

one queue to the VPFE with let's say buffer1

one dequeue from the VPFE in buffer1

Processing of image buffer1

one queue to the VPBE of buffer1

one dequeue of the VPBE in buffer1

Phase 2:

one queue in VPFE with the buffer1 (the buffer dequued is queued again without been processed)

one deqeue of the VPFE in a buffer2

one queue in VPBE with buffer1 ( the buffer 1 is re displayed)

one dequeu in VPBE of buffer1

Phase 3

one queue in VPFE with the buffer1 (the buffer dequued is queued again without been processed)

one deqeue of the VPFE in a buffer2

one queue in VPBE with buffer1 ( the buffer 1 is re displayed)

one dequeu in VPBE of buffer1

What do you actually think of that ?

Regards

Here you can find the full video_preview.c example:

/*
* ======== video_preview.c ========
*
*/


/* runtime include files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/* BIOS include files */
#include <std.h>
#include <gio.h>
#include <tsk.h>
#include <trc.h>

/* PSP include files */
#include <psp_i2c.h>
#include <psp_vpfe.h>
#include <psp_vpbe.h>
#include <fvid.h>
#include <psp_tvp5146_extVidDecoder.h>

/* CSL include files */
#include <soc.h>
#include <cslr_sysctl.h>

/* BSL include files */
#include <evmdm6437.h>
#include <evmdm6437_dip.h>

/* Video Params Defaults */
#include <vid_params_default.h>

/* This example supports either PAL or NTSC depending on position of JP1 */
#define STANDARD_PAL 0
#define STANDARD_NTSC 1

#define FRAME_BUFF_CNT 6

static int read_JP1(void);

static CSL_SysctlRegsOvly sysModuleRegs = (CSL_SysctlRegsOvly )CSL_SYS_0_REGS;


/*
* ======== main ========
*/
void main() {

printf("Video Preview Application\n");
fflush(stdout);

/* Initialize BSL library to read jumper switches: */
EVMDM6437_DIP_init();

/* VPSS PinMuxing */
/* CI10SEL - No CI[1:0] */
/* CI32SEL - No CI[3:2] */
/* CI54SEL - No CI[5:4] */
/* CI76SEL - No CI[7:6] */
/* CFLDSEL - No C_FIELD */
/* CWENSEL - No C_WEN */
/* HDVSEL - CCDC HD and VD enabled */
/* CCDCSEL - CCDC PCLK, YI[7:0] enabled */
/* AEAW - EMIFA full address mode */
/* VPBECKEN - VPBECLK enabled */
/* RGBSEL - No digital outputs */
/* CS3SEL - LCD_OE/EM_CS3 disabled */
/* CS4SEL - CS4/VSYNC enabled */
/* CS5SEL - CS5/HSYNC enabled */
/* VENCSEL - VCLK,YOUT[7:0],COUT[7:0] enabled */
/* AEM - 8bEMIF + 8bCCDC + 8 to 16bVENC */
sysModuleRegs -> PINMUX0 &= (0x005482A3u);
sysModuleRegs -> PINMUX0 |= (0x005482A3u);

/* PCIEN = 0: PINMUX1 - Bit 0 */
sysModuleRegs -> PINMUX1 &= (0xFFFFFFFEu);
sysModuleRegs -> VPSSCLKCTL = (0x18u);

return;
}

/*
* ======== video_preview ========
*/
void video_preview(void) {

FVID_Frame *frameBuffTable[FRAME_BUFF_CNT];
FVID_Frame *frameBuffPtr;
GIO_Handle hGioVpfeCcdc;
GIO_Handle hGioVpbeVid0;
GIO_Handle hGioVpbeVenc;
int status = 0;
int result;
int i;
int standard;
int width;
int height;

/* Set video display/capture driver params to defaults */
PSP_VPFE_TVP5146_ConfigParams tvp5146Params =
VID_PARAMS_TVP5146_DEFAULT;
PSP_VPFECcdcConfigParams vpfeCcdcConfigParams =
VID_PARAMS_CCDC_DEFAULT_D1;
PSP_VPBEOsdConfigParams vpbeOsdConfigParams =
VID_PARAMS_OSD_DEFAULT_D1;
PSP_VPBEVencConfigParams vpbeVencConfigParams;

standard = read_JP1();

/* Update display/capture params based on video standard (PAL/NTSC) */
if (standard == STANDARD_PAL) {
width = 720;
height = 576;
vpbeVencConfigParams.displayStandard = PSP_VPBE_DISPLAY_PAL_INTERLACED_COMPOSITE;
}
else {
width = 720;
height = 480;
vpbeVencConfigParams.displayStandard = PSP_VPBE_DISPLAY_NTSC_INTERLACED_COMPOSITE;
}
vpfeCcdcConfigParams.height = vpbeOsdConfigParams.height = height;
vpfeCcdcConfigParams.width = vpbeOsdConfigParams.width = width;
vpfeCcdcConfigParams.pitch = vpbeOsdConfigParams.pitch = width * 2;

/* init the frame buffer table */
for (i=0; i<FRAME_BUFF_CNT; i++) {
frameBuffTable[i] = NULL;
}

/* create video input channel */
if (status == 0) {
PSP_VPFEChannelParams vpfeChannelParams;
vpfeChannelParams.id = PSP_VPFE_CCDC;
vpfeChannelParams.params = (PSP_VPFECcdcConfigParams*)&vpfeCcdcConfigParams;
hGioVpfeCcdc = FVID_create("/VPFE0",IOM_INOUT,NULL,&vpfeChannelParams,NULL);
status = (hGioVpfeCcdc == NULL ? -1 : 0);
}

/* create video output channel, plane 0 */
if (status == 0) {
PSP_VPBEChannelParams vpbeChannelParams;
vpbeChannelParams.id = PSP_VPBE_VIDEO_0;
vpbeChannelParams.params = (PSP_VPBEOsdConfigParams*)&vpbeOsdConfigParams;
hGioVpbeVid0 = FVID_create("/VPBE0",IOM_INOUT,NULL,&vpbeChannelParams,NULL);
status = (hGioVpbeVid0 == NULL ? -1 : 0);
}

/* create video output channel, venc */
if (status == 0) {
PSP_VPBEChannelParams vpbeChannelParams;
vpbeChannelParams.id = PSP_VPBE_VENC;
vpbeChannelParams.params = (PSP_VPBEVencConfigParams *)&vpbeVencConfigParams;
hGioVpbeVenc = FVID_create("/VPBE0",IOM_INOUT,NULL,&vpbeChannelParams,NULL);
status = (hGioVpbeVenc == NULL ? -1 : 0);
}

/* configure the TVP5146 video decoder */
if (status == 0) {
result = FVID_control(hGioVpfeCcdc, VPFE_ExtVD_BASE+PSP_VPSS_EXT_VIDEO_DECODER_CONFIG, &tvp5146Params);
status = (result == IOM_COMPLETED ? 0 : -1);
}

/* allocate some frame buffers */
if (status == 0) {
for (i=0; i<FRAME_BUFF_CNT && status == 0; i++) {
result = FVID_allocBuffer(hGioVpfeCcdc, &frameBuffTable[i]);
status = (result == IOM_COMPLETED && frameBuffTable[i] != NULL ? 0 : -1);
}
}

/* prime up the video capture channel */
if (status == 0) {
FVID_queue(hGioVpfeCcdc, frameBuffTable[0]);
FVID_queue(hGioVpfeCcdc, frameBuffTable[1]);
FVID_queue(hGioVpfeCcdc, frameBuffTable[2]);
}

/* prime up the video display channel */
if (status == 0) {
FVID_queue(hGioVpbeVid0, frameBuffTable[3]);
FVID_queue(hGioVpbeVid0, frameBuffTable[4]);
FVID_queue(hGioVpbeVid0, frameBuffTable[5]);
}

/* grab first buffer from input queue */
if (status == 0) {
FVID_dequeue(hGioVpfeCcdc, &frameBuffPtr);
}

/* loop forever performing video capture and display */
while ( status == 0 ) {

/* grab a fresh video input frame */
FVID_exchange(hGioVpfeCcdc, &frameBuffPtr);

/* display the video frame */
FVID_exchange(hGioVpbeVid0, &frameBuffPtr);

}

}

/*
* ======== read_JP1 ========
* Read the PAL/NTSC jumper.
*
* Retry, as I2C sometimes fails:
*/
static int read_JP1(void)
{
int jp1 = -1;

while (jp1 == -1) {
jp1 = EVMDM6437_DIP_get(JP1_JUMPER);
TSK_sleep(1);
}
return(jp1);
}

  • Hi,

    Thanks for your post.

    To start out though, have you tried the example in dvsdk_1_01_00_15\psp_1_00_02_00\pspdrivers\system\dm6437\bios\dm6437_evm\src\video\sample\rawcapture\build? This is probably the best place to start if you are planning on working with a camera sensor

    Likewise, for the previewer to start, please look at the example in \dvsdk_1_01_00_15\psp_1_00_02_00\pspdrivers\system\dm6437\bios\dm6437_evm\src\video\sample\previewer\build\

    The best documentation on the PSP VPFE driver seems to be \dvsdk_1_01_00_15\psp_1_00_02_00\pspdrivers\drivers\vpfe\doc\BIOS_VPFE_Driver_UserGuide.pdf, if you would wish to use the previewer driver there is some documentation in \dvsdk_1_01_00_15\psp_1_00_02_00\pspdrivers\drivers\previewer\docs that would help you better.

    Note that the FVID_exchange call is actually equivalent to sequential calls to FVID_queue and FVID_dequeue, so you could queue a frame and than do some work and than dequeue a frame to block for the next frame being available. The Exchange call will avoid the simultaneous call of Queue and Dequeue Application passes an in/out parameter that points to frame buffer that is to be relinquished by the driver. After the call returns successfully, this function fills with the pointer to the frame buffer that was previously queued in the device driver

    Please refer to example code below to exchange the FrameBuffer using FVID_exchange function:

    FVID_Handle CcdcHandle;

    FVID_Frame *CcdcallocFB = NULL;

    FVID_Frame *FBAddr = NULL;

    /* Allocate memory to Frame Buffer */

    FVID_allocBuffer (CcdcHandle, &CcdcallocFB);

    /* Queue the Frame Buffer after allocation */

    FVID_queue (vpfeCcdcHandle, CcdcallocFB);

    /* Allocate memory to Frame Buffer */

    FVID_allocBuffer (CcdcHandle, & FBAddr);

    /* Exchange the Frame Buffers */

    status = FVID_exchange (CcdcHandle, &FBAddr);

    FVID_exchange returns IOM_COMPLETED when it returns successfully. If an error occurs, a negative value will be returned.

    Please refer section 6.1.3 to know more details on the buffer management in the BIOS_VPFE_Driver_UserGuide.pdf doc

    \dvsdk_1_01_00_15\psp_1_00_02_00\pspdrivers\drivers\vpfe\doc\BIOS_VPFE_Driver_UserGuide.pdf

    May be, you could debug the FVID_exchange API for any CCDC or video exchange failure thruough debug print message like VPSS_DBG from the code snippet below from VPSS loopback example:

    VPSS_DBG("VPSS :VPSS Loopback Started \r\n");

    FVID_allocBuffer(CcdcHandle, &CcdcallocFB[1]);

    FBAddr = CcdcallocFB[1];

                      for(i = 0; i < NumOfIterations; i++)

                      {

                      if(IOM_COMPLETED != FVID_exchange(CcdcHandle,&FBAddr))

                      {

                      VPSS_DBG("VPSS :CCDC Exchange.......FAILED \r\n");

                      }

                      if(IOM_COMPLETED != FVID_exchange(Vid0Handle,&FBAddr))

                      {

                      VPSS_DBG("VPSS :Video -0 Exchange.......FAILED \r\n");

                     }

    }

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Thank you for your response,

    I have tried the same code with FVID_exchange ( which works) when I change them by the FVID_queue followed by a FVID_dequeue it is not working

    Do you have an explanation ?

    the core of the code is like that:

    FVID_exchange

    traitement

    FVID_exchange



    replaced by

    FVID_queue
    FVID_dequeue

    traitement

    FVID_queue
    FVID_dequeue


    Regards