以前在公司作的一個小項目,功能很簡單,就是在Ubuntu下采集 指定採集卡(模轉數)的電視畫面,以及音頻輸入信號,完成後再在本機進行視頻的全屏播放,以及音頻的本地播放(麥克風>>揚聲器)。git
中間視頻畫面通過了圖像格式的轉換,最終由SDL進行渲染播放。服務器
同時附加簡單的冗餘功能,有兩臺設備同事運行,之間互有心跳,一臺設備掛機後,另外一臺設備自動開始工做。併發
程序使用QT/C/C++進行開發,使用V4L2,FFMPEG,SDL進行開發。app
入口:ide
#include <QtGui/QApplication> #include "widget.h" #include <QSharedMemory> int main(int argc, char *argv[]) { QApplication a(argc, argv); //共享內存保證單實例運行 QSharedMemory *shareMem = new QSharedMemory(QString("SingleInstanceIdentify")); /* if the sharedmemory has not been created, it returns false, otherwise true. * But if the application exit unexpectedly, the sharedmemory will not detach. * So, we try twice. */ volatile short i = 2; while (i--) { if (shareMem->attach(QSharedMemory::ReadOnly)) /* no need to lock, bcs it's read only */ { shareMem->detach(); } } if (shareMem->create(1)) { //採集並播放類開始運行,所有放到UI類中進行 MainWindow w; w.setWindowTitle("LCD Player"); // w.show(); w.showFullScreen(); a.exec(); } }
主要的設備管理、邏輯管理類接口:ui
class CDeviceCtrl : public QObject { Q_OBJECT public: explicit CDeviceCtrl(QObject *parent = 0); ~CDeviceCtrl(); int OpenDevice(); int ReadAndDisplay(); int CloseDevice(); int GetDeviceHandle() {return fd;} PSDLMODULE GetSdlModule(){return pSdlModule;} PTAVSDLYUVSURFACE GetSurface(){return pSurface;} struct VideoBuffer *GetVideoBuffer(){return video_buffers;} bool GetCapFlag() {return devam;} CDebugLog* GetDebugLog(){ return pLog;} protected: int ReadConfigure(const char *filename); private: QObject* parent; CDebugLog* pLog; pthread_t hThreadDisplayHandle; //渲染線程句柄 pthread_t hThreadRecordHandle; //錄製線程句柄 bool devam; int fd; unsigned int buffer_count; char out_name[256]; PSDLMODULE pSdlModule; //SDL資源 PTAVSDLYUVSURFACE pSurface; //SDL資源 struct VideoBuffer* video_buffers; }
完整代碼,請前往個人碼雲平臺下載,地址是:https://git.oschina.net/icedbeer/LinuxMediaCapture編碼
這是QT工程,請使用QtCreator打開工程文件.pro。.net
上面的這個工程這是簡單的把畫面進行本地顯示,若是須要進行編碼並傳輸的話,請參考另外一個工程(QT+Linux),源碼下載地址是:https://git.oschina.net/icedbeer/LinuxMediaCaptureRtsp線程
此工程主要功能是:code
Linux下視頻採集並編碼H.264格式,同時封裝爲TS流;
開啓RTST流服務器監控,接受客戶端鏈接請求,並建立一個新的線程將TS流數據發送給Client。
此代碼只是實驗性的代碼,每一個Client都會開啓一個線程,因此若是須要大併發運行的話,請勿效仿。