iniwf

风是温柔的,雨是伤心的,云是快乐的,月是多情的,爱是迷失的,恋是醉人的,情是难忘的,天是长久的,地是永恒的

spcaview.spcaserver源码详解

转自http://blog.csdn.net/neohuo/archive/2006/04/01/646507.aspx

首先看看对视频设备自定义的数据结构,源码在spcav4l中:

struct vdIn {
 
int fd;
 
char *videodevice ;                                                          
 
struct video_mmap vmmap;                                   //内存影射
 struct video_capability videocap;
 
int mmapsize;
 
struct video_mbuf videombuf;
 
struct video_picture videopict;
 
struct video_window videowin;
 
struct video_channel videochan;
 
struct video_param videoparam; 
 
int cameratype ;
 
char *cameraname;
 
char bridge[9];
 
int sizenative;                                       // available size in jpeg
 int sizeothers;                                      // others palette 
 int palette;                                             // available palette
 int norme ;                                            // set spca506 usb video grabber
 int channel ;                                         // set spca506 usb video grabber
 int grabMethod ;
 unsigned 
char *pFramebuffer;         //内存影射后指向数据指针
 unsigned char *ptframe[4];                //frameconverse以后指向将要发送到网络的数据指针
 int framelock[4];                                     //占用与否标识
 pthread_mutex_t grabmutex;              
 
int framesizeIn ;                                    //在init中确定
 volatile int frame_cour;                        //目前要传输到网络的frame
 int bppIn;                                                //depth
 int  hdrwidth;
 
int  hdrheight;
 
int  formatIn;                                         //palette
 int signalquit; 
 }
;
在linux内核源代码中的
/include/linux/videodev.h中定义了各个format格式的值

从main函数出发,跟踪int format

1.1 初始化int format

int format = VIDEO_PALETTE_YUV420P;

1.2 根据输入的参数识别用户要求的format

if (strcmp (argv[i], "-f"== 0{
   
if (i + 1 >= argc) {
    printf (
"No parameter specified with -f, aborting.\n");
    exit (
1);
   }

   mode 
= strdup (argv[i + 1]);

 
if (strncmp (mode, "r32"3== 0{
    format 
= VIDEO_PALETTE_RGB32;
    }
 else if (strncmp (mode, "r24"3== 0{
    format 
= VIDEO_PALETTE_RGB24;
    }
 else if (strncmp (mode, "r16"3== 0{
    format 
= VIDEO_PALETTE_RGB565;
    }
 else if (strncmp (mode, "yuv"3== 0{
    format 
= VIDEO_PALETTE_YUV420P;
    }
 else if (strncmp (mode, "jpg"3== 0{
    format 
= VIDEO_PALETTE_JPEG;
    }
else {
    format 
= VIDEO_PALETTE_YUV420P;
    }

 }


2. 初始化设备的时候

init_videoIn (
&videoIn, videodevice, width, height, format,grabmethod)

2.1

vd
->formatIn = format; 
vd
->bppIn = GetDepth (vd->formatIn);            //根据format值确定vd.depth

2.2 进入init_v4l (vd)

2.2.1

probePalette(vd )                               
//将五个palette类型传到video_picture数据结构里面,set之后在get一次,比较前后palette值,如果两者一致,说明该palette类型为可用

probeSize(vd )                                 
//同上理,将7个width*height结构传到video_window里面,察看是否可用

check_palettesize(vd)                   
//   首先转换大小int needsize = convertsize(vd->hdrwidth,vd->hdrheight),convertsize(),根据w*h返回7个类型:VGA,PAL,SIF,CIF,QPAL,QSIF,QCIF,上述七个宏定义在spcav4l.h中:

#define MASQ 1
#define VGA MASQ
#define PAL (MASQ << 1)
#define SIF (MASQ << 2)
#define CIF (MASQ << 3)
#define QPAL (MASQ << 4)
#define QSIF (MASQ << 5)
#define QCIF (MASQ << 6)            int needsize的智应该为这七个值之一

int needpalette=0,needpalette = checkpalette(vd),在checkpalette(vd)中,convertpalette(vd->formatIn); see is the palette available? 根据vd->formatIn返回jpeg yuv420p rbg24 rgb565 and rgb32

#define JPG MASQ    //JPEG 1
#define YUV420P (MASQ << 1)
#define RGB24 (MASQ << 2)
#define RGB565 (MASQ << 3)
#define RGB32 (MASQ << 4)    

根据needpalette的值察看是否available
?将测试结果写入函数palette = paletteconvert( needpalette),if (palette),对palette的返回将它赋值到vd->vmmap.height = vd->hdrheight;
      vd
->vmmap.width = vd->hdrwidth;
      vd
->vmmap.format = palette;设置VIDIOCMCAPTURE,测试一下是否可以采集,ok的话vd->formatIn = palette;

根据needsize和vd.sizeother察看是否还有别的palettesize可以支持,test 
is palette and size are available otherwhise return the next available palette and size palette is set by preference order jpeg yuv420p rbg24 rgb565 and rgb32 

2.2.2

vd
->videopict.palette = vd->formatIn; 设置video_picture数据结构

vd
->videopict.depth = GetDepth (vd->formatIn);
vd
->bppIn = GetDepth (vd->formatIn);

2.2.3

vd
->framesizeIn = (vd->hdrwidth * vd->hdrheight * vd->bppIn) >> 3;       设置framesize大小

erreur 
= SetVideoPict (vd);
erreur 
= GetVideoPict (vd);
if (vd->formatIn != vd->videopict.palette ||
vd
->bppIn != vd->videopict.depth)
exit_fatal (
"could't set video palette Abort !");
if (erreur < 0)
exit_fatal (
"could't set video palette Abort !");

2.2.4

开始采集两个frame的视频数据,指向数据的指针为pFramebuffer

3 打开采集视频线程 pthread_create (&w1, NULL, (void *) grab, NULL),进入grab函数

3.1 vd->vmmap.format = vd->formatIn;

VIDIOCSYNC:开始check在init时候采集的数据是否已经完成

3.2 采集完成,进行jpeg压缩处理,里面大有文章

jpegsize
= convertframe(vd->ptframe[vd->frame_cour]+ sizeof(struct frame_t),
    vd
->pFramebuffer + vd->videombuf.offsets[vd->vmmap.frame],
   vd
->hdrwidth,vd->hdrheight,vd->formatIn,qualite);

在 
int convertframe(unsigned char *dst,unsigned char *src, int width,int height, int formatIn, int qualite)中

switch (formatIn)根据不同的palette值做不同的数据压缩处理,返回压缩后的数据大小值,如果是JPEG格式,意味着硬件采集近来的数据已经做了压缩,不需要再用软件进行压缩处理,而除了VIDEO_PALETTE_JPEG以外的palette,都需要进行encode,函数为UINT32 encode_image (UINT8 * input_ptr, UINT8 * output_ptr,UINT32 quality_factor, UINT32 image_format,UINT32 image_width, UINT32 image_height),UINT32 image_format为输入的palette,压缩使用huffman编码,详细代码在huffman.c和encode.c中

4. 打开数据远程网络传输线程,在accept阻塞处代开线程pthread_create(&server_th, NULL, (void *)service, &new_sock),

首先在连接处读取frame_t message数据结构的内容,read(sock,(unsigned 
char*)&message,sizeof(struct client_t)),根据message的内容决定如何传输,下一步做循环发送,根据frame_lock和frame_cour发送没有被占用的compressed frame

 

#include 
"utils.h"
#include 
"tcputils.h"
#include 
"spcaframe.h"                                  主要用到的自定义头文件

1 . 在main函数中:

/* default mmap */
 
int grabMethod = 1;
 
int format = VIDEO_PALETTE_YUV420P;                                 default  format

SPCASTATE funct                                                    根均输入的参数决定三种处理功能

funct 
= GRABBER;                                                default

if (strcmp (argv[i], "-i"== 0{                                          输入参数 -i有效
   
if (i + 1 >= argc) {
    printf (
"No parameter specified with -i, aborting.\n");
    exit (
1);
   }

   inputfile 
= strdup (argv[i + 1]);
   funct 
= PLAYER ;                                                           执行play功能
  }


if (strcmp (argv[i], "-w"== 0{                                            如果输入参数 -w有效
   
if (i + 1 >= argc) {
    printf (
"No parameter specified with -w, aborting.\n");
    exit (
1);
   }

   AdIpPort 
= strdup (argv[i + 1]);
   
if(reportip(AdIpPort,AdIp,&ports) < 0)
   printf(
"error in port convertion \n");
   printf (
"using Server %s Port %d \n",AdIp,ports);
   funct 
= CLIENT ;                                                               执行client功能
  }


switch (funct) {
 
case PLAYER:
  
{
  
/* that is spcaview player */
  spcaPlay (inputfile, owidth, oheight); 
 }
 
 
break;
 
case GRABBER:
 
{
  
/* spcaview grabber */
  spcaGrab (outputfile,fourcc , videodevice, image_width,image_height, format, owidth, oheight,
   grabMethod, videoOn, audioout, videocomp, autobright, statOn, decodeOn);
 }

 
break;
 
case CLIENT:
 
{
  spcaClient(AdIp,ports,owidth,oheight, statOn);
 }

 main函数结束,这里指对 spcaClient(AdIp,ports,owidth,oheight, statOn);
做详细解释。owidth和oheight是
-m参数有效的时候传下来的特定W*H要求的参数,statOn为-t有效时打印统计数据,三述三个参数初始值都为0。

2 . SpcaClient()

to be 
continue..

posted on 2009-03-17 22:31 iniwf 阅读(1307) 评论(0)  编辑 收藏 引用 所属分类: 嵌入式


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


导航

统计

常用链接

留言簿(2)

随笔分类

随笔档案

收藏夹

IT技术

积分与排名

最新评论

阅读排行榜

评论排行榜