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.

saLoopBack failed at startCapture with "VPSS_FVID2: create handle is NULL" error message

Other Parts Discussed in Thread: TVP5158, TVP7002

Hi all,

Currently I'm working on our TI8148 custom board with a camera module OV7740 attached to VIN[1] port A.

I had added in the driver for OV7740 based on http://processors.wiki.ti.com/index.php/DM81xx_AM38xx_Adding_External_Decoders_to_V4L2_Capture_Driver.

During ti81xxvin module probing, this device OV7740 can be accessed via I2C and programmed properly with its default values.

The OV7740 output is 640 x 480 at 30fps in YUV format.

I wanted to use saLoopBack test example to capture video from the camera and display on our LCD.

When I executed saLoopBack, I encountered the following error at startCapture:

[startCapture]
TI81XXVIN: vidioc_streamon
ti81xxvin ti81xxvin: ti81xxvin_check_format
TI81XXVIN: ti81xxvin_check_format
OV7740: ov7740_s_stream
VPSS_CAPTURE: create capture2
VPSS_SHRBUF: FOUND 0xa0215000, end 0xa0400000, map vir 0xe1015000 size 4096
VPSS_FVID2: Fvid2 handle 0x00000000 with notifyno 14 within 1 ms
VPSS_FVID2: drvid=256 instanceid=2
VPSS_FVID2: create handle is NULL
VPSS_SHRBUF: free mem paddr 0xa0215000 vaddr 0xe1015000 size 4096
ti81xxvin ti81xxvin: ti81xxvin_vps_create failed
ti81xxvin ti81xxvin: Vps create failed


I had set CAPTURE_DEVICE as /dev/video5.

Please help to advise what could be causing the problem or which configuration I might have set wrongly.

As this is the last milestone for this project, this issue is highly urgent!

Thank you.


Regards

May

  • Hi,

    This says the creating of the FVID2 driver on the firmware side is failing. That means some parameter is getting wrongly selected. You need to share details of the "Vps_CaptCreateParams" structure which is getting set in the file drivers/video/ti81xx/capt.c

  • Hi Hardik,

    I had printed the "Vps_CaptCreateParams" parameters in capture_create function right before call vps_fvid2_create.

    The camera output is 8bit YUV in VGA format at 30fps and its connected to VIN[1] port A, clock supplied to the camera is sourced from 20MHz system clock.

    VPSS_CAPTURE: create capture2
    VPSS_CAPTURE: [capture_create] cctrl->ccparams {
    VPSS_CAPTURE: .videoCaptureMode = 4
    VPSS_CAPTURE: .videoIfMode = 0
    VPSS_CAPTURE: .inDataFormat = 1
    VPSS_CAPTURE: .periodicCallbackEnable = 0
    VPSS_CAPTURE: .numCh = 1
    VPSS_CAPTURE: .numStream = 1
    VPSS_CAPTURE: .outStreamInfo[0].dataFormat = 1
    VPSS_CAPTURE: .outStreamInfo[0].memType = 0
    VPSS_CAPTURE: .outStreamInfo[0].pitch[0] = 1280
    VPSS_CAPTURE: .outStreamInfo[0].pitch[1] = -1
    VPSS_CAPTURE: .outStreamInfo[0].pitch[2] = -1
    VPSS_CAPTURE: .outStreamInfo[0].maxOutWidth = 0
    VPSS_CAPTURE: .outStreamInfo[0].maxOutHeight = 0
    VPSS_CAPTURE: .outStreamInfo[0].scEnable = 0
    VPSS_CAPTURE: .outStreamInfo[0].subFrameModeEnable = 0
    VPSS_CAPTURE: .outStreamInfo[0].numLinesInSubFrame = 0
    VPSS_CAPTURE: .scParams {
    VPSS_CAPTURE: ..inWidth = -1
    VPSS_CAPTURE: ..inHeight = -1
    VPSS_CAPTURE: ..outWidth = -1
    VPSS_CAPTURE: ..outHeight = -1
    VPSS_CAPTURE: ..inCropCfg {
    VPSS_CAPTURE: ...cropstartx = -1
    VPSS_CAPTURE: ...cropstarty = -1
    VPSS_CAPTURE: ...cropwidth = -1
    VPSS_CAPTURE: ...cropheight = -1
    VPSS_CAPTURE: ..}
    VPSS_CAPTURE: ..inScanFormat = -1
    VPSS_CAPTURE: ..enableCoeffLoad = -1
    VPSS_CAPTURE: .}
    VPSS_CAPTURE: .vipParserInstConfig {
    VPSS_CAPTURE: ..clipActive = 0
    VPSS_CAPTURE: ..clipBlank = 0
    VPSS_CAPTURE: .}
    VPSS_CAPTURE: .vipParserPortConfig {
    VPSS_CAPTURE: ..ctrlChanSel = -1
    VPSS_CAPTURE: ..ancChSel8b = -1
    VPSS_CAPTURE: ..pixClkEdgePol = 0
    VPSS_CAPTURE: ..invertFidPol = 0
    VPSS_CAPTURE: ..embConfig {
    VPSS_CAPTURE: ...errCorrEnable = 1
    VPSS_CAPTURE: ...srcNumPos = -1
    VPSS_CAPTURE: ...isMaxChan3Bits = 0
    VPSS_CAPTURE: ..}
    VPSS_CAPTURE: ..disConfig {
    VPSS_CAPTURE: ...fidSkewPostCnt = 0
    VPSS_CAPTURE: ...fidSkewPreCnt = 0
    VPSS_CAPTURE: ...lineCaptureStyle = 0
    VPSS_CAPTURE: ...fidDetectMode = 0
    VPSS_CAPTURE: ...actvidPol = -1
    VPSS_CAPTURE: ...vsyncPol = 1
    VPSS_CAPTURE: ...hsyncPol = 1
    VPSS_CAPTURE: ..}
    VPSS_CAPTURE: .}
    VPSS_CAPTURE: .cscConfig is NULL
    VPSS_CAPTURE: .channelNumMap[0][0] = 128
    VPSS_CAPTURE: .inScanFormat = 1
    VPSS_CAPTURE: .muxModeStartChId = 0
    VPSS_CAPTURE: }

    Thanks & Regards

    May

  • Hi Hardik,

    I found that when I changed the .input_data_format from FVID2_DF_YUV422I_YUYV to FVID2_DF_YUV422P.

    I'm able to get the handle and camera output is displayed on the LCD.

    However the image color is not correct.

    Our camera output is YUV interleaved as YUYV hence I configure to FVID2_DF_YUV422I_YUYV but seem like this is not supported.

    Please advise.

    Regards

    May

  • Hi,

    P and I matters only when data is in memory. For externally driven data you only need to say its in 422, 444 or RGB format. That why with 422P 'P' is ignored.. This is part of vps_capture.h file.  See below

      u32 inDataFormat;
        /**< Input source color data format, valid values are given below \n
          FVID2_DF_YUV422P, ( 'P' is not relavent for input data format) \n
          FVID2_DF_YUV444P, ( 'P' is not relavent for input data format) \n
          FVID2_DF_RGB24_888.
          For valid values see #FVID2_DataFormat.
         */
    Good to know you solve the problem.

  • Hi Hardik,

    One more question regarding saLoopBack.

    The camera out is YUV422 and our LCD is RGB888.

    Currently, I'm checking the camera output by setting the camera to output color bar image.

    The color seem to be wronged.

    I read from TI8148 TRM that colorspace conversion is supported.

    Can I confirm if I configure the LCD as follows:

    echo triplediscrete,rgb888 > /sys/devices/platform/vpss/display1/output

    And the attached is the saLoopBack that I'm running.

    Please help to advise if the setupDisplay in saLoopBack is configured correctly.

    /*
     * saLoopBack.c
     *
     * Copyright (C) 2011 TI
     * Author: Hardik Shah <hardik.shah@ti.com>
     *
     * This is a sample for loopback application. This application captures through
     * V4L2 capture driver on TVP7002 input and displays the captured content
     * on the V4L2 display driver. Application uses userpointer mechanism for
     * both capture and display drivers. Buffers for the userpointer are taken from
     * framebuffer driver (fbdev).
     *
     * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    */
    
    /*
     * Header File Inclusion
     */
    #define CONFIG_MACH_UX200	1
    
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <errno.h>
    #include <string.h>
    #include <linux/videodev2.h>
    #include <linux/fb.h>
    #include <linux/ti81xxfb.h>
    #include <linux/ti81xxhdmi.h>
    #include <linux/ti81xxvin.h>
    
    #undef LMF_NOT_NEED
    #undef LMF_TEMP_DISABLE
    
    /* Number of buffers required for application. Less that this may cause
     * considerable frame drops
     */
    #define MAX_BUFFER			8
    
    /* device node to be used for capture */
    #define INPUT_SOURCE_VIN0	0
    #if INPUT_SOURCE_VIN0
    #define CAPTURE_DEVICE		"/dev/video0"
    #else
    #define CAPTURE_DEVICE		"/dev/video5"
    #endif
    #define CAPTURE_NAME		"Capture"
    /* device node to be used for display */
    #define DISPLAY_DEVICE		"/dev/video1"
    #define DISPLAY_NAME		"Display"
    /* number of frames to be captured and displayed
     * Increase this for long runs
     */
    #define MAXLOOPCOUNT		10000
    
    /* Pixel format for capture and display. Capture supports
     * V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV16, V4L2_PIX_FMT_RGB24 but display
     * supports only V4L2_PIX_FMT_YUYV. So this has to be V4L2_PIX_FMT_YUYV
     */
    #define DEF_PIX_FMT		V4L2_PIX_FMT_YUYV
    
    /* Application name */
    #define APP_NAME		"saLoopBack"
    
    /* Define below #def for debug information enable */
    //#undef SALOOPBACK_DEBUG
    #define SALOOPBACK_DEBUG
    
    
    /* Structure for storing buffer information */
    struct buf_info {
    	int index;
    	unsigned int length;
    	char *start;
    };
    
    /* Structure for storing application data like file pointers, format etc. */
    struct app_obj {
    	int fd;
    	struct v4l2_capability cap;
    	struct v4l2_format fmt;
    	struct v4l2_dv_preset dv_preset;
    	struct v4l2_requestbuffers reqbuf;
    	int numbuffers;
    	struct v4l2_buffer buf;
    	struct ti81xxvin_overflow_status over_flow;
    };
    
    /* Globals for capture and display application objects */
    struct app_obj disp, capt;
    
    /* File pointer for fbdev. fbdev is only used to get buffers
     */
    static int fbdev_fd;
    
    /* Pointers for storing buffer addresses */
    unsigned char *buffer_addr[MAX_BUFFER];
    
    /* Utility function for printing format */
    static void printFormat(char *string, struct v4l2_format *fmt)
    {
    	printf("=============================================================\n");
    	printf("%s Format:\n", string);
    	printf("=============================================================\n");
    	printf("fmt.type\t\t = %d\n", fmt->type);
    	printf("fmt.width\t\t = %d\n", fmt->fmt.pix.width);
    	printf("fmt.height\t\t = %d\n", fmt->fmt.pix.height);
    	printf("fmt.pixelformat\t = %d\n", fmt->fmt.pix.pixelformat);
    	printf("fmt.bytesperline\t = %d\n", fmt->fmt.pix.bytesperline);
    	printf("fmt.sizeimage\t = %d\n", fmt->fmt.pix.sizeimage);
    	printf("=============================================================\n");
    }
    /* Open and query dv preset for capture driver*/
    static int initCapture(void)
    {
    	int mode = O_RDWR;
    
    	printf("\n[%s]\n", __func__);
    
    	/* Open capture driver */
    	capt.fd = open((const char *)CAPTURE_DEVICE, mode);
    	if (capt.fd == -1) {
    		printf("failed to open capture device\n");
    		return -1;
    	}
    	/* Query for capabilities */
    	if (ioctl(capt.fd, VIDIOC_QUERYCAP, &capt.cap)) {
    		printf("Query capability failed\n");
    		exit(2);
    	} else 	{
    		printf("Driver Name: %s\n", capt.cap.driver);
    		printf("Driver bus info: %s\n", capt.cap.bus_info);
    		if (capt.cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
    			printf("Driver is capable of doing capture\n");
    		if (capt.cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
    			printf("Driver is capabled of scaling and cropping\n");
    
    	}
    	system("echo 0 > /sys/devices/platform/vpss/display1/enabled");
    	/* Query the preset. Set it to invalid and query for it */
    	capt.dv_preset.preset = 0x0;
    	if (ioctl(capt.fd, VIDIOC_QUERY_DV_PRESET, &capt.dv_preset)) {
    		printf("Querying DV Preset failed\n");
    		exit(2);
    	}
    
    #ifdef LMF_NOT_NEED
    	switch (capt.dv_preset.preset) {
    	case V4L2_DV_720P60:
    		printf("%s:\n Mode set is 720P60\n", APP_NAME);
    		system ("echo 720p-60 > /sys/devices/platform/vpss/display1/mode");
    		break;
    	case V4L2_DV_1080I60:
    		printf("%s:\n Mode set is 1080I60\n", APP_NAME);
    		system ("echo 1080i-60 > /sys/devices/platform/vpss/display1/mode");
    		break;
    	case V4L2_DV_1080P60:
    		printf("%s:\n Mode set is 1080P60\n", APP_NAME);
    		system ("echo 1080p-60 > /sys/devices/platform/vpss/display1/mode");
    		break;
    	case V4L2_DV_1080P30:
    		printf("%s:\n Mode set is 1080P30\n", APP_NAME);
    		system ("echo 1080p-30 > /sys/devices/platform/vpss/display1/mode");
    		break;
    	default:
    		printf("%s:\n Mode set is %d\n", APP_NAME, capt.dv_preset.preset);
    	}
    #endif
    
    	if (ioctl(capt.fd, VIDIOC_S_DV_PRESET, &capt.dv_preset)) {
    		printf("Setting DV Preset failed\n");
    		exit(2);
    	}
    	printf("LMF: capt.dv_preset.preset 0x%X\n", capt.dv_preset.preset);
    	system("echo 1 > /sys/devices/platform/vpss/display1/enabled");
    	return 0;
    }
    /* Open display driver and set format according to resolution on capture */
    static int initDisplay(void)
    {
    	int mode = O_RDWR;
    
    	printf("\n[%s]\n", __func__);
    
    	/* Open display driver */
    	disp.fd = open((const char *)DISPLAY_DEVICE, mode);
    	if (disp.fd == -1) {
    		printf("failed to open display device\n");
    		return -1;
    	}
    	/* Query driver capability */
    	if (ioctl(disp.fd, VIDIOC_QUERYCAP, &disp.cap)) {
    		printf("Query capability failed for display\n");
    		exit(2);
    	}  else {
    		printf("Driver Name: %s\n", disp.cap.driver);
    		printf("Driver bus info: %s\n", disp.cap.bus_info);
    		if (disp.cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
    			printf("Driver is capable of doing capture\n");
    		if (disp.cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
    			printf("Driver is capabled of scaling and cropping\n");
    
    	}
    	return 0;
    }
    /* Setup capture driver */
    int setupCapture(void)
    {
    	int ret;
    
    	printf("\n[%s]\n", __func__);
    
    	/* Get current format */
    	capt.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	ret = ioctl(capt.fd, VIDIOC_G_FMT, &capt.fmt);
    	if (ret < 0) {
    		printf("Set Format failed\n");
    		return -1;
    	}
    	/* Set format according to mode detected */
    	if (capt.dv_preset.preset == V4L2_DV_720P60) {
    		capt.fmt.fmt.pix.width = 1280;
    		capt.fmt.fmt.pix.height = 720;
    	} else if (capt.dv_preset.preset == V4L2_DV_1080P60) {
    		capt.fmt.fmt.pix.width = 1920;
    		capt.fmt.fmt.pix.height = 1080;
    	} else if (capt.dv_preset.preset == V4L2_DV_480P30) {
    		capt.fmt.fmt.pix.width = 640;
    		capt.fmt.fmt.pix.height = 480;
    	}  else {
    		capt.fmt.fmt.pix.width = 1920;
    		capt.fmt.fmt.pix.height = 1080;
    	}
    	capt.fmt.fmt.pix.bytesperline = capt.fmt.fmt.pix.width * 2;
    	capt.fmt.fmt.pix.sizeimage = capt.fmt.fmt.pix.bytesperline *
    		capt.fmt.fmt.pix.height;
    	ret = ioctl(capt.fd, VIDIOC_S_FMT, &capt.fmt);
    	if (ret < 0) {
    		printf("Set Format failed\n");
    		return -1;
    	}
    	/* Get format again and print it on console */
    	capt.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	ret = ioctl(capt.fd, VIDIOC_G_FMT, &capt.fmt);
    	if (ret < 0) {
    		printf("Set Format failed\n");
    		return -1;
    	}
    	printFormat("Capture", &capt.fmt);
    
    	/* Request buffers. We are operating in userPtr mode */
    	capt.reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	capt.reqbuf.count = MAX_BUFFER;
    	capt.reqbuf.memory = V4L2_MEMORY_USERPTR;
    	ret = ioctl(capt.fd, VIDIOC_REQBUFS, &capt.reqbuf);
    	if (ret < 0) {
    		printf("Could not allocate the buffers\n");
    		return -1;
    	}
    	return 0;
    }
    
    /* Setup display driver */
    int setupDisplay(void)
    {
    	int ret;
    
    	printf("\n[%s]\n", __func__);
    
    	/* Get format */
    	disp.fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    	ret = ioctl(disp.fd, VIDIOC_G_FMT, &disp.fmt);
    	if (ret < 0) {
    		printf("Get Format failed\n");
    		return -1;
    	}
    	/* Set format according to display mode */
    #if 1
    	disp.fmt.fmt.pix.width = 640;
    	disp.fmt.fmt.pix.height = 480;
    #else
    	if (capt.dv_preset.preset == V4L2_DV_720P60) {
    		disp.fmt.fmt.pix.width = 1280;
    		disp.fmt.fmt.pix.height = 720;
    	} else if (capt.dv_preset.preset == V4L2_DV_1080P60) {
    		disp.fmt.fmt.pix.width = 1920;
    		disp.fmt.fmt.pix.height = 1080;
    	}  else {
    		disp.fmt.fmt.pix.width = 1920;
    		disp.fmt.fmt.pix.height = 1080;
    	}
    #endif
    	disp.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    	disp.fmt.fmt.pix.bytesperline = disp.fmt.fmt.pix.width * 2;
    	disp.fmt.fmt.pix.sizeimage = disp.fmt.fmt.pix.bytesperline *
    		disp.fmt.fmt.pix.height;
    	ret = ioctl(disp.fd, VIDIOC_S_FMT, &disp.fmt);
    	if (ret < 0) {
    		printf("Set Format failed\n");
    		return -1;
    	}
    	/* Get format again and display it on console */
    	disp.fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    	ret = ioctl(disp.fd, VIDIOC_G_FMT, &disp.fmt);
    	if (ret < 0) {
    		printf("Get Format failed for display\n");
    		return -1;
    	}
    	printFormat("Display", &disp.fmt);
    	/* Requests buffers, we are operating in userPtr mode */
    	disp.reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    	disp.reqbuf.count = MAX_BUFFER;
    	disp.reqbuf.memory = V4L2_MEMORY_USERPTR;
    	ret = ioctl(disp.fd, VIDIOC_REQBUFS, &disp.reqbuf);
    	if (ret < 0) {
    		perror("Could not allocate the buffers\n");
    		return -1;
    	}
    	return 0;
    }
    /* Stop capture */
    static int stopCapture(void)
    {
    	printf("\n[%s]\n", __func__);
    
    	/* Stop capture */
    	int a = V4L2_BUF_TYPE_VIDEO_CAPTURE, ret;
    	ret = ioctl(capt.fd, VIDIOC_STREAMOFF, &a);
    	if (ret < 0) {
    		perror("VIDIOC_STREAMOFF\n");
    		return -1;
    	}
    	return 0;
    }
    /* Stop display */
    static int stopDisplay(void)
    {
    	int a = V4L2_BUF_TYPE_VIDEO_OUTPUT, ret;
    
    	printf("\n[%s]\n", __func__);
    
    	ret = ioctl(disp.fd, VIDIOC_STREAMOFF, &a);
    	if (ret < 0) {
    		perror("VIDIOC_STREAMOFF\n");
    		return -1;
    	}
    	return 0;
    }
    /* Start display */
    static int startDisplay(void)
    {
    	int a = V4L2_BUF_TYPE_VIDEO_OUTPUT, ret;
    
    	printf("\n[%s]\n", __func__);
    
    	ret = ioctl(disp.fd, VIDIOC_STREAMON, &a);
    	if (ret < 0) {
    		perror("VIDIOC_STREAMON\n");
    		return -1;
    	}
    	return 0;
    }
    /* Start capture */
    static int startCapture(void)
    {
    	int a = V4L2_BUF_TYPE_VIDEO_CAPTURE, ret;
    
    	printf("\n[%s]\n", __func__);
    
    	ret = ioctl(capt.fd, VIDIOC_STREAMON, &a);
    	if (ret < 0) {
    		perror("VIDIOC_STREAMON\n");
    		return -1;
    	}
    	return 0;
    }
    /* Start display */
    static int deInitCapture(void)
    {
    	printf("\n[%s]\n", __func__);
    
    	if (close(capt.fd))
    		return -1;
    	return 0;
    }
    
    /* Close display */
    static int deInitDisplay(void)
    {
    	printf("\n[%s]\n", __func__);
    
    	if (close(disp.fd))
    		return -1;
    	return 0;
    }
    
    /* Get fix screeninfo on fbdev */
    static int get_fixinfo(struct fb_fix_screeninfo *fixinfo)
    {
    	int ret;
    
    	printf("\n[%s]\n", __func__);
    	
    	ret = ioctl(fbdev_fd, FBIOGET_FSCREENINFO, fixinfo);
    	if (ret < 0) {
    		perror("Error reading fixed information.\n");
    		return ret;
    	}
    #ifdef SALOOPBACK_DEBUG
    	printf("\nFix Screen Info:\n");
    	printf("----------------\n");
    	printf("Line Length - %d\n", fixinfo->line_length);
    	printf("Physical Address = %lx\n", fixinfo->smem_start);
    	printf("Buffer Length = %d\n", fixinfo->smem_len);
    #endif
    	return 0;
    }
    /* Get variable screeninfo on FBDEV */
    static int get_varinfo(struct fb_var_screeninfo *varinfo)
    {
    	int ret;
    
    	printf("\n[%s]\n", __func__);
    
    	ret = ioctl(fbdev_fd, FBIOGET_VSCREENINFO, varinfo);
    	if (ret < 0) {
    		perror("Error reading variable information.\n");
    		return ret;
    	}
    #ifdef SALOOPBACK_DEBUG
    	printf("\nVar Screen Info:\n");
    	printf("----------------\n");
    	printf("Xres - %d\n", varinfo->xres);
    	printf("Yres - %d\n", varinfo->yres);
    	printf("Xres Virtual - %d\n", varinfo->xres_virtual);
    	printf("Yres Virtual - %d\n", varinfo->yres_virtual);
    	printf("nonstd       - %d\n", varinfo->nonstd);
    	printf("Bits Per Pixel - %d\n", varinfo->bits_per_pixel);
    	printf("blue lenth %d msb %d offset %d\n",
    			varinfo->blue.length,
    			varinfo->blue.msb_right,
    			varinfo->blue.offset);
    	printf("red lenth %d msb %d offset %d\n",
    			varinfo->red.length,
    			varinfo->red.msb_right,
    			varinfo->red.offset);
    	printf("green lenth %d msb %d offset %d\n",
    			varinfo->green.length,
    			varinfo->green.msb_right,
    			varinfo->green.offset);
    	printf("trans lenth %d msb %d offset %d\n",
    			varinfo->transp.length,
    			varinfo->transp.msb_right,
    			varinfo->transp.offset);
    #endif
    	return 0;
    
    }
    /* We derive buffers from fbdev for userpointer operation.
     * We have to setupBuffers
     * fbdev to get enough number of buffers and with enough size
     *
     */
    static int setupBuffers(void)
    {
    	struct fb_fix_screeninfo fixinfo;
    	struct fb_var_screeninfo varinfo, org_varinfo;
    	int ret;
    	int buffersize;
    	int i;
    
    	printf("\n[%s]\n", __func__);
    
    	/*Open FB device*/
    	fbdev_fd = open("/dev/fb0", O_RDWR);
    	if (fbdev_fd <= 0) {
    		perror("Could not open fb device\n");
    		return -1;
    	}
    	/* Get fix screen information. Fix screen information gives
    	 * fix information like panning step for horizontal and vertical
    	 * direction, line length, memory mapped start address and length etc.
    	 */
    	if (get_fixinfo(&fixinfo)) {
    		perror("Could not get fixed screen info\n");
    		return -1;
    	}
    	/* Get variable screen information. Variable screen information
    	 * gives informtion like size of the image, bites per pixel,
    	 * virtual size of the image etc. */
    	if (get_varinfo(&varinfo)) {
    		perror("getting variable screen info failed\n");
    		return -1;
    	}
    	/*store the original information*/
    	memcpy(&org_varinfo, &varinfo, sizeof(varinfo));
    
    	/*
    	 * Set the resolution which read before again to prove the
    	 * FBIOPUT_VSCREENINFO ioctl, except virtual part which is required for
    	 * panning.
    	 */
    	varinfo.xres = disp.fmt.fmt.pix.width;
    	varinfo.yres = disp.fmt.fmt.pix.height;
    	varinfo.xres_virtual = varinfo.xres;
    	varinfo.yres_virtual = varinfo.yres * MAX_BUFFER;
    	varinfo.bits_per_pixel = 16;
    	varinfo.transp.offset = 0;
    	varinfo.transp.length = 0;
    	varinfo.transp.msb_right = 0;
    	varinfo.red.offset = 16;
    	varinfo.red.length = 5;
    	varinfo.blue.offset = 0;
    	varinfo.blue.length = 5;
    	varinfo.green.offset = 8;
    	varinfo.green.length = 6;
    
    	ret = ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &varinfo);
    	if (ret < 0) {
    		perror("Error writing variable information.\n");
    		return -1;
    	}
    	if (get_varinfo(&varinfo)) {
    		perror("Error getting variable screen information\n");
    		return -1;
    	}
    	/* It is better to get fix screen information again. its because
    	 * changing variable screen info may also change fix screen info. */
    	ret = ioctl(fbdev_fd, FBIOGET_FSCREENINFO, &fixinfo);
    	if (ret < 0) {
    		perror("Error reading fixed information.\n");
    		return -1;
    	}
    
    	/* Get fix screen information. Fix screen information gives
    	 * fix information like panning step for horizontal and vertical
    	 * direction, line length, memory mapped start address and length etc.
    	 */
    	if (get_fixinfo(&fixinfo)) {
    		perror("Getting fixed screen info failed\n");
    		return -1;
    	}
    	/* Mmap the driver buffers in application space so that application
    	 * can write on to them. Driver allocates contiguous memory for
    	 * three buffers. These buffers can be displayed one by one. */
    	buffersize = fixinfo.line_length * varinfo.yres;
    	buffer_addr[0] = (unsigned char *)mmap(0,
    			buffersize *  MAX_BUFFER,
    			(PROT_READ | PROT_WRITE),
    			MAP_SHARED, fbdev_fd, 0);
    	for (i = 1; i < MAX_BUFFER; i++)
    		buffer_addr[i] = buffer_addr[i-1] + buffersize;
    
    	memset(buffer_addr[0], 0xFF, buffersize * MAX_BUFFER);
    	return 0;
    }
    /* Prime capture buffers */
    static int queueCaptureBuffers(void)
    {
    	int ret, i;
    
    	printf("\n[%s]\n", __func__);
    
    	for (i = 0; i < (MAX_BUFFER / 2); i++) {
    		capt.buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    		capt.buf.memory = V4L2_MEMORY_USERPTR;
    		capt.buf.index = i;
    		capt.buf.m.userptr = (unsigned long)buffer_addr[capt.buf.index];
    		capt.buf.length = capt.fmt.fmt.pix.sizeimage;
    		ret = ioctl(capt.fd, VIDIOC_QBUF, &capt.buf);
    		if (ret < 0) {
    			perror("VIDIOC_QBUF\n");
    			return -1;
    		}
    	}
    	return ret;
    }
    /* Prime display buffers */
    static int queueDisplayBuffers(void)
    {
    	int ret, i;
    
    	printf("\n[%s]\n", __func__);
    
    	for (i = (MAX_BUFFER / 2); i < MAX_BUFFER; i++) {
    		disp.buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    		disp.buf.memory = V4L2_MEMORY_USERPTR;
    		disp.buf.index = i - (MAX_BUFFER / 2);
    		disp.buf.m.userptr = (unsigned long)buffer_addr[i];
    		disp.buf.length = capt.fmt.fmt.pix.sizeimage;
    		ret = ioctl(disp.fd, VIDIOC_QBUF, &disp.buf);
    		if (ret < 0) {
    			perror("VIDIOC_QBUF\n");
    			return -1;
    		}
    	}
    	return 0;
    }
    /* This is a utility function to calculate time  between start and stop. This
     * is used to calculate FPS
     */
    static int calc_result_time(struct timeval *result, struct timeval *after,
    		struct timeval *before)
    {
    	/* Perform the carry for the later subtraction by updating "before" */
    	if (after->tv_usec < before->tv_usec) {
    		int nsec = (before->tv_usec - after->tv_usec) / 1000000 + 1;
    		before->tv_usec -= 1000000 * nsec;
    		before->tv_sec += nsec;
    	}
    	if (after->tv_usec - before->tv_usec > 1000000) {
    		int nsec = (after->tv_usec - before->tv_usec) / 1000000;
    
    		before->tv_usec += 1000000 * nsec;
    		before->tv_sec -= nsec;
    	}
    	/* Compute the time remaining to wait, tv_usec is certainly positive.
    	 * */
    	result->tv_sec = after->tv_sec - before->tv_sec;
    	result->tv_usec = after->tv_usec - before->tv_usec;
    	/* Return 1 if result is negative. */
    	return after->tv_sec < before->tv_sec;
    }
    /* Main function */
    int main(int argc, char *argv[])
    {
    	int i = 0, ret = 0;
    	struct v4l2_buffer temp_buf;
    	struct timeval before, after, result;
    
    	/* Divert fbdev to dvo2 so that it does  not do blending with display*/
    	system ("echo 1:dvo2 > /sys/devices/platform/vpss/graphics0/nodes");
    	/* Open the capture driver. Query the resolution from the capture driver
    	 */
    	printf("\nCapture Device: %s\n", CAPTURE_DEVICE);
    	ret = initCapture();
    	if (ret < 0) {
    		printf("Error in opening capture device for channel 0\n");
    		return ret;
    	}
    	/* Open the Display driver. */
    	ret = initDisplay();
    	if (ret < 0) {
    		printf("Error in opening display device for channel 0\n");
    		return ret;
    	}
    restart:
    	/* Setup the capture driver Step includes
    	 * Set the format according to the resolution queried.
    	 * request for buffer descriptors for userpointer buffers
    	 */
    	ret = setupCapture();
    	if (ret < 0) {
    		printf("Error in setting up of capture\n");
    		return ret;
    	}
    	/* Setup the display driver Step includes
    	 * Set the format according to the resolution queried by capture.
    	 * request for buffer descriptors for userpointer buffers
    	 */
    	ret = setupDisplay();
    	if (ret < 0) {
    		printf("Error in setting up of Display\n");
    		return ret;
    	}
    	/* As application works on userPointer, Buffers for both capture and
    	 * display driver are allocated using the fbdev, buffers. Below functionality
    	 * setups the fbdev to mmap the buffers and later capture and display
    	 * will use those buffers
    	 */
    	ret = setupBuffers();
    	if (ret < 0) {
    		printf("Error in setting up of Buffers\n");
    		return ret;
    	}
    	/* Total 8 buffers are allocated using fbdev, 4 buffers are primed to
    	 * capture driver.
    	 */
    	ret = queueCaptureBuffers();
    	if (ret < 0) {
    		printf("Error in queuing capture buffers\n");
    		return ret;
    	}
    
    	/* Total 8 buffers are allocated using fbdev, 4 buffers are primed to
    	 * display driver.
    	 */
    	ret = queueDisplayBuffers();
    	if (ret < 0) {
    		printf("Error in queuing display buffers\n");
    		return ret;
    	}
    
    	/* Start display driver always first. This is because display driver
    	 * takes 2 frames to come out of start. If capture is started first
    	 * frame drops will be seen, since capture will already complete two
    	 * frame by time display starts
    	 */
    	ret = startDisplay();
    	if (ret < 0) {
    		printf("Error starring capture \n");
    		return ret;
    	}
    
    	/* Start capture driver after display driver */
    	ret = startCapture();
    	if (ret < 0) {
    		printf("Error starring capture \n");
    		return ret;
    	}
    
    	/* Get time of day to calculate FPS */
    	gettimeofday(&before, NULL);
    	/* Start the steady state loop. Following steps are followed
    	 * 1 dequeue buffer from capture
    	 * 2 dequeue buffer from display
    	 * 3 exchange capture and display buffer pointers
    	 * 4 queue dislay buffer pointer to capture
    	 * 5 queue capture buffer pointer to display
    	 */
    	
    	printf("\n#### start of looping #### \n");
    	for (i = 0; i < MAXLOOPCOUNT; i++) {
    		/* Dq capture buffer */
    		ret = ioctl(capt.fd, VIDIOC_DQBUF, &capt.buf);
    		if (ret < 0) {
    			perror("VIDIOC_DQBUF\n");
    			return -1;
    		}
    		/* Because of IP bugs, capture hardware gets locked up once in
    		 * a while. In that case DQbuf will return  V4L2_BUF_FLAG_ERROR
    		 * in flags.
    		 */
    		if (capt.buf.flags & V4L2_BUF_FLAG_ERROR) {
    			/* If DQbuf returned error check for the hardware lockup
    			 */
    			ret = ioctl(capt.fd, TICAPT_CHECK_OVERFLOW, &capt.over_flow);
    			if (ret < 0) {
    				perror("TICAPT_CHECK_OVERFLOW\n");
    				return -1;
    			} else {
    				/* If hardware locked up, restart display and
    				 * capture driver
    				 */
    				if (capt.over_flow.porta_overflow) {
    					printf("Port a overflowed\n\n\n\n\n\n\n");
    					stopCapture();
    					stopDisplay();
    					goto restart;
    
    				}
    				if (capt.over_flow.portb_overflow) {
    					printf("Port b overflowed\n\n\n\n\n\n\n");
    					stopCapture();
    					stopDisplay();
    					goto restart;
    				}
    			}
    		}
    		/* DQ display buffer */
    		ret = ioctl(disp.fd, VIDIOC_DQBUF, &disp.buf);
    		if (ret < 0) {
    			perror("VIDIOC_DQBUF Display\n");
    			return -1;
    		}
    		/* Exchange display and capture buffer pointers */
    		temp_buf.m.userptr = capt.buf.m.userptr;
    		capt.buf.m.userptr = disp.buf.m.userptr;
    		disp.buf.m.userptr = temp_buf.m.userptr;
    		/* Queue the capture buffer with updated address */
    		ret = ioctl(capt.fd, VIDIOC_QBUF, &capt.buf);
    		if (ret < 0) {
    			perror("VIDIOC_QBUF\n");
    			return -1;
    		}
    		disp.buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    		disp.buf.memory = V4L2_MEMORY_USERPTR;
    		disp.buf.length = capt.fmt.fmt.pix.sizeimage;
    		/* Queue the display buffer back with updated address */
    		ret = ioctl(disp.fd, VIDIOC_QBUF, &disp.buf);
    		if (ret < 0) {
    			perror("VIDIOC_QBUF Display\n");
    			return -1;
    		}
    		if ((i % 1000) == 0)
    			printf("Count=%d\n", i);
    	}
    	printf("\n#### end of looping #### \n");
    
    	/* Get end time to calculate FPS */
    	gettimeofday(&after, NULL);
    	/* Calculate FPS */
    	calc_result_time(&result, &after, &before);
    	printf("Frame rate = %lu\n", MAXLOOPCOUNT/result.tv_sec);
    	
    	/* Stop capture driver */
    	ret = stopCapture();
    	if (ret < 0) {
    		printf("Error in stopping capture\n");
    		return ret;
    	}
    	/* Stop display driver */
    	ret = stopDisplay();
    	if (ret < 0) {
    		printf("Error in stopping display\n");
    		return ret;
    	}
    
    	/* Deinit capture driver */
    	ret = deInitCapture();
    	if (ret < 0) {
    		printf("Error in capture deInit\n");
    		return ret;
    	}
    	/* Deinit display driver */
    	ret = deInitDisplay();
    	if (ret < 0) {
    		printf("Error in display deInit\n");
    		return ret;
    	}
    	close(fbdev_fd);
    	system("echo 0 > /sys/devices/platform/vpss/display1/enabled");
    	system ("echo 1024x768@60 > /sys/devices/platform/vpss/display1/mode");
    	system("echo 0 > /sys/devices/platform/vpss/graphics0/enabled");
    	system("echo 1 > /sys/devices/platform/vpss/display1/enabled");
    	system("echo 1:dvo2 > /sys/devices/platform/vpss/graphics0/nodes");
    	return 0;
    }
    

    Thank you for your help with this. 

    Regards

    May

  • Hi,

    Yes it should work. Are you able to see correct color bar from capture. If  you dump color bar in file are you able to see correct yuv color. If you are seeing correct yuv colors and then you give this to display with above configuration as RGB  you should see correct colors.

  • Hi Hardik,

    I set the camera to output color bar test pattern to VIN[1] port A and the image displayed on the LCD is as attached.

    This is the expected image:

    Are you able to advise what could be wrong?

    Thank you.

    Regards

    May

  • Hi Hardik,

    Sorry, the image from the camera is as follows:

    Regards

    May

  • What is your input capture size? 1080P30, or 1080P60,or other format?

  • The input capture size is 640 x 480 at 30fps. YUV422, YUYVYUYV format. 

  • Hi Hardik,

    I dumped out the capture buffer before passing to display queue and found that captured data is shifted left by 1 byte as compared to the camera data output captured on the camera EVM.

    Data are zeroes after 576,147th count.

    Please help to highlight which are the areas that could result in these issues?

    Thank you.

    Regards

    May

  • Hello:

       The saloop** is refer from EZSDK? 

      your problem is use dvr_rdk platform to call a V4L2 capture device.

      It looks like dvr_rdk platform is not support V4L2 drivers. So when you call it commit errors.

     As my know, dvr_rdk is use M3 to capture vedio.

    For example ,its capture device tvp5158 is use this mode. May be you should write a capture device OV7740 dvriver use

    M3 mode not V4L2 mode. You can refer 5158' device code.

    Another way, ask ti engineers to solve the dvr_rdk call  V4L2 essue, I have meet this problem too,My capture vedio size changed if i use it,but it is correct if i run it seprately.

     looking forward to communicating...now I use the front way and add a HD capture device driver.


  • Hi,

    V4L2 is supported only for IO Expansion board.  Its not possible to support DVRRDK boad on V4L2 because of multi channel use case.

  • Hi all,

    I'm using EZSDK 5.05.01.04 and loading M3 firmware from "HDVPSS_01_00_01_37" release.

    I followed TI81xx video driver to use ti814x_hdvpss_1G.xem3 as the M3 firmware.

    The application saLoopBack is gotten from EZSDK package and I had modified it to cater to my camera format of VGA.

    I'm not using DVRRDK board.

    The hardware is our custom board which referenced TI8148 evaluation board. But we do not have any IO expansion board.

    Our camera is directly wired to TI8148 VIN[1] port A.

    I had written the OV7740 driver and the driver is able to access the camera and program its default registers via I2C.

    I followed http://processors.wiki.ti.com/index.php/DM81xx_AM38xx_Adding_External_Decoders_to_V4L2_Capture_Driver to add OV7740 decoder and also removed TVP7002 decoder.

    Please clarify if what I'm doing is supported.

    Thank you.


    Regards

    May

  • Hi:

      I dont' know how you driver the device OV7740,if you use it as a V4l2 device, it looks like some diffrent with me: 

    Under platform EZSDK, my print information output by uart as follow;

    ti81xxvin ti81xxvin: registered sub device tvp7002
    ti81xxvin ti81xxvin: TI81xx HDVPSS Capture driver initialized
    Unhandled fault: external abort on non-linefetch (0x1018) at 0x46c00524
    ti81xxvin ti81xxvin: ti81xxvin_open
    ti81xxvin ti81xxvin: vidioc_query_dv_preset
    ~~~~~~~~~Talent vidioc_query_dv_preset

    ti81xxvin ti81xxvin: ti81xxvin_update_std_info
    ti81xxvin ti81xxvin: ti81xxvin_config_format
    dc_get_modeid
    dc_get_modeid
    dc_get_modeid

    ti81xxvin ti81xxvin: vidioc_s_dv_preset
    ti81xxvin ti81xxvin: ti81xxvin_update_std_info
    ti81xxvin ti81xxvin: ti81xxvin_config_format
    ti81xxfb_open !!!!
    ti81xxvin ti81xxvin: VIDIOC_S_FMT
    ti81xxvin ti81xxvin: ti81xxvin_check_format
    ti81xxvin ti81xxvin: vidioc_reqbufs
    ti81xxvin ti81xxvin: ti81xxvin_buffer_setup
    ti81xxvin ti81xxvin: vidioc_qbuf
    ti81xxvin ti81xxvin: ti81xxvin_buffer_prepare
    ti81xxvin ti81xxvin: vidioc_qbuf
    ti81xxvin ti81xxvin: ti81xxvin_buffer_prepare
    ti81xxvin ti81xxvin: vidioc_qbuf
    ti81xxvin ti81xxvin: ti81xxvin_buffer_prepare
    ti81xxvin ti81xxvin: vidioc_streamon
    ti81xxvin ti81xxvin: ti81xxvin_check_format
    ti81xxvin ti81xxvin: ti81xxvin_buffer_queue
    ti81xxvin ti81xxvin: ti81xxvin_buffer_queue
    ti81xxvin ti81xxvin: ti81xxvin_buffer_queue
    ti81xxvin ti81xxvin: vidioc_dqbuf
    ti81xxvin ti81xxvin: ti81xxvin_release

    you can take a look for compare, It  run no err and have no vpss print 

  • Hi,

    I changed macro VPSSDBG in core.h file to have the vpss print eg "VPSS_CAPTURE" for better view of the flow from ti81xxvin to FVID2 where M3 command is sent out.

    Thanks for your dump.

    Without those vpss printouts, the prints are similar to yours.

    When executing saLoopBack, no error reported, just the image is wrong.

    Regards

    May

  • Hi all,

    I found the problem that caused the color bar to display gradient in each bar.

    Its caused by a register setting in the camera hence it generate the output in this matter.

    Thank you all for your help extended.

    Regards

    May