// StartUDA5Dlg.cpp : implementation file // #include "stdafx.h" #include "StartUDA5.h" #include "StartUDA5Dlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define MAX_IMAGE_SIZE_WIDTH 720 #define MAX_IMAGE_SIZE_HEIGHT 576 void * malloc16(size_t size) { char * ptr=(char*)malloc(size+16+4); char* ptr2=(char*)((((DWORD)ptr)+15+4)&0xFFFFFFF0); *(((char**)ptr2)-1)=ptr; return ptr2; } void free16(void * ptr) { char * ptr2=*(((char**)ptr)-1); free(ptr2); } ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CStartUDA5Dlg dialog CStartUDA5Dlg::CStartUDA5Dlg(CWnd* pParent /*=NULL*/) : CDialog(CStartUDA5Dlg::IDD, pParent) { //{{AFX_DATA_INIT(CStartUDA5Dlg) m_strID = _T(""); m_strPWD = _T(""); m_strURL = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_pOverlay = NULL; m_pDispWnd = NULL; m_hVideo = NULL; m_hKillVideo = NULL; m_hThreadVideo = NULL; m_pVideoData = NULL; m_uWidth = 0; m_uHeight = 0; for (ULONG i=0; iAppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_pDispWnd = new CDispWnd; LPCTSTR pszClassDispWnd = AfxRegisterWndClass(CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, NULL, (HBRUSH)::GetStockObject(WHITE_BRUSH)); m_pDispWnd->CreateEx(WS_EX_CLIENTEDGE, pszClassDispWnd, _T("DispWnd"), WS_POPUP | WS_CAPTION , 0, 0, 720, 576, GetSafeHwnd(), NULL); m_strURL = "rtsp://192.168.13.4"; m_strID = "root"; m_strPWD = "pass"; UpdateData(FALSE); HMODULE hModule = NULL; hModule = LoadLibrary("UdaNVE.dll"); if(hModule){ *(FARPROC*)&m_Uda5Api.Cmn5CreateInstance = GetProcAddress(hModule,"Cmn5CreateInstance"); } else { MessageBox("Failed to load UdaNVE.dll", "StartUDA5", MB_ICONERROR); PostMessage(WM_CLOSE); return TRUE; } IUnknown * pUnknown; m_Uda5Api.Cmn5CreateInstance(&pUnknown); pUnknown->QueryInterface (IID_ICod5,(void**)&m_pCod5Api); pUnknown->QueryInterface (IID_INet5,(void**)&m_pNet5Api); pUnknown->Release(); AnchorWindowToDesktop(m_hWnd,AWTD_HCENTER|AWTD_BOTTOM); SetWindowPos(&wndTop,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); m_bConnect = FALSE; m_bCapture = FALSE; m_bRtDecode = FALSE; m_btnDisconnect.EnableWindow(FALSE); m_btnStop.EnableWindow(FALSE); m_pVideoData = (UCHAR*)malloc16(MAX_IMAGE_SIZE_WIDTH*MAX_IMAGE_SIZE_HEIGHT*3); if (!m_pVideoData) { return FALSE; } return TRUE; // return TRUE unless you set the focus to a control } void CStartUDA5Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CStartUDA5Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CStartUDA5Dlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CStartUDA5Dlg::OnBtnConnect() { // TODO: Add your control notification handler code here UpdateData(TRUE); ULONG uIdData = 0; ULONG rs; rs = m_pNet5Api->Net5ConnectEx(m_strURL, NET5_ST_RTP_UDP, 5); if(!rs){ MessageBox("Connection failed\n"); return; } rs = m_pNet5Api->Net5Login(m_strID, m_strPWD); if(!rs){ MessageBox("Login failed\n"); return; } m_btnConnect.EnableWindow(FALSE); m_btnDisconnect.EnableWindow(TRUE); m_bConnect = TRUE; } void CStartUDA5Dlg::OnBtnDisconnect() { // TODO: Add your control notification handler code here if (m_bCapture) { StopCapture(TRUE); } if (m_pNet5Api) { m_pNet5Api->Net5Logout(); m_pNet5Api->Net5Disconnect(); } m_btnConnect.EnableWindow(TRUE); m_btnDisconnect.EnableWindow(FALSE); m_bConnect = FALSE; } void CStartUDA5Dlg::OnBtnStart() { // TODO: Add your control notification handler code here if(!StartCapture()){ return; } m_btnStart.EnableWindow(FALSE); m_btnStop.EnableWindow(TRUE); } void CStartUDA5Dlg::OnBtnStop() { // TODO: Add your control notification handler code here StopCapture(TRUE); m_btnStart.EnableWindow(TRUE); m_btnStop.EnableWindow(FALSE); } void CStartUDA5Dlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here if (m_bCapture) { StopCapture(FALSE); } if(m_bConnect){ OnBtnDisconnect(); } if(m_bCapture){ m_pCod5Api->Cod5Stop(); if(m_hKillVideo && m_hThreadVideo){ SetEvent(m_hKillVideo); WaitForSingleObject(m_hThreadVideo, INFINITE); CloseHandle(m_hThreadVideo); m_hThreadVideo = NULL; CloseHandle(m_hKillVideo); m_hKillVideo = NULL; } m_pCod5Api->Cod5Endup(); if(m_pOverlay) { delete m_pOverlay; m_pOverlay = NULL; g_poverlaySurface = NULL; } } if(m_pVideoData){ free16(m_pVideoData); m_pVideoData = NULL; } if(m_bRtDecode){ StopRtDecode(); } if(m_pDispWnd) { m_pDispWnd->DestroyWindow(); delete m_pDispWnd; m_pDispWnd = NULL; } if(m_pCod5Api){ m_pCod5Api->Release(); m_pCod5Api = NULL; } if(m_pNet5Api){ m_pNet5Api->Release(); m_pNet5Api = NULL; } } BOOL CStartUDA5Dlg::StartCapture() { if(!m_bConnect){ TRACE("Not connected\n"); return FALSE; } BOOL rs; BYTE activateCode[16]; rs = m_pCod5Api->Cod5Activate(0, activateCode); if(!rs){ TRACE("Cod5Activate failed\n"); return FALSE; } m_pDispWnd->ShowWindow(SW_SHOW); rs = OverlaySetup(720, 576); if(!rs){ return FALSE; } CRect rect(0, 0, 720, 576); m_pDispWnd->CalcWindowRect(&rect,CWnd::adjustOutside); m_pDispWnd->UpdateVSuface(); rs = m_pCod5Api->Cod5Setup(); if(!rs){ TRACE("Cod5Setup failed\n"); return FALSE; } rs = m_pCod5Api->Cod5GetEventHandle(CMN5_DT_COD_EX, &m_hVideo); if(!rs){ TRACE("Cod5GetEventHandle failed\n"); return FALSE; } CMN5_MULTI_COMMAND Cmds[2]; Cmds[0].uBoard = 0; Cmds[0].uChannel = 0; Cmds[0].uCommand = COD5_CPC_VIDEO_FORMAT; Cmds[1].uBoard = 0; Cmds[1].uChannel = 0; Cmds[1].uCommand = COD5_CPC_VIDEO_IMAGE_SIZE; rs = m_pCod5Api->Cod5GetMultiCodecProperties(2, Cmds); if (!rs) { MessageBox("Cannot get properties\n"); return FALSE; } m_uWidth = CMN5_GETIMGWIDTH(Cmds[1].uParam[0]); m_uHeight = CMN5_GETIMGHEIGHT(Cmds[1].uParam[0]); for(ULONG i=0; iInit(m_uWidth, m_uHeight, XVID_CSP_YUY2); } m_hKillVideo = CreateEvent(NULL, FALSE, FALSE, NULL); ULONG id; m_hThreadVideo = CreateThread(NULL, 0, CapProcStub, this, 0, &id); rs = m_pCod5Api->Cod5Run(); if(!rs){ TRACE("Cod5Run failed\n"); return FALSE; } m_bCapture = TRUE; return TRUE; } void CStartUDA5Dlg::StopCapture(BOOL bHide) { if (!m_bCapture) { return; } if (m_pCod5Api) { m_pCod5Api->Cod5Stop(); } if(m_hKillVideo && m_hThreadVideo){ SetEvent(m_hKillVideo); WaitForSingleObject(m_hThreadVideo, INFINITE); CloseHandle(m_hThreadVideo); m_hThreadVideo = NULL; CloseHandle(m_hKillVideo); m_hKillVideo = NULL; } if (m_pCod5Api) { m_pCod5Api->Cod5Endup(); } for(ULONG i=0; iClose(); delete m_pXvidDec[i]; m_pXvidDec[i] = NULL; } } if(m_pOverlay) { delete m_pOverlay; m_pOverlay = NULL; g_poverlaySurface = NULL; } if (bHide) { m_pDispWnd->ShowWindow(SW_HIDE); } m_bCapture = FALSE; } BOOL CStartUDA5Dlg::StartRtDecode() { m_bRtDecode = TRUE; return TRUE; } void CStartUDA5Dlg::StopRtDecode() { m_bRtDecode = FALSE; } BOOL CStartUDA5Dlg::OverlaySetup(DWORD overlaySurfaceWidth, DWORD overlaySurfaceHeight) { if(m_pOverlay) { delete m_pOverlay; m_pOverlay = NULL; g_poverlaySurface = NULL; } RECT srcRect = { 0, 0, overlaySurfaceWidth, overlaySurfaceHeight }; COverlaySurface* pOverlay = new COverlaySurface; if(!pOverlay) return FALSE; if(FAILED(pOverlay->InitDirectDraw(m_pDispWnd->GetSafeHwnd()))) { MessageBox("InitDirectDraw"); goto $FAIL; } if(FAILED(pOverlay->HasOverlaySupport())) { MessageBox("HasOverlaySupport"); goto $FAIL; } if (FAILED(pOverlay->CreateDirectDrawSurfaces(m_pDispWnd->GetSafeHwnd(), overlaySurfaceWidth, overlaySurfaceHeight))) { MessageBox("CreateDirectDrawSurfaces"); goto $FAIL; } m_pOverlay = pOverlay; g_poverlaySurface = pOverlay; g_poverlaySurface->SetDstRect(srcRect); g_poverlaySurface->UpdateOverlay(); return TRUE; $FAIL: TRACE("Fail to OverlaySetup\n"); if(pOverlay) { delete pOverlay; g_poverlaySurface = NULL; m_pOverlay = NULL; } return FALSE; } BOOL CStartUDA5Dlg::VideoEventDetected() { //TRACE("Video Event Detected\n"); COD5_DATA_INFO_EX Data = { 0, }; do { if(m_pCod5Api->Cod5GetEventData(CMN5_DT_COD_EX, &Data)) { if(Data.uErrCode == CMN5_EC_NO_DATA){ //TRACE("ATTR_NO_DATA\n"); break; } if (Data.uFrameType == COD5_FT_PCM_AUDIO) { continue; } //TRACE("get data\n"); BYTE* pSurf; DDSURFACEDESC2 ddsd; LPDIRECTDRAWSURFACE7 pDDSOverlay = m_pOverlay->GetOverlayObject(); ZeroMemory( &ddsd, sizeof(ddsd) ); ddsd.dwSize = sizeof(ddsd); if(!m_pXvidDec[Data.uChannelNum]->Decode(Data.pDataBuffer, m_pVideoData, Data.uDataSize, m_uWidth)){ TRACE("Decode failed\n"); return FALSE; } HRESULT hr = pDDSOverlay->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); if (FAILED(hr)) { TRACE("Overlay lock failed. error code : %d\n", HRESULT_CODE(hr)); TRACE("DDERR_INVALIDPARAMS : %d\n", HRESULT_CODE(DDERR_INVALIDPARAMS)); TRACE("DDERR_INVALIDOBJECT : %d\n", HRESULT_CODE(DDERR_INVALIDOBJECT)); TRACE("DDERR_SURFACEBUSY : %d\n", HRESULT_CODE(DDERR_SURFACEBUSY)); TRACE("DDERR_SURFACELOST : %d\n", HRESULT_CODE(DDERR_SURFACELOST)); TRACE("DDERR_WASSTILLDRAWING : %d\n", HRESULT_CODE(DDERR_WASSTILLDRAWING)); TRACE("DDERR_OUTOFMEMORY : %d\n", HRESULT_CODE(DDERR_OUTOFMEMORY)); return FALSE; } pSurf = (BYTE*)ddsd.lpSurface; ULONG dataPos=0, surfacePos=0, i; surfacePos = 0; for(i=0; iUnlock(NULL); m_pCod5Api->Cod5ReleaseData(&Data); } else { TRACE("Cod5GetEventData failed"); break; } } while(1); return TRUE; } DWORD WINAPI CStartUDA5Dlg::CapProcStub(LPVOID lpParameter) { return static_cast(lpParameter)->CapProc(); } DWORD WINAPI CStartUDA5Dlg::CapProc() { ULONG uRet; BOOL bRun = TRUE; HANDLE hEvents[] = { m_hKillVideo, m_hVideo }; while(bRun){ uRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE); switch(uRet){ case WAIT_OBJECT_0: bRun = FALSE; break; case WAIT_OBJECT_0+1: VideoEventDetected(); break; } } return 0; }