解碼海康攝像機的錄像 及 延時裝載庫


    使用海康的解碼庫playctrl.dll來解碼海康的錄像。下面的代碼僅供參考。

    下面的代碼演示了這樣一種機制:在多個工程中共享代碼的時候,有的工程需要調用某些庫,有的工程不需要,但是由於源代碼互相引用導致即使用不到某個庫的程序,也需要隨同發布這個庫,否則程序會在啟動的時候報錯找不到指定的庫。

    解決這個問題的方法之一是使用動態裝載,用 LoadLibrary 動態裝載庫,用 GetProcAddress 獲得要調用的函數的地址,用函數指針調用。但是這個方法比較麻煩。

    下面代碼解決的方法是使用延時裝載(DelayLoad)機制,同時使用 LoadLibrary 來判斷是否有庫。

(1)用延時裝載庫來避免啟動的時候就需要庫

        #pragma comment(linker, "/DelayLoad:PlayCtrl.dll")
        #pragma comment(lib, "Delayimp.lib")

(2)當執行到庫里面的函數的時候,會自動延時裝載(此時若無法裝載庫程序會報錯)

        程序代碼里面都是直接靜態鏈接調用庫里面的函數。

(3)但在執行之前,用動態裝載的方法先判斷是否有這個庫,如果沒有,則返回失敗,不繼續執行

 

#ifndef __HSS_HIK_MP4_HSS__
#define __HSS_HIK_MP4_HSS__


/**************************************************************************************************\
 *  2012-09-13
 播放海康的錄像

  用法:
  
    int __stdcall auto_hikmp4_callback_imp(LPARAM lParam, DWORD dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits)
    {
        if (dwTick == 0)
        {
            //播放停止了
        }
        else
        {
            ProcessRgb(0, lParam, dwTick, pbih, pBits, pbih->biSizeImage, 0, 0);
        }

        return 0;
    }

    auto_hikmp4 ahk;
    ahk.param.pCallback = auto_hikmp4_callback_imp;
    ahk.param.lParma = (LPARAM)this;
    ahk.Open(pszFile);

    ahk.Close();
\**************************************************************************************************/

#include <auto_dll.h>
#include <auto_yuv.h>
#include <HBuffer.h>
#include <auto_bitmap_file.h>
#include <StringN.h>

#include "PlayM4.h"
#pragma comment(lib, "\\hss\\R2\\Projects\\Common\\hikmp4\\PlayCtrl.lib")
#pragma comment(linker, "/DelayLoad:PlayCtrl.dll")
#pragma comment(lib, "Delayimp.lib")

typedef int (__stdcall *auto_hikmp4_callback) (LPARAM lParam, DWORD dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits);

class auto_hikmp4
{
public:
    auto_hikmp4()
    {
        m_bLibOk = 0;
        m_lPort = -1;
        m_dwPlayTick = 0;
        m_dwFrameCount = 0;

        __memzero(param);
    }

    ~auto_hikmp4()
    {
        Close();
    }

    struct
    {
        auto_hikmp4_callback    pCallback;
        LPARAM                    lParam;
        DWORD                    bPlayFastest : 1;        //2013年4月28日 最高速度播放,不控制幀率
    }param;

public:

    BOOL Open(LPCTSTR pszFile)
    {
        Close();

        if (!m_bLibOk)
        {
            auto_lib lib;

            //由於對 PlayCtrl.dll 庫的調用是延時裝載的(DelayLoad)因此即使沒有這個庫,程序
            //也可以正常啟動,但是當執行到調用庫里面的函數的時候會導致錯誤。因此這里還要動態裝載一下這個庫
            //這樣如果沒有這個庫,則返回失敗不繼續執行。如果有這個庫,則這里釋放動態裝載的,下面調用庫里面的函數
            //的時候 DelayLoad 機制會起作用。
            //這種方式即避免了動態裝載程序的復雜性,也避免了靜態連接庫的時候發布也必須帶着這個庫
            //因為在很多工程中共享代碼的時候,可能有的工程用不到這個庫,但代碼互相引用導致還需要包含這個代碼
            //這樣用不到這個庫的程序,不用附帶發布這個庫,也可以正常啟動運行。
            if (!lib.LoadLibrary("PlayCtrl.dll"))
                return FALSE;

            lib.Release();

            Sleep(10);

            m_bLibOk = TRUE;
        }

        auto_file af;

        if (!af.OpenRead(pszFile))
            return FALSE;

        DWORD mark = 0;
        if (!af.Read((LPBYTE)&mark, 4))
            return FALSE;

        if (mark != *(DWORD*)"4HKH"
            && mark != *(DWORD*)"IMKH"
            )
        {
            return FALSE;
        }

        af.Close();

        Sleep(10);

        PlayM4_GetPort(&m_lPort);
        if (m_lPort == -1)
            return FALSE;

        PlayM4_SetDecCallBackMend(m_lPort, DecCBFun, (long)this);
        PlayM4_SetFileEndCallback(m_lPort, FileEndCallback, (void*)this);

        if (param.bPlayFastest)
        {
            PlayM4_SetStreamOpenMode(m_lPort, STREAME_REALTIME);
        }

        if(!PlayM4_OpenFile(m_lPort, (char*)pszFile))
            return FALSE;

        m_dwFrameCount = PlayM4_GetFileTotalFrames(m_lPort);

        PlayM4_Play(m_lPort, 0);

        return TRUE;
    }

    void CallbackDecode(FRAME_INFO* pfi, LPBYTE pBuffer, int nSize)
    {
        if (pfi->nType != T_YV12)        //T_RGB32, T_UYVY
            return;

        DWORD dwTick = GetTickCount();

        if (m_dwPlayTick == 0)
            m_dwPlayTick = dwTick;

        if (!param.bPlayFastest)    //2013年4月28日
        {
            while (dwTick + 5 < m_dwPlayTick + pfi->nStamp)
            {
                Sleep(5);
                dwTick = GetTickCount();
            }
        }

        int width = pfi->nWidth;
        int height = pfi->nHeight;

        auto_bitmap_file abf;
        LPBYTE pb = abf.GetBitmap(&m_BufBmp, 24, width, height);
        if (pb == 0)
            return;

        m_yuv.i420(pBuffer, pb, width, height);

        if (param.pCallback)
        {
            param.pCallback(param.lParam, dwTick, abf.bih(), abf.bits());
        }
    }

    static void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)
    {
        auto_hikmp4* phm = (auto_hikmp4*)nReserved1;
        if (phm == 0)
            return;

        ASSERT(nPort == phm->m_lPort);

        phm->CallbackDecode(pFrameInfo, (LPBYTE)pBuf, nSize);
    }

    static void CALLBACK FileEndCallback(long nPort, void *pUser)
    {
        auto_hikmp4* phm = (auto_hikmp4*)pUser;
        if (phm == 0)
            return;

        ASSERT(nPort == phm->m_lPort);

        if (phm->param.pCallback)
        {
            phm->param.pCallback(phm->param.lParam, 0, 0, 0);
        }
    }

    void Close()
    {
        if (m_lPort != -1)
        {
            PlayM4_Stop(m_lPort);
            PlayM4_CloseFile(m_lPort);
            PlayM4_FreePort(m_lPort);

            m_lPort = -1;
        }

        m_dwPlayTick = 0;
    }

public:
    BOOL        m_bLibOk;
    LONG        m_lPort;
    auto_yuv    m_yuv;
    HBuffer        m_BufBmp;
    DWORD        m_dwPlayTick;

    DWORD        m_dwFrameCount;
};


#endif


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM