1. 程式人生 > 實用技巧 >Qt音視訊開發20-海康sdk本地播放

Qt音視訊開發20-海康sdk本地播放

一、前言

海康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停止函式來通知介面。

關於本地檔案請注意以下幾點:

  1. 檔案方式播放下,不能呼叫PlayM4_CloseStream。
  2. 流播放下,不能呼叫PlayM4_CloseFile介面。
  3. 流開關介面和檔案開關介面不能交叉使用。

二、功能特點

  1. 支援播放視訊流和本地MP4檔案。
  2. 支援控制代碼和回撥兩種模式。
  3. 多執行緒顯示影象,不卡主介面。
  4. 自動重連網路攝像頭。
  5. 可設定邊框大小即偏移量和邊框顏色。
  6. 可設定是否繪製OSD標籤即標籤文字或圖片和標籤位置。
  7. 可設定兩種OSD位置和風格。
  8. 可設定是否儲存到檔案以及檔名。
  9. 可直接拖曳檔案到haikangwidget控制元件播放。
  10. 支援h264/h265視訊流。
  11. 可暫停播放和繼續播放。
  12. 支援儲存單個視訊檔案和定時儲存視訊檔案。
  13. 自定義頂部懸浮條,傳送單擊訊號通知,可設定是否啟用。
  14. 可設定畫面拉伸填充或者等比例填充。
  15. 可設定解碼是速度優先、質量優先、均衡處理。
  16. 可對視訊進行截圖(原始圖片)和截圖(視訊窗體)。
  17. 錄影檔案儲存為MP4檔案。
  18. 支援焦距控制、雲臺控制。
  19. 可定製功能。

三、效果圖

四、相關站點

  1. 國內站點:https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 國際站點:https://github.com/feiyangqingyun/QWidgetDemo
  3. 個人主頁:https://blog.csdn.net/feiyangqingyun
  4. 知乎主頁:https://www.zhihu.com/people/feiyangqingyun/
  5. 體驗地址: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;
    }
}