遠(yuǎn)程視頻監(jiān)控程序設(shè)計(jì)實(shí)驗(yàn)指導(dǎo)_第1頁
遠(yuǎn)程視頻監(jiān)控程序設(shè)計(jì)實(shí)驗(yàn)指導(dǎo)_第2頁
遠(yuǎn)程視頻監(jiān)控程序設(shè)計(jì)實(shí)驗(yàn)指導(dǎo)_第3頁
遠(yuǎn)程視頻監(jiān)控程序設(shè)計(jì)實(shí)驗(yàn)指導(dǎo)_第4頁
遠(yuǎn)程視頻監(jiān)控程序設(shè)計(jì)實(shí)驗(yàn)指導(dǎo)_第5頁
已閱讀5頁,還剩30頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

...v.遠(yuǎn)程視頻監(jiān)控程序設(shè)計(jì)攝像頭采集驅(qū)動移植〔在2.4核平臺下:此步驟可以省略〕移植gspcav1-20071224gspcav1-20071224下載地址:由于linux-.4/drivers/usb目錄下沒有media目錄,故移植步驟如下:a)在linux-.4/drivers/usb目錄下新建media目錄,將gspcav1-20071224.tar.gzcopy到media下并解壓。為了使media編譯進(jìn)內(nèi)核,需修改linux-2.6.24.4/drivers/usb目錄下的Kconfig、Makefile文件。[rootvm-devusb]$pwd/work/kernel/linux-.4/drivers/usb[rootvm-devusb]$viKconfig添加source"drivers/usb/media/Kconfig"[rootvm-devusb]$viMakefile添加obj-$(CONFIG_USB_SPCA5XX)+=media/b)為添加gspcav1-20071224編譯選項(xiàng),在media下新建Kconfig、Makefile文件。[rootvm-devmedia]$pwd/work/kernel/linux-.4/drivers/usb/media[rootvm-devmedia]$viKconfig##USBMultimediadeviceconfiguration#ment"USBMultimediadevices"dependsonUSBconfigUSB_SPCA5XXtristate"USBSPCA5XXSunplus/Vimicro/SonixjpegCameras"dependsonUSB&&VIDEO_DEV---help---SayYorMhereifyouwanttouseoneofthesewebcams:Thebuilt-inmicrophoneisenabledbyselectingUSBAudiosupport.ThisdriverusestheVideoForLinuxAPI.YoumustsayYorMto"VideoForLinux"(underCharacterDevices)tousethisdriver.InformationonthisAPIandpointersto"v4l"programsmaybefoundat<file:Documentation/video4linux/API.html>.Topilethisdriverasamodule,chooseMhere:themodulewillbecalledspca5xx.[rootvm-devmedia]$viMakefile##MakefileforUSBMediadrivers#obj-$(CONFIG_USB_SPCA5XX)+=gspcav1-20071224/c)修改gspcav1-20071224的Makefile[rootvm-devgspcav1-20071224]$pwd/work/kernel/linux-.4/drivers/usb/media/gspcav1-20071224[rootvm-devgspcav1-20071224]$viMakefilegspca-objs:=gspca_core.odecoder/gspcadecoder.oobj-$(CONFIG_USB_SPCA5XX)+=gspca.oclean:rm-f*.[oas].*.flags*.ko.*d.*.d.*.tmp*.mod.crm-rf.tmp_versionsd)編譯內(nèi)核〔1〕Multimediadevices--->VideoForLinux〔2〕USBsupport--->SupportforHost-sideUSB---USBHostControllerDriversOHCIHCDsupport〔3〕---USBMultimediadevicesUSBSPCA5XXSunplus/Vimicro/SonixjpegCameras2、 此時(shí),可能會提示gspca_core.c的一些輕微錯(cuò)誤,稍作修改即可://staticconstchargspca_version[]=GSPCA_VERSION;staticconstchargspca_version[]="00.60.00";把新生成的uImage燒進(jìn)開發(fā)板,重啟,插上中星微芯片的攝像頭,命令行出現(xiàn)#usb1-1:newfullspeedUSBdeviceusings3c2410-ohciandaddress2usb1-1:configuration#1chosenfrom1choicedrivers/usb/media/gspcav1-20071224/gspca_core.c:USBGSPCAcamerafound.(ZC3XX)說明移植的驅(qū)動已經(jīng)能識別設(shè)備,設(shè)備名所在路徑/dev/video0。攝像頭采集應(yīng)用程序接口(V4L接口),接口函數(shù)編寫〔可以直接將文件到/home/文件下,解壓縮#完成解壓成mouse_capture-daily3,運(yùn)行此文件夾下的make,在arm機(jī)在能看到的的位置上打上spca兩個(gè)驅(qū)動。insmodvideodev.oinsmodspca5xx.o./mouse_capture到/var/tmp/下看到是否有1.jpg圖片,必須有,否那么錯(cuò)。再看video0有沒有:〕一、Video4linux簡介Video4Linux是為市場現(xiàn)在常見的電視捕獲卡和并口及USB口的攝像頭提供統(tǒng)一的編程接口。同時(shí)也提供無線電通信和文字電視播送解碼和垂直消隱的數(shù)據(jù)接口。本文主要針對USB攝像頭設(shè)備文件/dev/video0,進(jìn)展視頻圖像采集方面的程序設(shè)計(jì)。二、Video4linux編程指南1.視頻編程的流程〔1〕翻開視頻設(shè)備:〔2〕讀取設(shè)備信息〔3〕更改設(shè)備當(dāng)前設(shè)置〔可以不做〕〔4〕進(jìn)展視頻采集,兩種方法:a.內(nèi)存映射b.直接從設(shè)備讀取〔5〕對采集的視頻進(jìn)展處理〔6〕關(guān)閉視頻設(shè)備。定義的數(shù)據(jù)構(gòu)造及使用函數(shù)struct_v4l_struct{intfd;structvideo_capabilitycapability;structvideo_bufferbuffer;structvideo_windowwindow;structvideo_channelchannel[8];structvideo_picturepicture;structvideo_mmapmmap;structvideo_mbufmbuf;unsignedchar*map;};typedefstruct_v4l_structv4l_device;externintv4l_open(char*,v4l_device*);externintv4l_close(v4l_device*);externintv4l_get_capability(v4l_device*);externintv4l_set_norm(v4l_device*,int);externintv4l_get_picture(v4l_device*);externintv4l_grab_init(v4l_device*,int,int);externintv4l_grab_frame(v4l_device*,int);externintv4l_grab_sync(v4l_device*);externintv4l_mmap_init(v4l_device*);externintv4l_get_mbuf(v4l_device*);externintv4l_get_picture(v4l_device*);externintv4l_grab_picture(v4l_device*,unsignedint);externintv4l_set_buffer(v4l_device*);externintv4l_get_buffer(v4l_device*);externintv4l_switch_channel(v4l_device*,int);3.Video4linux支持的數(shù)據(jù)構(gòu)造及其用途〔1〕video_capability包含設(shè)備的根本信息〔設(shè)備名稱、支持的最大最小分辨率、信號源信息等〕name[32]設(shè)備名稱maxwidthmaxheightminwidthminheightChannels信號源個(gè)數(shù)type是否能capture,彩色還是黑白,是否能裁剪等等。值如VID_TYPE_CAPTURE等〔2〕video_picture設(shè)備采集的圖象的各種屬性Brightness0~65535huecolourcontrastwhitenessdepth8162432paletteVIDEO_PALETTE_RGB24|VIDEO_PALETTE_RGB565|VIDEO_PALETTE_JPEG|VIDEO_PALETTE_RGB32〔3〕video_channel關(guān)于各個(gè)信號源的屬性Channel信號源的編號nametunersTypeVIDEO_TYPE_TV|IDEO_TYPE_CAMERANorm制式PAL|NSTC|SECAM|AUTO〔4〕video_window包含關(guān)于capturearea的信息xxwindows中的坐標(biāo).yywindows中的坐標(biāo).widthThewidthoftheimagecapture.heightTheheightoftheimagecapture.chromakeyAhostorderRGB32valueforthechromakey.flagsAdditionalcaptureflags.clipsAlistofclippingrectangles.(Setonly)clipcountThenumberofclippingrectangles.(Setonly)〔5〕video_mbuf利用mmap進(jìn)展映射的幀的信息size每幀大小Frames最多支持的幀數(shù)Offsets每幀相對基址的偏移〔6〕video_mmap用于mmap4.關(guān)鍵步驟介紹【注】接多個(gè)攝像頭。方法如下:買一個(gè)usbhub接到開發(fā)板的usbhost上。cat/proc/devices可以知道videocapturedevice的major是81,再ls–l/dev看到video0的次設(shè)備號是0。兩個(gè)攝像頭當(dāng)然要兩個(gè)設(shè)備號,所以mknod/dev/video1c811,如果接4個(gè),就mknod/dev/video2c812,mknod/dev/video3c813。依次類推。〔1〕翻開視頻:intv4l_open(char*dev,v4l_device*vd){if(!dev)dev=〞/dev/video0”;if((vd->fd=open(dev,O_RDWR))<0){perror("v4l_open:");return-1;}if(v4l_get_capability(vd))return-1;if(v4l_get_picture(vd))return-1;return0;}〔2〕讀video_capabilityXX息intv4l_get_capability(v4l_device*vd){if(ioctl(vd->fd,VIDIOCGCAP,&(vd->capability))<0){perror("v4l_get_capability:");return-1;}return0;}成功后可讀取vd->capability各分量〔3〕讀video_pictureXX息intv4l_get_picture(v4l_device*vd){if(ioctl(vd->fd,VIDIOCGPICT,&(vd->picture))<0){perror("v4l_get_picture:");return-1;}return0;}成功后可讀取圖像的屬性〔4〕改變video_picture中分量的值〔可以不做的〕先為分量賦新值,再調(diào)用VIDIOCSPICTvd->picture.colour=65535;if(ioctl(vd->fd,VIDIOCSPICT,&(vd->picture))<0){perror("VIDIOCSPICT");return-1;}〔5〕初始化channel〔可以不做的〕必須先做得到vd->capability中的信息intv4l_get_channels(v4l_device*vd){inti;for(i=0;i<vd->capability.channels;i++){vd->channel[i].channel=i;if(ioctl(vd->fd,VIDIOCGCHAN,&(vd->channel[i]))<0){perror("v4l_get_channel:");return-1;}}return0;}〔6〕關(guān)閉設(shè)備intv4l_close(v4l_device*vd){close(vd->fd);return0;}重點(diǎn):截取圖象的兩種方法一、用mmap〔內(nèi)存映射〕方式截取視頻mmap()系統(tǒng)調(diào)用使得進(jìn)程之間通過映射同一個(gè)普通文件實(shí)現(xiàn)共享內(nèi)存。普通文件被映射到進(jìn)程地址空間后,進(jìn)程可以向訪問普通內(nèi)存一樣對文件進(jìn)展訪問,不必再調(diào)用read(),write〔〕等操作。兩個(gè)不同進(jìn)程A、B共享內(nèi)存的意思是,同一塊物理內(nèi)存被映射到進(jìn)程A、B各自的進(jìn)程地址空間。進(jìn)程A可以即時(shí)看到進(jìn)程B對共享內(nèi)存中數(shù)據(jù)的更新,反之亦然。采用共享內(nèi)存通信的一個(gè)顯而易見的好處是效率高,因?yàn)檫M(jìn)程可以直接讀寫內(nèi)存,而不需要任何數(shù)據(jù)的拷貝〔1〕設(shè)置picture的屬性〔2〕初始化video_mbuf,以得到所映射的buffer的信息ioctl(vd->fd,VIDIOCGMBUF,&(vd->mbuf))〔3〕可以修改video_mmap和幀狀態(tài)的當(dāng)前設(shè)置〔4〕將mmap與video_mbuf綁定void*mmap(void*addr,size_tlen,intprot,intflags,intfd,off_toffset)len:映射到調(diào)用進(jìn)程地址空間的字節(jié)數(shù),它從被映射文件開頭offset個(gè)字節(jié)開場算起Prot:指定共享內(nèi)存的訪問權(quán)限PROT_READ〔可讀〕,PROT_WRITE〔可寫〕,PROT_EXEC〔可執(zhí)行〕Flags:MAP_SHAREDMAP_PRIVATE中必選一個(gè),MAP_FIXED不推薦使用Addr:共內(nèi)存享的起始地址,一般設(shè)0,表示由系統(tǒng)分配Mmap()返回值是系統(tǒng)實(shí)際分配的起始地址intv4l_mmap_init(v4l_device*vd){if(v4l_get_mbuf(vd)<0)return-1;if((vd->map=mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0))<0){perror("v4l_mmap_init:mmap");return-1;}return0;}〔5〕Mmap方式下真正做視頻截取的VIDIOCMCAPTUREioctl(vd->fd,VIDIOCMCAPTURE,&(vd->mmap));假設(shè)調(diào)用成功,開場一幀的截取,是非阻塞的,是否截取完畢留給VIDIOCSYNC來判斷〔6〕調(diào)用VIDIOCSYNC等待一幀截取完畢if(ioctl(vd->fd,VIDIOCSYNC,&frame)<0){perror("v4l_sync:VIDIOCSYNC");return-1;}假設(shè)成功,說明一幀截取已完成??梢蚤_場做下一次VIDIOCMCAPTUREframe是當(dāng)前截取的幀的序號。********關(guān)于雙緩沖************video_bmufbmuf.frames=2;一幀被處理時(shí)可以采集另一幀intframe;//當(dāng)前采集的是哪一幀intframestat[2];//幀的狀態(tài)沒開場采集|等待采集完畢幀的地址由vd->map+vd->mbuf.offsets[vd->frame]得到。采集工作完畢后調(diào)用munmap取消綁定munmap(vd->map,vd->mbuf.size)在實(shí)際應(yīng)用時(shí)還可以采用緩沖隊(duì)列等方式。二、視頻截取的第二種方法:直接讀設(shè)備關(guān)于緩沖大小,圖象等的屬性須由使用者事先設(shè)置調(diào)用read〔〕;intread(要訪問的文件描述符;指向要讀寫的信息的指針;應(yīng)該讀寫的字符數(shù));返回值為實(shí)際讀寫的字符數(shù)intlen;unsignedchar*vd->map=(unsignedchar*)malloc(vd?capability.maxwidth*vd?capability.maxheight);len=read(vd?fd,vd?vd->map,vd?capability.maxwidth*vd?capability.maxheight*3);2.3編程實(shí)例〔mouse_capture〕zc301是采集jpeg編碼的位流,mouse_capture是根據(jù)servfox改編的一個(gè)專門從zc301攝像頭獲取一Xjpeg圖片,用來測試攝像頭是否加載成功的小程序。這樣就可以不用cat/dev/video0>1.jpg來測試攝像頭是否正常。cat命令一運(yùn)行,就源源不斷地采集jpeg流。但是采到的圖片只能顯示第一個(gè)jpeg頭和jpeg尾之間的數(shù)據(jù)。mouse_capture僅僅獲得一X完整的jpeg??梢詮摹?hh./cgi-bin/topic.cgi?forum=1&topic=247&start=144&show=0〕處下載參考。現(xiàn)將主要函數(shù)的功能介紹如下:staticintGetVideoPict(structvdIn*vd);//獲取圖片屬性信息。staticintSetVideoPict(structvdIn*vd);//設(shè)置圖片屬性。staticintisSpcaChip(constchar*BridgeName);//測試芯片類型staticintGetStreamId(constchar*BridgeName);//測試輸出數(shù)據(jù)的格式staticintGetDepth(intformat);//獲取顏色深度。voidexit_fatal(char*messages);//錯(cuò)誤顯示。intinit_videoIn(structvdIn*vd,char*device,intwidth,intheight,intformat,intgrabmethod);//初始化設(shè)備。intconvertframe(unsignedchar*dst,unsignedchar*src,intwidth,intheight,intformatIn,intsize);//把共享緩沖區(qū)中的數(shù)據(jù)放到一個(gè)變量中,通知系統(tǒng)已獲得一幀。intv4lGrab(structvdIn*vd,char*filename);//從攝像頭采集圖片。intclose_v4l(structvdIn*vd);//關(guān)閉攝像頭。intget_jpegsize(unsignedchar*buf,intinsize);//獲取jpeg圖片大小。關(guān)鍵代碼分析:(server.c)#include<stdlib.h>#include<stdio.h>#include<string.h>#include"spcav4l.h"structvdInvideoIn;intmain(intargc,char*argv[]){charvideodevice[]="/dev/video0";charjpegfile[]="/var/tmp/1.jpg";//采集圖片到本地目錄intgrabmethod=0;//修改為0才可以記錄圖片到/var/tmp/1.jpgintformat=VIDEO_PALETTE_JPEG;intwidth=352;intheight=288;memset(&videoIn,0,sizeof(structvdIn));if(init_videoIn(&videoIn,videodevice,width,height,format,grabmethod)==0){while(1){v4lGrab(&videoIn,jpegfile);if(grabmethod==1)printf("youusemmapmethod!\n");elseif(grabmethod==0)printf("youusereadmethod!\n");}printf("youhavegetapicturein%s\n",jpegfile);}elseprintf("can'topenyourcamera!\n");close_v4l(&videoIn);return0;}可將該文件拷貝到pc上進(jìn)展查看這里關(guān)于應(yīng)用程序的編譯方法,就不再多講了,只需要make重新編譯一下就好!下面我們再介紹如何講采集圖片直接顯示到本地LCD,我們會用到j(luò)peg的類庫到/var/tmp/看有沒有圖片,如沒有運(yùn)行攝像頭程序看看攝像頭是否正常工作。在arm機(jī)在能看到的的位置上打上兩個(gè)驅(qū)動?!沧⒁忭樞颉砳nsmodvideodev.o〔如果此從別處考過去的,它是白色,那要寫:chmod+xvideodev.o將此參加此工程,此時(shí)為黃色〕insmodspca5xx.o即:后運(yùn)行看到圖像。如自己make需要修改Makefile 文件:即:〔或者先查內(nèi)核地址:然后修改Makefile的LDFLAG:如圖:〕編譯JPEG庫環(huán)境〔注意仔細(xì)配,否那么makeinstall之后,負(fù)責(zé)圖形圖像的庫不能用,我圖形可以用,但圖像不能用。就是用X工的〕一、實(shí)驗(yàn)步驟1、獲取jpeg-6b源代碼直接從我們提供的配套光盤中獲取。得到〔#完成〕后,運(yùn)行如下命令解壓:cd/opt/develop/lyj/up_apthome/webcamtarjxvf此時(shí),在當(dāng)前目錄下就包含了我們所需要的源碼jpeg-6b目錄 2、配置jpeg庫 從光盤獲取的源碼解壓之后,在jpeg-6b中會有一個(gè)build.sh文件[rootvm-devjpeg-6b]#catbuild.sh./configure--prefix=/mnt/nfs/jpeg4arm--exec-prefix=/mnt/nfs/jpeg4arm--enable-shared--enable-static[rootvm-devjpeg-6b]#./build.sh下面分別介紹這幾個(gè)參數(shù)的作用:???

--prefix=/mnt/nfs/jpeg4arm

:

執(zhí)行make

install

后,會將與體系無關(guān)的文件拷貝到此目錄下,具體如下:

/mnt/nfs/jpeg4arm.....................................

|

+---include........................................

|

---jconfig.h

|

---jerror.h

|

---jmorecfg.h

|

---jpeglib.h

+---man............................................

|

+---man1.......................................

|

---cjeg.1

|

---djpeg.1

|

---jpegtran.1

|

---rdjpg.1

|

---wrjpg.1

--exec-prefix=/mnt/nfs/jpeg4arm

:

執(zhí)行make

install

后,會將與體系無關(guān)的文件拷貝到此目錄下,即將一些可執(zhí)行程序、動態(tài)庫和靜態(tài)庫拷貝到此目錄的相應(yīng)目錄下,具體如下:

/mnt/nfs/jpeg4arm........................................

|

+---bin............................................

|

---cjeg

|

---djpeg

|

---jpegtran

|

---rdjpg

|

---wrjpg

+---lib...........................................

|

---libjpeg.la

|

---libjpeg.so

|

---libjpeg.so.62

|

---libjpeg.so.62.0.0

--enable-shared

:

用GNU

libtool編譯成動態(tài)庫

。下面分別對應(yīng)有無此參數(shù)所生成的Makefile的比擬:

-------------------------------------------------------------------------------------------

無--enable-shared參數(shù)

|

有--enable-shared參數(shù)

-------------------------------------------------------------------------------------------

LIBTOOL

=

|

LIBTOOL

=

./libtool

-------------------------------------------------------------------------------------------

O

=

o

A

=

a

|

O

=

lo

A

=

la

-------------------------------------------------------------------------------------------

LN=

$(CC)

|

LN=

$(LIBTOOL)

--mode=link

$(CC)

-------------------------------------------------------------------------------------------

INSTALL_PROGRAM=

${INSTALL}

|

INSTALL_PROGRAM=

$(LIBTOOL)

--mode=install

${INSTALL}

INSTALL_LIB=

${INSTALL}

-m

644

|

INSTALL_LIB=

$(LIBTOOL)

--mode=install

${INSTALL}

-------------------------------------------------------------------------------------------------------

無參數(shù):

#

.c.lo:

#

$(LIBTOOL)

--mode=pile

$(CC)

$(CFLAGS)

-c

$(srcdir)/$*.c

有參數(shù):

.c.lo:

$(LIBTOOL)

--mode=pile

$(CC)

$(CFLAGS)

-c

$(srcdir)/$*.c

----------------------------------------------------------------------------------------------------------

無參數(shù):

install:

cjpeg

djpeg

jpegtran

rdjpg

wrjpg

有參數(shù):

install:

cjpeg

djpeg

jpegtran

rdjpg

wrjpg

install-lib

-----------------------------------------------------------------------------------------------------------3、修改生成的Makefile文件

#

The

name

of

your

C

piler:

CC=

gcc

該成

CC=/usr/local/arm-linux/bin/arm-linux-gcc

(根據(jù)你自己穿插編譯器的位置修改)〔需要安裝arm-linux-gcc,〕

#

library

(.a)

file

creation

mand

AR=

ar

rc

該成

AR=

/usr/local/arm-linux/arm-linux/bin/ar

rc

(同上)

#

second

step

in

.a

creation

(use

"touch"

if

not

needed)

AR2=

ranlib

該成

AR2=

/usr/local/arm-linux/arm-linux/bin/ranlib

(同上)4、編譯安裝[rootvm-devjpeg-6b]#makeclean[rootvm-devjpeg-6b]#make要手動建立以下文件并在man下要建一個(gè)man1文件夾[rootvm-devjpeg-6b]#makeinstall[rootvm-devjpeg-6b]#

這樣JPEG庫就穿插編譯成功了,相應(yīng)的庫和頭文件都/mnt/nfs/jpeg4arm/下了![rootvm-devjpeg-6b]#ls/mnt/nfs/jpeg4arm/binincludelibman[rootvm-devjpeg-6b]#關(guān)于jpeg庫的使用,在源代碼中example.c文件中又詳細(xì)的說明,也可以參考這篇文章了。22/showart.php?id=1081947獲取圖像數(shù)據(jù)到LCD設(shè)備〔我就是用文件〕實(shí)驗(yàn)步驟1、從光盤獲取源代碼,解壓縮進(jìn)入/opt/develop/lyj/up_apthome/webcam目錄[roo[rootvm-devwebcam]#lsjpegshow[rootvm-devwebcam]#解壓后的目錄在jpegshow文件夾下2、代碼分析修改Makefile使include和lib指向自己的路徑?!埠隗w文字要根據(jù)自己include,lib路徑修改〕[rootvm-devjpegshow]#catMakefileall:main.oarm-linux-gcc-I/mnt/nfs/jpeg4arm/include-L/mnt/nfs/jpeg4arm/lib-I/home/oyx/porting/curl-l-omyjpegmain.ofb.ojpeg.ogetFile.o-ljpegmain.o:fb.ojpeg.oarm-linux-gcc-I/mnt/nfs/jpeg4arm/include-L/mnt/nfs/jpeg4arm/lib-cmain.cfb.o:fb.cfb.harm-linux-gcc-cfb.cjpeg.o:jpeg.cjpeg.hgetFile.oarm-linux-gcc-I/mnt/nfs/jpeg4arm/include-L/mnt/nfs/jpeg4arm/lib-cjpeg.cgetFile.o:getFile.cgetFile.harm-linux-gcc-I/home/oyx/porting/curl-clean:rm-rf*.omyjpeg[rootvm-devjpegshow]#這里使用gcc編譯的時(shí)候,要使用-I指向前兩個(gè)實(shí)驗(yàn)編譯的代碼安裝的inlcude目錄使用-L執(zhí)行前兩個(gè)實(shí)驗(yàn)編譯的代碼安裝的lib目錄 并使用–l表示使用的是哪個(gè)庫 分析mian.c[rootvm-devjpegshow]#catmain.c#include"fb.h"#include"jpeg.h"intmain(){unsignedchar*fb_mem;unsignedcharbuffer[1000000];//創(chuàng)立一個(gè)存放數(shù)據(jù)的bufferinti,j,fb;unsignedchar*data;fb=fb_open();//獲取framebuffer的設(shè)備句柄fb_mem=fb_mmap(fb);//獲取指向frambuffer的指針while(1){//數(shù)據(jù)通過網(wǎng)絡(luò)獲取之后,先經(jīng)過jpeg解碼,然后存放在buffer中if(!read_JPEG_file("/var/tmp/1.jpg",buffer,640,480)){printf("mainreturnerr");return0;}}return1;}[rootvm-devjpegshow]#3、重點(diǎn)分析read_JPEG_file()函數(shù)(篇幅原因,去掉了一些注釋和調(diào)試信息)(不需要改)//jpeg.c文件中intread_JPEG_file(char*filename,unsignedchar*mem,intwidth,intheight){inti,j,line,output_width;unsignedshort*fb_mem=(unsignedshort*)mem;charindata[1000000];intnSize;intwidth_offset;intheight_offset;/*ThisstructcontainstheJPEGdepressionparametersandpointersto*workingspace(whichisallocatedasneededbytheJPEGlibrary).*/structjpeg_depress_structcinfo;/*WeuseourprivateextensionJPEGerrorhandler.*NotethatthisstructmustliveaslongasthemainJPEGparameter*struct,toavoiddangling-pointerproblems.*/structmy_error_mgrjerr;/*Morestuff*/FILE*infile;/*sourcefile*/JSAMPARRAYbuffer;/*Outputrowbuffer*/introw_stride;/*physicalrowwidthinoutputbuffer*//*Inthisexamplewewanttoopentheinputfilebeforedoinganythingelse,*sothatthesetjmp()errorrecoverybelowcanassumethefileisopen.*VERYIMPORTANT:use"b"optiontofopen()ifyouareonamachinethat*requiresitinordertoreadbinaryfiles.*//*Step1:allocateandinitializeJPEGdepressionobject*///1、分配并初始化一個(gè)JPEG解壓對象/*WesetupthenormalJPEGerrorroutines,thenoverrideerror_exit.*/cinfo.err=jpeg_std_error(&jerr.pub);jerr.pub.error_exit=my_error_exit;/*Establishthesetjmpreturncontextformy_error_exittouse.*/if(setjmp(jerr.setjmp_buffer)){/*Ifwegethere,theJPEGcodehassignaledanerror.*WeneedtocleanuptheJPEGobject,closetheinputfile,andreturn.*/jpeg_destroy_depress(&cinfo);return0;}/*NowwecaninitializetheJPEGdepressionobject.*/jpeg_create_depress(&cinfo);/*Step2:specifydatasource(eg,afile)*///2、指定要解壓縮的圖像文件:jpeg_stdio_src(&cinfo,infile);/*Step3:readfileparameterswithjpeg_read_header()*///3、調(diào)用jpeg_read_header()獲取圖像信息:(void)jpeg_read_header(&cinfo,TRUE);/*Wecanignorethereturnvaluefromjpeg_read_headersince*(a)suspensionisnotpossiblewiththestdiodatasource,and*(b)wepassedTRUEtorejectatables-onlyJPEGfileasanerror.*Seelibjpeg.docformoreinfo.*//*Step4:setparametersfordepression*///4、這是一個(gè)可選步驟,用于設(shè)置JPEG解壓縮對象cinfo的一些參數(shù)/*Inthisexample,wedon'tneedtochangeanyofthedefaultssetby*jpeg_read_header(),sowedonothinghere.*//*Step5:Startdepressor*///5、調(diào)用jpeg_start_depress()開場解壓過程(void)jpeg_start_depress(&cinfo);/*Wecanignorethereturnvaluesincesuspensionisnotpossible*withthestdiodatasource.*//*Wemayneedtodosomesetupofourownatthispointbeforereading*thedata.Afterjpeg_start_depress()wehavethecorrectscaled*outputimagedimensionsavailable,aswellastheoutputcolormap*ifweaskedforcolorquantization.*Inthisexample,weneedtomakeanoutputworkbufferoftherightsize.*//*JSAMPLEsperrowinoutputbuffer*/row_stride=cinfo.output_width*cinfo.output_ponents;//這是圖像輸出的寬度output_width=cinfo.output_width;/*Makeaone-row-highsamplearraythatwillgoawaywhendonewithimage*/buffer=(*cinfo.mem->alloc_sarray)((j_mon_ptr)&cinfo,JPOOL_IMAGE,row_stride,1);/*Step6:while(scanlinesremaintoberead)*//*jpeg_read_scanlines(...);*///6、讀取一行或者多行掃描線數(shù)據(jù)并處理,通常的代碼是這樣的:/*Hereweusethelibrary'sstatevariablecinfo.output_scanlineasthe*loopcounter,sothatwedon'thavetokeeptrackourselves.*/j=0;width_offset=171;height_offset=91;fb_mem+=height_offset*width;while(cinfo.output_scanline<cinfo.output_height){/*jpeg_read_scanlinesexpectsanarrayofpointerstoscanlines.*Herethearrayisonlyoneelementlong,butyoucouldaskfor*morethanonescanlineatatimeifthat'smoreconvenient.*/(void)jpeg_read_scanlines(&cinfo,buffer,1);/*Assumeput_scanline_someplacewantsapointerandsamplecount.*/#if1intline=cinfo.output_scanline-1;fb_mem+=width_offset;for(i=0;i<cinfo.output_width;i++){//rgb_24_2_565函數(shù)將rgb格式轉(zhuǎn)換為565顯示格式*fb_mem=rgb_24_2_565((unsignedchar)buffer[0][i*3],(unsignedchar)buffer[0][i*3+1],(unsignedchar)buffer[0][i*3+2]);fb_mem++;}if(output_width<=width)fb_mem+=(width-output_width-width_offset);#endif}/*Step7:Finishdepression*///7、調(diào)用jpeg_finish_depress()完成解壓過程:(void)jpeg_finish_depress(&cinfo);/*Wecanignorethereturnvaluesincesuspensionisnotpossible*withthestdiodatasource.*//*Step8:ReleaseJPEGdepressionobject*///8、調(diào)用jpeg_destroy_depress()釋放JPEG解壓對象cinfo/*Thisisanimportantstepsinceitwillreleaseagooddealofmemory.*/jpeg_destroy_depress(&cinfo);/*Afterfinish_depress,wecanclosetheinputfile.*HerewepostponeituntilafternomoreJPEGerrorsarepossible,*soastosimplifythesetjmperrorlogicabove.(Actually,Idon't*thinkthatjpeg_destroycandoanerrorexit,butwhyassumeanything...)*///fclose(infile);/*Atthispointyoumaywanttochecktoseewhetheranycorrupt-data*warningsoccurred(testwhetherjerr.pub.num_warningsisnonzero).*//*Andwe'redone!*/return1;}4、下載測試直接在目錄下編譯[rootvm-devjpegshow]#makeclean;make[rootvm-devjpegshow]#lsexample.cfb.cfb.hfb.ogetFile.cgetFile.hgetFile.ojpeg.cjpeg.hjpeg.omain.cmain.oMakefileMakefile.bakmyjpeg[rootvm-devjpegshow]#生成文件myjpeg下載到開發(fā)板上運(yùn)行注意該文件依賴的兩個(gè)庫的動態(tài)庫文件一定要一并下載到開發(fā)板上!直接在開發(fā)板上執(zhí)行myjpeg

就可以了,如不行打入:exportLD_LIBRARY_PATH=$PWD[/mnt/yaffs/webcam]lsmyjpeg[/mnt/yaffs/webcam]./myjpeg在屏幕上輸出的就是剛剛看到的畫面!libjpeg實(shí)現(xiàn)內(nèi)存內(nèi)位圖的壓縮及解壓縮實(shí)驗(yàn)步驟在前一個(gè)的根底上進(jìn)展本實(shí)驗(yàn)。libjpeg是利用FILE進(jìn)展存取圖像數(shù)據(jù)的,下面分析一下libjpeg是怎樣利用FILE進(jìn)展存取圖像數(shù)據(jù)的,然后用內(nèi)存拷貝的方式替換掉所有的文件操作〔I/O〕,也就實(shí)現(xiàn)了內(nèi)存中進(jìn)展圖像壓縮和解壓縮的目標(biāo)。分析壓縮圖像時(shí)libjpeg如何利用FILE進(jìn)展存儲數(shù)據(jù)。1).對outfile變量的修改先查看在進(jìn)展圖像壓縮時(shí),所調(diào)用的跟文件有關(guān)系的函數(shù):jpeg_stdio_dest(j_pres_ptrcinfo,FILE*outfile)〔jdatadst.c文件第130行〕:1GLOBAL(void)2jpeg_stdio_dest(j_press_ptrcinfo,FILE*outfile)3{4my_dest_ptrdest;5/*ThedestinationobjectismadepermanentsothatmultipleJPEGimages6*canbewrittentothesamefilewithoutre-executingjpeg_stdio_dest.7*Thismakesitdangeroustousethismanagerandadifferentdestination8*managerseriallywiththesameJPEGobject,becausetheirprivateobject9*sizesmaybedifferent.Caveatprogrammer.10*/11if(cinfo->dest==NULL){/*firsttimeforthisJPEGobject?*/12cinfo->dest=(structjpeg_destination_mgr*)13(*cinfo->mem->alloc_small)((j_mon_ptr)cinfo,JPOOL_PERMANENT,14SIZEOF(my_destination_mgr));15}16dest=(my_dest_ptr)cinfo->dest;17dest->pub.init_destination=init_destination;18dest->pub.empty_output_buffer=empty_output_buffer;19dest->pub.term_destination=term_destination;20dest->outfile=outfile;21}在第20行,函數(shù)將FILE類型的指針賦值給了dest->outfile,很顯然,以后對文件的操作,就轉(zhuǎn)向了對dest->outfile的操作,我們只要找到所有引用outfile的函數(shù),就可以知道libjpeg是怎樣壓縮圖像到文件的,因此,我們繼續(xù)搜outfile〔[rootBCjpeg-6b]#grep-r"outfile".〕,搜索結(jié)果如下:?Findall"outfile",Subfolders,FindResults1,"EntireSolution"E:\VS2005\libjpeg\libjpeg\jpeglib.h(910):EXTERN(void)jpeg_stdio_destJPP((j_press_ptrcinfo,FILE*outfile));E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(28):FILE*outfile;/*targetstream*/E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(85):if(JFWRITE(dest->outfile,dest->buffer,OUTPUT_BUF_SIZE)!=E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(113):if(JFWRITE(dest->outfile,dest->buffer,datacount)!=datacount)E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(116):fflush(dest->outfile);E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(118):if(ferror(dest->outfile))E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(130):jpeg_stdio_dest(j_press_ptrcinfo,FILE*outfile)E:\VS2005\libjpeg\libjpeg\jdatadst.cpp(150):dest->outfile=outfile;Matchinglines:8Matchingfiles:2Totalfilessearched:57可以看到,共有8處引用了outfile變量,第一處為函數(shù)聲明,第二處為變量聲明,第三、四、五、六處為文件操作,第七處和第八處已經(jīng)見過了,現(xiàn)在只需要將這八處修改就

可以實(shí)現(xiàn)目標(biāo)了。具體修改步驟如下:a、在jpeglib.h文件中將EXTERN(void)jpeg_stdio_destJPP((j_press_ptrcinfo,FILE*outfile));改為EXTERN(void)jpeg_stdio_destJPP((j_press_ptr

cinfo,char*outdata));b、在jdatadst.c文件第81行empty_output_buffer(j_press_ptrcinfo)函數(shù)中,將JFWRITE(dest->outfile,dest->buffer,OUTPUT_BUF_SIZE)改為memcpy(dest->outdata,dest->buffer,OUTPUT_BUF_SIZE)c、在jdatadst.c文件第113行term_destination(j_press_ptrcinfo)函數(shù)中,a).將JFWRITE(dest->outfile,dest->buffer,datacount) 改為:memcpy(dest->outdata,dest->buffer,datacount);b).刪除fflush(dest->outfile);和if(ferror(dest->outfile))及相關(guān)的其它語句。c).將jpeg_stdio_dest(j_press_ptrcinfo,FILE*outfile) 改為:jpeg_stdio_dest(j_press_ptrcinfo,char*outdata)d).將dest->outfile=outfile;改為dest->outdata=outdata;2).為內(nèi)存區(qū)域提供偏移量〔每次追加圖像數(shù)據(jù)后,偏移量指向當(dāng)前的位置〕由于只有到壓縮完才能知道圖像壓縮完后的數(shù)據(jù)量大小,我們還需要一個(gè)指示圖像數(shù)據(jù)大小的變量。具體修改步驟如下:a、將這兩個(gè)變量添加到outdata后面,跟outdata一樣,作為dest的成員變量,在jdatadst.c文件的構(gòu)造體定義中添加兩個(gè)變量,修改后如下: typedefstruct{ structjpeg_destination_mgrpub;/*publicfields*/ char*outdata;/*targetstream*/ int*pSize;//新加變量,該指針為調(diào)用者提供,壓縮完后返回圖像大小 intnOutOffset;//新加變量 JOCTET*buffer;/*startofbuffer*/ }my_destination_mgr;b、通過jpeg_stdio_dest函數(shù)提供pSize指針,并在jpeg_stdio_dest的實(shí)現(xiàn)函數(shù)里對新添加的變量進(jìn)展初始化,更改后的代碼如下: GLOBAL(void) jpeg_stdio_dest(j_press_ptrcinfo,char*outdata,int*pSize) { my_dest_ptrdest; /*ThedestinationobjectismadepermanentsothatmultipleJPEGimages *canbewrittentothesamefilewithoutre-executingjpeg_stdio_dest. *Thismakesitdangeroustousethismanagerandadifferentdestination *managerseriallywiththesameJPEGobject,becausetheirprivateobject *sizesmaybedifferent.Caveatprogrammer. */ if(cinfo->dest==NULL){/*firsttimeforthisJPEGobject?*/ cinfo->dest=(structjpeg_destination_mgr*) (*cinfo->mem->alloc_small)((j_mon_ptr)cinfo,JPOOL_PERMANENT, SIZEOF(my_destination_mgr)); } dest=(my_dest_ptr)cinfo->dest; dest->pub.init_destination=init_destination; dest->pub.empty_output_buffer=empty_output_buffer; dest->pub.term_destination=term_destination; /*修改正的代碼*/ dest->outdata=outdata; dest->nOutOffset=0; dest->pSize=pSize; *(dest->pSize)=0; }c、在jpeglib.h文件中改寫聲明函數(shù) EXTERN(void)jpeg_stdio_destJPP((j_press_ptrcinfo,char*outdata,int*pSize));

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論