Qt音視訊開發20-海康sdk本地播放
阿新 • • 發佈:2020-08-28
一、前言
海康sdk中包含了MP4解碼播放庫,對應的API函式都是PlayM4開頭的,顧名思義播放MP4,海康的視訊預設可以儲存成MP4檔案,可以用通用的播放器來播放,這就是為啥前面好多篇文章講到的各種核心錄影儲存都改成MP4來儲存,vlc、mpv、ffmpeg等,最終錄影儲存都轉換成MP4檔案,看來大公司大廠做的也是儲存成MP4檔案,肯定是有他的道理,至於有多少道理,跟著他學者他這樣處理就行,可以先不用問不用管,直接上手擼程式碼就對了,有些東西需要深究原理,而有些東西就沒有必要太過於細緻詢問下去了,折騰下去陷入死衚衕,好比知道1+1=2就行,至於為啥=2,交給專門的研究人員去研究就行。
海康sdk的MP4解碼庫,即支援自身的MP4檔案,也支援常規的MP4檔案,而且最新版本還支援AVI檔案格式,隨便試了本地的MP4檔案,也都是支援的,如果需要拿到音視訊資料,只需要呼叫PlayM4_SetDecCallBackMend設定下解碼回撥函式即可,比視訊流的回撥流程簡單很多,少了設定回撥處理函式一大堆處理,只需要解碼轉換成QImage即可。本地檔案還需要增加一個檔案結束回撥,這樣能知道什麼時候檔案播放完成了,發出對應的訊號進行處理,可以呼叫PlayM4_SetFileEndCallback設定檔案播放完畢回撥函式,在FileEndCallback回撥函式中,通過非同步執行QMetaObject::invokeMethod停止函式來通知介面。
關於本地檔案請注意以下幾點:
- 檔案方式播放下,不能呼叫PlayM4_CloseStream。
- 流播放下,不能呼叫PlayM4_CloseFile介面。
- 流開關介面和檔案開關介面不能交叉使用。
二、功能特點
- 支援播放視訊流和本地MP4檔案。
- 支援控制代碼和回撥兩種模式。
- 多執行緒顯示影象,不卡主介面。
- 自動重連網路攝像頭。
- 可設定邊框大小即偏移量和邊框顏色。
- 可設定是否繪製OSD標籤即標籤文字或圖片和標籤位置。
- 可設定兩種OSD位置和風格。
- 可設定是否儲存到檔案以及檔名。
- 可直接拖曳檔案到haikangwidget控制元件播放。
- 支援h264/h265視訊流。
- 可暫停播放和繼續播放。
- 支援儲存單個視訊檔案和定時儲存視訊檔案。
- 自定義頂部懸浮條,傳送單擊訊號通知,可設定是否啟用。
- 可設定畫面拉伸填充或者等比例填充。
- 可設定解碼是速度優先、質量優先、均衡處理。
- 可對視訊進行截圖(原始圖片)和截圖(視訊窗體)。
- 錄影檔案儲存為MP4檔案。
- 支援焦距控制、雲臺控制。
- 可定製功能。
三、效果圖
四、相關站點
- 國內站點: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
五、核心程式碼
bool HaiKangThread::playLocal()
{
//轉碼以便支援中文路徑
QTextCodec *codec = QTextCodec::codecForName("gb2312");
QByteArray data = codec->fromUnicode(url);
PlayM4_GetPort(&port);
bool ok = PlayM4_OpenFile(port, data.data());
if (ok) {
//設定檔案播放完畢回撥函式
PlayM4_SetFileEndCallback(port, FileEndCallback, this);
//回撥則可以拿到音視訊資料,否則就直接控制代碼播放
if (callback) {
PlayM4_SetDecCallBackMend(port, DecCallBack, (quser)this);
PlayM4_Play(port, NULL);
} else {
PlayM4_Play(port, (HWND)playWidget->winId());
}
//同時播放聲音
PlayM4_PlaySound(port);
//倒放
//PlayM4_ReversePlay(port);
//快進播放,多次呼叫速度更快
//PlayM4_Fast(port);
//PlayM4_Fast(port);
ok = true;
qDebug() << TIMEMS << "開啟視訊檔案成功" << url;
} else {
qDebug() << TIMEMS << "開啟視訊檔案失敗" << url << PlayM4_GetLastError(port);
}
return ok;
}
void HaiKangThread::free()
{
if (isRtsp) {
//停止播放+登出裝置
NET_DVR_StopRealPlay(hand);
NET_DVR_Logout(hand);
hand = -1;
} else {
//停止播放+關閉檔案+釋放埠
PlayM4_Stop(port);
PlayM4_StopSound();
PlayM4_CloseFile(port);
PlayM4_FreePort(port);
port = -1;
}
}