/*
* TEST V4L2
*
* bushi@mizi.com
*
* preview : 240x160 overlay on 240x320 16bpp LCD
*
* capture : 640x480
*
*
*/
#include <sys/time.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <jpeglib.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include "videodev.h"
#include <linux/fb.h>
#define PIXFMT_NUM 5
#define INPUT_NUM 5
#define CTRL_NUM 100
#define COLS 320
#define ROWS 240
//#define JPEG_TEST
//#define V4L2_DEV_NODE "/dev/video/preview"
#define V4L2_DEV_NODE "/dev/video14"
#define FB_DEV_NODE "/dev/fb0"
#define RGB_FILE "rgb.jpg"
#define YUV420_FILE "yuv420.jpg"
#define VIDIOC_S_TVOUT_ON _IO('V',BASE_VIDIOC_PRIVATE+0)
static unsigned short image_width = 240;
static unsigned short image_height = 320;
static int fb_xres = 480;
static int fb_yres = 272;
typedef struct v4l2_input V_INPUT;
typedef struct v4l2_format V_FORMAT;
typedef struct v4l2_fmtdesc V_FMTDESC;
typedef struct v4l2_queryctrl V_QRYCTRL;
typedef struct fb_var_screeninfo F_VINFO;
static struct jpeg_compress_struct cinfo;
static int quality = 100;
static struct jpeg_error_mgr jerr;
typedef unsigned long long v4l2_std_id;
/* one bit for each */
#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001)
#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002)
#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004)
#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008)
#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010)
#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020)
#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040)
#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080)
#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100)
#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200)
#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400)
#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800)
#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000)
#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000)
#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000)
#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000)
#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000)
#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000)
#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000)
#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000)
#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000)
#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000)
#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000)
#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000)
/* some merged standards */
#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
/* some common needed stuff */
#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\
V4L2_STD_PAL_B1 |\
V4L2_STD_PAL_G)
#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\
V4L2_STD_PAL_D1 |\
V4L2_STD_PAL_K)
#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\
V4L2_STD_PAL_DK |\
V4L2_STD_PAL_H |\
V4L2_STD_PAL_I)
#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\
V4L2_STD_NTSC_M_JP |\
V4L2_STD_NTSC_M_KR)
#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\
V4L2_STD_SECAM_K |\
V4L2_STD_SECAM_K1)
#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\
V4L2_STD_SECAM_G |\
V4L2_STD_SECAM_H |\
V4L2_STD_SECAM_DK |\
V4L2_STD_SECAM_L |\
V4L2_STD_SECAM_LC)
#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\
V4L2_STD_PAL_60 |\
V4L2_STD_NTSC |\
V4L2_STD_NTSC_443)
#define V4L2_STD_625_50 (V4L2_STD_PAL |\
V4L2_STD_PAL_N |\
V4L2_STD_PAL_Nc |\
V4L2_STD_SECAM)
#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\
V4L2_STD_ATSC_16_VSB)
#define V4L2_STD_UNKNOWN 0
#define V4L2_STD_ALL (V4L2_STD_525_60 |\
V4L2_STD_625_50)
static char *name_of_ctrl_type[] = {
[V4L2_CTRL_TYPE_INTEGER] = "INTEGER",
[V4L2_CTRL_TYPE_BOOLEAN] = "BOOLEAN",
[V4L2_CTRL_TYPE_MENU] = "MENU",
[V4L2_CTRL_TYPE_BUTTON] = "BUTTON",
};
#define YCbCrtoR(Y,Cb,Cr) (1000*Y + 1371*(Cr-128))/1000
#define YCbCrtoG(Y,Cb,Cr) (1000*Y - 336*(Cb-128) - 698*(Cr-128))/1000
#define YCbCrtoB(Y,Cb,Cr) (1000*Y + 1732*(Cb-128))/1000
#define min(x1, x2) (((x1)<(x2))?(x1):(x2))
__u32 Conv_YCbCr_Rgb(__u8 y0, __u8 y1, __u8 cb0, __u8 cr0)
{
// bit order is
// YCbCr = [Cr0 Y1 Cb0 Y0], RGB=[R1,G1,B1,R0,G0,B0].
int r0, g0, b0, r1, g1, b1;
__u16 rgb0, rgb1;
__u32 rgb;
#if 1 // 4 frames/s @192MHz, 12MHz ; 6 frames/s @450MHz, 12MHz
r0 = YCbCrtoR(y0, cb0, cr0);
g0 = YCbCrtoG(y0, cb0, cr0);
b0 = YCbCrtoB(y0, cb0, cr0);
r1 = YCbCrtoR(y1, cb0, cr0);
g1 = YCbCrtoG(y1, cb0, cr0);
b1 = YCbCrtoB(y1, cb0, cr0);
#endif
if (r0>255 ) r0 = 255;
if (r0<0) r0 = 0;
if (g0>255 ) g0 = 255;
if (g0<0) g0 = 0;
if (b0>255 ) b0 = 255;
if (b0<0) b0 = 0;
if (r1>255 ) r1 = 255;
if (r1<0) r1 = 0;
if (g1>255 ) g1 = 255;
if (g1<0) g1 = 0;
if (b1>255 ) b1 = 255;
if (b1<0) b1 = 0;
// 5:6:5 16bit format
rgb0 = (((__u16)r0>>3)<<11) | (((__u16)g0>>2)<<5) | (((__u16)b0>>3)<<0); //RGB565.
rgb1 = (((__u16)r1>>3)<<11) | (((__u16)g1>>2)<<5) | (((__u16)b1>>3)<<0); //RGB565.
rgb = (rgb1<<16) | rgb0;
return(rgb);
}
static char yuv_interval[] = {0, 2, 4, 8, 16};
static void ccvt_420p_rgb565(int width, int height, const unsigned char *src, __u16 *dst)
{
int line, col, linewidth;
int y, u, v, yy, vr, ug, vg, ub;
int r, g, b;
const unsigned char *py, *pu, *pv;
linewidth = width >> 1;
py = src;
pu = py + (width * height);
pv = pu + (width * height) / 4;
y = *py++;
yy = y << 8;
u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;
for (line = 0; line < height; line++) {
for (col = 0; col < width; col++) {
r = (yy + vr) >> 8;
g = (yy - ug - vg) >> 8;
b = (yy + ub ) >> 8;
if (r < 0) r = 0;
if (r > 255) r = 255;
if (g < 0) g = 0;
if (g > 255) g = 255;
if (b < 0) b = 0;
if (b > 255) b = 255;
*((__u16 *)dst++) = (((__u16)r>>3)<<11) | (((__u16)g>>2)<<5) | (((__u16)b>>3)<<0);
y = *py++;
yy = y << 8;
if (col & 1) {
pu++;
pv++;
u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;
}
} /* ..for col */
if ((line & 1) == 0) { // even line: rewind
pu -= linewidth;
pv -= linewidth;
}
} /* ..for line */
}
static void show_cam_img(void *scr, __u8 *y_buf, __u8 *cb_buf, __u8 *cr_buf)
{
__u16 x, y, w, h;//, i, f;
__u16 *fb_buf = (__u16 *)scr;
__u32 rgb_data;
//int palette = optional_image_format[image_format].palette;
w=320;h=240;
fb_buf += (480*14);
for(y=0; y<h; y++) {
for(x=0; x<w; x+=2) { //calculate 2 times
rgb_data = Conv_YCbCr_Rgb(y_buf[x],
y_buf[(x)+1],
cb_buf[(x)>>1],
cr_buf[(x)>>1]);
fb_buf[28+x] = rgb_data;
fb_buf[x+29] = rgb_data>>16;
}
fb_buf += 480;
y_buf += 320;
cb_buf += (320)>>1;
cr_buf += (320)>>1;
}
}
static void show_cam_img1(void *scr, __u8 *y_buf, __u8 *cb_buf, __u8 *cr_buf)
{
__u16 x, y, w, h;//, i, f;
__u16 *fb_buf = (__u16 *)scr;
__u32 rgb_data;
//int palette = optional_image_format[image_format].palette;
w=240;h=240;
fb_buf += (480*14);
for(y=0; y<h; y+