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);
}