#define _WIN32_DCOM  
#include <SDKDDKVer.h>
#include <direct.h> 
#include <thr/threads.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <stdio.h>  
#include <tchar.h>
#include <io.h>
#include <time.h>
#include <sys/types.h>  
#include <sys/stat.h> 
#include "..\..\lib\libcii\cii11\include\libcii.h"   
#include "algo.h" 

extern TCHAR tcLogFile[56];
//
#ifdef UNICODE
#define __FILET__ __FILEW__
#define __FUNCTIONT__ __FUNCTIONW__
#else
#define __FILET__ __FILE__
#define __FUNCTIONT__ __FUNCTION__
#endif 
#define TRACE_OUT(out ,fmt,...) do{TCHAR tcDate[24],tcTime[24];_tstrdate_s(tcDate),_tstrtime_s(tcTime);\
 _ftprintf_s(out, _T(" %s %s - FILE:%s - FUN:%s - LINE:%d \r\n MESSAGE: ") fmt  _T("\r\n")\
,tcDate,tcTime,__FILET__,__FUNCTIONT__,__LINE__, ##__VA_ARGS__); } while (0)
//
#define TRACE_LOG(fmt,...) do{ FILE* stream ; TRACE_OUT(stderr, fmt ,  ##__VA_ARGS__); \
    if( 0 != _tfopen_s(&stream,tcLogFile,_T("a"))) break; \
    TRACE_OUT(stream, fmt ,  ##__VA_ARGS__);  \
    fclose(stream); \
    } while(0)

#import <IsVision_9007\ISCFaceRecognize.dll> no_namespace
#import <IsVision_9007\ISCFaceDetect.dll>    no_namespace
#import <IsVision_9007\ISCFaceRectify.dll>   no_namespace
#import <IsVision_9007\ISCFaceTools.dll>     no_namespace
#import <IsVision_9007\ISCFaceTracking.dll>  no_namespace
#import <IsVision_9007\ISCImageProc.dll>     no_namespace
#import <IsVision_9007\ISCImageQuality.dll>  no_namespace
#import <IsVision_9007\ISXImage.dll>         no_namespace
#import <IsVision_9007\ISCFaceMedia.dll>     no_namespace

#ifdef __cplusplus 
typedef struct Algo_T * LpAlgo_T;
typedef struct Args_T * LpArgs_T;
typedef struct Pipe_T * LpPipe_T;
typedef struct Item_T * LpItem_T;
#define T LpAlgo_T
#define R LpArgs_T
#define P LpPipe_T
#define I LpItem_T
#else 
#define T Arena_T
#define R Args_T
#define P Pipe_T
typedef struct Algo_T *Algo_T;
typedef struct Args_T *Args_T;
typedef struct Pipe_T *Pipe_T;
#endif   

#define _CT_FileName_  0x01
#define _CT_FileData_  0x02
#define _CT_ImageRgb_  0x03

#define _IRecognize    0x0001
#define _ITransImage   0x0002
#define _IFaceDetect   0x0004
#define _IFaceRectify  0x0008
#define _IFaceTool     0x0010
#define _IFaceTrack    0x0020
#define _IImageProc    0x0040
#define _IImageQuality 0x0080
#define _IVisionImage  0x0100 
#define _IPosition     0x0200
#define _IComImageAll  0x01FF

#ifndef _THR_THREADS_H 
#define mtx_init(mtx, typ)  InitializeSRWLock(mtx)
#define mtx_destroy(mtx)   __noop
#define mtx_lock(mtx)        AcquireSRWLockExclusive (mtx)
#define mtx_unlock(mtx)        ReleaseSRWLockExclusive (mtx);
#define cnd_init(cnd)       InitializeConditionVariable(cnd); 
#define cnd_destroy(cnd)   __noop
#define cnd_signal(cnd)        WakeConditionVariable(cnd)
#define cnd_wait(cnd, mtx)  SleepConditionVariableSRW(cnd, mtx, INFINITE, 0)
#define mtx_t_ SRWLOCK
#define cnd_t_ CONDITION_VARIABLE
#else
#define mtx_t_ mtx_t
#define cnd_t_ cnd_t
#endif
#define NUMBER_ALGO 7
#define NUMBER_ITEM 7

struct Global_T
{ 
   long nNumberCpu; 
};
static volatile struct Global_T _global;
TCHAR tcLogFile[56]; 
struct Args_T
{ 
    enumTemplateType eTemplateType;
    PTP_WORK pwkNewTemplate;
    _TCHAR tcIniFile[56];
    _TCHAR tcSN[56];
    _TCHAR tcLicense[56];  
    long lTemplateSize;

    int iNetLogin;  
    int used;
    int total; 
    T* algo; 
    SRWLOCK  srw_;
    static mtx_t_ mtx_;
    static long once; 
    static long count_ref;
};   
mtx_t_ Args_T::mtx_;
long Args_T::once = 0L; 
long Args_T::count_ref = 0L;
//
struct Algo_T
{ 
    IRecognizePtr m_IRecognize;
    ITransImagePtr m_ITransImage;
    IDetectPtr m_pIDetect;
    IFaceRectifyPtr m_pFaceRectify;
    IFaceToolsPtr m_pIFaceTool;
    IFaceTrackingPtr m_pIFaceTrack;
    IImageProcPtr m_pIImageProc;
    IImageQualityPtr m_pIImageQuality;
    IVisionImagePtr m_pIVisionImage; 
    IPositionPtr m_pIPosition;  
    unsigned long nIptrFlag; 
    R m_lpArgs; 
};
typedef struct Data_T *LpData_T;
typedef struct Pipe_T
{
    LpData_T* ptr;
    size_t length;
    size_t used;
    size_t iget;
    size_t iput;
    mtx_t_ _mtx;
    cnd_t_ _cndr;
    cnd_t_ _cndw; 
}* LpPipe_T;
enum eOptType{ eNewTemplate, eNewTemplate2, eCmprTemplate ,eNullOpt };
struct Item_T
{
    T cl;
    eOptType opt;  
    HANDLE event;
    LpPipe_T pipe;
    LpPipe_T pipe2;  
    long ref_count;
    long ref_signal;
    long num_thread;
    long seq;
    bool result;
    static long ref_selfbuf;
    static I selfbuf[NUMBER_ITEM];
    //
    union
    {
        struct
        {
            const char* srcpath;
            const char* wildcard;
            const char* dstfile;  
        }ready;
        struct
        {
            unsigned char** img;
            long* length;
            long  size;
            long  size2;
            const char* imgtype;
            unsigned char** tmp;  
        }ready2;
    };  
    void* pvResult; 
    LpList_T list;
    SRWLOCK  mtx_;
}; 
long Item_T::ref_selfbuf;
I Item_T::selfbuf[NUMBER_ITEM];
struct Data_T
{ 
        union
        {
            struct
            {
                char* file;
            }result;
            struct
            {
                unsigned char** img;
                long* length;
                long  size;
                const char* imgtype;
                long  pos;
            }result2; 
        }; 
        void* pvResult;
        struct
        {  
            double simi;
            long  seq;
            long  size;
        }vTemplate; 
    eOptType opt;
}; 
static P Pipe_new(size_t length)
{
    P pi = (P)malloc(sizeof *pi);
    assert(pi);
    mtx_init(&pi->_mtx, _Mtx_plain);
    cnd_init(&pi->_cndr);
    cnd_init(&pi->_cndw); 
    pi->ptr = (LpData_T*)calloc(length, sizeof LpData_T );
    assert(pi->ptr);
    pi->length = length; 
    pi->used = 0;
    pi->iget = 0;
    pi->iput = 0; 
    return pi;
}
static void Pipe_put(P pi, LpData_T ptr)
{  
    assert(pi);
    mtx_lock(&pi->_mtx);
    while (pi->used >= pi->length)
    {
        cnd_wait(&pi->_cndr, &pi->_mtx);
    }
    pi->ptr[pi->iput++] = ptr;
    ++pi->used;
    if (pi->iput >= pi->length)
    {
        pi->iput = 0;
    }
    cnd_signal(&pi->_cndw);
    mtx_unlock(&pi->_mtx);
}
static void Pipe_get(P pi, LpData_T* ptr)
{
    assert(pi);
    mtx_lock(&pi->_mtx);
    while (pi->used <= 0)
    {
        cnd_wait(&pi->_cndw, &pi->_mtx);
    }
    --pi->used;
    *ptr = pi->ptr[pi->iget++];
    if (pi->iget >= pi->length)
    {
        pi->iget = 0;
    }
    cnd_signal(&pi->_cndr);
    mtx_unlock(&pi->_mtx);
}
static void Pipe_free(P* pi)
{
    assert(pi && *pi);
    assert((*pi)->ptr);
    free((*pi)->ptr);
    mtx_destroy(&(*pi)->_mtx);
    cnd_destroy(&(*pi)->_cndr);
    cnd_destroy(&(*pi)->_cndw); 
    free(*pi);
    (*pi) = nullptr;
}
static R Args_new()
{
    static R ag = nullptr;   
    if (0 == InterlockedCompareExchange(&ag->once, 1L, 0L))
    {
         ag = (R)malloc( sizeof *ag );
         ag->count_ref = 0L;  
         ag->pwkNewTemplate = nullptr;// CreateThreadpoolWork(__ThreadCreateTemplate, ag, NULL);
         InitializeSRWLock(&ag->srw_); 
         mtx_init(&ag->mtx_, _Mtx_plain);  
         {
             TCHAR tcFileName[56], tcModuleFile[MAX_PATH];
             SYSTEM_INFO _syInfo;
             GetSystemInfo(&_syInfo);
             _global.nNumberCpu = _syInfo.dwNumberOfProcessors; 
             GetModuleFileName(NULL, tcModuleFile, MAX_PATH);
             _tsplitpath_s(tcModuleFile, NULL, 0, NULL, 0, tcFileName, 56, NULL, 0);
             _tmakepath_s(ag->tcIniFile, 56, NULL, NULL, tcFileName, _T("ini"));
             _tmakepath_s(tcLogFile, 56, NULL, NULL, tcFileName, _T("log"));
             if (_taccess_s(ag->tcIniFile, 0x04) == 0)
             {
                 GetPrivateProfileString(_T("Register"), _T("sn"), _T(""), ag->tcSN, _countof(ag->tcSN), ag->tcIniFile);
                 GetPrivateProfileString(_T("Register"), _T("license"), _T(""), ag->tcLicense, _countof(ag->tcLicense), ag->tcIniFile);
                 ag->iNetLogin = GetPrivateProfileInt(_T("Register"), _T("netlogin"), 1, ag->tcIniFile);
                 ag->eTemplateType = (enumTemplateType)GetPrivateProfileInt(_T("Parameters"), _T("TemplateType"), 2, ag->tcIniFile);
             }
             else
             {
                 ag->iNetLogin = 1;
                 ag->eTemplateType = (enumTemplateType)2;
                 _tcscpy_s(ag->tcSN, _T(""));
                 _tcscpy_s(ag->tcLicense, _T(""));
             }
         }
         ag->total = _global.nNumberCpu;
         ag->used  = 0;
         ag->algo = (T*)malloc(ag->total * sizeof T); 
         _tprintf(_T("+++++++++++++++++++++++++++++++++++++++++++++++++++++++Args_new.\r\n"));
    }  
    InterlockedIncrement(&ag->count_ref); 
    return ag;
}
static T Algo_get(R ag)
{
    T al;
    mtx_lock(&ag->mtx_);
    if (ag->used > 0)
        al = ag->algo[--ag->used];
    else
        al = nullptr;
    mtx_unlock(&ag->mtx_);
    return al;
}
static bool Algo_put(T al)
{
    R ag = al->m_lpArgs;
    mtx_lock(&ag->mtx_);
    if (ag->used < ag->total && ag->count_ref > 0 )
        ag->algo[ag->used++] = al; 
    else
        al = nullptr;
    mtx_unlock(&ag->mtx_);
    return al != nullptr;
}
static I Item_get()
{
    I im = nullptr; 
    mtx_lock(&Args_T::mtx_);
    if (Item_T::ref_selfbuf > 0) 
    {
        im = Item_T::selfbuf[--Item_T::ref_selfbuf];
        im->ref_count = 0;
        im->seq = 0;
        im->cl = nullptr;
        im->result = false;
        im->pipe->used = 0;
        im->pipe->iget = 0;
        im->pipe->iput = 0;
        im->pipe2->used = 0;
        im->pipe2->iget = 0;
        im->pipe2->iput = 0; 
    }
    else
        im = nullptr;
    mtx_unlock(&Args_T::mtx_);
    return im;
}
static bool Item_put(I im)
{ 
    mtx_lock(&Args_T::mtx_);
    if (Item_T::ref_selfbuf < NUMBER_ITEM && Args_T::count_ref > 0) 
        Item_T::selfbuf[Item_T::ref_selfbuf++] = im; 
    else
        im = nullptr;
    mtx_unlock(&Args_T::mtx_);
    return im != nullptr;
}
static void Item_free(I *im)
{
    assert(im && *im);
    if (!Item_put(*im))
    {
        CloseHandle((*im)->event);
        Pipe_free(&(*im)->pipe);
        Pipe_free(&(*im)->pipe2);
        free(*im);
        (*im) = nullptr;
    }
}
static I Item_new()
{
    I im = Item_get();
    if (nullptr == im)
    {
        im = (I)malloc(sizeof *im);
        im->ref_count = 0;
        im->seq = 0;
        im->cl = nullptr;
        im->result = false;
        InitializeSRWLock(&im->mtx_);
        im->pipe = Pipe_new(3702);
        im->pipe2 = Pipe_new(3702);
        im->event = CreateEvent(NULL, FALSE, FALSE, NULL);
    }
    return im;
}
static void Args_free(R* ag)
{
    long ref;
    assert(ag && *ag);
    ref = InterlockedDecrement(&(*ag)->count_ref);
    if (ref == 0)
    {
        T al;// this code is not excute
        I im;
        assert(ref == 0);
        InterlockedExchange(&(*ag)->once, 0L); 
        while (al = Algo_get(*ag))
        {
            Algo_free(&al);
        } 
        while (im = Item_get())
        {
            Item_free(&im);
        }
        mtx_destroy(&(*ag)->mtx_);
        free((*ag)->algo);
        free(*ag);
        (*ag) = nullptr; 
        _tprintf(_T("-------------------------------------------------------Args_free.\r\n"));
    }
} 
T Algo_new()
{
    R ag = Args_new();
    T al = Algo_get(ag);
    if (!al)
    {
        CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY);
        al = new Algo_T;
        al->nIptrFlag = 0UL; 
        al->m_lpArgs = ag;
    }
    assert(al);
    return al;
} 
static bool NewTemplateFile( const char* filename) 
{  
    size_t len;
    if (0 == _access(filename, 0x06))
    {
        return true;
    }
    if ( 0 < (len = strlen(filename)))
    {
        char* tmpbuf, *p, c;
        tmpbuf = (char*)malloc(len + 1);
        strcpy_s(tmpbuf, len + 1, filename);
        for (p = tmpbuf; *p; ++p)
        {
            if ('\\' != *p && '/' != *p)
            {
                continue;
            }
            c = *++p;
            *p = '\0';
            if ((_access(tmpbuf, 0)) != 0)
            {
                if (0 != _mkdir(tmpbuf))
                { 
                    break;
                }
            }
            *p = c;
        } 
        {
            bool bret;
            FILE* file;
            bret = (0 == _tfopen_s(&file, tmpbuf, _T("a"))); 
            free(tmpbuf);
            fclose(file);
            return bret;
        } 
    }
    else
        return false;
}
static bool IsMatched(CONST TCHAR* p, CONST TCHAR* q)
{
    CONST TCHAR *r, *z, *x = _T("");
    for (r = p; *p; ++p)
        if (*p == '\\')
            r = p + 1;
        else if (*p == '.')
            x = p;
    z = r;
    while (*q)
    {
        while (*q == '|')q++;
        if (*q == '*')
        {
            r = x;
            while (*++q != '.' && *q);
        }
        while (tolower(*q) == tolower(*r) && *r) r++, q++;
        if (*q == '*' || !*r && (!*q || *q == '|'))
        {
            return true;
        }
        while (*q != '|' && *q)++q;
        r = z;
    }
    return false;
}
static void FetchFile(TCHAR* tcFile, size_t nChars, CONST TCHAR* tcWard, P pi)
{
    _tfinddata_t _tfddt;
    intptr_t intptr = _tfindfirst(tcFile, &_tfddt);
    if (-1 == intptr)
    {
        return;
    }
    do
    {
        tcFile[nChars] = '\0';
        if (_tfddt.attrib & _A_SUBDIR )
        {
            if (_tfddt.name[0] != '.')
            {
                _tcscat_s(tcFile, MAX_PATH, _tfddt.name);
                _tcscat_s(tcFile, MAX_PATH, _T("\\"));
                _tcscat_s(tcFile, MAX_PATH, _T("*.*"));
                FetchFile(tcFile, nChars + 1 + _tcslen(_tfddt.name), tcWard, pi);
            }
        }
        else if (IsMatched(_tfddt.name, tcWard))
        {
            LpData_T ptr = (LpData_T)malloc(sizeof(*ptr));
            size_t length = nChars + _tcslen(_tfddt.name) + 1;
            ptr->result.file = new char[length];// (_TCHAR*)malloc( length * sizeof _TCHAR); 
            _tcscat_s(tcFile, MAX_PATH, _tfddt.name);
            _tcscpy_s(ptr->result.file, length, tcFile);
            ptr->opt = eNewTemplate;
            Pipe_put(pi, ptr); 
        }
    } while (0 == _tfindnext(intptr, &_tfddt));
    _findclose(intptr);  
}
static void GetSubDir(CONST TCHAR* tcFile, CONST TCHAR  *tcWard, P pi)
{
    TCHAR tcFileName[MAX_PATH], *pEnd;
    //if (_taccess_s(ag->tcIniFile, 0x04) == 0)
    //
    struct stat s_buf; 
    stat(tcFile, &s_buf);

    /*判断输入的文件路径是否目录,若是目录,则往下执行,分析目录下的文件*/
    if ( s_buf.st_mode&_S_IFDIR)
    {
        _tcscpy_s(tcFileName, tcFile);
        (pEnd = _tcsrchr(tcFileName, '\\'))[1] = '\0';
        _tcscat_s(tcFileName, _T("*.*"));
        FetchFile(tcFileName, pEnd - tcFileName + 1, tcWard, pi);
    }
    else if (s_buf.st_mode&_S_IFREG)
    { 
        TCHAR tcFileExt[24];
        _tsplitpath_s(tcFile, NULL, 0, NULL, 0, tcFileName, MAX_PATH, tcFileExt, 24);
        _tmakepath_s(tcFileName, MAX_PATH, NULL, NULL, tcFileName, tcFileExt);
        if (IsMatched(tcFileName, tcWard))
        {
            LpData_T ptr = (LpData_T)malloc(sizeof(*ptr)); 
            ptr->result.file = new char[MAX_PATH];
            _tcscpy_s(ptr->result.file, MAX_PATH, tcFile);
            ptr->opt = eNewTemplate;
            Pipe_put(pi, ptr);
        }
    }
    Pipe_put(pi, nullptr); 
}  
static void ComObjectInstance(T al, unsigned long nIptrFlag)
{
    HRESULT hr;
    assert(al);
    if ((nIptrFlag & _IRecognize) && !(_IRecognize & al->nIptrFlag))
    {
        al->nIptrFlag &= ~_IRecognize;
        if (FAILED(hr = al->m_IRecognize.CreateInstance(__uuidof(Recognize))))
        {
            TRACE_LOG(_T("_IRecognize接口创建失败:%#08x"), hr);
        }
        else if (FAILED(hr = al->m_IRecognize->SetModelType((enumFrameModelType)al->m_lpArgs->eTemplateType)))
        {
            TRACE_LOG(_T("_IRecognize::SetModelType:ErrCode = %d"), al->m_IRecognize->GetLastError());
        }
        else
        {
            if (al->m_lpArgs->iNetLogin && al->m_IRecognize->Initialize(VARIANT_TRUE) == VARIANT_TRUE
                || !al->m_lpArgs->iNetLogin
                && (((0 == _tcslen(al->m_lpArgs->tcSN) || 0 == _tcslen(al->m_lpArgs->tcLicense))
                    && al->m_IRecognize->Initialize(VARIANT_FALSE) == VARIANT_TRUE) || al->m_IRecognize->SetRegisteredInfo(_bstr_t(al->m_lpArgs->tcSN), _bstr_t(al->m_lpArgs->tcLicense)) == VARIANT_TRUE))
            {
                al->nIptrFlag |= _IRecognize;
                al->m_lpArgs->lTemplateSize = al->m_IRecognize->GetTemplateSize(al->m_lpArgs->eTemplateType);
                TRACE_LOG(_T("_IRecognize:GetVersion() = %s,_IRecognize::GetTemplateSize() = %d"), (const char*)al->m_IRecognize->GetVersion(), al->m_lpArgs->lTemplateSize);
            }
            else
            {
                TRACE_LOG(_T("_IRecognize接口初始化失败:ErrCode = %d"), al->m_IRecognize->GetLastError());
            }
        }
    }
    if ((nIptrFlag & _ITransImage) && !(_ITransImage & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_ITransImage.CreateInstance(__uuidof(TransImage))))
        {
            TRACE_LOG(_T("_ITransImage接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_ITransImage;
        }
        else
        {
            al->nIptrFlag |= _ITransImage;
            TRACE_LOG(_T("_ITransImage:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IFaceDetect) && !(_IFaceDetect & al->nIptrFlag))
    {
        al->nIptrFlag &= ~_IFaceDetect;
        if (FAILED(hr = al->m_pIDetect.CreateInstance(__uuidof(Detect))))
        {
            TRACE_LOG(_T("_IFaceDetect接口创建失败:%#08x"), hr);
        }
        else
        {
            if (al->m_lpArgs->iNetLogin && al->m_pIDetect->Initialize(VARIANT_TRUE) == VARIANT_TRUE
                || !al->m_lpArgs->iNetLogin
                && (((0 == _tcslen(al->m_lpArgs->tcSN) || 0 == _tcslen(al->m_lpArgs->tcLicense))
                    && al->m_pIDetect->Initialize(VARIANT_FALSE) == VARIANT_TRUE) || al->m_pIDetect->SetRegisteredInfo(_bstr_t(al->m_lpArgs->tcSN), _bstr_t(al->m_lpArgs->tcLicense)) == VARIANT_TRUE))
            {
                al->nIptrFlag |= _IFaceDetect;
                TRACE_LOG(_T("_IFaceDetect:GetVersion() = %s"), (const char*)al->m_pIDetect->GetVersion());
            }
            else
            {
                TRACE_LOG(_T("_IFaceDetect接口初始化失败:ErrCode = %d"), al->m_pIDetect->GetLastError());
            }
        }
    }
    if ((nIptrFlag & _IFaceRectify) && !(_IFaceRectify & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pFaceRectify.CreateInstance(__uuidof(FaceRectify))))
        {
            TRACE_LOG(_T("_IFaceRectify接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IFaceRectify;
        }
        else
        {
            al->nIptrFlag |= _IFaceRectify;
            TRACE_LOG(_T("_IFaceRectify:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IFaceTool) && !(_IFaceTool & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pIFaceTool.CreateInstance(__uuidof(FaceTools))))
        {
            TRACE_LOG(_T("_IFaceTool接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IFaceTool;
        }
        else
        {
            al->nIptrFlag |= _IFaceTool;
            TRACE_LOG(_T("_IFaceTool:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IFaceTrack) && !(_IFaceTrack & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pIFaceTrack.CreateInstance(__uuidof(FaceTracking))))
        {
            TRACE_LOG(_T("_IFaceTrack接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IFaceTrack;
        }
        else
        {
            al->nIptrFlag |= _IFaceTrack;
            TRACE_LOG(_T("_IFaceTrack:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IImageProc) && !(_IImageProc & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pIImageProc.CreateInstance(__uuidof(ImageProc))))
        {
            TRACE_LOG(_T("_IImageProc接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IImageProc;
        }
        else
        {
            al->nIptrFlag |= _IImageProc;
            TRACE_LOG(_T("_IImageProc:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IImageQuality) && !(_IImageQuality & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pIImageQuality.CreateInstance(__uuidof(ImageQuality))))
        {
            TRACE_LOG(_T("_IImageQuality接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IImageQuality;
        }
        else
        {
            al->nIptrFlag |= _IImageQuality;
            TRACE_LOG(_T("_IImageQuality:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IVisionImage) && !(_IVisionImage & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pIVisionImage.CreateInstance(__uuidof(VisionImage))))
        {
            TRACE_LOG(_T("_IFaceTrack接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IVisionImage;
        }
        else
        {
            al->nIptrFlag |= _IVisionImage;
            TRACE_LOG(_T("_IFaceTrack:CreateInstance Finished."));
        }
    }
    if ((nIptrFlag & _IPosition) && !(_IPosition & al->nIptrFlag))
    {
        if (FAILED(hr = al->m_pIPosition.CreateInstance(__uuidof(Position))))
        {
            TRACE_LOG(_T("_IPosition接口创建失败:%#08x"), hr);
            al->nIptrFlag &= ~_IPosition;
        }
        else
        {
            al->nIptrFlag |= _IPosition;
        }
    }
}
static void ComObjectRelease(T al, unsigned long nIptrFlag)
{
    if ((nIptrFlag & _IRecognize) && (_IRecognize & al->nIptrFlag))
    {
        al->m_IRecognize->Uninitialize();
        al->m_IRecognize.Release();
        al->nIptrFlag &= ~_IRecognize;
    }
    if ((nIptrFlag & _ITransImage) && (_ITransImage & al->nIptrFlag))
    {
        al->m_ITransImage.Release();
        al->nIptrFlag &= ~_ITransImage;
    }
    if ((nIptrFlag & _IFaceDetect) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pIDetect->Uninitialize();
        al->m_pIDetect.Release();
        al->nIptrFlag &= ~_IFaceDetect;
    }
    if ((nIptrFlag & _IFaceRectify) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pFaceRectify.Release();
        al->nIptrFlag &= ~_IFaceRectify;
    }
    if ((nIptrFlag & _IFaceTool) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pIFaceTool->Uninitialize();
        al->m_pIFaceTool.Release();
        al->nIptrFlag &= ~_IFaceTool;
    }
    if ((nIptrFlag & _IFaceTrack) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pIFaceTrack.Release();
        al->nIptrFlag &= ~_IFaceTrack;
    }
    if ((nIptrFlag & _IImageProc) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pIImageProc.Release();
        al->nIptrFlag &= ~_IImageProc;
    }
    if ((nIptrFlag & _IImageQuality) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pIImageQuality->Uninitialize();
        al->m_pIImageQuality.Release();
        al->nIptrFlag &= ~_IImageQuality;
    }
    if ((nIptrFlag & _IVisionImage) && (_ITransImage & al->nIptrFlag))
    {
        al->m_pIVisionImage.Release();
        al->nIptrFlag &= ~_IVisionImage;
    }
    if ((nIptrFlag & _IPosition) && (_IPosition & al->nIptrFlag))
    {
        al->m_pIPosition.Release();
        al->nIptrFlag &= ~_IPosition;
    }
}
static long Algo_create_template(T al, char* lpData, unsigned char** ppTemplate, int *iTemplateSize, int DataType, long Datalength)
{
    unsigned char* pTemplate;
    assert(al && lpData && ppTemplate);
    if (!(al->nIptrFlag & _ITransImage))
    {
        ComObjectInstance(al, _ITransImage);
    }
    if (!(al->nIptrFlag & _ITransImage))
    {
        return (-1);
    }
    if (!(al->nIptrFlag & _IFaceDetect))
    {
        ComObjectInstance(al, _IFaceDetect);
    }
    if (!(al->nIptrFlag & _IFaceDetect))
    {
        return (-1);
    }
    if (!(al->nIptrFlag & _IPosition))
    {
        ComObjectInstance(al, _IPosition);
    }
    if (!(al->nIptrFlag & _IPosition))
    {
        return (-1);
    }
    switch (DataType)
    {
    case _CT_FileName_:
        if (VARIANT_TRUE != al->m_ITransImage->ReadImageFile(_bstr_t(lpData), enumFileType::TRANS_FILE_TYPE_UNKNOWN))
        {
            TRACE_LOG(_T("加载图像文件失败, ErrCode = %d"), GetLastError());
            return (-1);
        }
        break;
    case _CT_FileData_:
        if (VARIANT_TRUE != al->m_ITransImage->ReadImageData((unsigned char*)lpData, Datalength, enumFileType::TRANS_FILE_TYPE_UNKNOWN))
        {
            TRACE_LOG(_T("加载图像文件失败, ErrCode = %d"), GetLastError());
            return (-1);
        }
        break;
    case _CT_ImageRgb_:
    default:
        TRACE_LOG(_T("建模数据源类型不明确!"));
        return (-1);
    }
    al->m_pIPosition->Clear();
    if (VARIANT_TRUE != al->m_pIDetect->FindFace(al->m_ITransImage, al->m_pIPosition))
    {
        TRACE_LOG(_T("检测人脸失败, ErrCode = %d"), al->m_pIDetect->GetLastError());
        return (-1);
    }
    *iTemplateSize = Algo_template_size(al);
    if (*iTemplateSize < 0)
    {
        return (-1);
    }
    pTemplate = new unsigned char[*iTemplateSize * al->m_pIPosition->GetlFaceNum()];
    if (VARIANT_TRUE != al->m_IRecognize->CreateTemplate(al->m_ITransImage, al->m_pIPosition
        , enumTemplateType::TEMPLATE_TYPE_GENERAL, al->m_pIPosition->GetlFaceNum(), pTemplate))
    {
        TRACE_LOG(_T("创建模版失败, ErrCode = %d"), al->m_IRecognize->GetLastError());
        delete[] pTemplate;
        return (-1);
    }
    *ppTemplate = pTemplate;
    return al->m_pIPosition->GetlFaceNum();
}
static long Algo_create_template(T al, const char* lpFile, unsigned char** ppTemplate, int *iTemplateSize)
{
    return Algo_create_template(al, const_cast<char*>(lpFile), ppTemplate, iTemplateSize, _CT_FileName_, 0);
}
//#define _tprintf 
static void __stdcall __TrySubmitCompareTemplate(
    PTP_CALLBACK_INSTANCE instance,
    PVOID pvctx)
{
    I im = (I)pvctx;
    T al = Algo_new();
    R ag = al->m_lpArgs;
    P in = im->pipe;
    P out = im->pipe2;
    LpData_T ptr = nullptr;
    LpData_T ptr2 = nullptr;
    eOptType eOpt = im->opt;
    PSRWLOCK mtx_ = &im->cl->m_lpArgs->srw_;
    unsigned char *pTemplate = nullptr;
    unsigned char **tmpbuf, **vtmp, *tmp, **vtmp2;
    double *simibuf;
    long i, j, k, size, size2, pos, *length;
    bool result = im->result;
    long seq = InterlockedIncrement(&im->seq);
    CallbackMayRunLong(instance);
    for (;;)
    {
        Pipe_get(in, &ptr);
        if (ptr == nullptr)
        {
            Pipe_put(in, nullptr); //_tprintf(_T("ptr %d == nullptr\r\n"),i);
            if (result)
            {
                Pipe_put(out, nullptr);
            }
            break;
        } 
        vtmp = ptr->result2.img;
        vtmp2 = im->ready2.tmp;
        size = ptr->result2.size;
        size2 = im->ready2.size2;
        pos = ptr->result2.pos;
        simibuf = &((double*)im->pvResult)[pos];
        for (i = 0, k = 0; i < size; ++i)
        {
            tmpbuf = &vtmp[pos + i];
            pTemplate = tmpbuf[0];
            for (j = 0; j < size2; ++j, ++k)
            {
                tmp = vtmp2[j];
                simibuf[k] = k;
#ifndef _DEBUG
                al->m_IRecognize->CompareTemplate(pTemplate, tmp, 0);
#endif
            //    printf("simibuf[%d]= %f\r\n",k+pos, simibuf[k]);
            }
        }
        if (result)
        {

        }
        else
        {

            free(ptr);
        }
    }
    Algo_free(&al);
    assert(im->ref_signal >= 0);
    if (InterlockedDecrement(&im->ref_signal) == 0)
    {
        SetEventWhenCallbackReturns(instance, im->event);
        //_tprintf(_T("%s: SetEventWhenCallbackReturns\r\n"), __FUNCTION__); 
    }
    //_tprintf(_T("%s[%d] - Type[%d] :Exit\r\n"),  __FUNCTION__,seq, im->opt);
}
static void __stdcall __TrySubmitCreateTemplate(
    PTP_CALLBACK_INSTANCE instance,
    PVOID pvctx)
{
    I im = (I)pvctx;
    T al = Algo_new();
    R ag = al->m_lpArgs;
    P in = im->pipe, out = im->pipe2;
    LpData_T ptr = nullptr;
    LpData_T ptr2 = nullptr;
    eOptType eOpt = im->opt;
    PSRWLOCK mtx_ = &ag->srw_;
    unsigned char *pTemplate = nullptr;
    int iTemplateSize = 0;
    bool result = im->result;
    long seq = InterlockedIncrement(&im->seq);
    CallbackMayRunLong(instance);
    for (;;)
    {
        Pipe_get(in, &ptr);
        if (ptr == nullptr)
        {
            Pipe_put(in, nullptr); //_tprintf(_T("ptr %d == nullptr\r\n"),i);
            if (result)
            {
                Pipe_put(out, nullptr);
            }
            break;
        }
        switch (eOpt)
        {
        case eNewTemplate:
        {
            LpList_T *list = &im->list;
            char* file = ptr->result.file; 
#ifndef _DEBUG
            Algo_create_template(al,file , &pTemplate, &iTemplateSize); 
#else
            _tprintf(_T(" %s iTemplateSize %d\r\n"), file,iTemplateSize);
            pTemplate = (unsigned char *)ptr->result.file;
#endif 
            if (result)
            {
                ptr->pvResult = pTemplate;
                Pipe_put(out, ptr);
            }
            else
            {
                AcquireSRWLockExclusive(mtx_);
                *list = List_push(*list, pTemplate);
                *list = List_push(*list, file); 
                ReleaseSRWLockExclusive(mtx_);
                free(ptr);
            }
        }
        break;
        case eNewTemplate2:
        {
            unsigned char **r_pvbuf, **pvTemplate, **img = ptr->result2.img;
            const char* imgtype = ptr->result2.imgtype; 
            long* length = ptr->result2.length, size = ptr->result2.size;
            long pos = ptr->result2.pos, i = 0;
            pvTemplate = &((unsigned char **)im->pvResult)[pos];
            for (; i < size; ++i)
            {
                r_pvbuf = &img[i];   
#ifndef _DEBUG
                Algo_create_template(al, (char *)r_pvbuf[0],&pTemplate, &iTemplateSize, _CT_FileData_, length[i]);
#else
                pTemplate = r_pvbuf[0];
#endif
                pvTemplate[i] = pTemplate;
            }
            if (result)
            {
                ptr->vTemplate.seq = pos;
                ptr->vTemplate.size = size;
                ptr->pvResult = pvTemplate;
                Pipe_put(out, ptr);
            }
            else
            {
                free(ptr);
            }
        }
        default:
            break;
        }//switch  
    }// for  
    assert(im->ref_signal >= 0);
    Algo_free(&al);
    if (InterlockedDecrement(&im->ref_signal) == 0)
    {
        SetEventWhenCallbackReturns(instance, im->event);
        //    _tprintf(_T("______________________ SetEventWhenCallbackReturns[%d]:Exit\r\n"),seq);
    }
    //    _tprintf(_T("__ThreadCreateTemplate[%d]:Exit\r\n"), seq);
}
static void __stdcall __TrySubmitResultThread(
    PTP_CALLBACK_INSTANCE instance,
    PVOID pvctx)
{
    I im = (I)pvctx;
    P pi = im->pipe2;
    T al = im->cl;
    eOptType eOpt = im->opt;
    LpData_T ptr = nullptr;
    PSRWLOCK mtx_ = &al->m_lpArgs->srw_;
    unsigned char *pTemplate = nullptr;
    long seq = InterlockedIncrement(&im->seq);
    CallbackMayRunLong(instance);
    switch (seq)
    {
    case 1:
        for (;;)
        {
            Pipe_get(pi, &ptr);
            if (ptr == nullptr)
            {
                Pipe_put(pi, nullptr);
                break;
            }
            switch (eOpt)
            {
            case eNewTemplate:
            {
                LpList_T *list = &im->list;  
                AcquireSRWLockExclusive(mtx_);
                *list = List_push(*list, ptr->pvResult);
                *list = List_push(*list, ptr->result.file);
                ReleaseSRWLockExclusive(mtx_);
            }break;
            case eNewTemplate2:
            {
                unsigned char **pvTemplate = (unsigned char **)im->pvResult;
                // 
            }break;
            case eCmprTemplate:
            {
                double *vsimi = (double *)im->pvResult;
                vsimi[ptr->vTemplate.seq] = ptr->vTemplate.simi;
            }
            default:
                break;
            } // switch 
            free(ptr);
        } // for
    default:
        break;
    } // switch 
    assert(im->ref_signal >= 0);
    if (InterlockedDecrement(&im->ref_signal) == 0)
    {
        SetEventWhenCallbackReturns(instance, im->event);
        //    _tprintf(_T("+++++++++++++SetEventWhenCallbackReturns[%d]:Exit\r\n"), seq);
    }
        //_tprintf(_T("__TrySubmitThread[%d] - Type[%d] :Exit\r\n"), seq, im->opt);
}
static void ReaySubmitThread(I im, PTP_SIMPLE_CALLBACK __pfTrySubmit)
{
    T al = (T)im->cl;
    P out = im->pipe;
    eOptType eOpt = im->opt;
    long  i, block, size, *length = nullptr;
    long nThrd = 0; 
    im->num_thread = 2;
    im->ref_signal = im->num_thread;
    if (im->result)
    {
        ++nThrd;
        TrySubmitThreadpoolCallback(__TrySubmitResultThread, im, NULL);
        //    _tprintf(_T("__TrySubmitResultThread :Start\r\n"));
    }
    for (; nThrd < im->ref_signal; ++nThrd)
    {
        TrySubmitThreadpoolCallback(__pfTrySubmit, im, NULL);
        //        _tprintf(_T("__TrySubmitCreateTemplate :Start\r\n"));
    }
    switch (eOpt)
    {
    case eNewTemplate:
        GetSubDir(im->ready.srcpath, im->ready.wildcard, out);
        break;
    case eNewTemplate2:
        length = im->ready2.length;
    case eCmprTemplate:
    {
        unsigned char** img = im->ready2.img;
        const char* imgtype = im->ready2.imgtype;
        size = im->ready2.size;
        block = size / max(1, nThrd);
        i = 0;
        if (block >= nThrd)
        {
            for (; i < nThrd; ++i)
            {
                LpData_T ptr = (LpData_T)malloc(sizeof(*ptr));
                ptr->opt = eOpt;
                ptr->result2.imgtype = imgtype;
                ptr->result2.size = block;
                ptr->result2.length = eCmprTemplate != eOpt ? &length[i] : nullptr;
                ptr->result2.pos = block * i;
                ptr->result2.img = &img[block * i];
                Pipe_put(out, ptr);
            }
            size = im->ready2.size %  max(1, nThrd);
            i = block * i;
            size += i;
            img = &img[i];
        }
        for (; i < size; ++i)
        {
            LpData_T ptr = (LpData_T)malloc(sizeof(*ptr));
            ptr->opt = eOpt;
            ptr->result2.imgtype = imgtype;
            ptr->result2.size = 1;
            ptr->result2.pos = i;
            ptr->result2.length = length ? &length[i] : nullptr;
            ptr->result2.img = &img[i];
            Pipe_put(out, ptr);
        }
        Pipe_put(out, nullptr);
    }
    default:
        break;
    }
    WaitForSingleObject(im->event, INFINITE);
    //    _tprintf(_T("ReaySubmitThread :End\r\n"));
    //_tprintf(_T("CloseHandle()[%d]\r\n"), InterlockedDecrement(&watch_1));
    //IdleCpu_put(nThreadNum); 
}
void Algo_free(T *al)
{
    R ag = (*al)->m_lpArgs;  
    if (!Algo_put(*al))
    {
        ComObjectRelease(*al, _IComImageAll); 
        delete (*al);
        (*al) = nullptr;
        CoUninitialize();
    }
    Args_free(&ag);
}
long Algo_template_size(T al)
{
    assert(al);
    if (!(al->nIptrFlag & _IRecognize))
    {
        ComObjectInstance(al, _IRecognize);
    }
    if (!(al->nIptrFlag & _IRecognize))
    {
        return (-1);
    }
    return al->m_lpArgs->lTemplateSize;
} 
long Algo_template_type(T al, long type)
{
    R ag;
    HRESULT hr;
    enumTemplateType etype;
    assert(al);
    if (!(al->nIptrFlag & _IRecognize))
    {
        ComObjectInstance(al, _IRecognize);
    }
    if (!(al->nIptrFlag & _IRecognize))
    {
        return (-1);
    }
    ag = al->m_lpArgs;
    assert(ag); 
    switch (type) {
    case 1: etype = TEMPLATE_TYPE_SIMPLE; break;
    case 2: etype = TEMPLATE_TYPE_GENERAL; break;
    case 4: etype = TEMPLATE_TYPE_COMPLEX; break;
    default:
        return (-1);
    } 
    if (FAILED(hr = al->m_IRecognize->SetModelType((enumFrameModelType)etype)))
    {
        TRACE_LOG(_T("_IRecognize::SetModelType:ErrCode = %d"), al->m_IRecognize->GetLastError());
    }
    else
    { 
        enumTemplateType retv = ag->eTemplateType;
        ag->eTemplateType = etype;
        switch (retv) {
        case TEMPLATE_TYPE_SIMPLE  : return 1; 
        case TEMPLATE_TYPE_GENERAL : return 2; 
        case TEMPLATE_TYPE_COMPLEX : return 4; 
        default:
            return (-1);
        } 
    } 
}
unsigned char** Algo_create_template(T al, const char* path,long* size, const char* file, const char *ward )
{   
    I im = Item_new();  
    unsigned char** pvTemplate;  
    assert(al);
    im->ready.srcpath = path;// lpPath;
    im->ready.wildcard = ward;
    im->ready.dstfile = file;
    im->opt = eNewTemplate; 
    im->cl = al;
    im->list = nullptr;
    im->result = file && file[0] != '\0'; 
    ReaySubmitThread(im, __TrySubmitCreateTemplate);
    AcquireSRWLockExclusive(&al->m_lpArgs->srw_);
    *size = List_length(im->list) / 2 ;
    pvTemplate = (unsigned char**)List_toArray(im->list, nullptr);  
    List_free(&im->list);
    ReleaseSRWLockExclusive(&al->m_lpArgs->srw_);
    Item_free(&im);   
    return pvTemplate;
}
unsigned char** Algo_create_template(T al, unsigned char* img[], long length[], long size, const char* file, const char* imgtype)
{ 
    I im = Item_new();  
    unsigned char** pvTemplate; 
    assert(al); 
    pvTemplate = new unsigned char* [size];
    memset(pvTemplate, 0, size * sizeof *pvTemplate);
    im->ready2.img = img;// lpPath;
    im->ready2.length = length;
    im->ready2.size = size;
    im->ready2.imgtype = imgtype;
    im->pvResult = pvTemplate;
    im->opt = eNewTemplate2; 
    im->cl = al; 
    im->result = file && file[0] != '\0' ;
    ReaySubmitThread(im, __TrySubmitCreateTemplate);
    Item_free(&im);
//    _tprintf(_T("free(lpItem)[]\r\n"));  
    return pvTemplate;
}
double* Algo_compare_template(T al, unsigned char* vtmp[], long size, unsigned char* vtmp2[], long size2)
{ 
    I im = Item_new(); 
    double * vsimi = nullptr;
    assert(al && vtmp2 && vtmp); 
    vsimi = new double[size * size2];
    memset(vsimi, 0, size * size2 * sizeof *vsimi);
    im->ready2.img = vtmp;// lpPath;
    im->ready2.length = nullptr;
    im->ready2.size = size;
    im->ready2.size2 = size2;
    im->ready2.imgtype = "";
    im->ready2.tmp = vtmp2;
    im->pvResult = vsimi;
    im->opt = eCmprTemplate;
    im->cl = al; 
    ReaySubmitThread(im, __TrySubmitCompareTemplate);
    Item_free(&im);
    //_tprintf(_T("free(lpItem)[]\r\n")); 
    return vsimi;
} 

 

posted on 2018-04-20 14:14  静观海月  阅读(284)  评论(0编辑  收藏  举报