91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Qt海康sdk回調方法是什么

發布時間:2021-12-15 10:30:01 來源:億速云 閱讀:352 作者:iii 欄目:互聯網科技

這篇文章主要介紹“Qt海康sdk回調方法是什么”,在日常操作中,相信很多人在Qt海康sdk回調方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Qt海康sdk回調方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一、前言

海康sdk顯示實時視頻流除了支持句柄方式以外,也支持回調的方式拿到每一張圖片自己繪制處理,當然回調除了拿到視頻數據,其實音頻數據也一塊拿到了,自行調用音頻設備播放就行,關于海康sdk回調這塊,還著實折騰了一陣子才搞定,可能最開始沒有參照提供的demo以及沒有徹底的搜索吧,只是單單看sdk的文檔折騰來折騰去的,搞了一星期居然沒搞定,后面找到了正確的辦法才發現,原來就差一點點一丟丟呢,這又讓我聯想到很多事情,包括生活中的事情,不都是如此么?當你鉚足了勁,試驗搞了各種辦法,快要精疲力盡放棄的時候,其實此時離成功就差一步了,真的就差那么一丟丟,處理生活中的很多事情也是如此,所以很多時候如果方向對了,堅持過努力過,還不行的話,再努力一把估計就ok了。

折騰了很久總結失敗在哪里,調用NET_DVR_RealPlay_V40設置回調函數也是對的,回調函數里面也進去了,調用PlayM4_SetDecCallBackMend設置解碼回調函數也是對的(這地方也著實折騰了一陣子,沒想到還要用播放MP4的形式來處理),最后發現問題出在解碼后的數據,數據也都是拿到了,默認是yv12的數據,如果需要轉成image的話就需要做個轉換,這個轉換網上找了一堆的函數來測試,都失敗了,后面找到一個yv12轉rgb888格式的,終于可以了,我勒個去。

海康sdk回調流程:

  1. 調用NET_DVR_RealPlay_V40設置回調處理函數。

  2. 在回調處理函數RealDataCallBack中依次處理打開、播放、解碼。

  3. 調用PlayM4_GetPort獲取播放庫未使用的通道號。

  4. 調用PlayM4_OpenStream打開視頻流。

  5. 調用PlayM4_SetDecCallBackMend設置解碼回調函數,只解碼不顯示。

  6. 調用PlayM4_Play播放視頻流。

  7. 調用PlayM4_InputData循環解碼數據。

  8. 在解碼回調函數DecCallBack中分別處理音視頻數據。

  9. 調用自己封裝的yv12ToRGB888函數將數據轉成QImage。

關于回調函數請注意以下幾點:

  1. 回調函數必須有關鍵詞 CALLBACK。

  2. 回調函數本身必須是全局函數或者靜態函數,不可定義為某個特定的類的成員函數。

  3. 回調函數并不由開發者直接調用執行,只是使用系統接口API函數作為起點。

  4. 回調函數通常作為參數傳遞給系統API,由該API來調用。

  5. 回調函數可能被系統API調用一次,也可能被循環調用多次。

二、功能特點

  1. 支持播放視頻流和本地MP4文件。

  2. 支持句柄和回調兩種模式。

  3. 多線程顯示圖像,不卡主界面。

  4. 自動重連網絡攝像頭。

  5. 可設置邊框大小即偏移量和邊框顏色。

  6. 可設置是否繪制OSD標簽即標簽文本或圖片和標簽位置。

  7. 可設置兩種OSD位置和風格。

  8. 可設置是否保存到文件以及文件名。

  9. 可直接拖曳文件到haikangwidget控件播放。

  10. 支持h364/h365視頻流。

  11. 可暫停播放和繼續播放。

  12. 支持存儲單個視頻文件和定時存儲視頻文件。

  13. 自定義頂部懸浮條,發送單擊信號通知,可設置是否啟用。

  14. 可設置畫面拉伸填充或者等比例填充。

  15. 可設置解碼是速度優先、質量優先、均衡處理。

  16. 可對視頻進行截圖(原始圖片)和截屏(視頻窗體)。

  17. 錄像文件存儲為MP4文件。

  18. 支持焦距控制、云臺控制。

  19. 可定制功能。

三、效果圖

Qt海康sdk回調方法是什么

四、核心代碼

//yv12轉RGB888
static bool yv12ToRGB888(const unsigned char *yv12, unsigned char *rgb888, int width, int height)
{
    if ((width < 1) || (height < 1) || (yv12 == NULL) || (rgb888 == NULL)) {
        return false;
    }

    int len = width * height;
    unsigned char const *yData = yv12;
    unsigned char const *vData = &yData[len];
    unsigned char const *uData = &vData[len >> 2];

    int rgb[3];
    int yIdx, uIdx, vIdx, idx;

    for (int i = 0; i < height; ++i) {
        for (int j = 0; j < width; ++j) {
            yIdx = i * width + j;
            vIdx = (i / 2) * (width / 2) + (j / 2);
            uIdx = vIdx;

            rgb[0] = static_cast<int>(yData[yIdx] + 1.370705 * (vData[uIdx] - 128));
            rgb[1] = static_cast<int>(yData[yIdx] - 0.698001 * (uData[uIdx] - 128) - 0.703125 * (vData[vIdx] - 128));
            rgb[2] = static_cast<int>(yData[yIdx] + 1.732446 * (uData[vIdx] - 128));

            for (int k = 0; k < 3; ++k) {
                idx = (i * width + j) * 3 + k;
                if ((rgb[k] >= 0) && (rgb[k] <= 255)) {
                    rgb888[idx] = static_cast<unsigned char>(rgb[k]);
                } else {
                    rgb888[idx] = (rgb[k] < 0) ? (0) : (255);
                }
            }
        }
    }
    return true;
}

//解碼回調 視頻為YUV420P數據(YV12),音頻為PCM數據
static void CALLBACK DecCallBack(qport nPort, char *pBuf, qport nSize, FRAME_INFO *pFrameInfo, quser luser, quser nReserved2)
{
    HaiKangThread *thread = (HaiKangThread *)luser;
    long frameType = pFrameInfo->nType;

    //視頻數據是 T_YV12 音頻數據是 T_AUDIO16
    if (frameType == T_YV12) {
        //qDebug() << TIMEMS << width << height << thread;
        int width = pFrameInfo->nWidth;
        int height = pFrameInfo->nHeight;
        QImage image(width, height, QImage::Format_RGB888);
        if (yv12ToRGB888((unsigned char *)pBuf, image.bits(), width, height)) {
            thread->setImage(image);
        }
    } else if (frameType == T_AUDIO16) {
        //qDebug() << TIMEMS << "T_AUDIO16" << thread;
    }
}

static void CALLBACK RealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *dwUser)
{
    //每個類都對應自己的 port
    HaiKangThread *thread = (HaiKangThread *)dwUser;
    qport nPort = thread->port;

    DWORD dRet;
    switch (dwDataType) {
        case NET_DVR_SYSHEAD:
            //獲取播放庫未使用的通道號
            if (!PlayM4_GetPort(&nPort)) {
                break;
            }

            if (dwBufSize > 0) {
                thread->port = nPort;
                if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024)) {
                    dRet = PlayM4_GetLastError(nPort);
                    break;
                }

                //設置解碼回調函數 只解碼不顯示
                if (!PlayM4_SetDecCallBackMend(nPort, DecCallBack, (quser)dwUser)) {
                    dRet = PlayM4_GetLastError(nPort);
                    break;
                }

                //打開視頻解碼
                if (!PlayM4_Play(nPort, NULL)) {
                    dRet = PlayM4_GetLastError(nPort);
                    break;
                }

                //打開音頻解碼, 需要碼流是復合流
                if (!PlayM4_PlaySound(nPort)) {
                    dRet = PlayM4_GetLastError(nPort);
                    break;
                }
            }
            break;

        case NET_DVR_STREAMDATA:
            //解碼數據
            if (dwBufSize > 0 && nPort != -1) {
                BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
                while (!inData) {
                    sleep(10);
                    inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
                }
            }
            break;
    }
}

到此,關于“Qt海康sdk回調方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

qt
AI

平陆县| 长丰县| 新田县| 叙永县| 琼海市| 黄梅县| 桦川县| 英吉沙县| 台江县| 攀枝花市| 潮安县| 华阴市| 丹阳市| 南木林县| 德化县| 雅安市| 昌吉市| 潍坊市| 榆中县| 资溪县| 资源县| 姚安县| 定日县| 桐梓县| 龙陵县| 利川市| 安徽省| 涞水县| 大英县| 寿光市| 正定县| 嵩明县| 九江市| 彭水| 崇阳县| 延边| 临桂县| 沿河| 鹿泉市| 沾化县| 靖边县|