mjpg-streamer程框架圖如下所示:
程序運行起來后,主進程根據傳入的參數設置的輸入輸出通道打開對應的輸入輸出動態鏈接庫,并依次調用以下函數
1、輸入---倉庫-----輸出(mjpg-streamer.h)
(1)global結構體
stop為停止標志位,置1時程序停止運行;
db和db_update分別為互斥鎖和條件變量,兩者用于線程同步,當輸入通道把數據放入倉庫后,通知輸出通道來取數據
倉庫對應的是buf指針,倉庫的大小是size.
輸出對應的是output結構體(輸出插件)
outcnt表示當前輸出通道中有幾種方式
(2)mjpg-streamer-r63文件
???????.so文件是插件,可能是輸入插件(前面帶有input字樣),也可能是輸出插件(前面帶有output插件)。?
運行mjpg_streamer時通過命令行mjpg_streamer -i "input_uvc.so -f 10 -r 320*240" -o "output_http.so -w www"指定輸入輸出通道
???????由于用的是USB攝像頭來采集數據,因此選擇input_uvc.so輸入插件作為輸入渠道(如上所示,通過-i指定哪一個插件作為輸入渠道)。
??????由于我們要用的是網頁顯示,因而選擇output_http.so輸出插件作為輸出渠道。(如上圖所示,通過-o選項指定哪一個插件作為輸出渠道)
(3)主函數通過解析命令行-i "input_uvc.so -f 10 -r 320*240“ ,打開對應的input_uvc.so動態鏈接庫
通過dlopen函數打開動態鏈接庫
(4)?主函數通過解析命令行-o "output_http.so -w www" ,打開對應的out_http.so動態鏈接庫
2、輸入插件和輸出插件所做的工作
(1)輸入插件1(input_uvc.c文件)
input結構體
(2)輸入插件2
init函數
主要執行init_videoIn函數
傳入參數寬度width ,高度height,幀率fps,格式format
init_videoIn所做工作:①調用init_v4l2函數(通過V4L2提供的一系列的ioctl來設置攝像頭的分辨率,幀率,以及攝像頭的輸出格式,并分配緩沖區然后映射到應用程序空間videoIn->mem[i]);②分配一個臨時緩沖區videoIn->tmpbuffer,用于接收攝像頭數據(攝像頭數據流向為:videoIn->mem[i]? ? ?----->? videoIn->tmpbuffer? ? ?----->? globals->buf(我們所說的倉庫) ---------->輸出通道取出數據外發)
run函數
主要執行創建線程函數參數里面的cam_thread函數
所做工作:調用uvcGrab函數(該函數把一幀數據從拷貝videoIn->mem[i]?里拷貝到videoIn->tmpbuffer)獲取一幀數據
判斷獲得數據的格式,如果輸入數據格式是MJPEG格式,直接把它拷貝到 global結構體的buf里面(也就是放入倉庫);如果是YUV格式,要把YUV格式數據轉變成MJPEG格式的數據再拷貝到global結構體的buf里面(也就是放入倉庫globals->buf)
stop函數
做一些清理工作
?
(3)輸出插件1
output結構體
?
(4)輸出插件2
init函數
socket編程以及用socket來模擬http協議,因此做socket的一些初始化工作,如端口號
run函數
從倉庫中取出數據,存到一個緩沖區中,然后通過write函數將數據發送出去,供手機或其他設備接收
stop函數
做一些清理工作
?
本文參考鏈接:
https://blog.csdn.net/qingkongyeyue/article/details/52400036
https://blog.csdn.net/qingkongyeyue/article/details/52401514
https://blog.csdn.net/qingkongyeyue/article/details/52824165