溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Qt海康sdk回調(diào)方法是什么

發(fā)布時(shí)間:2021-12-15 10:30:01 來(lái)源:億速云 閱讀:338 作者:iii 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹“Qt??祍dk回調(diào)方法是什么”,在日常操作中,相信很多人在Qt??祍dk回調(diào)方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Qt海康sdk回調(diào)方法是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

一、前言

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

折騰了很久總結(jié)失敗在哪里,調(diào)用NET_DVR_RealPlay_V40設(shè)置回調(diào)函數(shù)也是對(duì)的,回調(diào)函數(shù)里面也進(jìn)去了,調(diào)用PlayM4_SetDecCallBackMend設(shè)置解碼回調(diào)函數(shù)也是對(duì)的(這地方也著實(shí)折騰了一陣子,沒想到還要用播放MP4的形式來(lái)處理),最后發(fā)現(xiàn)問題出在解碼后的數(shù)據(jù),數(shù)據(jù)也都是拿到了,默認(rèn)是yv12的數(shù)據(jù),如果需要轉(zhuǎn)成image的話就需要做個(gè)轉(zhuǎn)換,這個(gè)轉(zhuǎn)換網(wǎng)上找了一堆的函數(shù)來(lái)測(cè)試,都失敗了,后面找到一個(gè)yv12轉(zhuǎn)rgb888格式的,終于可以了,我勒個(gè)去。

??祍dk回調(diào)流程:

  1. 調(diào)用NET_DVR_RealPlay_V40設(shè)置回調(diào)處理函數(shù)。

  2. 在回調(diào)處理函數(shù)RealDataCallBack中依次處理打開、播放、解碼。

  3. 調(diào)用PlayM4_GetPort獲取播放庫(kù)未使用的通道號(hào)。

  4. 調(diào)用PlayM4_OpenStream打開視頻流。

  5. 調(diào)用PlayM4_SetDecCallBackMend設(shè)置解碼回調(diào)函數(shù),只解碼不顯示。

  6. 調(diào)用PlayM4_Play播放視頻流。

  7. 調(diào)用PlayM4_InputData循環(huán)解碼數(shù)據(jù)。

  8. 在解碼回調(diào)函數(shù)DecCallBack中分別處理音視頻數(shù)據(jù)。

  9. 調(diào)用自己封裝的yv12ToRGB888函數(shù)將數(shù)據(jù)轉(zhuǎn)成QImage。

關(guān)于回調(diào)函數(shù)請(qǐng)注意以下幾點(diǎn):

  1. 回調(diào)函數(shù)必須有關(guān)鍵詞 CALLBACK。

  2. 回調(diào)函數(shù)本身必須是全局函數(shù)或者靜態(tài)函數(shù),不可定義為某個(gè)特定的類的成員函數(shù)。

  3. 回調(diào)函數(shù)并不由開發(fā)者直接調(diào)用執(zhí)行,只是使用系統(tǒng)接口API函數(shù)作為起點(diǎn)。

  4. 回調(diào)函數(shù)通常作為參數(shù)傳遞給系統(tǒng)API,由該API來(lái)調(diào)用。

  5. 回調(diào)函數(shù)可能被系統(tǒng)API調(diào)用一次,也可能被循環(huán)調(diào)用多次。

二、功能特點(diǎn)

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

  2. 支持句柄和回調(diào)兩種模式。

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

  4. 自動(dòng)重連網(wǎng)絡(luò)攝像頭。

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

  6. 可設(shè)置是否繪制OSD標(biāo)簽即標(biāo)簽文本或圖片和標(biāo)簽位置。

  7. 可設(shè)置兩種OSD位置和風(fēng)格。

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

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

  10. 支持h364/h365視頻流。

  11. 可暫停播放和繼續(xù)播放。

  12. 支持存儲(chǔ)單個(gè)視頻文件和定時(shí)存儲(chǔ)視頻文件。

  13. 自定義頂部懸浮條,發(fā)送單擊信號(hào)通知,可設(shè)置是否啟用。

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

  15. 可設(shè)置解碼是速度優(yōu)先、質(zhì)量?jī)?yōu)先、均衡處理。

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

  17. 錄像文件存儲(chǔ)為MP4文件。

  18. 支持焦距控制、云臺(tái)控制。

  19. 可定制功能。

三、效果圖

Qt??祍dk回調(diào)方法是什么

四、核心代碼

//yv12轉(zhuǎn)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;
}

//解碼回調(diào) 視頻為YUV420P數(shù)據(jù)(YV12),音頻為PCM數(shù)據(jù)
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;

    //視頻數(shù)據(jù)是 T_YV12 音頻數(shù)據(jù)是 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)
{
    //每個(gè)類都對(duì)應(yīng)自己的 port
    HaiKangThread *thread = (HaiKangThread *)dwUser;
    qport nPort = thread->port;

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

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

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

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

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

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

到此,關(guān)于“Qt海康sdk回調(diào)方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

qt
AI