123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587 |
- #ifndef _TWINKLE_DOC_VIDEOCAP_H__
- #define _TWINKLE_DOC_VIDEOCAP_H__
- #pragma once
- #include "SpBase.h"
- #include <opencv2/opencv.hpp>
- #include <string>
- #include <vector>
- #include <deque>
- #include "Dshow.h"
- #include "atlconv.h"
- #include "Dbt.h"
- #include "fileutil.h"
- #include "PortableScannerFSM.h"
- #pragma comment(lib,"Strmiids.lib")
- #pragma comment(lib,"Quartz.lib")
- #define TEST_FUNCTION
- #define DEFAULT_MAT_WINDOW_NAME TEXT("DOC-SCANNER_AREA_WINDOWS")
- using namespace cv;
- using namespace std;
- #define SAFE_RELEASE_IDEV(hd) \
- do { \
- if(hd != NULL) { \
- hd->Release(); \
- hd = NULL; \
- } \
- } while (false)
- typedef struct _CAMERA_INFOR_ITEM
- {
- char szDevName[MAX_PATH];
- char szCLSID[MAX_PATH];
- char szDevPath[MAX_PATH];
- LONG uWaveInID;
- void Cleanup() {
- uWaveInID = 0;
- memset(szDevName, 0, sizeof(szDevName));
- memset(szCLSID, 0, sizeof(szCLSID));
- memset(szDevPath, 0, sizeof(szDevPath));
- }
- void Copy(struct _CAMERA_INFOR_ITEM* prhs) {
- if(prhs != NULL) {
- uWaveInID = prhs->uWaveInID;
- strcpy(szDevPath, prhs->szDevPath);
- strcpy(szDevName, prhs->szDevName);
- strcpy(szCLSID, prhs->szCLSID);
- }
- }
- void Display() {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("[%ld]%s(%s)",uWaveInID, szDevName, szDevPath);
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("CLSID:%s", szCLSID);
- }
- } CAMERA_INFOR_ITEM, *PCAMERA_INFOR_ITEM;
- static int WrapW2A(VARIANT& varirant, char* szDst, const size_t maxLen) {
- int count = 0;
- WCHAR tmp[256];
- tmp[0] = 0;
- memset(szDst, '\0', sizeof(char)*maxLen);
- HRESULT hr = StringCchCopyW(tmp, 256, varirant.bstrVal);
- if(hr == S_OK) {
- count = WideCharToMultiByte(CP_ACP, 0, tmp, -1, szDst, maxLen, 0, NULL);
- } else {
- while (varirant.bstrVal[count] != 0x00 && count < maxLen) {
- szDst[count] = (char)varirant.bstrVal[count];
- count++;
- }
- }
- return count;
- /*
- USES_CONVERSION;
- lptstrValue = W2T(Value.bstrVal);
- */
- }
- typedef vector<PCAMERA_INFOR_ITEM> CAMERA_BUCKET;
- typedef CAMERA_BUCKET::const_iterator CAMERA_BUCKET_CITER;
- typedef CAMERA_BUCKET::iterator CAMERA_BUCKET_ITER;
- static void DestoryCamereBuckets(CAMERA_BUCKET& vtCameras)
- {
- if(!vtCameras.empty()) {
- for(CAMERA_BUCKET_ITER it=vtCameras.begin(); it!=vtCameras.end(); ++it) {
- if(*it) {
- delete (*it);
- (*it) = NULL;
- }
- }
- vtCameras.clear();
- }
- }
- // return the origin old count of video devices.
- int UpdateCameraInfors(CAMERA_BUCKET& vtCameraList);
- int GetCameraInfors(CAMERA_BUCKET& vtCameraList);
- int GetCameraCount();
- //returned value:
- // -2:inner error; -1:not founed; 0:idle; 1:busy
- int IsDeviceBusy(const char* lpcszDeviceName);
- void DisplayCameraInfos(const CAMERA_BUCKET& vtCameraList);
- // condition: lhs contains rhs or rhs contains lhs, use size() to judge which is more wider
- // return the diff elements
- int ExclusiveCameraBuckes(const CAMERA_BUCKET& lhs, const CAMERA_BUCKET& rhs, CAMERA_BUCKET& diff);
- #define EVTCODE_SCAN 0x0001
- #define EVTSTATUS_LOOSE 0x00
- #define EVTSTATUS_QUEUING 0x01
- #define EVTSTATUS_DEALING 0x02
- #define EVTSTATUS_DONE_MASK 0x10
- #define EVTSTATUS_DONE_SUCC 0x11
- #define EVTSTATUS_DONE_FAIL 0x12
- #define EVTSTATUS_ERROR_MASK 0x80
- #define EVTSTATUS_NOT_FOUND 0x81
- #define EVTSTATUS_TIMEOUT 0x82
- #define EVTPRIO_DEFAULT 0x00
- enum { GRAY=0, COLORFUL, MAX_COLORMODE };
- enum { ROI_DEFAULT=0, ROI_A4, ROI_IDCER, ROI_CUSTOM, MAX_RIOMODE };
- #define DR_X 0
- #define DR_Y 0
- #define DR_W 960
- #define DR_H 540
- class CDocScannerCap;
- typedef void (CDocScannerCap::*pFnEventFinished)
- (USHORT evtCode, UCHAR result, UINT checksum);
- extern pFnEventFinished OnEvtFinished;
- struct RequestEvent {
- RequestEvent():_cap(NULL){}
- UINT evtUniqueID; //Additional
- USHORT evtCode;
- UCHAR evtStatus;
- UCHAR evtPriority;
-
- void SetCapHandle(CDocScannerCap* cap) {
- _cap = cap;
- }
- void OnAnswer() {
- if(_cap && (evtStatus & EVTSTATUS_DONE_MASK)) {
- (_cap->*OnEvtFinished)(evtCode, evtStatus, evtUniqueID);
- }
- }
- enum { ReqLen, ReqVal, AnsLen, AnsVal } valType;
- union {
- DWORD dwDataLen;
- struct {
- WORD wHigh;
- WORD wLow;
- } dataVal;
- };
- CHAR* evtData;
- private:
- CDocScannerCap* _cap;
- };
- typedef RequestEvent *RequestEventPtr;
- static RequestEventPtr CreateRequestEvent(
- USHORT code,
- UCHAR status = EVTSTATUS_LOOSE,
- UCHAR priority = EVTPRIO_DEFAULT
- )
- {
- RequestEvent* evt = new RequestEvent();
- if(evt) {
- evt->evtCode = code;
- evt->evtStatus = status;
- evt->evtPriority = priority;
- evt->valType = RequestEvent::ReqLen;
- evt->dwDataLen = 0;
- evt->evtData = NULL;
- }
- return evt;
- }
- static void DestroyRequestEvent(RequestEventPtr *reqEvt)
- {
- if(reqEvt == NULL || (*reqEvt) == NULL) {
- return;
- }
- //TODO: Need Resouce Lock?
- RequestEventPtr pReqEvt = *reqEvt;
- if((pReqEvt->valType == RequestEvent::ReqLen || pReqEvt->valType == RequestEvent::ReqLen)
- && pReqEvt->dwDataLen > 0) {
- assert(pReqEvt->evtData != NULL);
- free(pReqEvt->evtData);
- pReqEvt->evtData = NULL;
- pReqEvt->dwDataLen = 0;
- }
- delete pReqEvt;
- reqEvt = NULL;
- return;
- }
- typedef std::deque<RequestEventPtr> EVENT_QUEUE;
- typedef EVENT_QUEUE::const_iterator EVENT_QUEUE_CITER;
- typedef EVENT_QUEUE::iterator EVENT_QUEUE_ITER;
- class CDocScannerCap
- {
- public:
- CDocScannerCap(CPortableScannerFSM* pFSM = NULL);
- ~CDocScannerCap(void);
- void Test();
- int GetCurScanID() const {
- return m_videoID;
- }
- cv::String GetCurDevName() {
- return devName;
- }
- int GetSpecificedCamInfor(const int camID, PCAMERA_INFOR_ITEM info);
- int GetCurCamInfo(PCAMERA_INFOR_ITEM info) {
- if(m_videoID >= 0) {
- return GetSpecificedCamInfor(m_videoID, info);
- }
- return m_videoID;
- }
- bool Open(unsigned int idx);
- bool OpenCamera(LPCTSTR lpcszDev);
- bool StartPreview();
- bool TerminatePreview();
- bool ScanImage(const char* lpcszFilePath);
- bool CloseCamera();
- bool ResetCamera();
- //Query status;
- bool IsAttached() const {
- return _isVal();
- }
- bool IsPreview() const {
- return m_fPreviewing;
- }
- bool IsWinHide() {
- return (!!m_bHide);
- }
- void DestroyPreviewWindow() {
- if(m_fPreviewing) {
- TerminatePreview();
- }else {
- _destroyWindow();
- }
- }
- //Attribute
- void SetColor(uchar attr) {
- if(attr >=0 && attr < MAX_COLORMODE) {
- m_colorMode = attr;
- }
- }
- uchar GetColorMode() const {
- return m_colorMode;
- }
- void SetWinPosition(int x, int y, int width, int height) {
- if(x >= 0 && y >= 0 && width >= 0 && height >= 0) {
-
- int nFullWidth = GetSystemMetrics(SM_CXSCREEN);
- int nFullHeight = GetSystemMetrics(SM_CYSCREEN);
- m_winSize.x = x;
- m_winSize.y = y;
- m_winSize.width = width;
- m_winSize.height = height;
- _resizeWindow();
- }
- }
- //Set region of capture.
- void SetROC(uchar region) {
- if(ROI_DEFAULT <= region && region < MAX_RIOMODE) {
- m_roiMode = region;
- if(m_roiMode == ROI_IDCER) {
- m_roiRate = 0.4f;
- } else {
- m_roiRate = 1.0f;
- }
- }
- }
- void SetROCValue(float value) {
- if(value >= 0.0f && value <= 1.0f) {
- m_roiRate = value;
- m_roiMode = ROI_CUSTOM;
- }
- }
- uchar GetROC() const {
- return m_roiMode;
- }
- void SetWinShown(bool bShown = true) {
- if(m_defWnd) {
- int nCmdShow = bShown ? SW_SHOW : SW_HIDE;
- ::ShowWindow(m_defWnd, nCmdShow);
- m_bHide = !bShown;
- }
- }
- void MouseClick( int event, int x, int y, int flags);
- void EvtFinishedHandle(USHORT evtCode, UCHAR result, UINT checksum);
- void SetHSPSType(bool bTrue = true) {
- m_bHSPSType = bTrue;
- }
- void SetResoultionRatio(int width, int height, int nframes = -1);
- DWORD GetError() const {
- return m_dwErrCode;
- }
- int ImageWriteUntil(LPCTSTR srcFilePath, const cv::Mat& src);
- int Resize(LPCTSTR srcFilePath, DWORD dwSrcFileSize, int compressRate);
- static DWORD GetFileSize(LPCTSTR srcFilePath);
- private:
- static UINT WINAPI WndPreviewDlgProc(PVOID param);
-
- bool InitHwndForNotify();
- bool RegisterVideoNotify();
- bool UnRegisterVideoNotify();
- bool IsColorAbnormal(IplImage* src);
- bool IsFrameFuzzy(IplImage* src);
- void _cleanup(bool toReleaseVC = true) {
- if(m_fPreviewing) {
- TerminatePreview();
- if(!toReleaseVC)
- Sleep(1000); /* 减少 m_cvCap 析构时调用 release 卡死的几率 */
- }
- _destroyWindow();
- if(m_cvCap.isOpened()) {
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("cvCap release...");
- m_cvCap.release();
- m_videoID = -1;
- winName.clear();
- devName.clear();
- }
- //_resetWinSize();
- m_dwErrCode = ERROR_NOT_READY;
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("cvCap release done");
- return;
- }
- void _setProperty();
- void _setMouseCallback();
- size_t _combineFileName(char* szFnBuf, size_t sizeLen);
- int _getCamIDByDevName(LPCTSTR lpcszDevName);
- size_t _setDevName(LPCTSTR lpszName) {
- if(lpszName == NULL) {
- devName = "";
- } else {
- if(!devName.empty()) {
- devName.clear();
- }
- devName = lpszName;
- }
- return devName.size();
- }
- int MatResize(const cv::Mat& src, cv::Mat& dest, int quantity = 95);
- private:
- int m_videoID;
- cv::VideoCapture m_cvCap;
- Mat m_cmFrame;
- HWND m_defWnd;
- DWORD m_dwErrCode;
- HRESULT m_hrCoInited;
- //Windows
- bool _initWindow(bool fShown = false);
- //It would be invoked when received TerminatePreview requirement.
- void _destroyWindow();
- HANDLE m_hPreviewPro;
- cv::String winName;
- cv::String devName;
- //status
- bool _isVal() const{
- return !!m_cvCap.isOpened();
- }
- //event queue
- EVENT_QUEUE m_requestList;
- bool HasRequest() {
- if(m_requestList.empty()) {
- return false;
- }
- return true;
- }
- UINT GetUniqueID() const {
- UINT id = m_requestList.size();
- assert(id < UINT_MAX);
- return id;
- }
- RequestEventPtr CreateRequestEvent(
- USHORT code,
- UCHAR status = EVTSTATUS_LOOSE,
- UCHAR priority = EVTPRIO_DEFAULT
- )
- {
- RequestEventPtr evt = ::CreateRequestEvent(code, status, priority);
- if(evt) {
- evt->evtUniqueID = GetUniqueID();
- evt->SetCapHandle(this);
- }
- return evt;
- }
- RequestEventPtr GetRequest(bool fServerSide = true, USHORT matchedCode = (USHORT)0) {
- assert(!fServerSide || !matchedCode);
- RequestEventPtr ptr = NULL;
- if(!m_requestList.empty()) {
- for(EVENT_QUEUE_ITER iter=m_requestList.begin();
- iter!=m_requestList.end(); ++iter) {
- assert((*iter));
- RequestEventPtr item = *iter;
- if(fServerSide && item->evtStatus == EVTSTATUS_QUEUING) {
- //TODO:
- item->evtStatus = EVTSTATUS_DEALING;
- ptr = item;
- break;
- }
- if(!fServerSide && ((item->evtStatus & EVTSTATUS_DONE_MASK) == EVTSTATUS_DONE_MASK)) {
- if(!matchedCode || (matchedCode == item->evtCode)) {
- ptr = item;
- break;
- }
- }
- }
- }
- return ptr;
- }
-
- int WaitForResponse(USHORT aimCode, DWORD dwMillSecond = INFINITE) {
- int nRet = EVTSTATUS_NOT_FOUND;
- RequestEventPtr item = NULL;
- const DWORD dwStart = GetTickCount();
- if(dwMillSecond == INFINITE) {
- //TODO:
- return nRet;
- }
- else {
- nRet = EVTSTATUS_TIMEOUT;
- while (getTickCount() >= dwStart + dwMillSecond)
- {
- item = GetRequest(false, aimCode);
- if(item) {
- nRet = item->evtStatus;
- break;
- }
- }
- }
- if(item) {
- //Destroy ??
- TakeOutFromRequestQueue(item);
- }
- return nRet;
- }
-
- bool TakeOutFromRequestQueue(RequestEventPtr pEvtReq) {
- int offset = -1;
- if(!m_requestList.empty()) {
- int tmp = 0;
- for(EVENT_QUEUE_ITER iter=m_requestList.begin() ;
- iter!=m_requestList.end(); ++iter, ++tmp) {
- if(pEvtReq->evtUniqueID == (*iter)->evtUniqueID
- && pEvtReq->evtCode == (*iter)->evtCode) {
- assert((*iter) == pEvtReq);
- offset = tmp;
- break;
- }
- }
- }
- if(offset != -1) {
- m_requestList.erase(m_requestList.begin()+offset);
- DestroyRequestEvent(&pEvtReq);
- return true;
- }
- return false;
- }
- int PostIntoRequestQueue(RequestEventPtr* ppEvtReq) {
- assert(ppEvtReq && *ppEvtReq);
- (*ppEvtReq)->evtStatus = EVTSTATUS_QUEUING;
- m_requestList.push_back(*ppEvtReq);
- return (int)(m_requestList.size());
- }
- void RequestQueueCleanup() {
- LOG_FUNCTION();
- if(!m_requestList.empty()) {
- for(EVENT_QUEUE_ITER iter=m_requestList.begin() ;
- iter!=m_requestList.end(); ++iter) {
- if((*iter) != NULL) {
- DestroyRequestEvent(&(*iter));
- }
- }
- m_requestList.clear();
- }
- }
- //Preview
- bool _executePreview();
- volatile bool m_fPreviewing;
- bool m_tpStopPreview;
- //Attributes
- uchar m_colorMode;
- uchar m_roiMode;
- float m_roiRate;
- BOOL m_bHide;
- cv::Rect m_winSize;
- void _resizeWindow() {
- if(m_defWnd != NULL) {
- BOOL bRet = ::SetWindowPos(m_defWnd, HWND_TOPMOST,
- m_winSize.x, m_winSize.y, m_winSize.width, m_winSize.height,
- m_bHide ? SWP_HIDEWINDOW : SWP_SHOWWINDOW);
- Area area = _getWindowRect();
- }
- }
- void _resetWinSize() {
- m_winSize.x = DR_X;
- m_winSize.y = DR_Y;
- m_winSize.width = DR_W;
- m_winSize.height = DR_H;
- }
- typedef Point Area;
- Area _getWindowRect() {
- Area res;
- if(m_defWnd != NULL) {
- RECT rect;
- GetClientRect(m_defWnd, &rect);
- res.x = rect.right - rect.left;
- res.y = rect.bottom - rect.top;
- }
- return res;
- }
- //Cut
- enum{ NOT_SET = 0, IN_PROCESS = 1, SET = 2 };
- static const int rectangle_thickness = 2;
- uchar rectStatus;
- void _setInterestArea();
- void _setResizeArea(float ratio = 1.0f);
- Rect rect;
- Rect drawableRect;
- // 后置摄像头对于画幅设置无效 -Josephus@2017126 14:51:14
- bool m_bHSPSType;
- CPortableScannerFSM* m_pFSM;
- void SetResetEvent() {
- if(m_pFSM) {
- m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_ERROR_IN_PREVIEW));
- }
- }
- };
- #endif //_TWINKLE_DOC_VIDEOCAP_H__
|