女人被狂躁到高潮视频免费无遮挡,内射人妻骚骚骚,免费人成小说在线观看网站,九九影院午夜理论片少妇,免费av永久免费网址

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀]說明:1、本文所提及的攝像頭不是zc0301p,使用的API不是V4L,顯示所使用的上位機(jī)不是QT,特此說明。2、UVC只是一個驅(qū)動,如果它能成功驅(qū)動攝像頭,會在/dev目錄下出現(xiàn)video(或vid

說明:

1、本文所提及的攝像頭不是zc0301p,使用的API不是V4L,顯示所使用的上位機(jī)不是QT,特此說明。

2、UVC只是一個驅(qū)動,如果它能成功驅(qū)動攝像頭,會在/dev目錄下出現(xiàn)video(或video0、video1等等)。這樣,就可以使用Linux提供(準(zhǔn)確說不是Linux提供,具體的百度吧)的一套API,即V4L2來訪問攝像頭了?!笆褂谩笔侵肝覀儗懙牟杉瘮?shù)據(jù)的程序,而不是指“攝像頭驅(qū)動程序”。——驅(qū)動程序不是那么簡單就能寫出來的。

3、本文未涉及大量的如VIDIOC_S_FMT等命令字,也不涉及V4L2采集模型,一來網(wǎng)絡(luò)上很多這種說明(原創(chuàng)的,轉(zhuǎn)載的),本文不想偷竊他人的成果;二來諸君如果看V4L2手冊、看源代碼的話,會學(xué)得更多,——如果肯下心思的話。

4、源代碼中本來就沒有中文注釋,抄于此,也不再添加中文了。

5、本文所述的程序是根據(jù)開源項目luvcview寫的,理所當(dāng)然的,本文的程序也會公開源代碼,使用條款為GPL。至于這個程序是好是壞,就由眾人去評說了。

?

1、驅(qū)動——UVC

在Linux中,除了SPCA和GSPCA這類經(jīng)典的USB攝像頭驅(qū)動外,還有一種,即Linux UVC,全稱為Linux USB Video Class,從Class這個詞可以看出,UVC是代碼某一類的視頻設(shè)備驅(qū)動,官網(wǎng)上的說法包括了webcams, digital camcorders, analog video converters, analog 以及 digital television tuners等等。從2.6.26版本開始,Linux UVC驅(qū)動就納入到內(nèi)核中,不需要手動下載。但是需要自己手動配置內(nèi)核,才可使用UVC。

具體的測試示例,可以在這個網(wǎng)址上找到:

http://blog.chinaunix.net/u1/58951/showart_2199263.html

2、采集——V4L2

在Linux下,視頻數(shù)據(jù)的采集有兩套API,分別為V4L和V4L2。是Video For Linux的兩個版本。其實在Windows下也有一套API,名為Video For Windows,即VFW,具體怎么使用,我沒研究過,不過,按Windows的習(xí)俗,應(yīng)該不難。

本文所用的API為V4L2,雖然它的第一個版本也可以使用,但是為了表明筆者與時俱進(jìn)的精神,決心使用第二個版本。這個版本無外就下面三點:

1、打開或關(guān)閉攝像頭設(shè)備都是調(diào)用POSIX標(biāo)準(zhǔn)的open或close,很簡單;

2、最重要、最核心的是使用ioctl調(diào)用,通過不同的控制命令來控制攝像頭,如開始捕獲、停止捕獲、獲取攝像頭信息,等等。如果研究過Linux驅(qū)動的話,對ioctl應(yīng)該不陌生。

3、一些結(jié)構(gòu)體,如保存攝像頭信息的,捕獲攝像頭數(shù)據(jù)的緩沖區(qū)的,等等。

攝像頭的信息保存于自定義的結(jié)構(gòu)體video_info中。如下:

struct video_info

{

?int camfd; /**< camera file descriptor */

?struct v4l2_capability cap;

?struct v4l2_format fmt;

?struct v4l2_requestbuffers rb;

?struct v4l2_buffer buf;

?enum v4l2_buf_type type;

?void* mem[NB_BUFFER]; /**< main buffers */

?uint8* tmp_buffer; /**< for MJPEG */

?uint8* frame_buffer; /**< one frame buffer here */

?uint32 frame_size_in;

?

?uint32 format; /**< eg YUYV or MJPEG,etc. */

?int width;

?int height;

?int is_streaming; /**< start capture */

?int is_quit;

#ifdef DEBUG

?enum v4l2_field field;

?uint32 bytes_per_line;

?uint32 size_image;

?enum v4l2_colorspace color_space;

?uint32 priv;

#endif

?

};

在開始采集數(shù)據(jù)前,需要先看一下攝像頭的信息,下面三個函數(shù)完成的功能分別為得到攝像頭的屬性(capability),得到攝像頭的格式(format),設(shè)置攝像頭的格式。屬性包括了驅(qū)動信息,總線信息,是否支持流捕獲等等;格式包括了攝像頭數(shù)據(jù)格式(如MJPEG、YUYV等等),圖像的寬、高等等。

int v4l2_get_capability(struct video_info* vd_info);

int v4l2_get_format(struct video_info* vd_info);

int v4l2_set_foramt(struct video_info* vd_info,

?uint32 width, uint32 height,uint32 format);

圖1為在FC系統(tǒng)和ARM開發(fā)板上得到的攝像頭信息。從圖中可以清楚看到上述所講的各種信息。至于最后一行的錯誤提示,是由于我調(diào)用v4l2_set_foramt將攝像頭數(shù)據(jù)格式設(shè)置為YUYV出錯了,即它不支持YUYV格式。然而,當(dāng)我使用這個程序在紅旗操作系統(tǒng)下測試時,結(jié)果又不同了,它是YUYV格式了!我將它設(shè)置為MJPEG格式,同樣不行,所以圖2最后同樣出錯。(那時正興高采烈地做畢業(yè)設(shè)計,這個問題讓我足足郁悶了好幾天。我想不通是什么原因)

?

圖1 攝像頭信息

?

??

圖2 又一個信息

?

?下面簡單講一下程序片段,具體的程序,參見附錄中。

(1)、分配內(nèi)存

switch (vd_info->format) /**< format will be also ok */

{

case V4L2_PIX_FMT_MJPEG:

vd_info->tmp_buffer =

(uint8 *)calloc(1, (size_t)vd_info->frame_size_in);

if (vd_info->tmp_buffer == NULL)

error_out("unable alloc tmp_buffer");

vd_info->frame_buffer =

(uint8 *)calloc(1, (size_t)vd_info->width * (vd_info->height+8) * 2);

if (vd_info->frame_buffer == NULL)

error_out("unable alloc frame_buffer");

break;

case V4L2_PIX_FMT_YUYV:

vd_info->frame_buffer =

(uint8 *)calloc(1,(size_t)vd_info->frame_size_in);

if (vd_info->frame_buffer == NULL)

error_out("unable alloc frame_buffer");

break;

default:

msg_out("error!n");

return -1;

break;

}

因為YUYV是一種原始數(shù)據(jù),可以直接顯示,不需要編解碼,而MJPEG格式的,需要解碼,所以分要分配兩個緩沖區(qū)。

(2)、打開,O_NONBLOCK是以非阻塞方式打開。

vd_info->camfd = open(device, O_RDWR /*| O_NONBLOCK*/, 0);

if (vd_info->camfd < 0)

error_out("can not open the device");

(3)、查詢

if (-1 == ioctl(vd_info->camfd, VIDIOC_QUERYCAP, &vd_info->cap))

error_out("query camera failed");

if (0 == (vd_info->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))

{

debug_msg("video capture not supported.n");

return -1;

}

(4)、設(shè)置格式

memset(&vd_info->fmt, 0, sizeof(struct v4l2_format));

vd_info->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

vd_info->fmt.fmt.pix.width = width;

vd_info->fmt.fmt.pix.height = height;

vd_info->fmt.fmt.pix.field =V4L2_FIELD_ANY;

vd_info->fmt.fmt.pix.pixelformat = format;

if (-1 == ioctl(vd_info->camfd, VIDIOC_S_FMT, &vd_info->fmt))

error_out("unable to set format ");

(5)、查詢緩沖區(qū)、映射到用戶空間內(nèi)存

memset(&vd_info->rb, 0, sizeof(struct v4l2_requestbuffers));

vd_info->rb.count = NB_BUFFER; /**< 4 buffers */

vd_info->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

vd_info->rb.memory = V4L2_MEMORY_MMAP;

if (-1 == ioctl(vd_info->camfd, VIDIOC_REQBUFS, &vd_info->rb))

error_out("unable to allocte buffers");

?

/* map the buffers(4 buffer) */

for (i = 0; i < NB_BUFFER; i++)

{

memset(&vd_info->buf, 0, sizeof(struct v4l2_buffer));

vd_info->buf.index = i;

vd_info->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

vd_info->buf.memory = V4L2_MEMORY_MMAP;

if (-1 == ioctl(vd_info->camfd, VIDIOC_QUERYBUF, &vd_info->buf))

error_out("unable to query buffer");

/* map it, 0 means anywhere */

vd_info->mem[i] =

mmap(0, vd_info->buf.length, PROT_READ, MAP_SHARED,

vd_info->camfd, vd_info->buf.m.offset);

/* MAP_FAILED = (void *)-1 */

if (MAP_FAILED == vd_info->mem[i])

error_out("unable to map buffer");

}

(6)、進(jìn)入隊列

/* queue the buffers */

for (i = 0; i < NB_BUFFER; i++)

{

memset(&vd_info->buf, 0, sizeof(struct v4l2_buffer));

vd_info->buf.index = i;

vd_info->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

vd_info->buf.memory = V4L2_MEMORY_MMAP;

if (-1 == ioctl(vd_info->camfd, VIDIOC_QBUF, &vd_info->buf))

error_out("unable to queue the buffers");

}

(7)、開始捕獲(發(fā)出捕獲信號)

vd_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

?

if (-1 == ioctl(vd_info->camfd, VIDIOC_STREAMON, &vd_info->type))

error_out("unable to start capture");

vd_info->is_streaming = 1;

debug_msg("stream on OK!!n");

debug_msg("===============================nn");

(8)、采集(從緩沖區(qū)隊列中取出數(shù)據(jù),再將數(shù)據(jù)的內(nèi)存復(fù)制另一內(nèi)存區(qū))

static int count = 0;

if (!vd_info->is_streaming) /**< if stream is off, start it */

{

if (v4l2_on(vd_info)) /**< failed */

goto err;

}

memset(&vd_info->buf, 0, sizeof(struct v4l2_buffer));

vd_info->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

vd_info->buf.memory = V4L2_MEMORY_MMAP;

/* get data from buffers */

if (-1 == ioctl(vd_info->camfd, VIDIOC_DQBUF, &vd_info->buf))

{

msg_out("unable to dequeue buffern");

goto err;

}

switch (vd_info->format)

{

case V4L2_PIX_FMT_MJPEG:

if (vd_info->buf.bytesused <= HEADFRAME1)

{

msg_out("ignore empty frame...n");

return 0;

}

/* we can save tmp_buff to a jpg file,just write it! */

memcpy(vd_info->tmp_buffer, vd_info->mem[vd_info->buf.index],

vd_info->buf.bytesused);

?

/* here decode MJPEG,so we can dispaly it */

if (jpeg_decode(&vd_info->frame_buffer, vd_info->tmp_buffer,

&vd_info->width, &vd_info->height) < 0 )

{

msg_out("decode jpeg errorn");

goto err;

}

break;

case V4L2_PIX_FMT_YUYV:

if (vd_info->buf.bytesused > vd_info->frame_size_in)

memcpy(vd_info->frame_buffer, vd_info->mem[vd_info->buf.index],

(size_t)vd_info->frame_size_in);

else

memcpy(vd_info->frame_buffer, vd_info->mem[vd_info->buf.index],

(size_t)vd_info->buf.bytesused);

break;

default:

goto err;

break;

}

?

/* here you can process the frame! */

v4l2_process(vd_info);

/* queue buffer again */

if (-1 == ioctl(vd_info->camfd, VIDIOC_QBUF, &vd_info->buf))

{

fprintf(stderr,"requeue errorn");

goto err;

}

?

debug_msg("frame:%dn", count++);

debug_msg("frame size in: %d KBn", vd_info->frame_size_in>>10);

?

return 0;

err:

vd_info->is_quit = 0;

return -1;

(9)、停止捕獲(發(fā)送停止信號)

vd_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (-1 == ioctl(vd_info->camfd, VIDIOC_STREAMOFF, &vd_info->type))

error_out("unable to stop capture");

vd_info->is_streaming = 0;

debug_msg("stream off OK!n");

debug_msg("===============================nn");

(10)、關(guān)閉設(shè)備(釋放內(nèi)存、關(guān)閉設(shè)備)

uint16 i = 0;

if (vd_info->is_streaming) /**< stop if it is still capturing */

v4l2_off(vd_info);

?

if (vd_info->frame_buffer)

free(vd_info->frame_buffer);

if (vd_info->tmp_buffer)

free(vd_info->tmp_buffer);

vd_info->frame_buffer = NULL;

/* it is a good thing to unmap! */

for (i = 0; i < NB_BUFFER; i++)

{

if (-1 == munmap(vd_info->mem[i], vd_info->buf.length))

error_out("munmap");

}

?

close(vd_info->camfd);

debug_msg("close OK!n");

3、顯示——SDL

SDL是Simple DirectMedia Layer的簡稱,是一個自由的跨平臺的多媒體開發(fā)包,適用于游戲、游戲SDK、演示軟件、模擬器、MPEG播放器和其他應(yīng)用軟件。本文將它大材小用,用于顯示采集得到的視頻數(shù)據(jù)。

顯示的代碼片段如下:

SDL_Surface *pscreen = NULL;

SDL_Overlay *overlay = NULL;

SDL_Rect drect;

SDL_Event sdlevent;

SDL_mutex *affmutex = NULL;

unsigned char frmrate;

unsigned char *p = NULL;

uint32 currtime;

uint32 lasttime;

char* status = NULL;

?

/************* Test SDL capabilities ************/

/* memory leak here */

?

if (SDL_Init(SDL_INIT_VIDEO) < 0)

{

fprintf(stderr, "Couldn't initialize SDL: %sn", SDL_GetError());

exit(1);

}

?

/* it need to alloc space! */

vd_info = (struct video_info *) calloc(1, sizeof(struct video_info));

/* init the camera,you can change the last three params!!! */

if (v4l2_init(vd_info, V4L2_PIX_FMT_YUYV, 640, 480) < 0)

return EXIT_FAILURE;

?

pscreen =

SDL_SetVideoMode(vd_info->width, vd_info->height, 0,

SDL_VIDEO_Flags);

?

overlay =

SDL_CreateYUVOverlay(vd_info->width, vd_info->height,

SDL_YUY2_OVERLAY, pscreen);

/* here?? */

p = (unsigned char *) overlay->pixels[0];

drect.x = 0;

drect.y = 0;

drect.w = pscreen->w;

drect.h = pscreen->h;

?

lasttime = SDL_GetTicks();

?

affmutex = SDL_CreateMutex();

/* big loop */

while (vd_info->is_quit)

{

while (SDL_PollEvent(&sdlevent))

{

if (sdlevent.type == SDL_QUIT)

{

vd_info->is_quit = 0;

break;

}

}

currtime = SDL_GetTicks();

if (currtime - lasttime > 0)

{

frmrate = 1000/(currtime - lasttime);

}

lasttime = currtime;

?

if (v4l2_grab(vd_info) < 0)

{

printf("Error grabbing n");

break;

}

?

SDL_LockYUVOverlay(overlay);

/* frame_buffer to p */

memcpy(p, vd_info->frame_buffer,

vd_info->width * (vd_info->height) * 2);

SDL_UnlockYUVOverlay(overlay);

SDL_DisplayYUVOverlay(overlay, &drect); /* dispaly it */

status = (char *)calloc(1, 20*sizeof(char));

sprintf(status, "come on fps:%d",frmrate);

SDL_WM_SetCaption(status, NULL);

?

SDL_Delay(10);

}

?

SDL_DestroyMutex(affmutex);

SDL_FreeYUVOverlay(overlay);

?

v4l2_close(vd_info);

free(status);

free(vd_info);

printf("Clean Up done Quit n");

SDL_Quit();

return 0;

在紅旗操作系統(tǒng)下測試如圖3所示。最上面的即為SDL繪制的窗口(至于它向下調(diào)用什么圖形庫就不用理會了),中間的為控制臺,它不斷輸出采集到的幀數(shù)以及每一幀的大小。最下面的是emacs。

?

圖3 測試示例圖

為了演示emacs的多窗口gdb調(diào)試,現(xiàn)附上幾個圖。算是emacs篇的補充吧。

附圖1中,已經(jīng)加載了可執(zhí)行文件,并設(shè)置了斷點(命令為b main emacs,單步后,中間窗口出現(xiàn)紅點即為斷點處)。

附圖2所示的是正在顯示圖像,左上角即為控制臺,出現(xiàn)的信息同上述截圖一樣。

附圖3為結(jié)束的情形。重新回到gdb等待命令狀態(tài)。

此時的emacs五個窗口中各有自己的功能,從上而下,分別為控制臺、變量、源代碼、幀棧以及斷點。

看到了吧?emacs中調(diào)試不比VC差吧?



本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機(jī)驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機(jī)驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉