一、前言
現(xiàn)在各個(gè)監(jiān)控大廠做的設(shè)備,基本上都會(huì)支持通過(guò)rtsp直接取流顯示,而且做的比較好的還支持通過(guò)rtsp回放取流,基本上都會(huì)約定一個(gè)字符串的規(guī)則,每個(gè)廠家都是不一樣的規(guī)則,比如回放對(duì)應(yīng)的rtsp地址還要帶上時(shí)間范圍,回放肯定要指定一個(gè)開(kāi)始時(shí)間和結(jié)束時(shí)間。這里需要特別提示的是,按道理rtsp是實(shí)時(shí)視頻流,一般是沒(méi)有時(shí)長(zhǎng)的,而回放的rtsp視頻流是帶了時(shí)長(zhǎng)的,所以可以通過(guò)seek來(lái)定位播放位置,這個(gè)就很方便用戶(hù)在軟件上任意拖動(dòng)和切換播放位置,以前我一直以為rtsp實(shí)時(shí)視頻流不可能有時(shí)長(zhǎng),原來(lái)是自己孤陋寡聞了,在通過(guò)一個(gè)老萬(wàn)音視頻大佬的指點(diǎn)下才得知這個(gè)特性,這個(gè)特性當(dāng)然需要設(shè)備廠家在后端實(shí)現(xiàn)支持。
有了回放可以切換播放進(jìn)度位置這個(gè)特性,意味著回放這塊不需要用GB28181國(guó)標(biāo)去解析,直接構(gòu)建對(duì)應(yīng)的回放視頻流字符串就可以,目前測(cè)試下來(lái),正常播放和切換進(jìn)度播放一點(diǎn)問(wèn)題沒(méi)有,唯獨(dú)倍速播放有問(wèn)題,目前看下來(lái)還是不支持倍速播放的,不知道是不是還有其他的機(jī)關(guān)要素控制比如參數(shù)啥的。其實(shí)取流回放的核心就是根據(jù)不同廠家拿到對(duì)應(yīng)設(shè)備的rtsp字符串即可,解碼那邊要拿到時(shí)長(zhǎng),并當(dāng)做文件處理,因?yàn)槲募?lèi)型的可以切換播放進(jìn)度。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-513540.html
二、效果圖
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-513540.html
三、體驗(yàn)地址
- 國(guó)內(nèi)站點(diǎn):https://gitee.com/feiyangqingyun
- 國(guó)際站點(diǎn):https://github.com/feiyangqingyun
- 個(gè)人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
- 體驗(yàn)地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取碼:01jf 文件名:bin_video_demo。
四、功能特點(diǎn)
- 支持各種音視頻文件、本地?cái)z像頭設(shè)備,各種視頻流網(wǎng)絡(luò)流。
- 支持開(kāi)始播放、暫停播放、繼續(xù)播放、停止播放、設(shè)置播放進(jìn)度、倍速播放。
- 可設(shè)置音量、靜音切換、抓拍圖片、錄像存儲(chǔ)。
- 自動(dòng)提取專(zhuān)輯信息比如標(biāo)題、藝術(shù)家、專(zhuān)輯、專(zhuān)輯封面,自動(dòng)顯示專(zhuān)輯封面。
- 完美支持音視頻同步和倍速播放。
- 解碼策略支持速度優(yōu)先、質(zhì)量?jī)?yōu)先、均衡處理、最快速度。
- 支持手機(jī)視頻旋轉(zhuǎn)角度顯示,比如一般手機(jī)拍攝的視頻是旋轉(zhuǎn)了90度的,解碼顯示的時(shí)候需要重新旋轉(zhuǎn)90度才是正的。
- 自動(dòng)轉(zhuǎn)換yuv420格式,比如本地?cái)z像頭是yuyv422格式,有些視頻文件是xx格式,統(tǒng)一將非yuv420格式轉(zhuǎn)換,然后再進(jìn)行處理。
- 支持硬解碼dxva2、d3d11va等,性能極高尤其是大分辨率比如4K視頻。
- 視頻響應(yīng)極低延遲0.2s左右,極速響應(yīng)打開(kāi)視頻流0.5s左右,專(zhuān)門(mén)做了優(yōu)化處理。
- 硬解碼和GPU繪制組合,極低CPU占用,比??荡笕A等客戶(hù)端更優(yōu)。
- 支持視頻流中的各種音頻格式,AAC、PCM、G.726、G.711A、G.711Mu、G.711ulaw、G.711alaw、MP2L2等都支持,推薦選擇AAC兼容性跨平臺(tái)性最好。
- 視頻存儲(chǔ)支持yuv、h264、mp4多種格式,音頻存儲(chǔ)支持pcm、wav、aac多種格式。默認(rèn)視頻mp4格式、音頻aac格式。
- 支持分開(kāi)存儲(chǔ)音頻視頻文件,也支持合并到一個(gè)mp4文件,默認(rèn)策略是無(wú)論何種音視頻文件格式存儲(chǔ),最終都轉(zhuǎn)成mp4及aac格式,然后合并成音視頻一起的mp4文件。
- 支持本地?cái)z像頭實(shí)時(shí)視頻顯示帶音頻輸入輸出,音視頻錄制合并到一個(gè)mp4文件。
- 支持H264/H265編碼(現(xiàn)在越來(lái)越多的監(jiān)控?cái)z像頭是H265視頻流格式)生成視頻文件,內(nèi)部自動(dòng)識(shí)別切換編碼格式。
- 自動(dòng)識(shí)別視頻流動(dòng)態(tài)分辨率改動(dòng),重新打開(kāi)視頻流。
- 支持用戶(hù)信息中包含特殊字符(比如用戶(hù)信息中包含+#@等字符)的視頻流播放,內(nèi)置解析轉(zhuǎn)義處理。
- 純qt+ffmpeg解碼,非sdl等第三方繪制播放依賴(lài),gpu繪制采用qopenglwidget,音頻播放采用qaudiooutput。
- 同時(shí)支持ffmpeg2、ffmpeg3、ffmpeg4、ffmpeg5、ffmpeg6以及后續(xù)版本,全部做了兼容處理。如果需要支持xp需要選用ffmpeg3或ffmpeg2。
- 支持濾鏡,源頭帶各種水印及圖形效果,可以將OSD標(biāo)簽信息和各種圖形信息寫(xiě)入到MP4文件。
五、相關(guān)代碼
//地址參數(shù)結(jié)構(gòu)體
struct UrlPara {
QString deviceIP; //通信地址
int devicePort; //通信端口
QString userName; //用戶(hù)名稱(chēng)
QString userPwd; //用戶(hù)密碼
int channel; //通道編號(hào)
int streamType; //碼流類(lèi)型
QString companyName; //廠家標(biāo)識(shí)
CompanyType companyType; //廠家類(lèi)型
int videoType; //視頻類(lèi)型(0-實(shí)時(shí)/1-回放)
QDateTime dateTimeStart; //開(kāi)始時(shí)間(回放專(zhuān)用)
QDateTime dateTimeEnd; //結(jié)束時(shí)間(回放專(zhuān)用)
UrlPara() {
devicePort = 0;
channel = 0;
streamType = 0;
}
//重載打印輸出格式
friend QDebug operator << (QDebug debug, const UrlPara &urlPara) {
QStringList list;
list << QString("通信地址: %1").arg(urlPara.deviceIP);
list << QString("通信端口: %1").arg(urlPara.devicePort);
list << QString("用戶(hù)名稱(chēng): %1").arg(urlPara.userName);
list << QString("用戶(hù)密碼: %1").arg(urlPara.userPwd);
list << QString("通道編號(hào): %1").arg(urlPara.channel);
list << QString("碼流類(lèi)型: %1").arg(urlPara.streamType);
list << QString("廠家標(biāo)識(shí): %1").arg(urlPara.companyName);
list << QString("廠家類(lèi)型: %1").arg(urlPara.companyType);
#if (QT_VERSION >= QT_VERSION_CHECK(5,4,0))
debug.noquote() << list.join("\n");
#else
debug << list.join("\n");
#endif
return debug;
}
};
QString UrlHelper::getRtspUrl(const UrlPara &urlPara)
{
QString url;
//頭部地址格式完全一致
QString head = QString("rtsp://%1:%2@%3:554").arg(urlPara.userName).arg(urlPara.userPwd).arg(urlPara.deviceIP);
if (urlPara.companyType == CompanyType_HaiKang) {
//實(shí)時(shí)預(yù)覽格式 rtsp://admin:12345@192.168.1.128:554/Streaming/Channels/101?transportmode=unicast
//視頻回放格式 rtsp://admin:12345@192.168.1.128:554/Streaming/tracks/101?starttime=20120802t063812z&endtime=20120802t064816z
//流媒體視頻流 rtsp://172.6.24.15:554/Devicehc8://172.6.22.106:8000:0:0?username=admin&password=12345
//日期時(shí)間格式 ISO 8601 表示Zulu(GMT) 時(shí)間 YYYYMMDD”T”HHmmSS.fraction”Z”,
//unicast表示單播,multicast表示多播,默認(rèn)單播可以省略
//101解析: 1是通道號(hào) 01是通道的碼流編號(hào) 也可以是02 03
QString startTimeISO = urlPara.dateTimeStart.toString(Qt::ISODate);
startTimeISO.replace("-", "");
startTimeISO.replace(":", "");
startTimeISO.toLower();
QString endTimeISO = urlPara.dateTimeEnd.toString(Qt::ISODate);
endTimeISO.replace("-", "");
endTimeISO.replace(":", "");
endTimeISO.toLower();
//通道號(hào)和碼流編號(hào)
QString info = QString("%1%2%3").arg(urlPara.channel).arg(0).arg(urlPara.streamType + 1);
//回放時(shí)間范圍
QString time = QString("starttime=%1z&endtime=%2z").arg(startTimeISO).arg(endTimeISO);
//實(shí)時(shí)和回放地址格式不同
if (urlPara.videoType == 0) {
url = QString("%1/Streaming/Channels/%2").arg(head).arg(info);
} else if (urlPara.videoType == 1) {
url = QString("%1/Streaming/tracks/%2?%3").arg(head).arg(info).arg(time);
}
} else if (urlPara.companyType == CompanyType_DaHua) {
//實(shí)時(shí)預(yù)覽格式 rtsp://192.168.1.128:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
//視頻回放格式 rtsp://admin:12345@192.168.1.128:554/cam/playback?channel=1&subtype=0&starttime=2021_03_18_11_36_01&endtime=2021_03_18_12_05_01
QString startTimeStr = urlPara.dateTimeStart.toString("yyyy_MM_dd_HH_mm_ss");
QString endTimeStr = urlPara.dateTimeEnd.toString("yyyy_MM_dd_HH_mm_ss");
//通道號(hào)和碼流編號(hào)
QString info = QString("channel=%1&subtype=%2").arg(urlPara.channel).arg(urlPara.streamType);
//回放時(shí)間范圍
QString time = QString("starttime=%1&endtime=%2").arg(startTimeStr).arg(endTimeStr);
//實(shí)時(shí)和回放地址格式不同
if (urlPara.videoType == 0) {
url = QString("%1/cam/realmonitor?%2&unicast=true&proto=Onvif").arg(head).arg(info);
} else if (urlPara.videoType == 1) {
url = QString("%1/cam/playback?%2&%3").arg(head).arg(info).arg(time);
}
} else {
//實(shí)時(shí)預(yù)覽格式 rtsp://admin:12345@192.168.1.128:554/live?channel=1&stream=1
//視頻回放格式 rtsp://admin:12345@192.168.1.128:554/file?channel=1&start=1494485280&stop=1494485480
//先轉(zhuǎn)換時(shí)間戳,1970年到該時(shí)間經(jīng)過(guò)的秒數(shù)
qint64 startTimeSec = urlPara.dateTimeStart.toMSecsSinceEpoch() / 1000;
qint64 stopTimeSec = urlPara.dateTimeEnd.toMSecsSinceEpoch() / 1000;
//回放時(shí)間范圍
QString time = QString("start=%1&stop=%2").arg(startTimeSec).arg(stopTimeSec);
//實(shí)時(shí)和回放地址格式不同
if (urlPara.videoType == 0) {
url = QString("%1/live?channel=%2&stream=%3").arg(head).arg(urlPara.channel).arg(urlPara.streamType);
} else if (urlPara.videoType == 1) {
url = QString("%1/file?channel=%2&%3").arg(head).arg(urlPara.channel).arg(time);
}
}
//還有一種通用格式 rtsp://admin:12345@192.168.1.128:554/0 0-主碼流 1-子碼流
return url;
}
到了這里,關(guān)于Qt/C++編寫(xiě)監(jiān)控實(shí)時(shí)顯示和取流回放工具(回放支持切換進(jìn)度)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!