📄 spcaview_spcaserver源码详解(1) - legend - csdnblog.htm
字号:
<UL class=list></UL>
<H3 class=listtitle>资讯中心</H3>
<UL class=list>
<LI class=listitem><A href="http://www.chinaunix.net/"
target=_self>chinaUnix</A>
<LI class=listitem><A
href="http://community.csdn.net/Expert/ForumList.asp?typenum=1&Roomid=803"
target=_self>CSDN内核及驱动程序研究区</A>
<LI class=listitem><A href="http://www.21control.com/RTOS/Index.html"
target=_self>Embedded Control Lib</A>
<LI class=listitem><A href="http://sourceforge.net/index.php"
target=_self>sourceforge</A>
<LI class=listitem><A href="http://www.myembed.com/bbs/default.asp"
target=_self>嵌入式论坛</A></LI></UL>
<H3 class=listtitle>存档</H3>
<UL class=list>
<LI><A
href="http://blog.csdn.net/legendzjut/archive/2006/09.aspx">2006年09月(8)</A></LI></UL><SPAN
id=Anthem_RecentComments_ltlComments__><SPAN
id=RecentComments_ltlComments></SPAN></SPAN><BR><BR></DIV>
<DIV id=main>
<DIV class=Tag>
<SCRIPT language=javascript
src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/urltag.aspx"></SCRIPT>
<DIV style="CLEAR: both"></DIV></DIV>
<SCRIPT>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</SCRIPT>
<DIV class=post>
<DIV class=postTitle><A
href="http://blog.csdn.net/legendzjut/archive/2006/09/26/1287520.aspx"><IMG
height=13 src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/zhuan.gif"
width=15 border=0> spcaview.spcaserver源码详解(1)</A> </DIV>
<DIV class=postText>
<P>struct vdIn {<BR> int fd;<BR> char *videodevice
; <BR> struct
video_mmap
vmmap;
//内存影射<BR> struct video_capability videocap;<BR> int
mmapsize;<BR> struct video_mbuf videombuf;<BR> struct video_picture
videopict;<BR> struct video_window videowin;<BR> struct video_channel
videochan;<BR> struct video_param videoparam; <BR> int cameratype
;<BR> char *cameraname;<BR> char bridge[9];<BR> int
sizenative;
// available size in jpeg<BR> int
sizeothers;
// others palette <BR> int
palette; //
available palette<BR> int norme
;
// set spca506 usb video grabber<BR> int channel
;
// set spca506 usb video grabber<BR> int grabMethod
;<BR> unsigned char
*pFramebuffer;
//内存影射后指向数据指针<BR> unsigned char
*ptframe[4];
//frameconverse以后指向将要发送到网络的数据指针<BR> int
framelock[4];
//占用与否标识<BR> pthread_mutex_t
grabmutex;
<BR> int framesizeIn
;
//在init中确定<BR> volatile int
frame_cour;
//目前要传输到网络的frame<BR> int
bppIn;
//depth<BR> int hdrwidth;<BR> int
hdrheight;<BR> int
formatIn;
//palette<BR> int
signalquit; <BR> };<BR>在linux内核源代码中的/include/linux/videodev.h中定义了各个format格式的值</P>
<P>从main函数出发,跟踪int format</P>
<P>1.1 初始化int format</P>
<P>int format = VIDEO_PALETTE_YUV420P;</P>
<P>1.2 根据输入的参数识别用户要求的format</P>
<P>if (strcmp (argv[i], "-f") == 0) {<BR> if (i + 1 >= argc)
{<BR> printf ("No parameter specified with -f,
aborting.\n");<BR> exit
(1);<BR> }<BR> mode = strdup (argv[i +
1]);</P>
<P> if (strncmp (mode, "r32", 3) == 0) {<BR> format
= VIDEO_PALETTE_RGB32;<BR> } else if (strncmp (mode, "r24", 3)
== 0) {<BR> format =
VIDEO_PALETTE_RGB24;<BR> } else if (strncmp (mode, "r16",
3) == 0) {<BR> format =
VIDEO_PALETTE_RGB565;<BR> } else if (strncmp (mode,
"yuv", 3) == 0) {<BR> format =
VIDEO_PALETTE_YUV420P;<BR> } else if (strncmp (mode,
"jpg", 3) == 0) {<BR> format =
VIDEO_PALETTE_JPEG;<BR> }else
{<BR> format =
VIDEO_PALETTE_YUV420P;<BR> }<BR> }</P>
<P>2. 初始化设备的时候</P>
<P>init_videoIn (&videoIn, videodevice, width, height,
format,grabmethod)</P>
<P>2.1</P>
<P>vd->formatIn = format; <BR>vd->bppIn = GetDepth
(vd->formatIn);
//根据format值确定vd.depth</P>
<P>2.2 进入init_v4l (vd)</P>
<P>2.2.1</P>
<P>probePalette(vd
)
//将五个palette类型传到video_picture数据结构里面,set之后在get一次,比较前后palette值,如果两者一致,说明该palette类型为可用</P>
<P>probeSize(vd
)
//同上理,将7个width*height结构传到video_window里面,察看是否可用</P>
<P>check_palettesize(vd)
// 首先转换大小int needsize =
convertsize(vd->hdrwidth,vd->hdrheight),convertsize(),根据w*h返回7个类型:VGA,PAL,SIF,CIF,QPAL,QSIF,QCIF,上述七个宏定义在spcav4l.h中:</P>
<P>#define MASQ 1<BR>#define VGA MASQ<BR>#define PAL (MASQ <<
1)<BR>#define SIF (MASQ << 2)<BR>#define CIF (MASQ << 3)<BR>#define
QPAL (MASQ << 4)<BR>#define QSIF (MASQ << 5)<BR>#define QCIF (MASQ
<< 6)
int needsize的智应该为这七个值之一</P>
<P>int needpalette=0,needpalette =
checkpalette(vd),在checkpalette(vd)中,convertpalette(vd->formatIn); see is
the palette available? 根据vd->formatIn返回jpeg yuv420p rbg24 rgb565 and
rgb32</P>
<P>#define JPG MASQ //JPEG 1<BR>#define YUV420P (MASQ <<
1)<BR>#define RGB24 (MASQ << 2)<BR>#define RGB565 (MASQ <<
3)<BR>#define RGB32 (MASQ << 4) </P>
<P>根据needpalette的值察看是否available?将测试结果写入函数palette = paletteconvert(
needpalette),if (palette),对palette的返回将它赋值到vd->vmmap.height =
vd->hdrheight;<BR> vd->vmmap.width =
vd->hdrwidth;<BR> vd->vmmap.format =
palette;设置VIDIOCMCAPTURE,测试一下是否可以采集,ok的话vd->formatIn = palette;</P>
<P>根据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 </P>
<P>2.2.2</P>
<P>vd->videopict.palette = vd->formatIn; 设置video_picture数据结构</P>
<P>vd->videopict.depth = GetDepth (vd->formatIn);<BR>vd->bppIn =
GetDepth (vd->formatIn);</P>
<P>2.2.3</P>
<P>vd->framesizeIn = (vd->hdrwidth * vd->hdrheight * vd->bppIn)
>> 3; 设置framesize大小</P>
<P>erreur = SetVideoPict (vd);<BR>erreur = GetVideoPict (vd);<BR>if
(vd->formatIn != vd->videopict.palette ||<BR>vd->bppIn !=
vd->videopict.depth)<BR>exit_fatal ("could't set video palette Abort
!");<BR>if (erreur < 0)<BR>exit_fatal ("could't set video palette Abort
!");</P>
<P>2.2.4</P>
<P>开始采集两个frame的视频数据,指向数据的指针为pFramebuffer</P>
<P>3 打开采集视频线程 pthread_create (&w1, NULL, (void *) grab, NULL),进入grab函数</P>
<P>3.1 vd->vmmap.format = vd->formatIn;</P>
<P>VIDIOCSYNC:开始check在init时候采集的数据是否已经完成</P>
<P>3.2 采集完成,进行jpeg压缩处理,里面大有文章</P>
<P>jpegsize= convertframe(vd->ptframe[vd->frame_cour]+ sizeof(struct
frame_t),<BR> vd->pFramebuffer +
vd->videombuf.offsets[vd->vmmap.frame],<BR> vd->hdrwidth,vd->hdrheight,vd->formatIn,qualite);</P>
<P>在 int convertframe(unsigned char *dst,unsigned char *src, int width,int
height, int formatIn, int qualite)中</P>
<P>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中</P>
<P>4. 打开数据远程网络传输线程,在accept阻塞处代开线程pthread_create(&server_th, NULL, (void
*)service, &new_sock),</P>
<P>首先在连接处读取frame_t message数据结构的内容,read(sock,(unsigned
char*)&message,sizeof(struct
client_t)),根据message的内容决定如何传输,下一步做循环发送,根据frame_lock和frame_cour发送没有被占用的compressed
frame</P>
<P> </P> <BR><BR>
<P id=TBPingURL>Trackback:
http://tb.blog.csdn.net/TrackBack.aspx?PostId=1287520</P><BR></DIV>
<DIV class=postFoot>
<SCRIPT src=""></SCRIPT>
[<A title=功能强大的网络收藏夹,一秒钟操作就可以轻松实现保存带来的价值、分享带来的快乐
href="javascript:d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(saveit=window.open('http://wz.csdn.net/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=590,height=300,left=75,top=20,status=no,resizable=yes'));saveit.focus();">收藏到我的网摘</A>]
legendzjut发表于 2006年09月26日 14:22:00 </DIV></DIV><LINK
href="http://blog.csdn.net/legendzjut/Services/Pingback.aspx" rel=pingback><!--<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"><rdf:Descriptionrdf:about="http://blog.csdn.net/legendzjut/archive/2006/09/26/1287520.aspx"dc:identifier="http://blog.csdn.net/legendzjut/archive/2006/09/26/1287520.aspx"dc:title="spcaview.spcaserver源码详解(1)"trackback:ping="http://tb.blog.csdn.net/TrackBack.aspx?PostId=1287520" /></rdf:RDF>-->
<SCRIPT>function hide(){showComment();}</SCRIPT>
<BR>
<DIV class=post>
<DIV class=postTitle>相关文章:</DIV>
<UL class=postText>
<LI><A href="http://blog.csdn.net/neohuo/archive/2006/06/02/769849.aspx"
target=_blank>视频采集 (续)</A> 2006-06-02 <A href="http://blog.csdn.net/neohuo/"
target=_blank>neohuo</A>
<LI><A href="http://blog.csdn.net/neohuo/archive/2006/06/01/767414.aspx"
target=_blank>linux下V4L视频采集总结</A> 2006-06-01 <A
href="http://blog.csdn.net/neohuo/" target=_blank>neohuo</A>
<LI><A href="http://blog.csdn.net/neohuo/archive/2006/07/10/899728.aspx"
target=_blank>明天回家啦,庆祝一下,贡献一段源码,基于linux V4L视频采集摄像程序</A> 2006-07-10 <A
href="http://blog.csdn.net/neohuo/" target=_blank>neohuo</A>
<LI><A href="http://blog.csdn.net/taodm/archive/2003/03/07/15748.aspx"
target=_blank>Effective STL:Item 16:如何将vector和string的数据传给传统的API函数</A>
2003-03-07 <A href="http://blog.csdn.net/taodm/" target=_blank>taodm</A>
<LI><A href="http://blog.csdn.net/neohuo/archive/2006/02/16/600392.aspx"
target=_blank>Video4Linux Kernel API Reference v0_119990430</A> 2006-02-16 <A
href="http://blog.csdn.net/neohuo/"
target=_blank>neohuo</A></LI></UL></DIV><BR><BR>
<DIV class=post id=csdn_zhaig_ad_yahoo></DIV><SPAN
id=Anthem_Comments.ascx_ltlComments__><SPAN id=Comments.ascx_ltlComments><BR>
<DIV id=comments>
<H3></H3>没有评论。 </DIV></SPAN></SPAN>
<SCRIPT language=javascript>
ad_width=468;
ad_height=60;
adcss=2;
unionuser=19;
ad_type='j';
count=5;
</SCRIPT>
<SCRIPT language=javascript
src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/showads.js"
type=text/javascript></SCRIPT>
<SCRIPT language=javascript
src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/showgm.js"
type=text/javascript></SCRIPT>
<SCRIPT type=text/javascript>document.write("<img src=http://counter.csdn.net/pv.aspx?id=24 border=0 width=0 height=0>");</SCRIPT>
<DIV class=CommentForm id=commentform>
<H3>发表评论</H3>
<DIV id=Anthem_PostComment.ascx_UpdatePanel1__>
<DIV id=PostComment.ascx_UpdatePanel1>
<TABLE class=CommentForm>
<TBODY>
<TR>
<TD width=69 height=0></TD>
<TD></TD></TR>
<TR>
<TD width=70>大名:</TD>
<TD align=left><INPUT id=PostComment.ascx_tbName style="WIDTH: 300px"
disabled size=40 name=PostComment.ascx:tbName> <SPAN
id=PostComment.ascx_RequiredFieldValidator2
style="DISPLAY: none; COLOR: red" initialvalue=""
evaluationfunction="RequiredFieldValidatorEvaluateIsValid"
display="Dynamic" errormessage="<br>请输入尊姓大名"
controltovalidate="PostComment.ascx_tbName"><BR>请输入尊姓大名</SPAN> </TD></TR>
<TR>
<TD width=70>网址:</TD>
<TD align=left><INPUT id=PostComment.ascx_tbUrl style="WIDTH: 300px"
disabled size=40 name=PostComment.ascx:tbUrl> </TD></TR>
<TR>
<TD colSpan=3>评论 <SPAN id=PostComment.ascx_RequiredFieldValidator3
style="DISPLAY: none; COLOR: red" initialvalue=""
evaluationfunction="RequiredFieldValidatorEvaluateIsValid"
display="Dynamic" errormessage="<br>请输入评论"
controltovalidate="PostComment.ascx_tbComment"><BR>请输入评论</SPAN> <BR><TEXTAREA id=PostComment.ascx_tbComment style="WIDTH: 381px; HEIGHT: 193px" disabled name=PostComment.ascx:tbComment rows=10 cols=50></TEXTAREA>
</TD></TR>
<TR>
<TD colSpan=3><SPAN
id=Anthem_PostComment.ascx_btnSubmit__></SPAN> </TD></TR>
<TR>
<TD colSpan=3><SPAN id=PostComment.ascx_Message
style="COLOR: red">注册用户才能发表评论。如果你没有登录,请点击<A
href="http://passport.csdn.net/member/UserLogin.aspx?from=http://blog.csdn.net/legendzjut/archive/2006/09/26/1287520.aspx">登录</A></SPAN>
</TD></TR></TBODY></TABLE></DIV></DIV></DIV></DIV>
<P id=footer>Powered by: <BR><A id=Footer1_Hyperlink2
href="http://scottwater.com/blog" name=Hyperlink1><IMG
src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/100x30_Logo.gif"
border=0></A> <A id=Footer1_Hyperlink3 href="http://asp.net/"
name=Hyperlink1><IMG
src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/PoweredByAsp.Net.gif"
border=0></A> <BR>Copyright © legendzjut </P>
<SCRIPT
src="spcaview_spcaserver源码详解(1) - legend - CSDNBlog.files/counter.js"></SCRIPT>
<SCRIPT type=text/javascript>
<!--
var Page_Validators = new Array(document.getElementById("PostComment.ascx_RequiredFieldValidator2"), document.getElementById("PostComment.ascx_RequiredFieldValidator3"));
// -->
</SCRIPT>
<INPUT id=__EVENTVALIDATION type=hidden
value=/wEWBAL+raDpAgKqtOi0AwLAsuLbDAKi687YCaEdUuRgIvhS8PYPDsd5LslVNRL0
name=__EVENTVALIDATION>
<SCRIPT type=text/javascript>
<!--
var Page_ValidationActive = false;
if (typeof(ValidatorOnLoad) == "function") {
ValidatorOnLoad();
}
function ValidatorOnSubmit() {
if (Page_ValidationActive) {
return ValidatorCommonOnSubmit();
}
else {
return true;
}
}
// -->
</SCRIPT>
</FORM>
<SCRIPT language=javascript type=text/javascript>
<!--
try{
hide();
}
catch(e){
}
//-->
</SCRIPT>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -