一、前言
采用了回調方式的視頻通道,截圖只需要對解析好的QImage對象直接保存即可,而對於句柄的形式,需要調用不同的處理策略,比如vlc需要用它自己提供的api接口函數libvlc_video_take_snapshot傳入保存路徑即可,mpv的內核執行screenshot-to-file命令傳入路徑參數即可,而ffmpeg就需要設置抓拍標志位,在實時采集解析那邊,如果當前是截圖標志位真,則需要改成QImage轉換的機制發出圖片,而不是yuv的數據opengl繪制,海康的sdk調用NET_DVR_CapturePicture函數即可。
一般來說截圖都是保存的原始的圖片,對應的分辨率也是原始的分辨率,並沒有壓縮及等比例縮放過的,所以ffmpeg的監控內核必須是最原始的采集到的圖片為准,而不是最終繪制后的圖片,因為繪制后的很可能已經縮放過的。
有時候還有一種場景需求是不需要原始的圖片,只需要當前通道大小的尺寸,這個時候就需要對當前通道進行截屏,采用截屏的形式截圖,這種方式可以將設置的OSD等信息都截圖進去,相當於扣扣截圖。Qt本身提供了grabWindow方法來對指定句柄的窗體控件截屏,Qt4里面放在QPixmap類中的靜態方法QPixmap::grabWindow,而Qt5中放在QApplication::primaryScreen()的方法中。
二、功能特點
- 支持多畫面切換,全屏切換等,包括1+4+6+8+9+13+16+25+36+64畫面切換。
- 支持alt+enter全屏,esc退出全屏。
- 自定義信息框+錯誤框+詢問框+右下角提示框(包含多種格式)。
- 17套皮膚樣式隨意更換,所有樣式全部統一,包括菜單等。
- 雲台儀表盤鼠標移上去高亮,八個方位精准識別。
- 底部畫面工具欄(畫面分割切換+截圖聲音等設置)移上去高亮。
- 可在配置文件更改左上角logo+中文軟件名稱+英文軟件名稱。
- 封裝了百度地圖,視圖切換,運動軌跡,設備點位,鼠標按下獲取經緯度等。
- 支持圖片地圖,設備按鈕可以在圖片地圖上自由拖動自動保存位置信息。
- 在百度地圖和圖片地圖上,雙擊視頻可以預覽攝像頭實時視頻。
- 堆棧窗體,每個窗體都是個單獨的qwidget,方便編寫自己的代碼。
- 頂部鼠標右鍵菜單,可動態控制時間CPU+左上角面板+左下角面板+右上角面板+右下角面板的顯示和隱藏,支持恢復默認布局。
- 工具欄可以放置多個小圖標和關閉圖標。
- 左側右側可拖動拉伸,並自動記憶寬高位置,重啟后恢復。
- 雙擊攝像機節點自動播放視頻,雙擊節點自動依次添加視頻,會自動跳到下一個,雙擊父節點自動添加該節點下的所有視頻。
- 攝像機節點拖曳到對應窗體播放視頻,同時支持拖曳本地文件直接播放。
- 視頻畫面窗體支持拖曳交換,瞬間響應。
- 雙擊節點+拖曳節點+拖曳窗體交換位置,均自動更新url.txt。
- 支持從url.txt中加載通道視頻播放,自動記憶最后通道對應的視頻,軟件啟動后自動打開播放。
- 右下角音量條控件,失去焦點自動隱藏,音量條帶靜音圖標。
- 集成百度在線地圖和離線地圖,可以添加設備對應位置,自動生成地圖,支持縮放和添加覆蓋物等。
- 視頻拖動到通道窗體外自動刪除視頻。
- 鼠標右鍵可刪除當前+所有視頻,截圖當前+所有視頻。
- 錄像機管理、攝像機管理,可添加刪除修改導入導出打印信息,立即應用新的設備信息生成樹狀列表,不需重啟。
- 在pro文件中可以自由開啟是否加載地圖。
- 視頻播放可選2種內核自由切換,vlc+ffmpeg,均可在pro中設置。
- 可設置1+4+9+16畫面輪詢,可設置輪詢間隔以及輪詢碼流類型等,直接在主界面底部工具欄右側單擊啟動輪詢按鈕即可,再次單擊停止輪詢。
- 默認超過10秒鍾未操作自動隱藏鼠標指針。
- 支持onvif搜素設備,支持任意onvif攝像機,包括但不限於海康大華宇視天地偉業華為等。
- 支持onvif雲台控制,可上下左右移動雲台攝像機,包括復位和焦距調整等。
- 同時支持sqlite、mysql、postsql等數據庫。
- 可保存視頻,可選定時存儲或者單文件存儲,可選存儲間隔時間。
- 可設置視頻流通信方式tcp+udp,可設置視頻解碼是速度優先、質量優先、均衡等。
- 可設置硬解碼類型,支持qsv、dxva2、d3d11va等。
- 默認采用opengl繪制視頻,超低的CPU資源占用,支持yuyv和nv12兩種格式繪制,很牛逼。
- 高度可定制化,用戶可以很方便的在此基礎上衍生自己的功能,支持linux和mac系統。
三、效果圖
四、相關站點
- 國內站點:https://gitee.com/feiyangqingyun/QWidgetDemo
- 國際站點:https://github.com/feiyangqingyun/QWidgetDemo
- 個人主頁:https://blog.csdn.net/feiyangqingyun
- 知乎主頁:https://www.zhihu.com/people/feiyangqingyun/
- 體驗地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652
五、核心代碼
QImage FFmpegWidget::getImage() const
{
#ifdef opengl
thread->snap();
#endif
return this->image;
}
QPixmap FFmpegWidget::getPixmap() const
{
//采用截屏的形式截圖,這種方式可以將 設置的OSD等信息都截圖進去
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
QPixmap pixmap = QPixmap::grabWindow(winId(), 0, 0, width(), height());
#else
QScreen *screen = QApplication::primaryScreen();
QPixmap pixmap = screen->grabWindow(winId(), 0, 0, width(), height());
#endif
return pixmap;
}
void VlcThread::snap(const QString &fileName)
{
if (vlcPlayer != NULL) {
libvlc_video_take_snapshot(vlcPlayer, 0, fileName.toUtf8().constData(), videoWidth, videoHeight);;
}
}
void MpvThread::snap(const QString &fileName)
{
if (mpvPlayer != NULL) {
command(QVariantList() << "screenshot-to-file" << fileName << "video");
}
}
void HaiKangThread::snap(const QString &fileName)
{
if (isRtsp) {
QByteArray data = fileName.toUtf8();
NET_DVR_CapturePicture(hand, data.data());
} else {
//PlayM4_GetJPEG(port, data, size, &result);
//PlayM4_ConvertToJpegFile(pBuf, nSize, nWidth, nHeight, nType, file);
//通過設置顯示回調,在顯示回調中抓圖保存,抓圖完成立馬關閉回調
PlayM4_SetDisplayCallBack(port, DisplayCallback);
msleep(100);
PlayM4_SetDisplayCallBack(port, NULL);
}
}