mjpg-streamer源碼分析

作者:曹忠明,華清遠見嵌入式學院講師。

mjpg-streamer是一個很好的開源項目,用來做視頻服務器,使用的是v4l2的接口。前面我們說了它的移植過程,但是在某些特定的情況下這個工程不能達到我們的需求,所以我們需要對源碼進行修改,或者直接寫一個自己的視頻服務器。在修改源碼或寫自己的服務器之前我們分析下這個源碼的代碼。

這個代碼裏有三個部分是我們需要掌握的內容,第一是v4l2接口,第二個是socket編程,第三個是多線程編程。

一、 v4l2接口說明

這裏涉及到我們如何從攝像頭中把數據取出來,首先是封裝一個結構體用來描述攝像頭的一些信息,比如採集圖片的寬高,圖片的格式,等等。

struct vdIn {
                int fd;
                char *videodevice;
                char *status;
                char *pictName;
                struct v4l2_capability cap;
                struct v4l2_format fmt;
                struct v4l2_buffer buf;
                struct v4l2_requestbuffers rb;
                void *mem[NB_BUFFER];
                unsigned char *tmpbuffer;
                unsigned char *framebuffer;
                int isstreaming;
                int grabmethod;
                int width;
                int height;
                int fps;
                int formatIn;
                int formatOut;
                 int framesizeIn;
                int signalquit;
                int toggleAvi;
                int getPict;
                int rawFrameCapture;
                /* raw frame capture */
                unsigned int fileCounter;
                /* raw frame stream capture */
                unsigned int rfsFramesWritten;
                unsigned int rfsBytesWritten;
                /* raw stream capture */
                FILE *captureFile;
                unsigned int framesWritten;
                unsigned int bytesWritten;
                int framecount;
                int recordstart;
                int recordtime;
        };

接着是把這個結構體寫入驅動中,用來初始化攝像頭。這個操作通過ioctl完成,涉及到的命令包括VIDIOC_QUERYCAP、VIDIOC_S_FMT、VIDIOC_S_PARM、VIDIOC_REQBUFS,VIDIOC_QUERYBUF,並通過mmap完成內存的映射。

最後我們通過ioct命令完成圖片的讀取,涉及到的命令包括VIDIOC_QBUF和VIDIOC_DQBUF。然後把獲得的數據寫入到文件裏就是圖片,通過網絡傳輸出去連續的圖片就是視頻。

二、 socket編程

在這個程序裏使用的是tcp套接字,每有一個連接請求就創建一個線程單獨和這個請求通信,這裏涉及到的函數包括socket、bind、listen、accept和write。

三、 多線程編程

爲了能同時響應多個客戶端的請求,這裏使用了多線程編程,爲每一個請求建立一個連接,每個連接就是一個線程。這裏涉及到的函數包括pthread_create、pthread_detach、pthread_cond_init、pthread_cond_destroy、pthread_mutex_init、pthread_mutex_destroy。

四、 mjpg-streamer工作流程
mjpg-streamer源碼分析 - 烏雲然 - 香燒間有歇 花落無還時

原文:http://sourceforge.net/apps/mediawiki/mjpg-streamer/index.php?title=Main_Page

 

About the project   

"MJPG-streamer",是用於從webcam攝像頭採集圖像,把他們以流的形式通過基於ip的網絡傳輸到瀏覽器如Firehox,Cambozola,VLC播放器,Windows的移動設備或者其他擁有瀏覽器的移動設備。她可以利用某些webcams的硬件壓縮功能來降低服務器CPU的開銷。她爲嵌入式設備和一些常規服務器提供了一個輕量且更少CPU消耗的方案,因爲她無需爲視頻幀壓縮浪費大量的計算效率(這件事交給硬件了)。例子是:在一個主頻200MHz的路由器上(一個例子是cisco經典無線的linkfs WRT54G路由,其可以運行openWRT(迷你linux系統),主頻200MHz,4MRAM,16Flash),流編碼一個960x720像素的視頻,她可以減少10%的cpu使用。


mjpg-streamer源碼分析 - 烏雲然 - 香燒間有歇 花落無還時

Screenshot of the example webpage


mjpg-streamer源碼分析 - 烏雲然 - 香燒間有歇 花落無還時

Testpicture Frame #1


mjpg-streamer源碼分析 - 烏雲然 - 香燒間有歇 花落無還時

MJPEG-Client written in Lazarus (Free Pascal)


mjpg-streamer源碼分析 - 烏雲然 - 香燒間有歇 花落無還時

VideoLAN can display the stream


About the name

其他一些合適的名字有:MJPEG-streamer或者M-JPEG-streamer,由於在早期的項目中用的就是mpeg-streamer,所以我們決定保持原樣。


What it does
我們需要一個input-plugin來提供圖片。input-plugin負責產生圖片並把這些複製到內存中去。相應的output-plugin則負責把這些內存中的圖片取出來以便後續的處理。最常用的是webserver-output-plugin,他允許將圖片傳送到網絡瀏覽器上。mjpg-streamer充當粘合劑的角色,把這單一的input-plugin和衆多的output-plugin給連在一起,而幾乎所有的工作都交給了這些個插件。


Plugins

Input-Plugins
像其他普通的input-plugin一樣,這些個插件工作是把JPEG格式的圖片拷貝到全局可訪問內存中,接着給等待進程發送信號(告他:我來了!想幹哈幹哈吧)。


input_testpicture.so

這個模塊編譯的時候已經加入了圖片(正如其名:test),就是說你沒攝像頭也能進行測試工作(你編譯的對不對)。他也爲你提供了一個模板,一個你想寫自己的input-plugin的模板,因爲他被實現的儘可能的簡單易懂。它的作用就是把由testpictures模塊得到的JPEG-files文件轉變成一個頭文件,這個頭文件包含了一些被編譯進testpictures模塊的圖片(前面說過了)。當被激活時就會不停的往復上面的那個動作:獲得->轉變。


input_uvc.so

如其名她從兼容Linux-UVC V4L2標準的設備中抓取圖片。像Logitech Quickcam Sphere AF等等國產的有 ZC0303。她的源碼是基於開源項目"luvcview",當然做了很多方面的修改了。與"luvcview"不同的是,他初始化羅技他們家的攝像頭時用pan/tilt/focus命令即可。而無需庫的幫忙、擺弄XML文件或者udev規則(設備文件在系統中出現的方式)。現在很流行這種輸入插件,得益於它能夠在不增加CPU負載的情況下以大於15fps(frame per second)速率來將相片編碼成960x720象素大小。如果你有錢不用考慮CPU的負載問題,大可進行1600x1200象素(厲害)的無壓縮的編碼,然後用軟件實現壓縮並傳到客戶端!


input_control.so

這個模塊只實現了pan/tilt的控制接口,就是說他把視頻流的功能交給了其他程序(Linux中很推崇"簡潔",就是一款軟件一個功能,效率至上,功能有軟件數量保證)。曾經用他提供了一個網絡接口以允許通過網絡實現pan/tilt我的羅技Orbit AF,當然Skype就來補充音、視頻流的功能了。當我們通過Skype要開遠程會議的時候,她工作的非常好,看不見的手時候還方便他們控制這個攝像頭多好啊。


Output-Plugins
output_http.so

這絕對是個全版本的符合HTTP1.0標準的webserver。可以在單獨的文件夾中提供文件訪問,也可以執行一些命令。例子是,你可以訪問從輸入plugin(見上文)獲得的JPEG文件,或者按照M-JPEG標準編碼他們。可以從一個文件夾提供服務意味着你可以定製你自己的網頁,比如嵌入圖片啊神馬的。你可以參見MJPG-streamer 包中的例子。有點重要的是,多個實例是可以併發運行的,這意味着多個server-threads進程可以處理不同的密碼(不同的請求)啊,呈現的佈局啊或者有限制的命令。

這個模塊是用來把JPEG圖片存儲到指定的文件夾中。你一可以用來抓取圖片並只是存取,當然你也可以在存儲完之後通過執行命令把他們提交到FTP服務器上!你可以在output_file頁參看更多的文檔。


MoreProject Status
JavaScript Motion Detection
High resolution webcam with 1600x1200 pictures
Usage

發佈了2 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章