Qt+libvlc+rtsp:視訊層上繪圖探究
一、前言
1.起源
最近負責專案中的一個部分,需要從攝像頭獲取rtsp流,同時作tcp的客戶端收取人臉識別的資訊,用qt顯示視訊並繪製人臉識別框。2.成果
3.環境
系統環境:windows 10
Qt版本:5.8.0
vlc版本:2.2.4(這裡建議使用libvlc 3以上的版本,3以下很難找到debug庫,windows下自行編譯較麻煩)
開發工具:vs2015
4.致謝與宣告
向本文所有引用的作者表示感謝,也要感謝幫助過我的朋友們,正是他們的分享開源精神幫助我解決了問題。 同時感謝菊花怪,從學習程式設計至今一直互勉,包括本次的程式也是在他的幫助下,深夜解決的。 在此宣告:本文對所引用的所有文章的主觀觀點、言論,均不負法律責任。二、準備
1.瞭解視訊傳輸的原理
如果你對視訊傳輸充滿興趣,可以參考以下博文:(1)流媒體客戶端的傳送原理
http://blog.csdn.net/jianren994/article/details/8133395(2)RTSP/RTP媒體傳輸和控制協議
http://blog.csdn.net/ww506772362/article/details/52609379(3) RTSP詳解
http://blog.csdn.net/yangzhiloveyou/article/details/101612692.為什麼使用vlc
vlc是開源的多媒體播放器及框架,它支援大多數的媒體格式播放,體積雖不算非常精簡,但功能非常強大。 你可以訪問VideoLAN的官方網站,並且下載這款播放器:http://www.videolan.org/ 不僅僅是體驗,這對你的測試工作也非常有幫助。3.下載並配置libvlc
三、開始
1.使用庫播放一個rtsp流視訊
首先,你需要這麼幾個變數:libvlc_instance_t *_inst; // libvlc的執行例項
libvlc_media_t *_media; // 用於準備播放的媒體
libvlc_media_player_t *_media_player; // 用於使用vlc媒體播放器
(1)初始化你的rtsp流媒體
_media = libvlc_media_new_location(_inst, addr);
(2)為播放新增一些配置
(未實測)對於實時的rtsp流可能存在延遲,新增如下程式碼可能會減少延遲。libvlc_media_add_option(_media, ":network-caching=300 :live-caching=300;");
(3)初始化播放器
_media_player = libvlc_media_player_new_from_media(_media);
記得同時釋放你的媒體:
libvlc_media_release(_melibvlc_media_release(_media);
(4)播放媒體
libvlc_media_player_play(_media_player);
(5)rtsp測試連結
通過上述這些步驟,如果rtsp連結沒有問題的話,你應該可以在桌面上看見媒體啦。 這裡提供幾條rtsp測試連結:①某路段監控視訊(非實時,1080P)
rtsp://202.104.126.35/demo?from=2017-02-07②某節目(實時,240P)
rtsp://rtsp-v3-spbtv.msk.spbtv.com/spbtv_v3_1/214_110.sdp③一段可愛的動畫(非實時,160P)
rtsp://rtsp-v3-spbtv.msk.spbtv.com/spbtv_v3_1/214_110.sdp2.嵌入播放視窗到你的介面
看到這裡,如果你能成功播放媒體,那說明基本的環境配置都沒有問題,放心大膽地走下去吧。 對於大多數開發者來說,接下來應該把它嵌入到自己的介面中啦!(1)如果你僅僅是作為播放器
那麼我建議你使用API:libvlc_media_player_set_hwnd(_media_player, (void*)_wdgPlayer->winId());
這是最方便、快捷,並且穩定的方法,滿足一般的開發需求。
至此,你可以將本文看作一篇libvlc如何連線到rtsp流媒體的簡明小提示,後續內容僅供瞭解即可。
(2)如果你需要對視訊進行二次開發
比如我的例子中添加了人臉識別的邊框,或者類似的標註。更重要的是,如果你想要實現半透明在視訊上提示內容,那麼請繼續向下看。 我嘗試過各種方法,如:設定透明背景、加入QStackLayout、使用QGraphicsscene畫異形視窗啊等等… 與此類似的問題:①在qt+mplayer播放視訊上層設定半透明窗體,為什麼窗體透明不了,變成黑色了
http://bbs.csdn.net/topics/390482549②QT中實現多層Widget,而下層播放視訊處於不斷重繪的狀態,怎麼實現?
http://www.qtcn.org/bbs/simple/?t58461.html 相信讀到這裡的大家應該也焦頭爛額,找不到更好的辦法。 我在程式開發時遇到的問題:為了在視訊上新增透明內容,我先建立了一個QWidget,設定為透明,並raise()。執行現象是的確透明瞭,但也確確實實從視訊“穿越”了過去。 這裡看到的背景色是最底層的widget顏色。 可能的解釋是:使用了這段程式碼後,widget的控制代碼交給了windows下的directX繪製。libvlc_media_player_set_hwnd(_media_player, (void*)_wdgPlayer->winId());
要想解決這個辦法:可以選擇不使用這個api,自行繪製;也可以生成多個hwnd進行繪製(windows下不太瞭解,期間幫助過的朋友曾提過這個解決方案,不知是否可行,還希望能得到驗證)。
3.將繪圖統統交給Qt
那麼,在不使用api的前提下,如何繪製呢?術語不甚瞭解還請見諒,這裡我就說的通俗易懂些: 對於視訊來說,由一幅幅畫面組成,我們將每一張圖稱之為“幀”。每秒鐘傳輸了多少幀(FPS)是評價視訊是否流暢的標準。 不瞭解如何編碼解碼沒關係,libvlc在前面所做的那些工作已經為我們鋪墊好了基礎。既然如此,我們只要取出幀,並且繪製即可。 仔細檢視libvlc的api,發現可取出幀並操作的方法:void VideoSetCallBacks(IntPtr mediaPlayInstance, VideoLockCB lockCB, VideoUnlockCB unlockCB, VideoDisplayCB displayCB, IntPtr opaque);
IntPtr VideoLockCB(IntPtr opaque, IntPtr planes);
void VideoUnlockCB(IntPtr opaque, IntPtr picture, IntPtr planes);
void VideoDisplayCB(IntPtr opaque, IntPtr picture);
以下是我修改後的一部分程式碼:
typedef struct
{
QMutex mutex;
CVLCPainter *painter;
uchar *pixels;
}callback_param_t;
static void* lock(void* op, void** plane)
{
callback_param_t *p = (callback_param_t *)op;
p->mutex.lock();
*plane = p->pixels;
return NULL;
}
static void unlock(void* op, void* pic, void* const* plane)
{
callback_param_t *p = (callback_param_t *)op;
uchar* pp = (uchar*)*plane;
unsigned char* data = (unsigned char*)*plane;
QImage a(data, gWidth, gHeight, QImage::Format_RGBA8888);
p->painter->updatePic(a);
p->mutex.unlock();
}
static void display(void* op, void* pic)
{
}
初始化影象緩衝區(建議使用其他資料結構代替陣列)
void CVLCPlayer::init_vlc_param()
{
param = new callback_param_t;
param->painter = _vlcPainter;
param->pixels = new uchar[gWidth * gHeight * 4];
memset(param->pixels, 0, gWidth * gHeight * 4);
}
updatePic函式
void CVLCPainter::updatePic(QImage &img)
{
_pixmap = QPixmap::fromImage(img);
_image = img;
update();
}
在widget中渲染:
void CVLCPainter::paintEvent(QPaintEvent *event)
{
_mutex.lock();
QPainter painter(this);
if (_pixmap.isNull())
{
_mutex.unlock();
return;
}
v_width = this->rect().width();
multi = (float)v_width / (float)gWidth;
multi = QString::number(multi, 'f', 2).toFloat();
v_height = (int)((float)gHeight * multi);
o_height = (this->rect().height() - v_height) / 2;
painter.drawImage(QRect(0, o_height, v_width, v_height), _image);
//painter.drawPixmap(QRect(0, o_height, v_width, v_height), _pixmap);
if (_vecRect.count() > 0 && isFaceDist)
{
painter.setPen(Qt::red);
for (int i = 0; i < _vecRect.count(); ++i)
painter.drawRect(*_vecRect.at(i));
}
_mutex.unlock();
}
以上原理均可檢視博文:http://www.cnblogs.com/smartsensor/p/4343769.html 在這裡提供一篇貼子,並感謝作者提供的原始碼:http://bbs.csdn.net/topics/390817375
三、新問題的出現、解決與再探
使用drawPixmap()繪圖可能導致程式崩潰? 在我的機器上出現了崩潰的問題,由於是release版本只能追蹤到drawPixmap(),替換為drawImage()後問題不再出現。通過對於windows下兩者的差異,可能是由於QImage獨立於硬體,並且它也是一種QPaintDevice,不需要在UI執行緒中處理影象。但這種說法並不能完全立足,如果大家有興趣,也可以告知或推斷可能的原因。 博主的能力有限、經驗尚淺,本文可能存在諸多問題,僅供解決問題的參考方向。如果發現錯誤,也請給予指正,謝謝。相關推薦
Qt+libvlc+rtsp:視訊層上繪圖探究
一、前言 1.起源 最近負責專案中的一個部分,需要從攝像頭獲取rtsp流,同時作tcp的客戶端收取人臉識別的資訊,用qt顯示視訊並繪製人臉識別框。 2.成果 3.環境 系統環境:windows 10 Qt版本:5.8.0 vlc版本:2.2.4(這裡建議使用libvl
Qt如何在QTabWidget上繪圖
Qt繪圖事件必須在paintEvent事件下繪圖,這樣導致我們在向Qt設計師介面上拖拽的控制元件繪圖時,造成了很大的麻煩。 我們不能在拖拽的控制元件上寫paintEvent函式,但是可以自定義一個類,繼承某一個控制元件,在裡面寫繪圖事件函式,但是這個非常麻煩, 此時我們需要借用Qt事件過濾器函式eve
caffe21天書上的例子--qt讀取caffe deply網路層名
主要功能是讀取deply的層名字,程式碼如下: #include <vector> #include <iostream> #include "caffe/net.hpp" using namespace std; using namespace caff
Qt之在控制元件上繪圖
1.總述 Qt的要在當前類對應的視窗上繪圖一般需要重寫paintEvent函式,但是Qt的事件過濾器預設是把父視窗下子控制元件的繪圖事件給過濾了的,因此重寫父視窗的paintEvent函式是無法在子控制元件上進行繪圖的,下面舉一個例子。 1 void MainWindow::m
【TeeChart Pro ActiveX教程】(十三):圖表面板上的自定義繪圖(上)
下載TeeChart Pro ActiveX最新版本 TeeChart通過Canvas物件提供廣泛的自定義繪圖工具。使用Canvas,您可以在“Chart Panel”的任何位置新增形狀,線條和文字,並定義其顏色,筆和畫筆樣式。 TeeChart畫布 繪圖順序 使用TeeChart的Canvas方
Qt實用技巧:使用QMediaPlayer和Windows自帶元件播放swf、rmvb、mpg、mp4等視訊檔案
需求 做軟體時,點選進入介面需要播放一段視訊,該視訊的格式可相容swf、rmvb、mpg、mp4等視訊檔案。 原理 使用QMediaPlayer播放rmvb、mpg、mp4格式 使用windows Media Player
Qt實用技巧:QPainterPath繪圖路徑(多次畫同樣的圖形集合)
需求 根據配置檔案,可不改變程式只調整配置檔案可調整主頁面上的字串。 原理 1.讀取檔案,固定格式(檔案在本文章中省略) 2.寫一串字元,使用QPainterPath 3.注意QPainter的時候,需
iOS播放實時視訊,HLS的大延遲問題如何解決,RTSP 能在iOS 上低延遲播放麼
HLS 在實時視訊領域一直沒有很好的表現,但是HLS協議最近幾年的普及率也是越來越高, rfc8216 這是HLS最終的標準。https://datatracker.ietf.org/doc/rfc8216/ HLS能如此普及,得益於在CDN友好支援,由於HLS是基於檔案片的
Qt學習筆記(1)---QT5利用事件過濾器實現在控制元件上繪圖
首先,感謝 作者:一去丶二三裡 部落格地址:http://blog.csdn.net/liang19890820 Qt中要在控制元件中繪製圖像,需要重寫paintevent函式,本文通過EventFilter(事件過濾器)來實現在控制元件上的圖形繪製。 .h檔案 #
Oracle數據庫12cR2(項目實戰之一):在Windows上安裝Oracle12.2
oracle12c安裝 oracle12cr2安裝 oracle培訓教程 oracle視頻教程 oracle12cr2 oracle數據庫12cR2(項目實戰之二):linux系統安裝Oracle12.2一、課程主題:風哥Oracle數據庫教程12cR2(項目實戰之二):在linux操作系
人工智能VS投資者:股票市場上誰的勝算更高?
人工智能 華爾街 股票市場 異想天開 股票投資 人工智能研究歷史淵源,當人工智能與資本投資,尤其是股票投資相結合或許聽起來有些異想天開,但正如科幻作家William Gibson所言:“未來已經到來,只是分布不均。”在股票市場上想獲得高於平均水平的回報是非常困難的,事實上,研究顯示即使在華
文件上傳三:base64編碼上傳
說了 json datetime byte 調試 handle png mage hang 介紹三種上傳方式: 文件上傳一:偽刷新上傳 文件上傳二:FormData上傳 文件上傳三:base64編碼上傳 Flash的方式也玩過,不喜歡不拿來說了。 優點: 1.瀏覽器可以
net3:文件上傳與圖片顯示以及HiddenField隱藏字段值的使用
pos protect path 來源 file ipa gif sender uri 原文發布時間為:2008-07-29 —— 來源於本人的百度文章 [由搬家工具導入]using System;using System.Data;using System.Configu
ThinkPhp框架:文件上傳
load 1-1 method 文檔 文件夾 文件上傳 實例 成功 upload 實現文件上傳功能需要控制器,方法然後是顯示的頁面 1.在Controller下新建一個控制器TestController.class.php 2.創建操作方法 <?php names
Android開發實踐:JNI層線程回調Java函數示例
lan 並且 進行 img 工程 stat 責任 3.5 jpg 原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/1358558 JNI是Ja
(轉)第03節:在Canvas上插入圖片並設置旋轉屬性
doctype script border wid bsp viewport 設置 css樣式 png 我們已經學會了在Canvas上畫簡單的圖形,這節我們就在Canvas上加一張圖片。用到fabric.Image對象把圖片添加到Canvas上。 HTML文件:為了效果更好
穆尼裏奧:未派上最好點球手;齊達內成功並不意外
兩場 來講 目標 皇馬 洛杉磯 是我 小夥子 等等 有時 出色的上半場“我們訓練的結果很棒,對上一支皇馬這樣的頂級對手,那可以說是一個非常棒的上半場。我想在面對他們的年輕球員的時候我們失去了動力和饑餓感。我認為我們打了下半場的那些小夥子們很失望,因為他們踢的不是皇馬最好的球
算法:整數除法上取整
nbsp blog res 情況 bin math.h 代碼 方法 bsp 寫代碼會遇到整數除法需要上取整的情況。 1. 整數除法的話,可以自己寫^_^ 1 #!/bin/bash 2 3 num=101 ##被除數 4 pre=10 ##除數 5 6
計算機網絡【八】:應用層 【轉】
tac 都是 文件共享 編寫 .net pos 遠程 等待 src 轉自:http://blog.chinaunix.net/uid-26275986-id-4110819.html 今天我們來快速地瀏覽一下傳輸層之上的應用層所使用的協議,下面將簡要地列出應用
李笑來老師在《把時間當作朋友》曾說過:“所有學習上的成功,都只靠兩件事:策略和堅持,而堅持本身就應該是最重要的策略之一
tail tin keep each however http can 一次 練習 高效編程=工具+方法+體系+專註 前面根據個人的經驗,分享了一些提高編程效率的個人心得。每個人的經歷經驗不盡相同,相信其實每個人心中都有一份自己的清單。但最最重要的是堅持投入,不斷地練習、