- 浏览: 1112631 次
文章分类
最新评论
-
560130911:
100w,你的代码也不行吧!数组不能定义太大
POJ 1207 HDOJ/HDU 1032 3n+1数链问题 绝对不水的解法 -
revice:
how did you solve this problem? ...
ffmpeg ffmpeg 音频采集发送命令,以及播放的结果-----错误 -
shirne:
博主是用ubuntu吗
javascript 杂谈之哪种写法你更喜欢? -
mzc200803:
加油,相信你明年会找份好工作的。
实习改变了我什么 -
该用户名已经存在:
java类的实例化探究
更新一下摄像头采集程序
/* $Id: directshow.c,v 1.22 2005/11/12 14:12:39 fuhuizhong Exp $ */
#ifndef lint
static char vcid[] = "$Id: directshow.c,v 1.22 2005/11/12 14:12:39 fuhuizhong Exp $";
#endif /* lint */
/*
* 作者:傅惠忠
* /modified by xiaoshao_0_0
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/videodev.h>
#include "jpeglib.h"
#include <setjmp.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
//#define USB_VIDEO "/dev/video0"
#define FONT "./bit.ttf"
char USB_VIDEO[20];//make it changeabel
SDL_Color fontcolor;
SDL_Surface *screen,*img,*text;
int cam_fd;
char mesg[256];
int width,height;
const int bpp = 24;
struct video_mmap cam_mm;
struct video_capability cam_cap;
struct video_picture cam_pic;
struct video_mbuf cam_mbuf;
struct video_window win;
char *cam_data = NULL;
int nframe;
TTF_Font *font=NULL;
void errexit(char *msg)
{
fputs(msg,stderr);
exit(-1);
}
void e_sig(int signum)
{
printf(" ERROR:signal %d ",signum);
exit(-1);
}
void setup_sighandler()
{
signal(SIGTERM,&e_sig);
signal(SIGINT,&e_sig);
signal(SIGSEGV,&e_sig);
signal(SIGILL,&e_sig);
signal(SIGFPE,&e_sig);
}
void free_font();
void init_font();
void init_video(int w,int h,int bpp); /* bpp == bits per pixel, 暂时无效*/
void init_screen(int w,int h,int bpp); /* like above*/
void read_video(int ,int);
void show_img(char *pixels);
void window_loop();
void exchange_r_b( char * f,long size);
void compress_to_jpeg_file( FILE *outfile, char * image_buffer,int w,int h, int quality);
void save_snapshot();
void init_font()
{
if(TTF_Init()==-1)
{
return ;
}
font=TTF_OpenFont(FONT,16);
if(font==NULL)
return ;
SDL_Color c={255,255,255};
fontcolor=c;
return ;
}
void free_font()
{
SDL_FreeSurface(text);
TTF_CloseFont(font);
TTF_Quit();
}
void free_dev()
{
printf("free device/n");
close(cam_fd);
}
int main(int argc,char *argv[])
{
int i;
float scale = 1.0;
if(argc<3||argc>5){
errexit("usage as /"cam -d /dev/video* -s 03~1.0/",please check again");
}
if( argc >= 3 ) {
if(!strcmp(argv[1],"-d"))//devices!!
{
strcpy(USB_VIDEO,argv[2]);
printf("using USB_VIDEO,%s",USB_VIDEO);
}
else
errexit("usage as /"cam -d /dev/video* -s 03~1.0/",please check again");
}
if(argc ==5){
if(!strcmp(argv[3],"-s"))//scale
{
scale = atof(argv[4]);
if(scale<0.3||scale>1.0)
errexit("scale out of range (0.3 ~ 1.0)/n");
}
}
width = (int)(640*scale);
height = (int)(480*scale);
atexit( &free_dev );
init_video(width,height,bpp);
init_screen(width,height,bpp);
init_font();
setup_sighandler();
SDL_WM_SetCaption("Captrue the webcam,by xiaoshao_0_0",NULL);
window_loop();
// getchar();
free_font();
SDL_Quit();
munmap(cam_data,cam_mbuf.size);
exit(0);
}
void config_vid_pic()
{
char *hp = getenv("HOME");
char cfpath[100];
FILE *cf;
int ret;
sprintf( cfpath,"%s/.dshow.conf",hp );
cf = fopen(cfpath,"r");
/* The struct video_picture consists of the following fields
brightness Picture brightness
hue Picture hue (colour only)
colour Picture colour (colour only)
contrast Picture contrast
whiteness The whiteness (greyscale only)
depth The capture depth (may need to match the frame buffer depth)
palette Reports the palette that should be used for this image
The following palettes are defined
VIDEO_PALETTE_GREY Linear intensity grey scale (255 is brightest).
VIDEO_PALETTE_HI240 The BT848 8bit colour cube.
VIDEO_PALETTE_RGB565 RGB565 packed into 16 bit words.
VIDEO_PALETTE_RGB555 RGV555 packed into 16 bit words, top bit undefined.
VIDEO_PALETTE_RGB24 RGB888 packed into 24bit words.
VIDEO_PALETTE_RGB32 RGB888 packed into the low 3 bytes of 32bit words. The top 8bits are undefined.
VIDEO_PALETTE_YUV422 Video style YUV422 - 8bits packed 4bits Y 2bits U 2bits V
VIDEO_PALETTE_YUYV Describe me
VIDEO_PALETTE_UYVY Describe me
VIDEO_PALETTE_YUV420 YUV420 capture
VIDEO_PALETTE_YUV411 YUV411 capture
VIDEO_PALETTE_RAW RAW capture (BT848)
VIDEO_PALETTE_YUV422P YUV 4:2:2 Planar
VIDEO_PALETTE_YUV411P YUV 4:1:1 Planar
*/
if (ioctl(cam_fd, VIDIOCGPICT, &cam_pic) < 0) {
errexit("ERROR:VIDIOCGPICT ");
}
//cam_pic.palette =VIDEO_PALETTE_RAW;
cam_pic.palette =VIDEO_PALETTE_RGB24;
if( cf==NULL ) {
cam_pic.brightness = 44464;
cam_pic.hue = 36000;
cam_pic.colour = 0;
cam_pic.contrast = 43312;
cam_pic.whiteness = 13312;
cam_pic.depth = 24;
ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); /*设置摄像头缓冲中voideo_picture信息*/
if( ret<0 ) {
close(cam_fd);
errexit("ERROR: VIDIOCSPICT,Can't set video_picture format ");
}
return;
}
fscanf(cf,"%d",&cam_pic.brightness);
fscanf(cf,"%d",&cam_pic.hue);
fscanf(cf,"%d",&cam_pic.colour);
fscanf(cf,"%d",&cam_pic.contrast);
fscanf(cf,"%d",&cam_pic.whiteness);
fclose( cf );
ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); /*设置摄像头缓冲中voideo_picture信息*/
if( ret<0 ) {
close(cam_fd);
errexit("ERROR: VIDIOCSPICT,Can't set video_picture format ");
}
}
void init_video(int w,int h,int bpp) /* bpp == bytes per pixel*/
{
int ret;
cam_fd = open( USB_VIDEO, O_RDWR );
if( cam_fd<0 )
errexit("Can't open video device ");
ret = ioctl( cam_fd,VIDIOCGCAP,&cam_cap );
/* 摄像头的基本信息
struct video_capability cam_cap;
name[32] Canonical name for this interface
type Type of interface
channels Number of radio/tv channels if appropriate
audios Number of audio devices if appropriate
maxwidth Maximum capture width in pixels
maxheight Maximum capture height in pixels
minwidth Minimum capture width in pixels
minheight Minimum capture height in pixels
*/
if( ret<0 ) {
errexit("Can't get device information: VIDIOCGCAP ");
}
print_device_info();
/* The struct video_window contains the following fields.
x The X co-ordinate specified in X windows format.
y The Y co-ordinate specified in X windows format.
width The width of the image capture.
height The height of the image capture.
chromakey A host order RGB32 value for the chroma key.
flags Additional capture flags.
clips A list of clipping rectangles. (Set only)
clipcount The number of clipping rectangles. (Set only)
*/
if( ioctl(cam_fd,VIDIOCGWIN,&win)<0 ) {
errexit("ERROR:VIDIOCGWIN ");
}
win.x = 0;
win.y = 0;
win.width=width;
win.height=height;
if (ioctl(cam_fd, VIDIOCSWIN, &win) < 0) {
errexit("ERROR:VIDIOCSWIN ");
}
config_vid_pic();
ret = ioctl(cam_fd,VIDIOCGMBUF,&cam_mbuf);
/*
struct video_mbuf
{
int size; Total memory to map
int frames; Frames
int offsets[VIDEO_MAX_FRAME];
};
*/
/*struct video_buffer.
视频缓存的信息读取结构,设定也是一样的结构。但是一般是X自己设定,你只要读取就好了。
void *base Base physical address of the buffer
int height Height of the frame buffer
int width Width of the frame buffer
int depth Depth of the frame buffer
int bytesperline Number of bytes of memory between the start of two adjacent lines*/
if( ret<0 ) {
errexit("ERROR:VIDIOCGMBUF,Can't get video_mbuf ");
}
printf("/nFrames:%d ",cam_mbuf.frames);
nframe = cam_mbuf.frames;
cam_data = (char*)mmap(0, cam_mbuf.size, PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,0);
if( cam_data == MAP_FAILED ) {
errexit("ERROR:mmap ");
}
printf("Buffer size:%d Offset:%d/n ",cam_mbuf.size,cam_mbuf.offsets[0]);
}
void print_device_info()
{
int type=cam_cap.type;
int i;
char type_info[14][100]=
{
"VID_TYPE_CAPTURE Can capture to memory",
"VID_TYPE_TUNER Has a tuner of some form",
"VID_TYPE_TELETEXT Has teletext capability",
"VID_TYPE_OVERLAY Can overlay its image onto the frame buffer",
"VID_TYPE_CHROMAKEY Overlay is Chromakeyed",
"VID_TYPE_CLIPPING Overlay clipping is supported",
"VID_TYPE_FRAMERAM Overlay overwrites frame buffer memory",
"VID_TYPE_SCALES The hardware supports image scaling",
"VID_TYPE_MONOCHROME Image capture is grey scale only",
"VID_TYPE_SUBCAPTURE Capture can be of only part of the image",
"VID_TYPE_MPEG_DECODER Can decode MPEG streams",
"VID_TYPE_MPEG_ENCODER Can encode MPEG streams",
"VID_TYPE_MJPEG_DECODER Can decode MJPEG streams",
"VID_TYPE_MJPEG_ENCODER Can encode MJPEG streams",
};
printf("/nDevice name:%s Width:%d ~ %d Height:%d ~ %d /n",
cam_cap.name,
cam_cap.maxwidth, cam_cap.minwidth,
cam_cap.maxheight, cam_cap.minheight);
for(i=0;i<14;i++)
{
if(type&(2^i))
{ printf(type_info[i]);
printf(" ");
}
else
{
printf("/n==not supported==%s",type_info[i]);
printf("/n");
}
}
}
void init_screen(int w,int h,int bpp) // like above
{
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "无法初始化SDL: %s ", SDL_GetError());
exit(1);
}
screen = SDL_SetVideoMode(width, height, bpp, SDL_HWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "无法设置视频模式:%s ", SDL_GetError());
exit(1);
}
img = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, bpp, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
//这里改成SDL_HWSURFACE可能会快一点吧
atexit(SDL_Quit);
}
void read_video(int captrue_frame,int sync_frame)
{
/*
It is allowed to call VIDIOCMCAPTURE multiple times (with different frame numbers in video_mmap->frame of course) and thus have multiple outstanding capture requests. A simple way do to double-buffering using this feature looks like this:
* setup everything
VIDIOCMCAPTURE(0)
while (whatever) {
VIDIOCMCAPTURE(1)
VIDIOCSYNC(0)
// process frame 0 while the hardware captures frame 1
VIDIOCMCAPTURE(0)
VIDIOCSYNC(1)
// process frame 1 while the hardware captures frame 0
}
*/
int ret;
//int frame=0; /*这个似乎比较关键*/
//这个地方原作者弄错了。
cam_mm.frame=captrue_frame;
/* struct video_mmap
{
unsigned int frame; Frame (0 - n) for double buffer
int height,width;
unsigned int format; should be VIDEO_PALETTE_*
};
*/
ret = ioctl(cam_fd,VIDIOCMCAPTURE,&cam_mm);
if( ret<0 ) {
errexit("ERROR: VIDIOCMCAPTURE ");
}
//cam_mm.frame=sync_frame;
ret = ioctl(cam_fd,VIDIOCSYNC,&sync_frame);
if( ret<0 ) {
errexit("ERROR: VIDIOCSYNC ");
}
}
void show_img(char *pixels)
{
int row_stride = width*3;
char *pbuf = (char*)img->pixels;
int row;
/* for(row=0; row<height; row++) {
memcpy(pbuf, pixels, row_stride);
pbuf += img->pitch;
pixels += row_stride;
}*/
memcpy(pbuf,pixels,row_stride*height);
SDL_BlitSurface(img, NULL, screen, NULL);
text = TTF_RenderText_Solid(font, mesg, fontcolor);
SDL_BlitSurface(text,NULL,screen,NULL);
SDL_FreeSurface(text);
// SDL_UpdateRect(screen,0,0,width,height);
SDL_Flip(screen);
}
void window_loop()
{
int ret;
int frames=0;
int loop;
SDL_Event event;
int keystat = 0;
Uint32 ticks = 0;
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,1000);
//////////////
cam_mm.height = height;
cam_mm.width = width;
cam_mm.frame=0;
cam_mm.format=VIDEO_PALETTE_RGB24;
ret = ioctl(cam_fd,VIDIOCMCAPTURE,&cam_mm);
//capture 0 first here!!
if( ret<0 ) {
errexit("ERROR: VIDIOCMCAPTURE ");
}
//Here just start caputer frame0,it not in the loop.
//////////////
while ( loop ) {
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
loop=0;
break;
// exit(0);
case SDL_KEYDOWN:
if( event.key.keysym.sym == SDLK_F8 && keystat == 0 )
save_snapshot();
if( event.key.keysym.sym == SDLK_F9 && keystat == 0 )
config_vid_pic();
if( event.key.keysym.sym == SDLK_UP && keystat == 0 )
increase_brightness();
if( event.key.keysym.sym == SDLK_DOWN && keystat == 0 )
decrease_birghtness();
if( event.key.keysym.sym == SDLK_LEFT && keystat== 0 )
increase_contrast();
if( event.key.keysym.sym == SDLK_RIGHT && keystat==0 )
decrease_contrast();
keystat = 1;
break;
case SDL_KEYUP:
keystat = 0;
break;
default:
break;
}
//usleep(1);
if( (SDL_GetTicks()-ticks)<1000/24)
continue;
read_video(1,0);//captrue=1,sync=0
show_img( cam_data+cam_mbuf.offsets[0]);
//handle frame 0 here and wait for 1
read_video(0,1);//captrue=0,sync=1
// usleep(1000/24);
show_img( cam_data+cam_mbuf.offsets[1]);
//handle frame 1 here and wait for 0
ticks = SDL_GetTicks();
frames+=2;
}
printf("/n ticks=%d,frames=%d",ticks,frames);
}
void increase_brightness()
{
int ret=0;
cam_pic.brightness+=1000;
sprintf(mesg,"brightness=:%d",cam_pic.brightness);
ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); /*设置摄像头缓冲中voideo_picture信息*/
if( ret<0 ) {
close(cam_fd);
errexit("ERROR: VIDIOCSPICT,Can't set video_picture format ");
}
}
void decrease_birghtness()
{
int ret=0;
cam_pic.brightness-=1000;
sprintf(mesg,"brightness=:%d",cam_pic.brightness);
ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); /*设置摄像头缓冲中voideo_picture信息*/
if( ret<0 ) {
close(cam_fd);
errexit("ERROR: VIDIOCSPICT,Can't set video_picture format ");
}
}
void increase_contrast()
{
int ret=0;
cam_pic.contrast+=1000;
sprintf(mesg,"contrast=:%d",cam_pic.contrast);
ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); /*设置摄像头缓冲中voideo_picture信息*/
if( ret<0 ) {
close(cam_fd);
errexit("ERROR: VIDIOCSPICT,Can't set video_picture format ");
}
}
void decrease_contrast()
{
int ret=0;
cam_pic.contrast-=1000;
sprintf(mesg,"contrast=:%d",cam_pic.contrast);
ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); /*设置摄像头缓冲中voideo_picture信息*/
if( ret<0 ) {
close(cam_fd);
errexit("ERROR: VIDIOCSPICT,Can't set video_picture format ");
}
}
void compress_to_jpeg_file( FILE *outfile, char * image_buffer,int w,int h, int quality)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
int image_width;
int image_height;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
image_width = w;
image_height = h;
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
jpeg_start_compress(&cinfo, TRUE);
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = (JSAMPROW)& image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
/* And we're done! */
}
void exchange_r_b( char * f,long size)
{
char r,b;
long i;
for( i = 0; i < size ; i++)
{
r = *f;
b = *( f + 2);
*f = b;
*(f + 2) = r;
f = f +3;
}
}
void save_snapshot()
{
char *basepath = getenv("HOME");
char *basename = "/snapsot";
char *extname = ".jpg";
char filename[100];
int i = 0;
FILE *fo;
for(;;) {
sprintf(filename,"%s%s%d%s",basepath,basename,i,extname);
fo = fopen(filename,"rb");
if( fo==NULL )
break;
else
fclose(fo);
i += 1;
}
printf("snapshot:%s ",filename);
fo = fopen(filename,"wb");
exchange_r_b( cam_data, width*height );
compress_to_jpeg_file( fo, cam_data, width, height, 90 );
fclose(fo);
}
这次的更新,需要一个字体文件配合,英文和数字即可,名字我是叫做,bit.ttf.随便搞个字体就行。
采用了HWSURFACE,SDL_Flip提高了FPS大概到12左右。
提供了在屏幕上显示参数的功能。利用了SDL_ttf来显示屏幕上的信息。
另外,编译的命令请参考:
gcc old.c -o cam -lSDL -ljpeg -lSDL_ttf
不爱用makefile的人说。呵呵。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiaoshao_0_0/archive/2008/11/09/3261119.aspx
相关推荐
PB 图片 摄像头 采集程序 PB 图片 摄像头 采集程序
matlab摄像头采集程序 与大家分享 欢迎交流
基于labview的摄像头采集程序,能够通过本VI调用自己电脑的摄像头并显示出来
飞思卡尔智能车竞赛 ov7620的摄像头采集程序
VB摄像头采集源码VB摄像头采集源码VB摄像头采集源码VB摄像头采集源码VB摄像头采集源码VB摄像头采集源码
基于QT+Opencv的摄像头采集程序 Opencv的配置 QImage的保存
基于v4l2驱动的摄像头采集编码,然后用mpeg4方式编码并保存成可播放的avi文件。虽然没有加标注,不过程序比较小,理解起来不太难,并且也都是基于别人的例子程序做出来的,如果有不懂可以参考网上类似的资料。摄像头...
程序在Windows下面调试通过,修改了基础bug。
自己编写的基于对话框的摄像头采集程序,MFC编写的,用千兆工业以太网实现采集的。
visual C++ 基于MFC和OpenCV 的图像处理 摄像头图像采集程序
嵌入式摄像头采集程序 UVC摄像头 基于V4L2接口 YUV格式 linux2.6.29以上内核
我在MSDN 上下载的USB摄像头采集程序,功能较上一个上传的齐全,上学习基于VFW采集的非常好例子,我在VC6下测试程序完全可以跑通。
linux下基于V4L2/Qt的usb摄像头采集显示程序 Qt工程, 测试使用的是Qt5.6.0 可以正常使用, 采集usb摄像头的图像并显示, 可以正常配置摄像头像素
摄像头视频采集DELPHI程序,好东东。请顶起哟~
基于vc 6.0 mfc的摄像头采集程序, 使用vfw
适合arm2410 ,ov511网眼 摄像头驱动,交叉编译工具编译后可在arm2410平台执行。
飞思卡尔智能车CCD摄像头采集信息程序 采集信息的程序,将CCD摄像头采集的信息发送给单片机
V4L2 USB摄像头采集程序,采集一幅图片