// PlayWnd.cpp : implementation file // #include "stdafx.h" #include "recordertest.h" #include "PlayWnd.h" #include "PUBLIB2/WinUtil.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPlayWnd CPlayWnd::CPlayWnd() { m_pRenderer = NULL; m_bUpdate = TRUE; m_uColumn = 2; m_uRow = 2; m_bChangeTime = FALSE; ZeroMemory(m_PlayInfo, sizeof(m_PlayInfo)); } CPlayWnd::~CPlayWnd() { } BEGIN_MESSAGE_MAP(CPlayWnd, CWnd) //{{AFX_MSG_MAP(CPlayWnd) ON_WM_MOVE() ON_WM_SIZE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPlayWnd message handlers BOOL CPlayWnd::Init() { m_pRenderer = new CD3DRenderer(); if(!m_pRenderer->Setup()) return FALSE; m_pFont= new CD3DFont(); m_pFont->Setup(m_pRenderer,"Verdana",12,D3DFONT_BOLD|D3DFONT_SHADOW_LEVEL1|D3DFONT_ANTIALIAS|(1<<16)|(1<<24)); m_pDecBuffer = new BYTE[2*720*576]; for (ULONG i=0; iEndup(); delete m_pFont; m_pFont=NULL; } if(m_pRenderer){ m_pRenderer->Endup(); delete m_pRenderer; m_pRenderer=NULL; } } BOOL CPlayWnd::DecodeVideo(REC_DATA_HEADER *pHeader, BYTE *pData) { if (m_PlayInfo[pHeader->uChannelNum].uWidth != pHeader->MediaInfo.uWidth || m_PlayInfo[pHeader->uChannelNum].uHeight != pHeader->MediaInfo.uHeight) { m_PlayInfo[pHeader->uChannelNum].uWidth = pHeader->MediaInfo.uWidth; m_PlayInfo[pHeader->uChannelNum].uHeight = pHeader->MediaInfo.uHeight; TRACE("Changed Resolution. ch[%d], w[%d], h[%d]\n", pHeader->uChannelNum, pHeader->MediaInfo.uWidth, pHeader->MediaInfo.uHeight); ReleaseCodec(pHeader->uChannelNum); InitCodec(pHeader->uChannelNum); } DecodedVideo DecVid; int iDecodedSize; if (pHeader->uFrameType >= REC_FT_MP4_I && pHeader->uFrameType <= REC_FT_MP4_B) { if (pHeader->uFrameType == REC_FT_MP4_I) { m_PlayInfo[pHeader->uChannelNum].bArrivedIFrame = TRUE; } if (!m_PlayInfo[pHeader->uChannelNum].bArrivedIFrame) { return TRUE; } if (!m_PlayInfo[pHeader->uChannelNum].pUUCoreDivx->DecodeVideo(&DecVid, &iDecodedSize, pData, pHeader->uDataSize, FALSE)) { TRACE("Cannot decode divx\n"); return FALSE; } m_PlayInfo[pHeader->uChannelNum].uFourCC = UU_CODEC_DIVX; } else if (pHeader->uFrameType == REC_FT_MJPEG) { if (!m_PlayInfo[pHeader->uChannelNum].pUUCoreMjpeg->DecodeVideo(&DecVid, &iDecodedSize, pData, pHeader->uDataSize, FALSE)) { TRACE("Cannot decode mjpeg\n"); return FALSE; } m_PlayInfo[pHeader->uChannelNum].uFourCC = UU_CODEC_MJPEG; } else { return FALSE; } ConvertToPacked(m_pDecBuffer, &DecVid); if (!DrawFrame(pHeader)) { return FALSE; } return TRUE; } BOOL CPlayWnd::DecodeVideo(PAS_DATA_INFO *pInfo) { REC_DATA_HEADER Header; Header.uChannelNum = pInfo->uChannelNum; Header.uDataSize = pInfo->uDataSize; Header.uDataType = pInfo->uDataType; Header.uFrameType = pInfo->uFrameType; CopyMemory(&Header.TimeStamp, &pInfo->TimeStamp, sizeof(Header.TimeStamp)); if (Header.uDataType == PAS_DT_VIDEO) { Header.MediaInfo.uWidth = pInfo->MediaInfo.uWidth; Header.MediaInfo.uHeight = pInfo->MediaInfo.uHeight; } else if (Header.uDataType == PAS_DT_AUDIO) { Header.MediaInfo.uSampleRate = pInfo->MediaInfo.uSampleRate; Header.MediaInfo.uDataBits = pInfo->MediaInfo.uDataBits; Header.MediaInfo.uChannel = pInfo->MediaInfo.uChannel; } if (!DecodeVideo(&Header, pInfo->pBuffer)) { return FALSE; } return TRUE; } BOOL CPlayWnd::InitCodec(ULONG uCh) { CodecProperty CodProp; if (m_PlayInfo[uCh].pUUCoreDivx || m_PlayInfo[uCh].pUUCoreMjpeg) { TRACE("Already initialized codec\n"); return TRUE; } m_PlayInfo[uCh].pUUCoreDivx = new CUUCoreUtil; m_PlayInfo[uCh].pUUCoreMjpeg = new CUUCoreUtil; if (!m_PlayInfo[uCh].pUUCoreDivx->OpenCodec(UU_CODEC_DIVX, FALSE)) { return FALSE; } if (!m_PlayInfo[uCh].pUUCoreMjpeg->OpenCodec(UU_CODEC_MJPEG, FALSE)) { return FALSE; } ZeroMemory(&CodProp, sizeof(CodProp)); CodProp.video.uWidth = m_PlayInfo[uCh].uWidth; CodProp.video.uHeight = m_PlayInfo[uCh].uHeight; CodProp.video.uColorSpace = UU_CSP_YUY2; //CodProp.video.uFlags = UU_CPF_LOW_DELAY; m_PlayInfo[uCh].pUUCoreDivx->SetParam(CodProp); m_PlayInfo[uCh].pUUCoreMjpeg->SetParam(CodProp); m_PlayInfo[uCh].bArrivedIFrame = FALSE; return TRUE; } void CPlayWnd::ReleaseCodec(ULONG uCh) { if (m_PlayInfo[uCh].pUUCoreDivx) { m_PlayInfo[uCh].pUUCoreDivx->CloseCodec(); delete m_PlayInfo[uCh].pUUCoreDivx; m_PlayInfo[uCh].pUUCoreDivx=NULL; } if (m_PlayInfo[uCh].pUUCoreMjpeg) { m_PlayInfo[uCh].pUUCoreMjpeg->CloseCodec(); delete m_PlayInfo[uCh].pUUCoreMjpeg; m_PlayInfo[uCh].pUUCoreMjpeg=NULL; } } void CPlayWnd::ConvertToPacked(BYTE *pPackedOut, DecodedVideo *pIn) { UINT uCnt; BYTE *pSrcBuffer, *pDstBuffer; UINT uSrcLineSize, uDstLineSize; UINT uDstOrgLineSize = pIn->uWidth; UINT uDstOrgLineCount = pIn->uHeight; pDstBuffer = pPackedOut; ZeroMemory(pDstBuffer, uDstOrgLineSize*uDstOrgLineCount*2); // YV12 (YVU) Planar if (pIn->uColorSpace==UU_CSP_YV12) { pSrcBuffer = pIn->pData[0]; uSrcLineSize = pIn->uBytesPerLine[0]; pDstBuffer = pPackedOut; uDstLineSize = uDstOrgLineSize; for (uCnt=0; uCntpData[2]; uSrcLineSize = pIn->uBytesPerLine[2]; pDstBuffer = pPackedOut+uDstOrgLineSize*uDstOrgLineCount; uDstLineSize = uDstOrgLineSize/2; for (uCnt=0; uCntpData[1]; uSrcLineSize = pIn->uBytesPerLine[1]; pDstBuffer = pPackedOut+uDstOrgLineSize*uDstOrgLineCount+uDstOrgLineSize/2*uDstOrgLineCount/2; uDstLineSize = uDstOrgLineSize/2; for (uCnt=0; uCntuColorSpace==UU_CSP_YUY2) { ULONG uBitPerPixel=16; pDstBuffer = pPackedOut; uDstLineSize = uDstOrgLineSize*uBitPerPixel/8; pSrcBuffer = pIn->pData[0]; uSrcLineSize = pIn->uBytesPerLine[0]; for (uCnt=0; uCntuColorSpace==UU_CSP_RGB24||pIn->uColorSpace==UU_CSP_RGB32) { ULONG uBitCount; switch (pIn->uColorSpace) { case UU_CSP_RGB24:uBitCount=24;break; case UU_CSP_RGB32:uBitCount=32;break; } pDstBuffer = pPackedOut; uDstLineSize = uDstOrgLineSize*uBitCount/8; pSrcBuffer = pIn->pData[0]; uSrcLineSize = pIn->uBytesPerLine[0]; for (uCnt=0; uCnttv_sec * NSPERSEC + pTimeval->tv_usec * (NSPERSEC / 1000000) + FACTOR; pFileTime->dwHighDateTime = (ULONG)(x >> 32); pFileTime->dwLowDateTime = (ULONG)x; } BOOL CPlayWnd::DrawFrame(REC_DATA_HEADER *pHeader) { RECT rcClient; GetClientRect(&rcClient); if(!m_PlayInfo[pHeader->uChannelNum].bCommited){ RECT rc = rcClient; MapWindowPoints(NULL, &rc); m_pRenderer->SetHWnd(m_hWnd); EnterCriticalSection(&m_pRenderer->m_crit); m_pRenderer->Commit(rc); LeaveCriticalSection(&m_pRenderer->m_crit); for (ULONG i=0; iClear(rc); m_bUpdate=FALSE; } } m_PlayInfo[pHeader->uChannelNum].bCommited = TRUE; ULONG uWidth = rcClient.right-rcClient.left; ULONG uHeight = rcClient.bottom-rcClient.top; int x, y; y = pHeader->uChannelNum/m_uColumn; x = pHeader->uChannelNum%m_uColumn; RECT rc; rc.left = (x+0)*uWidth/m_uColumn; rc.top = (y+0)*uHeight/m_uRow; rc.right = (x+1)*uWidth/m_uColumn; rc.bottom= (y+1)*uHeight/m_uRow; MapWindowPoints(NULL, &rc); DrawRecord recs[8]; SIZE imgSize; RECT roi; imgSize.cx = m_PlayInfo[pHeader->uChannelNum].uWidth; imgSize.cy = m_PlayInfo[pHeader->uChannelNum].uHeight; ZeroMemory(&roi, sizeof(roi)); FILETIME ftime; SYSTEMTIME sysTime; if (m_bChangeTime) { timevalToFileTime(&pHeader->TimeStamp, &ftime); } else { CopyMemory(&ftime, &pHeader->TimeStamp, sizeof(ftime)); } FileTimeToSystemTime(&ftime, &sysTime); char indexName[256]; wsprintf(indexName,"Ch: %d\nResolution: %dx%d\nCodec: %s\nDTS: %d-%d-%d %02d:%02d:%02d.%03d\n", pHeader->uChannelNum, imgSize.cx, imgSize.cy, m_PlayInfo[pHeader->uChannelNum].uFourCC == UU_CODEC_DIVX ? "DIVX" : "MJPEG", sysTime.wYear,sysTime.wMonth,sysTime.wDay, sysTime.wHour,sysTime.wMinute,sysTime.wSecond,sysTime.wMilliseconds); recs[0].drawType = DRT_IMAGE; recs[0].colorValue = 0xFFFFFFFF; recs[0].srcSize = imgSize; recs[0].img.colorFormat = CF_YUY2; recs[0].img.pSrc = m_pDecBuffer; recs[0].img.flag = 0; recs[0].img.roi = roi; recs[1].drawType = DRT_TEXT; recs[1].colorValue = 0x00F0F080|(200<<24);//color; recs[1].srcSize = imgSize; recs[1].text.pFont = m_pFont; recs[1].text.pText = indexName; recs[1].text.pt.x = 0; recs[1].text.pt.y = 0; m_pRenderer->DrawRecords(rc,0.9f,2,recs); EnterCriticalSection(&m_pRenderer->m_crit); m_pRenderer->Commit(rc); LeaveCriticalSection(&m_pRenderer->m_crit); return TRUE; } void CPlayWnd::OnMove(int x, int y) { CWnd::OnMove(x, y); // TODO: Add your message handler code here RECT rcNew; if(m_pRenderer){ GetClientRect(&rcNew); MapWindowPoints(NULL,&rcNew); EnterCriticalSection(&m_pRenderer->m_crit); m_pRenderer->m_pddsBackbuffer->Blt(&rcNew,m_pRenderer->m_pddsBackbuffer,&m_recentRect,DDBLT_ASYNC |DDBLT_DONOTWAIT ,NULL); LeaveCriticalSection(&m_pRenderer->m_crit); } m_recentRect=rcNew; m_bUpdate=TRUE; } void CPlayWnd::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); // TODO: Add your message handler code here RECT rcNew; if(m_pRenderer){ GetClientRect(&rcNew); MapWindowPoints(NULL,&rcNew); EnterCriticalSection(&m_pRenderer->m_crit); m_pRenderer->m_pddsPrimary->Blt(&rcNew,m_pRenderer->m_pddsBackbuffer,&m_recentRect,DDBLT_ASYNC |DDBLT_DONOTWAIT ,NULL); m_pRenderer->m_pddsBackbuffer->Blt(&rcNew,m_pRenderer->m_pddsBackbuffer,&m_recentRect,DDBLT_ASYNC |DDBLT_DONOTWAIT ,NULL); LeaveCriticalSection(&m_pRenderer->m_crit); } m_recentRect=rcNew; m_bUpdate=TRUE; }