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.

OMAPL138 LCDK:frame buffer mmap error

Other Parts Discussed in Thread: OMAPL138, TVP5146, TVP5147M1, SYSBIOS

Hi, i am a newcomer to linux, v4l2 and fb. I want to capture images by the "/dev/video0" and display them by "/dev/fb0".

because of lack of ti example for omapl138 lcdk, i use the saLoopBackFbdev for dm8148 and modify some parameters according to omapl138 lcdk hardware.

Some errors occur. The fb initial failed. The minicom display "MMap Failed". I don’t know the reason.

Can anyone help me please? thanks in advance.

./saLoop                                                  
initCapture()                                                                   
Driver Name: vpif capture                                                       
Driver bus info: VPtvp514x 1-005d: tvp5146 (Version - 0x07) found at 0xba (i2c-)
IF Platform                                                                     
Driver is capable of doing capture                                              
standard.name = NTSC                                                            
standard.name = NTSC-M                                                          
standard.name = NTSC-M-JP                                                       
standard.name = NTSC-M-KR                                                       
standard.name = PAL                                                             
Found standard support in the driver                                            
Input video standard is PAL.                                                    
initFbdev()                                                                     
setupCapture()                                                                  
saLoopBackFbdev: width = 720                                                    
saLoopBackFbdev: height = 576                                                   
saLoopBackFbdev: bytesperline = 720                                             
saLoopBackFbdev: sizeimage = 831488                                             
=============================================================                   
Capture Format:                                                                 
=============================================================                   
fmt.type                 = 1                                                    
fmt.width                = 720                                                  
fmt.height               = 576                                                  
fmt.pixelformat  = 1345466932                                                   
fmt.bytesperline         = 720                                                  
fmt.sizeimage    = 829440                                                       
========Unable to handle kernel NULL pointer dereference at virtual address 0004
================pgd = c0004000                                                  
================[00000004] *pgd=00000000================                        
=====                                                                           
setupFbdevAndBuffers()                                                          
Internal error: Oops: 17 [#1] PREEMPT                                           
Modules linked in:                                                              
CPU: 0    Not tainted  (3.3.0 #1)                                               
PC is at vpif_release+0x5c/0x1c4                                                
LR is at v4l2_release+0x4c/0x6c                                                 
pc : [<c0296790>]    lr : [<c02837e0>]    psr: 60000013                         
sp : c7041e80  ip : c7041ea0  fp : c7041e9c                                     
r10: 00000000  r9 : c780de70  r8 : c7321908                                     
r7 : 00000008  r6 : c7321900  r5 : c7178620  r4 : c7984000                      
r3 : 00000000  r2 : 00000000  r1 : c0543b24  r0 : c7321900                      
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user               
Control: 0005317f  Table: c701c000  DAC: 00000015                               
Process saLoop (pid: 976, stack limit = 0xc7040270)                             
Stack: (0xc7041e80 to 0xc7042000)                                               
1e80: c7be9800 c7321900 c74a7b00 00000008 c7041eb4 c7041ea0 c02837e0 c0296744   
1ea0: c7321900 c72d9170 c7041eec c7041eb8 c008e4cc c02837a4 00000000 00000000   
1ec0: 00000000 c7321900 00000000 c730d600 c7178280 0000000c c7040000 00000000   
1ee0: c7041f0c c7041ef0 c008ad50 c008e3c8 c71a900c c730d600 00000000 00000003   
1f00: c7041f34 c7041f10 c001b5e8 c008ace8 c730d600 0000ff00 46c27760 000000f8   
1f20: c00095c4 00000000 c7041f4c c7041f38 c001b6f8 c001b574 00000000 c78a5b80   
1f40: c7041f7c c7041f50 c001b8f8 c001b6ac b6f75000 00000001 00000000 0000001f   
1f60: c7041fa4 c7041f70 c008d108 000000f8 c7041f94 c7041f80 c001c17c c001b70c   
1f80: ffffffff 000953a0 c7041fa4 c7041f98 c001c1c0 c001c0cc 00000000 c7041fa8   
1fa0: c0009440 c001c1b8 000953a0 46c27760 ffffffff 0009538c 00000008 ffffffff   
1fc0: 000953a0 46c27760 46c27760 000000f8 46c29000 00000000 46afd000 00000000   
1fe0: b6f75000 bed6fcb0 46b30130 46b93db4 60000010 ffffffff 00000000 00000000   
Backtrace:                                                                      
[<c0296734>] (vpif_release+0x0/0x1c4) from [<c02837e0>] (v4l2_release+0x4c/0x6c)
 r7:00000008 r6:c74a7b00 r5:c7321900 r4:c7be9800                                
[<c0283794>] (v4l2_release+0x0/0x6c) from [<c008e4cc>] (fput+0x114/0x200)       
 r5:c72d9170 r4:c7321900                                                        
[<c008e3b8>] (fput+0x0/0x200) from [<c008ad50>] (filp_close+0x78/0x84)          
[<c008acd8>] (filp_close+0x0/0x84) from [<c001b5e8>] (put_files_struct+0x84/0xe)
 r6:00000003 r5:00000000 r4:c730d600 r3:c71a900c                                
[<c001b564>] (put_files_struct+0x0/0xe0) from [<c001b6f8>] (exit_files+0x5c/0x6)
[<c001b69c>] (exit_files+0x0/0x60) from [<c001b8f8>] (do_exit+0x1fc/0x708)      
 r4:c78a5b80 r3:00000000                                                        
[<c001b6fc>] (do_exit+0x0/0x708) from [<c001c17c>] (do_group_exit+0xc0/0xec)    
 r7:000000f8                                                                    
[<c001c0bc>] (do_group_exit+0x0/0xec) from [<c001c1c0>] (sys_exit_group+0x18/0x)
 r4:000953a0 r3:ffffffff                                                        
[<c001c1a8>] (sys_exit_group+0x0/0x20) from [<c0009440>] (ret_fast_syscall+0x0/)
Code: e3530000 1a00001d e59f1164 e5913000 (e5932004)                            
                                                                                
Fix Screen Info:                                                                
----------------                                                                
Line Length - 1280                                                              
Physical Address = c7a00000                                                     
Buffer Len---[ end trace be62152724069cd7 ]---                                  
gth = 1228800                                                                   
Fixing recursive fault but reboot is needed!                                    
                                                                                
Var Screen Info:                                                                
----------------                                                                
Xres - 640                                                                      
Yres - 480                                                                      
Xres Virtual - 640                                                              
Yres Virtual - 960                                                              
nonstd       - 0                                                                
Bits Per Pixel - 16                                                             
blue lenth 5 msb 0 offset 0                                                     
red lenth 5 msb 0 offset 11                                                     
green lenth 6 msb 0 offset 5                                                    
trans lenth 0 msb 0 offset 0                                                    
                                                                                
Var Screen Info:                                                                
----------------                                                                
Xres - 720                                                                      
Yres - 576                                                                      
Xres Virtual - 720                                                              
Yres Virtual - 1728                                                             
nonstd       - 0                                                                
Bits Per Pixel - 16                                                             
blue lenth 5 msb 0 offset 0                                                     
red lenth 5 msb 0 offset 11                                                     
green lenth 6 msb 0 offset 5                                                    
trans lenth 0 msb 0 offset 0                                                    
                                                                                
Fix Screen Info:                                                                
----------------                                                                
Line Length - 1280                                                              
Physical Address = c7a00000                                                     
Buffer Length = 1228800                                                         
MMap Failed.                                                                    
Error in setting up of Display 

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <linux/fb.h>
#include<linux/videodev2.h>
/* Number of buffers capture driver */
#define MAX_BUFFER	3     
/* Number of times queue/dequeue happens before stopping applications */
#define MAXLOOPCOUNT	500

/* Application name */
#define APP_NAME		"saLoopBackFbdev"

/* device node to be used for capture */
#define CAPTURE_DEVICE		"/dev/video0"
//#define CAPTURE_DEVICE		"/dev/video5"

/* device node to be used for fbdev */
#define FBDEV_DEVICE		"/dev/fb0"

v4l2_std_id input_std_id = V4L2_STD_PAL;
char *input_name = "Composite"; 

/* Define below #def for debug information enable */
#undef SALOOPBACKFBDEV_DEBUG

/* Structure for storing application data like file pointers, format etc.
 * Same structure will be used for fbdev as well as V4L2 capture. Only/
 * required fields will be initialized for both of them*/
struct app_obj {
	int fd;
	struct v4l2_capability cap;
	struct v4l2_format fmt;
	//struct v4l2_dv_preset dv_preset;
	struct v4l2_requestbuffers reqbuf;
	unsigned int numbuffers;
	unsigned int buffersize;
	unsigned char *buffer_addr[MAX_BUFFER];
	struct v4l2_buffer buf;
	//struct ti81xxvin_overflow_status over_flow;
	struct fb_var_screeninfo varinfo;
	struct fb_var_screeninfo org_varinfo;
	struct fb_fix_screeninfo fixinfo;
};


/* Buffer descriptor for caputre queue/dequeue */
struct buf_info {
	int index;
	unsigned int length;
	char *start;
};

/* Globals for capture and display application objects */
struct app_obj fbdev, capt;


/* Utility function to calculate FPS
 *
 */
static int timeval_subtract(struct timeval *result, struct timeval *x,
		struct timeval *y)
{
	/* Perform the carry for the later subtraction by updating y */
	if (x->tv_usec < y->tv_usec) {
		int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
		y->tv_usec -= 1000000 *	nsec;
		y->tv_sec += nsec;
	}
	if (x->tv_usec - y->tv_usec > 1000000) {
		int nsec = (x->tv_usec - y->tv_usec) / 1000000;
		y->tv_usec += 1000000 * nsec;
		y->tv_sec -= nsec;
	}
	/* Compute the time remaining to wait, tv_usec is certainly positive. */
	result->tv_sec = x->tv_sec - y->tv_sec;
	result->tv_usec = x->tv_usec - y->tv_usec;
	/* Return 1 if result is negative. */
	return x->tv_sec < y->tv_sec;
}

/* Utility function which gets the fixed screeninfo from driver and prints it
 */
static int get_fixinfo(int fbdev_fd, struct fb_fix_screeninfo *fixinfo)
{
	int ret;
	ret = ioctl(fbdev_fd, FBIOGET_FSCREENINFO, fixinfo);
	if (ret < 0) {
		perror("Error reading fixed information.\n");
		return ret;
	}

	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);
	return 0;
}
/* Utility function which gets the variable screen info from driver and prints\
 * it on console
 */
static int get_varinfo(int fbdev_fd, struct fb_var_screeninfo *varinfo)
{
	int ret;

	ret = ioctl(fbdev_fd, FBIOGET_VSCREENINFO, varinfo);
	if (ret < 0) {
		perror("Error reading variable information.\n");
		return ret;
	}
	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);
	return 0;

}
/* 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;
	int ret=0;
	v4l2_std_id std;
	struct v4l2_input input;
	struct v4l2_standard standard;
	int input_idx = 0;
	int found = 0;

	/* Open capture driver */
	capt.fd = open((const char *)CAPTURE_DEVICE, mode);
	if (capt.fd == -1) {
		printf("failed to open capture device\n");
		return -1;
	}
	input.index = 0;
	while(1) {
		ret = ioctl(capt.fd, VIDIOC_ENUMINPUT, &input);
		if (ret < 0) {
			perror("VIDIOC_ENUMINPUT\n");
			return -1;
		}
		if (!strcmp(input.name, input_name)) {
			found = 1;
			break;
		}
	}

	if (!found) {
		printf("Input %s not found\n", input_name);
		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");

	}
	
	input_idx = 0;

	ret = ioctl(capt.fd, VIDIOC_S_INPUT, &input.index);
	if (ret < 0) {
		perror("VIDIOC_S_INPUT\n");
		return -1;
	}
    ret = ioctl(capt.fd, VIDIOC_G_INPUT, &input_idx);
	if (ret < 0) {
		perror("VIDIOC_G_INPUT\n");
		return -1;
	}
	if (input_idx != input.index) {
		printf("Couldn't set input correctly\n");
		return -1;
	}

	found = 0;
	/* Enumerate standard to get the name of the standard detected */
	standard.index = 0;
	do {
		ret = ioctl(capt.fd, VIDIOC_ENUMSTD, &standard);
		if (ret < 0) {
			perror("VIDIOC_ENUM_STD failed\n");
			return -1;
		}
		printf("standard.name = %s\n", standard.name);
		if (standard.id & input_std_id) {
			printf("Found standard support in the driver\n");
			found = 1;
			break;
		}
		standard.index++;
	} while (1);

	if (!found) {
		printf("Driver doesn't support the standard\n");
		return -1;
	} 

	ret == ioctl(capt.fd, VIDIOC_S_STD, &input_std_id);
	if (ret < 0) {
		perror("VIDIOC_S_STD failed\n");
		return -1;
	}

	/* Detect the standard in the input detected */
	
	ret = ioctl(capt.fd, VIDIOC_QUERYSTD, &std);
	if (ret < 0) {
		perror("VIDIOC_QUERYSTD\n");
		return -1;
	}
	if (std & V4L2_STD_NTSC)
		printf("Input video standard is NTSC.\n");
	else if (std & V4L2_STD_PAL)
		printf("Input video standard is PAL.\n");
	else if (std & V4L2_STD_PAL_M)
		printf("Input video standard is PAL-M.\n");
	else if (std & V4L2_STD_PAL_N)
		printf("Input video standard is PAL-N.\n");
	else if (std & V4L2_STD_SECAM)
		printf("Input video standard is SECAM.\n");
	else if (std & V4L2_STD_PAL_60)
		printf("Input video standard to PAL60.\n");
	else 
		return -1;

	//printf("V4L2_STD_PAL = %08x\n",V4L2_STD_PAL);
	ret = ioctl(capt.fd, VIDIOC_S_STD, &std);

        if (ret < 0) {
                perror("VIDIOC_S_STD\n");
                return -1;
        }

	return 0;
}

static int initFbdev(void)
{
	int mode = O_RDWR;

	/* Open display driver */
	fbdev.fd = open((const char *)FBDEV_DEVICE, mode);
	if (fbdev.fd == -1) {
		printf("failed to open fbdev device\n");
		return -1;
	}
	return 0;
}

static int setupCapture(void)
{
	int ret;

	/* Get current format */
	capt.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(capt.fd, VIDIOC_G_FMT, &capt.fmt);
	if (ret < 0) {
		printf("Get Format failed\n");
		return -1;
	}

	printf("%s: width = %d\n", APP_NAME, capt.fmt.fmt.pix.width);
	printf("%s: height = %d\n", APP_NAME, capt.fmt.fmt.pix.height);
	printf("%s: bytesperline = %d\n", APP_NAME, capt.fmt.fmt.pix.bytesperline);
	printf("%s: sizeimage = %d\n", APP_NAME, capt.fmt.fmt.pix.sizeimage);
	
	/* Set format according to mode detected */
	if(capt.fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
		printf("%s: pixelformat = V4L2_PIX_FMT_RGB24\n", APP_NAME);
	else if(capt.fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
		printf("%s: pixelformat = V4L2_PIX_FMT_YUYV\n", APP_NAME);
	else if(capt.fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
		printf("%s: pixelformat = Others\n", APP_NAME);

	
	capt.fmt.fmt.pix.bytesperline = capt.fmt.fmt.pix.width;
	capt.fmt.fmt.pix.sizeimage = capt.fmt.fmt.pix.bytesperline *
	capt.fmt.fmt.pix.height*2;
	//capt.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
	capt.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
        capt.fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
	//printf("V4L2_PIX_FMT_UYVY = %d\n",V4L2_PIX_FMT_UYVY);

	ret = ioctl(capt.fd, VIDIOC_S_FMT, &capt.fmt);
	if (ret < 0) {
		printf("Set Format failed1\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 failed2\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 */
static int setupFbdevAndBuffers(void)
{
	int ret, i;

	/* 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(fbdev.fd, &fbdev.fixinfo))
		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(fbdev.fd, &fbdev.varinfo))
		return -1;
	/*store the original information*/
	memcpy(&fbdev.org_varinfo, &fbdev.varinfo, sizeof(fbdev.varinfo));

	/*
	 * Set the resolution which read before again to prove the
	 * FBIOPUT_VSCREENINFO ioctl, except virtual part which is required for
	 * panning.
	 */
	fbdev.varinfo.xres = capt.fmt.fmt.pix.width;
	fbdev.varinfo.yres = capt.fmt.fmt.pix.height;
	fbdev.varinfo.xres_virtual = fbdev.varinfo.xres;
	fbdev.varinfo.yres_virtual = fbdev.varinfo.yres * MAX_BUFFER;
	fbdev.varinfo.bits_per_pixel = 16;
	fbdev.varinfo.transp.offset = 0;
	fbdev.varinfo.transp.length = 0;
	fbdev.varinfo.transp.msb_right = 0;
	ret = ioctl(fbdev.fd, FBIOPUT_VSCREENINFO, &fbdev.varinfo);
	if (ret < 0) {
		perror("Error writing variable information.\n");
		return -1;
	}
	
	/* Get variable info and print it again after setting it */
	if (get_varinfo(fbdev.fd, &fbdev.varinfo))
		return -1;
	/* It is better to get fix screen information again. its because
	 * changing variable screen info may also change fix screen info.
	 * 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(fbdev.fd, &fbdev.fixinfo))
		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. */
	fbdev.buffersize = fbdev.fixinfo.line_length * fbdev.varinfo.yres;
	fbdev.buffer_addr[0] = (unsigned char *)mmap(0,
			fbdev.buffersize *  MAX_BUFFER,
			(PROT_READ | PROT_WRITE),
			MAP_SHARED, fbdev.fd, 0);

	if ((int)fbdev.buffer_addr[0] == -1) {
		printf("MMap Failed.\n");
		return -1;
	}
	/* Store each buffer addresses in the local variable. These buffer
	 * addresses can be used to fill the image. */
	for (i = 1; i < MAX_BUFFER; i++)
		fbdev.buffer_addr[i] = fbdev.buffer_addr[i-1] + fbdev.buffersize;

	memset(fbdev.buffer_addr[0], 0x00, fbdev.buffersize * MAX_BUFFER);

	return 0;
}

static int queueCaptureBuffers(void)
{
	int ret, i;
	for (i = 0; i < MAX_BUFFER; 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)fbdev.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;
}

/*
	Starts Streaming of capture
*/
static int startCapture(void)
{
	int a = V4L2_BUF_TYPE_VIDEO_CAPTURE, ret;
	ret = ioctl(capt.fd, VIDIOC_STREAMON, &a);
	if (ret < 0) {
		perror("VIDIOC_STREAMON\n");
		return -1;
	}
	return 0;
}

/*
 * Stop streaming on capture
 */
static int stopCapture(void)
{
	int a = V4L2_BUF_TYPE_VIDEO_CAPTURE, ret;
	ret = ioctl(capt.fd, VIDIOC_STREAMOFF, &a);
	if (ret < 0) {
		perror("VIDIOC_STREAMON\n");
		return -1;
	}
	return 0;
}

/* Application main */
static int app_main(int argc , char *argv[])
{
	int ret;
	int i;
	struct timeval before, after, result;
	/*FILE *filePtr;

	filePtr = fopen("captdump.yuv", "wb");
	if (filePtr == NULL) {
		printf("Cannot Open Output file:captdump.yuv \n");
		return 0;
	}
	system ("echo 1:hdmi > /sys/devices/platform/vpss/graphics0/nodes");
    */
	/* Open the capture driver. Query the resolution from the capture driver
	 */
	printf("initCapture()\n");
	ret = initCapture();
	if (ret < 0) {
		printf("Error in opening capture device for channel 0\n");
		return ret;
	}
	/* Open the Display driver. */
	printf("initFbdev()\n");
	ret = initFbdev();
	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
	 */
	printf("setupCapture()\n");
	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
	 */
	printf("setupFbdevAndBuffers()\n");
	ret = setupFbdevAndBuffers();
	if (ret < 0) {
		printf("Error in setting up of Display\n");
		return ret;
	}
	printf("queueCaptureBuffers()\n");
	ret = queueCaptureBuffers();
	if (ret < 0) {
		printf("Error in queuing capture buffers\n");
		return ret;
	}
	/* Start Captureing */
	printf("startCapture()\n");
	ret = startCapture();
	if (ret < 0) {
		printf("Error in starting capture\n");
		return ret;
	}
	/* Get time of day for calculating FPS */
	gettimeofday(&before, NULL);
	/* Start capture and display loop */
	for (i = 0; i < MAXLOOPCOUNT; i++) {
		/*
		   Get capture buffer using DQBUF ioctl
		 */
		printf("VIDIOC_DQBUF\n");
		ret = ioctl(capt.fd, VIDIOC_DQBUF, &capt.buf);
		if (ret < 0) {
			perror("VIDIOC_DQBUF\n");
			return -1;
		}
		if ((i % 1000) == 0)
			printf("C: %d\n TS: %d index %d\n", i,
					(unsigned int)capt.buf.timestamp.tv_usec,
					capt.buf.index);
		/* Pan the display to the next buffer captured.
		 * Application should provide y-offset in terms of number of
		 * lines to have panning effect. To entirely change to next
		 * buffer, yoffset needs to be changed to yres field. */

		fbdev.varinfo.yoffset = (capt.buf.index * 1080) % MAX_BUFFER;
		printf("FBIOPAN_DISPLAY\n");
		ret = ioctl(fbdev.fd, FBIOPAN_DISPLAY, &fbdev.varinfo);
		if (ret < 0) {
			perror("Cannot pan display.\n");
		}
		/* Wait for buffer to complete display */
		printf("FBIO_WAITFORVSYNC\n");
		//ret = ioctl(fbdev.fd, FBIO_WAITFORVSYNC, 0);
		//if (ret < 0) {
		//	perror("wait vsync failed.\n");
		//	break;
		//}

		/* HDVPSS VIP capture is having bug that it locks up some time
		 * under heavy bandwidth conditions. DQBUF will return error in
		 * case hardware lock up. Applicatin needs to check for the
		 * lockup and in case of lockup, restart the driver */
		/*printf("TICAPT_CHECK_OVERFLOW\n");
		if (capt.buf.flags & V4L2_BUF_FLAG_ERROR) {
			ret = ioctl(capt.fd, TICAPT_CHECK_OVERFLOW, &capt.over_flow);
			if (ret < 0) {
				perror("TICAPT_CHECK_OVERFLOW\n");
				return -1;
			} else {
				if (capt.over_flow.porta_overflow) {
					printf("Port a overflowed\n\n\n\n\n\n\n");
					stopCapture();
					goto restart;

				}
				if (capt.over_flow.portb_overflow) {
					printf("Port b overflowed\n\n\n\n\n\n\n");
					stopCapture();
					goto restart;
				}
			}
		}
		*/
		/* Queue the buffer back to display */
		capt.buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		capt.buf.memory = V4L2_MEMORY_USERPTR;
		capt.buf.m.userptr = (unsigned long)fbdev.buffer_addr[capt.buf.index];
		capt.buf.length = fbdev.buffersize;
		ret = ioctl(capt.fd, VIDIOC_QBUF, &capt.buf);
		if (ret < 0) {
			perror("VIDIOC_QBUF\n");
			return -1;
		}
	}
	/* Get time of day after to do FPS calculation */
	//fwrite(fbdev.buffer_addr[0], 1, capt.fmt.fmt.pix.sizeimage, filePtr);
	gettimeofday(&after, NULL);
	timeval_subtract(&result, &after, &before);
	printf("Result Time:\t%ld %ld\n", result.tv_sec, result.tv_usec);
	printf("Calculated Frame Rate:\t%ld Fps\n\n", MAXLOOPCOUNT/result.tv_sec);

	printf("FBIOPUT_VSCREENINFO\n");
	ret = ioctl(fbdev.fd, FBIOPUT_VSCREENINFO, &fbdev.org_varinfo);
	if (ret < 0) {
		perror("Error reading variable information.\n");
	}
	close(capt.fd);
	close(fbdev.fd);
	return ret;

}


int main(int argc , char *argv[])
{
	return app_main(argc , argv);
}

  • Hi,

    because of lack of ti example for omapl138 lcdk, i use the saLoopBackFbdev for dm8148 and modify some parameters according to omapl138 lcdk hardware.

    We have VPIF loopback examples in "DaVinci-PSP-SDK-03.22.00.02" release.

    DaVinci-PSP-SDK-03.22.00.02/src/examples/examples-03.22.00.02/vpif

    http://processors.wiki.ti.com/index.php/Demonstration_of_VPIF_raw_capture_using_MT9T031_sensor_on_AM18X/DA850/OMAP-L138_running_Linux

  • Hi, thanks for your reply.

    I know  VPIF loopback examples, but they all use the "/dev/video2"  to display. For lcdk, the hardware dont have the encoder(video2), so i want to use the fb0 to display.

  • I use the vpif loopback examples and replace the video2 with fb0.  It prints a lots which i dont understand.

    This  is my source code.  

    /*
     * vpif_mmap_loopback.c
     *
     * This is the sample to show capture and display functionality using
     * memory mapped buffers. 
     *
     * Copyright (C) 2010 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
     ******************************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <errno.h>
    #include <linux/fb.h>
    //#include <linux/videodev.h>
    #include <linux/videodev2.h>
    /******************************************************************************
     Macros
     MAX_BUFFER     : Changing the following will result different number of 
    		  instances of buf_info structure.
     BUFFER_HEIGHT	: This indicates maximum height of the image which is 
     		  captured or displayed.
     BUFFER_PITCH	: This indicates maximum widht of the image which is 
     		  captured or displayed.
     CAPTURE_DEVICE : This indicates device to be used for capture
     DISPLAY_DEVICE : This indicates device to be used for display
     MAXLOOPCOUNT	: This indicates number of frames to be captured and displayed
     ******************************************************************************/
    #define MAX_BUFFER	3
    #define CAPTURE_DEVICE0	"/dev/video0"
    #define CAPTURE_DEVICE1	"/dev/video1"
    #define DISPLAY_DEVICE	"/dev/fb0"
    #define BUFFER_PITCH	720
    #define BUFFER_HEIGHT	576
    #define MAXLOOPCOUNT	500
    #define CAPTURE_INPUT0 "Composite"
    #define CAPTURE_INPUT1 "S-Video"
    #define CLEAR(x)	memset (&(x), 0, sizeof (x))
    #define ALIGN(x, y)     (((x + (y-1))/y)*y)
    
    /******************************************************************************
     Declaration
     	Following structure is used to store information of the buffers which 
    	are mmapped.
     ******************************************************************************/
    struct buf_info {
    	int index;
    	unsigned int length;
    	char *start;
    };
    
    /******************************************************************************
     Globals
    	Following variables stores file descriptors returned when opening 
    	capture and display device.
    	capture_buff_info and display_buff_info stores mmaped buffer 
    	information of capture and display respectively.
    	capture_numbuffers, display_numbuffers is used to store number of 
    	buffers actually allocated by the driver.
    	outputidx is used to store index of the output to be selected in 
    	display depending on the input detecting on the capture.
    	capture_std used to store detected standard.
     ******************************************************************************/
    static struct buf_info capture_buff_info[MAX_BUFFER];
    static struct buf_info display_buff_info[3];
    /******************************************************************************
                            Function Definitions
     ******************************************************************************/
    static int initCapture(int *capture_fd, int *numbuffers, struct v4l2_format *fmt);
    static int startCapture(int *);
    static void *getCaptureBuffer(int *);
    static int stopCapture(int *);
    static int releaseCapture(int *, int);
    static int putCaptureBuffer(int *capture_fd, int numbuffers, void *addr);
    static int initDisplay(int *display_fd);
    static int releaseDisplay(int *display_fd);
    void convert(unsigned char *buf, unsigned char *rgb, int width, int height, int offset);
    v4l2_std_id input_std_id = V4L2_STD_NTSC;
    char *input_device;
    char *input_name;
    /*frame buffer*/
    char* frameptr;
    int screensize = 0;
    /* print frame number */
    int print_fn = 1;
    /* stress test */
    int stress_test = 1;
    /* enable/disable display */
    int display_enable = 1;
    /* save catptured frame */
    int save_frame = 0;
    
    FILE *file_fp = NULL;
    
    #define BYTESPERLINE 720
    
    int sizeimage = BYTESPERLINE*480*2;
    //int kernel_buf_size = ALIGN(BUFFER_PITCH * BUFFER_HEIGHT * 2, 4096);
    
    int app_main();
    
    /*=====================initCapture========================*/
    /* This function initializes capture device. It detects   *
     * first input connected on the channel-0 and detects the *
     * standard on that input. It, then, allocates buffers in *
     * the driver's memory space and mmaps them in the        *
     * application space.					  */
    static int initCapture(int *capture_fd, int *numbuffers, struct v4l2_format *fmt)
    {
    	int mode = O_RDWR, ret, i;
    	struct v4l2_requestbuffers reqbuf;
    	struct v4l2_buffer buf;
    	struct v4l2_input input;
    	int input_idx;
    	struct v4l2_standard standard;
    	v4l2_std_id std;
    	int found = 0;
    
    	/* Open the channel-0 capture device */
    	*capture_fd = open((const char *)input_device, mode);
    	if (*capture_fd <= 0) {
    		printf("Cannot open = %s device\n", input_device);
    		return -1;
    	}
    
    
    	/* Enumerate inputs to get the name of the input chosen by user*/
    	input.index = 0;
    	while(1) {
    		ret = ioctl(*capture_fd, VIDIOC_ENUMINPUT, &input);
    		if (ret < 0) {
    			perror("VIDIOC_ENUMINPUT\n");
    			return -1;
    		}
    		if (!strcmp(input.name, input_name)) {
    			found = 1;
    			break;
    		}
    	}
    
    	if (!found) {
    		printf("Input %s not found\n", input_name);
    		return -1;
    	}
    
    	/* Set input
    	 * VIDIOC_G_INPUT ioctl detects the inputs connected. It returns
    	 * error if no inputs are connected. Otherwise it returns index of 
    	 * the input connected. */
    	ret = ioctl(*capture_fd, VIDIOC_S_INPUT, &input.index);
    	if (ret < 0) {
    		perror("VIDIOC_S_INPUT\n");
    		return -1;
    	}
    
    	/* check if input is selected correctly */
    	ret = ioctl(*capture_fd, VIDIOC_G_INPUT, &input_idx);
    	if (ret < 0) {
    		perror("VIDIOC_G_INPUT\n");
    		return -1;
    	}
    
    	if (input_idx != input.index) {
    		printf("Couldn't set input correctly\n");
    		return -1;
    	}
    	/* Set the user selected standard */
    
    	found = 0;
    	/* Enumerate standard to get the name of the standard detected */
    	standard.index = 0;
    	do {
    		ret = ioctl(*capture_fd, VIDIOC_ENUMSTD, &standard);
    		if (ret < 0) {
    			perror("VIDIOC_ENUM_STD failed\n");
    			return -1;
    		}
    		printf("standard.name = %s\n", standard.name);
    		if (standard.id & input_std_id) {
    			printf("Found standard support in the driver\n");
    			found = 1;
    			break;
    		}
    		standard.index++;
    	} while (1);
    
    	if (!found) {
    		printf("Driver doesn't support the standard\n");
    		return -1;
    	} 
    
    	ret == ioctl(*capture_fd, VIDIOC_S_STD, &input_std_id);
    	if (ret < 0) {
    		perror("VIDIOC_S_STD failed\n");
    		return -1;
    	}
    
    	/* Detect the standard in the input detected */
    	ret = ioctl(*capture_fd, VIDIOC_QUERYSTD, &std);
    
    	if (ret < 0) {
    		perror("VIDIOC_QUERYSTD\n");
    		return -1;
    	}
    
    	if (std & V4L2_STD_NTSC)
    		printf("Input video standard is NTSC.\n");
    	else if (std & V4L2_STD_PAL)
    		printf("Input video standard is PAL.\n");
    	else if (std & V4L2_STD_PAL_M)
    		printf("Input video standard is PAL-M.\n");
    	else if (std & V4L2_STD_PAL_N)
    		printf("Input video standard is PAL-N.\n");
    	else if (std & V4L2_STD_SECAM)
    		printf("Input video standard is SECAM.\n");
    	else if (std & V4L2_STD_PAL_60)
    		printf("Input video standard to PAL60.\n");
    	else 
    		return -1;
    
    	/* Set format */
    	CLEAR(*fmt);
    	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	fmt->fmt.pix.bytesperline = BYTESPERLINE;
    	fmt->fmt.pix.sizeimage = sizeimage;
    	fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
    	fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
    
    	ret = ioctl(*capture_fd, VIDIOC_S_FMT, fmt);
    	if (ret < 0) {
    		perror("VIDIOC_S_FMT failed\n");
    		return -1;
    	}
    
    	CLEAR(*fmt);
    	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	ret = ioctl(*capture_fd, VIDIOC_G_FMT, fmt);
    	if (ret < 0) {
    		perror("VIDIOC_G_FMT failed\n");
    		return -1;
    	}
    
    	/* Buffer allocation 
    	 * Buffer can be allocated either from capture driver or
    	 * user pointer can be used 
    	 */
    	/* Request for 3 input buffers. As far as Physically contiguous 
    	 * memory is available, driver can allocate as many buffers as 
    	 * possible. If memory is not available, it returns number of 
    	 * buffers it has allocated in count member of reqbuf.
    	 * HERE count = number of buffer to be allocated.
    	 * type = type of device for which buffers are to be allocated. 
    	 * memory = type of the buffers requested i.e. driver allocated or 
    	 * user pointer */
    	reqbuf.count = *numbuffers;
    	reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	reqbuf.memory = V4L2_MEMORY_MMAP;
    
    	ret = ioctl(*capture_fd, VIDIOC_REQBUFS, &reqbuf);
    	if (ret < 0) {
    		perror("cannot allocate memory\n");
    		return -1;
    	}
    
    	/* Store the number of buffers actually allocated */
    	*numbuffers = reqbuf.count;
    
    	/* It is better to zero all the members of buffer structure */
    	memset(&buf, 0, sizeof(buf));
    
    	/* Mmap the buffers
    	 * To access driver allocated buffer in application space, they have
    	 * to be mmapped in the application space using mmap system call */
    	for (i = 0; i < reqbuf.count; i++) {
    		/* Query physical address of the buffers */
    		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    		buf.index = i;
    		buf.memory = V4L2_MEMORY_MMAP;
    		ret = ioctl(*capture_fd, VIDIOC_QUERYBUF, &buf);
    		if (ret < 0) {
    			perror("VIDIOC_QUERYCAP\n");
    			return -1;
    		}
    
    		/* Mmap the buffers in application space */
    		capture_buff_info[i].length = buf.length;
    		capture_buff_info[i].index = i;
    		capture_buff_info[i].start =
    		    mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
    			 MAP_SHARED, *capture_fd, buf.m.offset);
    
    		if (capture_buff_info[i].start == MAP_FAILED) {
    			printf("Cannot mmap = %d buffer\n", i);
    			return -1;
    		}
    		printf("capture_buff_info[%d].length = %d\n", i, capture_buff_info[i].length); 
    		printf("capture_buff_info[%d].index = %d\n", i, capture_buff_info[i].index); 
    		printf("capture_buff_info[%d].start = %p\n", i, capture_buff_info[i].start); 
    		/* It is better to zero buffers */
    		memset(capture_buff_info[i].start, 0x80,
    		       capture_buff_info[i].length);
    	}
    
    	/* Enqueue buffers
    	 * Before starting streaming, all the buffers needs to be en-queued 
    	 * in the driver incoming queue. These buffers will be used by the 
    	 * drive for storing captured frames. */
    	/* Enqueue buffers */
    	for (i = 0; i < reqbuf.count; i++) {
    		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    		buf.index = i;
    		buf.memory = V4L2_MEMORY_MMAP;
    		ret = ioctl(*capture_fd, VIDIOC_QBUF, &buf);
    		if (ret < 0) {
    			perror("VIDIOC_QBUF\n");
    			return -1;
    		}
    	}
    
    	return 0;
    }
    
    /*=====================startCapture========================*/
    /* This function starts streaming on the capture device	   */
    static int startCapture(int *capture_fd)
    {
    	int a = V4L2_BUF_TYPE_VIDEO_CAPTURE, ret;
    	/* Here type of device to be streamed on is required to be passed */
    	ret = ioctl(*capture_fd, VIDIOC_STREAMON, &a);
    	if (ret < 0) {
    		perror("VIDIOC_STREAMON\n");
    		return -1;
    	}
    	return 0;
    }
    
    /*=====================getCaptureBuffer====================*/
    /* This function de-queues captured buffer from the 	   *
     * capture device's outgoing queue. 			   */
    static void *getCaptureBuffer(int *capture_fd)
    {
    	int ret;
    	struct v4l2_buffer buf;
    	/* It is better to zero members of v4l2_buffer structure */
    	memset(&buf, 0, sizeof(buf));
    	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	buf.memory = V4L2_MEMORY_MMAP;
    	/* Dequeue buffer
    	 * VIDIOC_DQBUF ioctl de-queues a captured buffer from driver.
    	 * This call can be blocking or non blocking. For blocking call, it
    	 * blocks untill a capture frame is available. For non-blocking call,
    	 * it returns instantaneously with success or error depending on 
    	 * captured buffer is available or not. */
    	ret = ioctl(*capture_fd, VIDIOC_DQBUF, &buf);
    	if (ret < 0) {
    		perror("VIDIOC_DQBUF\n");
    		return NULL;
    	}
    	return capture_buff_info[buf.index].start;
    }
    
    /*=====================stopCapture========================*/
    /* This function stops streaming on the capture device	  */
    static int stopCapture(int *capture_fd)
    {
    	int ret, a = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	/* Here type of device to be streamed off is required to be passed */
    	ret = ioctl(*capture_fd, VIDIOC_STREAMOFF, &a);
    	if (ret < 0) {
    		perror("VIDIOC_STREAMOFF\n");
    		return -1;
    	}
    	return 0;
    }
    
    /*=====================releaseCapture========================*/
    /* This function un-maps all the mmapped buffers of capture  *
     * and closes the capture file handle			     */
    static int releaseCapture(int *capture_fd, int numbuffers)
    {
    	int i;
    	/* Un-map the buffers */
    	for (i = 0; i < numbuffers; i++) {
    		munmap(capture_buff_info[i].start, capture_buff_info[i].length);
    		capture_buff_info[i].start = NULL;
    	}
    	/* Close the file handle */
    	close(*capture_fd);
    	*capture_fd = 0;
    	return 0;
    }
    
    /*=====================putCaptureBuffer====================*/
    /* This function en-queues empty buffer into the 	   *
     * capture device's incoming queue. 			   */
    static int putCaptureBuffer(int *capture_fd, int numbuffers, void *addr)
    {
    	struct v4l2_buffer buf;
    	int i, index = 0;
    	int ret;
    	if (addr == NULL)
    		return -1;
    
    	/* It is better to zero members of v4l2_buffer structure */
    	memset(&buf, 0, sizeof(buf));
    
    	/* Find index of the buffer whose address is passed as the argument */
    	for (i = 0; i < numbuffers; i++) {
    		if (addr == capture_buff_info[i].start) {
    			index = capture_buff_info[i].index;
    			break;
    		}
    	}
    
    	if (i == numbuffers)
    		return -1;
    
    	/* Enqueue the buffer */
    	buf.m.offset = (unsigned long)addr;
    
    	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	buf.memory = V4L2_MEMORY_MMAP;
    	buf.index = index;
    	ret = ioctl(*capture_fd, VIDIOC_QBUF, &buf);
    
    	if (ret < 0) {
    		perror("VIDIOC_QBUF\n");
    		return ret;
    	}
    
    	return 0;
    }
    
    /*=====================initDisplay========================*/
    /* This function initializes display device. It sets      *
     * output and standard on channel-2. These output and     *
     * standard are same as those detected in capture device. *
     * It, then, allocates buffers in the driver's memory     *
     * space and mmaps them in the application space	  */
    static int initDisplay(int *display_fd)
    {
    	struct fb_var_screeninfo vinfo;
    	struct fb_fix_screeninfo finfo;
    	int fb_fd;
    	int ret_val;
    	
    
    	/*opening the framebuffer device*/
    	fb_fd = open("/dev/fb0", O_RDWR);
    	if(fb_fd  < 0) {
    		printf("open:Error opening framebuffer device\n");
    		exit(0);
    	}
    	*display_fd = fb_fd;
    	
    	/*Retrieving the variable and fixed screeninfo*/
    	ret_val = ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
    	if(ret_val) {
    		printf("ioctl:Error reading variable screen information\n");
    		exit(0);
    	}
    	
    	ret_val = ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
    	if(ret_val) {
    		printf("ioctl:Error reading fix screen information\n");	
    		exit(0);
    	}
    	vinfo.xres = 720;
    	vinfo.yres = 480;
    	vinfo.bits_per_pixel = 16;
    
    	printf("%d %d %d", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
    	
    	screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    	//display_buff_info.length = screensize;
    	frameptr = (char*) mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
    	if((int)frameptr == -1) {
    		printf("mmap:Failed to framebuffer device to memory\n");
    		exit(0);
    	}
    	return 0;
    }
    
    /*=====================releaseDisplay========================*/
    /* This function un-maps all the mmapped buffers of display  *
     * and closes the display file handle			     */
    static int releaseDisplay(int *display_fd)
    {
    	if(munmap(frameptr, screensize) < 0) {
    		printf("munmap:Failed to unmap frame buffer device from memory\n");
    		exit(0);
    	}
    	close(*display_fd);
    	*display_fd = 0;
    	return 0;
    }
    /* YUV422P to RGB16*/
    static inline void yuv_to_rgb16(unsigned char y,
                                    unsigned char u,
                                    unsigned char v,
                                    unsigned char *rgb)
    {
        register int r,g,b;
        int rgb16;
    
        r = (1192 * (y - 16) + 1634 * (v - 128) ) >> 10;
        g = (1192 * (y - 16) - 833 * (v - 128) - 400 * (u -128) ) >> 10;
        b = (1192 * (y - 16) + 2066 * (u - 128) ) >> 10;
    
        r = r > 255 ? 255 : r < 0 ? 0 : r;
        g = g > 255 ? 255 : g < 0 ? 0 : g;
        b = b > 255 ? 255 : b < 0 ? 0 : b;
    
        rgb16 = (int)(((r >> 3)<<11) | ((g >> 2) << 5)| ((b >> 3) << 0));
    
        *rgb = (unsigned char)(rgb16 & 0xFF);
        rgb++;
        *rgb = (unsigned char)((rgb16 & 0xFF00) >> 8);
    }
    
    void convert(unsigned char *buf, unsigned char *rgb, int width, int height, int offset)
    {
        int x,y,z=0;
        int blocks;
    	unsigned char Y1, Y2, U, V;
        
    	blocks = (width * height) * 2;
    
        for (x = 0, y = 0; y < blocks; x+=2,y+=4) {
           
           	Y1 = buf[x + 0];
    		Y2 = buf[x + 1];
    
           	U = buf[x + offset +0];
           	V = buf[x + offset +1];
    
            yuv_to_rgb16(Y1, U, V, &rgb[y]);
            yuv_to_rgb16(Y2, U, V, &rgb[y + 2]);
        }
    }
    /*=====================app_main===========================*/
    int app_main()
    {
    	int i = 0;
    	void *capturebuffer0;
    	void *displaybuffer;
    	int counter = 0;
    	int ret = 0;
    	struct v4l2_format capture_fmt;
    	struct v4l2_format display_fmt;
    	int capture_chroma_offset, display_chroma_offset;
    	int capture_size;
    	int capture_fd, display_fd;
    	char outputname[15];
    	char stdname[15];
    	int capture_numbuffers = MAX_BUFFER, display_numbuffers = MAX_BUFFER;
    
    	for (i = 0; i < MAX_BUFFER; i++) {
    		capture_buff_info[i].start = NULL;
    		display_buff_info[i].start = NULL;
    	}
    
    	/* STEP1:
    	 * Initialization section
    	 * Initialize capture and display devices. 
    	 * Here one capture channel is opened 
    	 * Display channel is opened with the same standard that is detected at
    	 * capture channel. same output name as input
    	 * */
    
    	/* open capture channel 0 */
    	ret = initCapture(&capture_fd, &capture_numbuffers, &capture_fmt);
    	if (ret < 0) {
    		printf("Error in opening capture device for channel 0\n");
    		return ret;
    	}
    
    	printf(" Capture initialized\n");
    	/* open display channel */
    	if (display_enable) {
    		ret = initDisplay(&display_fd);
    		if (ret < 0) {
    			printf("Error in opening display device\n");
    			return ret;
    		}
    		printf(" Display initialized\n");
    		printf(" display started \n");
    	}
    	/* start capturing for channel 0 */
    	ret = startCapture(&capture_fd);
    	if (ret < 0) {
    		printf("Error in starting capturing for channel 0\n");
    		return ret;
    	}
    
    	printf(" capture started \n");
    
    	/* calculate the offset from where chroma data will be stored for 
    	 * both capture and display */
    	//capture_chroma_offset = kernel_buf_size/2;
    	//display_chroma_offset = display_fmt.fmt.pix.sizeimage / 2;
    	//display_chroma_offset = kernel_buf_size/2;
    	capture_size = capture_fmt.fmt.pix.width * capture_fmt.fmt.pix.height;
    	capture_chroma_offset = capture_fmt.fmt.pix.sizeimage / 2;
    
    	/* One buffer is dequeued from display and capture channels.
    	 * Capture buffer will be copied to display buffer.
    	 * All two buffers are put back to respective channels.
    	 * This sequence is repeated in loop.
    	 * After completion of this loop, channels are stopped.
    	 * */
    	printf("Going into loopback\n");
    
    #if 0
    	sleep(10);
    #else
    	while (1) {
    		/* get capturing buffer for channel 0 */
    		capturebuffer0 = getCaptureBuffer(&capture_fd);
    		if (NULL == capturebuffer0) {
    			printf("Error in get capture buffer for channel 0\n");
    			return ret;
    		}
    
    		convert(capturebuffer0, frameptr, 720, 576, capture_chroma_offset);
    
    		/* put buffers in capture channels */
    		ret = putCaptureBuffer(&capture_fd, capture_numbuffers,
    				       capturebuffer0);
    		if (ret < 0) {
    			printf("Error in put capture buffer for channel 0\n");
    			return ret;
    		}
    		counter++;
    
    
    		if (print_fn)
    			printf("time:%lu    frame:%u\n", (unsigned long)time(NULL), counter);
    
    		if (stress_test && counter >= MAXLOOPCOUNT)
    			break;
    	}
    #endif
    
    	printf("After sleep, stop capture/display\n");
    	/* stop capturing for channel 0 */
    	ret = stopCapture(&capture_fd);
    	if (ret < 0) {
    		printf("Error in stopping capturing for channel 0\n");
    		return ret;
    	}
    
    	/* close capture channel 0 */
    	ret = releaseCapture(&capture_fd, capture_numbuffers);
    	if (ret < 0) {
    		printf("Error in closing capture device\n");
    		return ret;
    	}
    	/* Free section
    	 * Here channels for capture and display are close.
    	 * */
    	/* open display channel */
    	if (display_enable) {
    		ret = releaseDisplay(&display_fd);
    		if (ret < 0) {
    			printf("Error in closing display device\n");
    			return ret;
    		}
    	}
    	return ret;
    }
    
    void menu()
    {
    	printf("vpif_mmap_loopback -c <channel> -s <stress test> -p <print frame");
    	printf(" number, -m <ntsc or pal>\n");
    }
    
    /******************************************************************************
      			Program Main
    *******************************************************************************/
    int main(int argc, char *argv[])
    {
    	int ret = 0, d, index;
    	char shortoptions[] = "s:c:p:m:d:w:";
    	/* 0 or 1 */
    	static int channel_no;
    	/* 0 - NTSC, 1 - PAL */
    	static int input_std = V4L2_STD_NTSC;
    	
    	
    
    	input_device = CAPTURE_DEVICE0;
    	input_name = CAPTURE_INPUT0;
    
    	for (;;) {
    		d = getopt_long(argc, argv, shortoptions, (void *)NULL, &index);
    		if (-1 == d)
    			break;
    		switch (d) {
    		case 'm':
    		case 'M':
    			input_std = atoi(optarg);
    			if (input_std) {
    				input_std_id = V4L2_STD_PAL;
    				sizeimage = BYTESPERLINE*576*2;
    			}
    			break;
    		case 's':
    		case 'S':
    			stress_test = atoi(optarg);
    			break;
    		case 'p':
    		case 'P':
    			print_fn = atoi(optarg);
    			break;
    		case 'c':
    		case 'C':
    			channel_no = atoi(optarg);
    			if (channel_no == 1) {
    				input_device = CAPTURE_DEVICE1;
    				input_name = CAPTURE_INPUT1;
    			}
    			break;
    		case 'd':
    		case 'D':
    			display_enable =  atoi(optarg);
    			break;
    		case 'w':
    		case 'W':
    			save_frame = atoi(optarg);
    			break;
    		default:
    			menu();
    			exit(1);
    		}
    	}
    	if (save_frame) {
    		file_fp = fopen("./capt_frame.yuv", "wb");
    		if (file_fp == NULL) {
    			printf("Unable to open ./capt_frame.yuv\n");
    			exit(1);
    		}
    	}
    
    	app_main();
    	return 0;
    }
    

    root@omapl138-lcdk:~# ./vpif_mmap_zhou  -m 1                                   
    tvp514x 1-005d: tvp5146 (Version - 0x07) found at 0xba (i2c-gpio1)             
    standard.name = NTSC                                                           
    standard.name = NTSC-M                                                         
    standard.name = NTSC-M-JP                                                      
    standard.name = NTSC-M-KR                                                      
    standard.name = PAL                                                            
    Found standard support in the driver                                           
    Input video standard is PAL.                                                   
    capture_buff_info[0].length = 831488                                           
    capture_buff_info[0].index = 0                                                 
    capture_buff_info[0].start = 0xb6e6f000                                        
    capture_buff_info[1].length = 831488                                           
    capture_buff_info[1].index = 1                                                 
    capture_buff_info[1].start = 0xb6da4000                                        
    capture_buff_info[2].length = 831488                                           
    capture_buff_info[2].index = 2                                                 
    capture_buff_info[2].start = 0xb6cd9000                                        
     Capture initialUnable to handle kernel NULL pointer dereference at virtual addc
    ized                                                                           
    720 480 16pgd = c7028000                                                       
     Display initial[0000006c] *pgd=c702e831ized                                   
     display s, *pte=00000000tarted                                                
    , *ppte=00000000                                                               
    Internal error: Oops: 817 [#1] PREEMPT                                         
    Modules linked in:                                                             
    CPU: 0    Not tainted  (3.3.0 #1)                                              
    PC is at vpif_set_mode_info+0x44/0xcc                                          
    LR is at vpif_set_video_params+0x24/0x1d4                                      
    pc : [<c02939a4>]    lr : [<c0293a50>]    psr: 60000013                        
    sp : c70a5c9c  ip : 00000000  fp : c70a5cb4                                    
    r10: c051ff8c  r9 : 00000000  r8 : c792a190                                    
    r7 : c04f9b60  r6 : c03b8e58  r5 : 011805a0  r4 : c0543b24                     
    r3 : 0000006c  r2 : c03b8e58  r1 : 00000000  r0 : c792a048                     
    Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user              
    Control: 0005317f  Table: c7028000  DAC: 00000015                              
    Process vpif_mmap_zhou (pid: 975, stack limit = 0xc70a4270)                    
    Stack: (0xc70a5c9c to 0xc70a6000)                                              
    5c80:                                                                c792a030  
    5ca0: 00000000 c792a048 c70a5ce4 c70a5cb8 c0293a50 c0293970 c0014fe0 c792a000  
    5cc0: 00000000 c6400000 c04f9b60 c792a190 00000000 c051ff8c c70a5d0c c70a5ce8  
    5ce0: c0295dac c0293a3c 00000001 00000000 c7bea800 c03b9688 c704fa80 c713c420  
    5d00: c70a5e04 c70a5d10 c02866fc c0295a04 0000003d c0540cd8 c70a5d3c c70a5d28  
    5d20: c01cc5a0 c01cc4cc c01cc578 00000000 c70a5d6c c70a5d40 c0090528 00000000  
    5d40: c70a5d6c c70a5d50 c0090510 c0186f6c c0090528 40045612 01d00000 c7806000  
    5d60: c70a5d7c c70a5d70 c00903e4 c70a4000 c70a5dbc c70a5d80 c70a5d9c c70a5d88  
    5d80: c70a5da4 be81897c 00004602 c705f950 c00095c4 be81897c 00000044 00000000  
    5da0: c788c800 c019e33c c7864500 00000280 000001e0 00000280 000003c0 00000000  
    5dc0: 00000000 00000010 00000000 0000000b 00000005 00000000 00000005 40045612  
    5de0: 00000000 00000004 00000000 c70a5e20 00000000 00000000 c70a5ecc c70a5e08  
    5e00: c0284968 c0284b50 c70a5e24 c0284b40 c704fa80 00000000 00000001 be818a60  
    5e20: 00000001 c01c6a18 c784d0e0 00000000 c70a5e6c c70a5e40 c01c91b0 c01c7794  
    5e40: c01c90a4 c704536c 0000000a c7045000 c70a4000 c704f080 c01cc228 c70a4000  
    5e60: c70a5e7c c70a5e70 c01c6a54 c01cc238 c70a5e94 c70a5e80 c01c77b8 c01c6a18  
    5e80: 00000000 c70a4000 60000013 c726e830 c70a4000 00000012 b6f3d000 00000000  
    5ea0: c70a5ecc c7bea800 40045612 be818a60 c704fa80 be818a60 c70a4000 00000000  
    5ec0: c70a5edc c70a5ed0 c0284ac8 c0284610 c70a5f04 c70a5ee0 c0283900 c0284ac4  
    5ee0: c0283890 c704fa80 be818a60 be818a60 c71ca560 c00095c4 c70a5f7c c70a5f08  
    5f00: c009d184 c02838a0 00000000 00000000 c704fa00 00000012 c704f088 00000002  
    5f20: c726e800 00000000 c70a4000 00000000 c70a5f6c c70a5f40 c008cefc c00c309c  
    5f40: 00000000 00000000 000a8c00 c704f080 b6f3d000 00000000 c704fa80 be818a60  
    5f60: 40045612 00000003 c00095c4 c70a4000 c70a5fa4 c70a5f80 c009d248 c009cc78  
    5f80: 00000004 00000000 00000000 00000000 00000140 00000036 00000000 c70a5fa8  
    5fa0: c0009440 c009d218 00000000 00000000 00000003 40045612 be818a60 be818a60  
    5fc0: 00000000 00000000 00000140 00000036 46c29000 00000000 46afd000 be818a6c  
    5fe0: 00000000 be818a58 00008fc0 46bbf0ac 60000010 00000003 00000000 00000000  
    Backtrace:                                                                     
    [<c0293960>] (vpif_set_mode_info+0x0/0xcc) from [<c0293a50>] (vpif_set_video_pa)
     r6:c792a048 r5:00000000 r4:c792a030                                           
    [<c0293a2c>] (vpif_set_video_params+0x0/0x1d4) from [<c0295dac>] (vpif_streamon)
    [<c02959f4>] (vpif_streamon+0x0/0x678) from [<c02866fc>] (__video_do_ioctl+0x1b)
    [<c0284b40>] (__video_do_ioctl+0x0/0x4b74) from [<c0284968>] (video_usercopy+0x)
    [<c0284600>] (video_usercopy+0x0/0x4b4) from [<c0284ac8>] (video_ioctl2+0x14/0x)
    [<c0284ab4>] (video_ioctl2+0x0/0x1c) from [<c0283900>] (v4l2_ioctl+0x70/0x11c) 
    [<c0283890>] (v4l2_ioctl+0x0/0x11c) from [<c009d184>] (do_vfs_ioctl+0x51c/0x5a0)
     r8:c00095c4 r7:c71ca560 r6:be818a60 r5:be818a60 r4:c704fa80                   
    r3:c0283890                                                                    
    [<c009cc68>] (do_vfs_ioctl+0x0/0x5a0) from [<c009d248>] (sys_ioctl+0x40/0x64)  
     r9:c70a4000 r8:c00095c4 r7:00000003 r6:40045612 r5:be818a60                   
    r4:c704fa80                                                                    
    [<c009d208>] (sys_ioctl+0x0/0x64) from [<c0009440>] (ret_fast_syscall+0x0/0x2c)
     r7:00000036 r6:00000140 r5:00000000 r4:00000000                               
    Code: e59f408c e0836001 e594c000 e7933001 (e78c5003)                           
    ---[ end trace e70181dd73e98021 ]---                   

  • i guess, 

    (1)  This error is caused by the tvp5146 (print in terminal) ? because it should be tvp5147m1 in my lcdk.

    (2)  When i do some research online about this error, someone think that it is caused by menuconfig (should enable something. i2c gpio et al).

    (3)  This error is caused by the functions. The vpif examples may not be suitable for lcdk.

     if i comment this function  startCapture(&capture_fd), the following string("capture started") can  be printed.

    if not, not print string("capture started") .


  • Hi Hui,

    Really, I don't about this error.

    Actually, This VPIF examples given only for OMAPL138 EVM board and not for LCDK as you know.

    So, Firstly, Try to understand the OMAPL138 EVM concept and try to change the code.

    In my understanding,

    They are using the CAMERA for source input and taking output through COMPOSITE TV OUT.

    I would like to suggest to use the VPIF examples code especially for OMAPL138 LCDK board in starterware.

    C6748_StarterWare_1_20_04_01/examples/lcdkC6748/vpif_lcd_loopback/vpif_lcd_loopback.c

  • Thanks.

    I will try my best to solve this problem. If not, i will use the usb camera in linux or vpif in sysbios.

  • Hi Hui,

    Thanks for your understanding.

    If you planned to use the USB webcam is the video source input,

    then, We do support to streaming video (loopback) in linux through mplayer.

    Already I have tested the above mentioned case.