一江春水向东流

做一个有思想的人,期待与每一位热爱思考的人交流,您的关注是对我最大的支持。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  44 随笔 :: 139 文章 :: 81 评论 :: 0 Trackbacks

**//* $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 <string.h>
#include <signal.h>
#include <errno.h>
#define USB_VIDEO "/dev/video1"

SDL_Surface *screen,*img;
int cam_fd;
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;

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 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 free_dev()
...{
printf("free device ");
close(cam_fd);
}

int main(int argc,char *argv[])
...{
int i;
float scale = 1.0;
if( argc == 2 ) ...{
scale = atof(argv[1]);
if(scale<0.3 || scale>1.0)
errexit("scale out of range (0.3 ~ 1.0) ");
}
width = (int)(640*scale);
height = (int)(480*scale);

atexit( &free_dev );
init_video(width,height,bpp);
init_screen(width,height,bpp);
setup_sighandler();

window_loop();

getchar();
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("Frames:%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 ",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("Device name:%s Width:%d ~ %d Height:%d ~ %d ",
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("==not supported==%s",type_info[i]);
printf(" ");
}
}
}

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);
}
img = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, bpp, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE);
if ( screen == NULL ) ...{
fprintf(stderr, "无法设置视频模式:%s ", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
}

void read_video(int captrue_frame,int sync_frame)
...{
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);
SDL_UpdateRect(screen,0,0,width,height);
}

void window_loop()
...{
int ret;
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);

if( ret<0 ) ...{
errexit("ERROR: VIDIOCMCAPTURE ");
}
//Here just start caputer frame0,it not in the loop.
/**///////////////
while ( 1 ) ...{
SDL_PollEvent(&event);
switch (event.type) ...{
case SDL_QUIT:
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;
}
if( (SDL_GetTicks()-ticks)<30)
continue;
read_video(1,0);//captrue=1,sync=0
show_img( cam_data+cam_mbuf.offsets[0]);
read_video(0,1);//captrue=0,sync=1
show_img( cam_data+cam_mbuf.offsets[1]);
ticks = SDL_GetTicks();
}
}
void increase_brightness()
...{
int ret=0;
cam_pic.brightness+=1000;
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;
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;
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;
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);
}

一个比较清淅的摄像头参数设置

//loadVariablesNum("schlist.tx", 0);
//fscommand("fullscrean", true);
var my_cam = Camera.get();
//LAN
//Lower image quality, higher motion quality my_cam.setQuality(400000,0)
//Higher image quality, lower motion qualitymy_cam.setQuality(0,100)
//// 确保最低品质为 100,无论采用多大的带宽
my_cam.setQuality(0, 100); //
my_cam.setKeyFrameInterval(15);
my_cam.setLoopback(true);
//my_cam.setMotionLevel(35, 1000);
my_cam.setMode(320, 240, 25, true);


// 捕获摄像头
myVideo1.attachVideo(my_cam);
myVideo1.smoothing = true;
myVideo1._alpha = 100;
myVideo1._rotation = 360;
// 在舞台上的 myVideo1 对象的边界内显示视频流
my_cam.onStatus = function(infoMsg) {
 if (infoMsg.code == 'Camera.Muted') {
  // 拒绝
  trace('User denies access to the camera');
 } else if (infoMsg.code == 'Camera.Unmuted') {
  // 接受
  trace('User allows access to the camera');
 }

};
//System.showSettings(3);
// 显示指定的 Flash Player"设置"面板
stop(); 

posted on 2007-05-08 20:28 allic 阅读(2601) 评论(0)  编辑  收藏 所属分类: C/C++

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问