#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <linux/videodev.h>
#include <errno.h>
#include <linux/fb.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/un.h>
#include <signal.h>
#include "ffmpeg-0.4.8/libgm/ftmcp200_module/favc_avcodec/favc_avcodec.h"
#include "ratecontrol.h"
#include "fcap_api.h"
#include "h264_capture.h"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))
FILE* dout;
//bmp转换定义
typedef unsigned char BYTE;
typedef unsigned long DWORD;
typedef unsigned short WORD;
long U[256], V[256], Y1[256], Y2[256];
BYTE *pRGBBuf=NULL;
struct BITMAPFILEHEADER
{
char bftype [2];
int bfsize;
short bfReserved1;
short bfReserved2;
int bfoffset ;
}__attribute__((packed)) ;
struct BITMAPINFOHEADER
{
int biSize;
int biWidth;
int biHeight;
short biPlanes;
short biBitCount;
int biCompression;
int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
int biClrUsed;
int biClrImportant;
}__attribute__((packed)) ;
//---------------static variable-----------------------------//
static unsigned int colortype=0;
static unsigned int ingrab_typ;
static unsigned int image_width;
static unsigned int image_height;
// capture related variables
int frame_num = 0;
int i_video_fd=0;
static unsigned int video_buf_virt;
static struct video_mbuf gb_buffers;
static struct video_mmap gb_buf;
/* seq=0 for MPEG4 2D capture, seq=1 for MJPEG sequential capture, seq=2 for H264 2D capture*/
static int v4l_init(unsigned int cap_width, unsigned int cap_height, int grab_type, int seq, int fd, struct video_mbuf *video_buff, struct video_mmap *mmap_buff, unsigned int *buff_mapping)
{
int type;
struct video_capability video_cap;
struct video_window win;
int ret = 0;
/* query video capture capability */
if (ioctl(fd, VIDIOCGCAP, &video_cap) < 0)
{
printf("VIDIOCGCAP failure");
return - 1;
}
if (!(video_cap.type &VID_TYPE_CAPTURE))
{
printf("Fatal: grab device does not handle capture\n");
return - 1;
}
if (ioctl(fd, VIDIOCGMBUF, video_buff) < 0)
{
printf("capture not support mbuf\n");
return - 1;
}
/* memory mapping to the decode device */
*buff_mapping = (unsigned int)mmap(0, video_buff->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
//ingrab = 18;
ret = ioctl(fd, 0x5679, &grab_type);
printf("ioctl 0x5679 failed ret = %d\n",ret);
type = seq;
ioctl(fd, 0x5678, &type); //JPEG need sequential format; 0 means MPEG4 2D ; 1 means MJPEG sequential ; 2 means H264 2D
mmap_buff->width = cap_width;
mmap_buff->height = cap_height;
mmap_buff->format = VIDEO_PALETTE_YUV420P;
mmap_buff->frame = 0;
win.x = 0;
win.y = 0;
win.width = cap_width;
win.height = cap_height;
win.chromakey = - 1;
win.flags = 0;
if (ioctl(fd, VIDIOCSWIN, &win) < 0)
{
printf("capture not support mbuf\n");
return - 1;
}
return 0;
}
/**************************************************************************/
/* */
/**************************************************************************/
static void *capture_frame(int fd, struct video_mmap *mmap_buff, struct video_mbuf *video_buff, int *frame, unsigned int buff_mapping)
{
int errno;
void *ptr;
/* Setup to capture the next frame */
printf("BEFORE MCAPTURE\n ");
if ((errno = ioctl(fd, VIDIOCMCAPTURE, mmap_buff)) < 0)
{
if (errno == EAGAIN)
{
fprintf(stderr, "Cannot Sync\n");
return NULL ;
}
else
{
perror("VIDIOCMCAPTURE Error\n");
return NULL ;
}
}
printf("AFTER MCAPTURE\n");
if (ioctl(fd, VIDIOCSYNC, frame) < 0)
{
printf("VIDIOCSYNC Error\n");
return NULL ;
}
printf("AFTER SYNC \n");
ptr = (void*)(buff_mapping + video_buff->offsets[ *frame]);
*frame = mmap_buff->frame;
return ptr;
}
//释放资源
void DestroyH264Resource()
{
close(i_video_fd);
munmap((void*)video_buf_virt, (gb_buffers.size));
printf("now close H264\n");
}
//位图转换相关函数
void MakeConversionTable()
{
long i;
for (i=0; i<256; i++)
{
V[i] = 15938*i-2221300;
U[i] = 20238*i-2771300;
Y1[i] = 11644*i;
Y2[i] = 19837*i-311710;
}
}
int YUV420ToRGB (DWORD width,
DWORD height,
BYTE *pYUVBuf,
BYTE *pRGBBuf
)
{
unsigned char *pY, *pU, *pV, *pUbase, *pVbase;
DWORD i, j;
unsigned char *pR, *pG, *pB;
// check if width and height is both in unit of 16 pixels
if ((width % 16) || (height % 16))
return 0;
pY = pYUVBuf;
pU = pUbase = pYUVBuf + width*height;
pV = pVbase = pUbase + width*height/4;
for (i=0; i<height; i++)
{
pB = pRGBBuf+image_height*image_width*3-3*width*(i+1);
pG = pRGBBuf+image_height*image_width*3-3*width*(i+1)+1;
pR = pRGBBuf+image_height*image_width*3-3*width*(i+1)+2;
for (j=0; j<width; j+=2)
{
*pR = max (0, min (255, (V[*pV] + Y1[*pY])/10000) ); //R value
*pB = max (0, min (255, (U[*pU] + Y1[*pY])/10000) ); //B value
*pG = max (0, min (255, (Y2[*pY] - 5094*(*pR) - 1942*(*pB))/10000) ); //G value
pR += 3;
pB += 3;
pG += 3;
pY++;
*pR = max (0, min (255, (V[*pV] + Y1[*pY])/10000) ); //R value
*pB = max (0, min (255, (U[*pU] + Y1[*pY])/10000) ); //B value
*pG = max (0, min (255, (Y2[*pY] - 5094*(*pR) - 1942*(*pB))/10000) ); //G value
pR += 3;
pB += 3;
pG += 3;
pY++;
pU++;
pV++;
}
if ((i % 2 == 0))
{
pU = pU-(width >> 1);
pV = pV-(width >> 1);
}
}
return 1;
}
int WriteBMPFile()
{
int writenum = 0;
printf("size of file header =%d\n", sizeof(struct BITMAPFILEHEADER ) );
struct BITMAPFILEHEADER fileheader ;
fileheader.bftype[0]='B';
fileheader.bftype[1]='M';
fileheader.bfsize = 54 + image_height*image_width*3;
fileheader.bfReserved1 = 0 ;
fileheader.bfReserved2 = 0 ;
fileheader.bfoffset = 54;
writenum = fwrite(&fileheader,1,sizeof(fileheader),dout);
printf("write filehead =%d\n", writenum);
struct BITMAPINFOHEADER infoheader;
infoheader.biSize = 40;
infoheader.biHeight=image_height;
infoheader.biWidth=image_width;
infoheader.biPlanes = 1 ;
infoheader.biBitCount = 24 ;
infoheader.biCompression = 0 ;
infoheader.biSizeImage = image_height*image_width*3;
infoheader.biXPelsPerMeter= 0;
infoheader.biYPelsPerMeter= 0;
infoheader.biClrUsed= 0;
infoheader.biClrImportant= 0;
writenum = fwrite(&infoheader,1,sizeof(infoheader),dout);
printf("write infohead =%d\n", writenum);
writenum = fwrite(pRGBBuf,1,image_height*image_width*3,dout);
printf("write rgbdata =%d\n", writenum);
fclose(dout);
return 1;
}
int main(int argc,char **argv)
{
int i,j=0;
char filename[80];
unsigned char *ptr=NULL;
if(argc!=9)
{
printf("Usage:\n");
printf(" #./main -i [0/1 0 for BMP 1 for YUV] -w [WIDTH] -h [HEIGHT] -n [NAME]\n");
exit(-1);
}
i=1;
while(i<9){
if(strstr(argv[i],"-i")!=NULL)
{
colortype=atoi(argv[i+1]);
j++;
}
if(strstr(argv[i],"-w")!=NULL)
{
image_width=atoi(argv[i+1]);
j++;
}
if(strstr(argv[i],"-h")!=NULL)
{
i