使用海康的解碼庫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