#include "precomp.h" #define ZONE_AP ZONE_DP #define _GetState() (m_dwState & DP_MASK_STATE) #define _SetState(s) (m_dwState = (m_dwState & ~DP_MASK_STATE) | (s & DP_MASK_STATE)) #define _GetPlatform() (m_dwState & DP_MASK_PLATFORM) #define _SetPlatform(s) (m_dwState = (m_dwState & ~DP_MASK_PLATFORM) | (s & DP_MASK_PLATFORM)) int g_videoin_prepare = 0; int g_videoout_prepare = 0; /////////////////////////////////////////////////////// // // Public methods // HRESULT VideoPacket::Initialize ( MEDIAPACKETINIT * p ) { HRESULT hr = DPR_SUCCESS; ULONG cbSizeDevData; ULONG cbSizeRawData; FX_ENTRY ("VdPckt::Init") m_pBS = NULL; if (p == NULL) { DEBUGMSG (ZONE_AP, ("%s: invalid parameter (null ptr)\r\n", _fx_)); return DPR_INVALID_PARAMETER; } if (p->dwFlags & DP_FLAG_SEND) { cbSizeDevData = p->cbSizeDevData; cbSizeRawData = p->cbSizeRawData; if (IsSameMediaFormat(p->pStrmConvSrcFmt, p->pDevFmt)) p->cbSizeRawData = 0; p->cbSizeDevData = 0; } hr = MediaPacket::Initialize( p); // LOOKLOOK RP - if DP_FLAG_SEND, then we've allocated a memory header for the dev buffer, // but haven't actually allocated memory for the buffer if (p->dwFlags & DP_FLAG_SEND) { m_pDevData->data = NULL; m_pDevData->length = cbSizeDevData; } if (hr != DPR_SUCCESS) goto MyExit; // allocate conversion header only if m_pWaveData != m_pNetData if (m_pRawData != m_pNetData) { if (m_dwState & DP_FLAG_VCM) { m_pStrmConvHdr = MemAlloc (sizeof (VCMSTREAMHEADER)); if (m_pStrmConvHdr == NULL) { DEBUGMSG (ZONE_AP, ("%s: MemAlloc4 (%ld) failed\r\n", _fx_, (ULONG) sizeof (VCMSTREAMHEADER))); hr = DPR_OUT_OF_MEMORY; goto MyExit; } } else { DEBUGMSG (ZONE_AP, ("%s: invalid platform (vcm)\r\n", _fx_)); hr = DPR_INVALID_PLATFORM; goto MyExit; } } else { m_pStrmConvHdr = NULL; } MakeSilence (); MyExit: if (hr != DPR_SUCCESS) { m_fInitialized = FALSE; Release(); } return hr; } HRESULT VideoPacket::Play ( MMIODEST *pmmioDest, UINT uDataType ) { return DPR_INVALID_HANDLE; } HRESULT VideoPacket::Record ( void ) { FX_ENTRY ("VdPckt::Record") LOG((LOGMSG_VID_RECORD,m_index)); if (_GetState () != MP_STATE_RESET) { DEBUGMSG (ZONE_AP, ("%s: out of seq, state=0x%lX\r\n", _fx_, m_dwState)); return DPR_OUT_OF_SEQUENCE; } if (m_pBS && m_pDevData->data) { m_pBS->UnlockBits(NULL, m_pDevData->data); m_pBS->Release(); m_pDevData->data = NULL; m_pBS = NULL; } _SetState (MP_STATE_RECORDING); return DPR_SUCCESS; } HRESULT VideoPacket::SetSurface (IBitmapSurface *pBS) { void* pBits; long pitch; FX_ENTRY ("VdPckt::SetSurface") if (pBS) { m_pBS = pBS; m_pBS->LockBits(NULL, 0, &pBits, &pitch); if (!pBits) { m_pBS->UnlockBits(NULL, pBits); return ERROR_IO_INCOMPLETE; } m_pBS->AddRef(); m_pDevData->data = (UCHAR *)pBits; return DPR_SUCCESS; } return E_INVALIDARG; } HRESULT VideoPacket::Recycle ( void ) { if (m_pBS && m_pDevData->data) { m_pBS->UnlockBits(NULL, m_pDevData->data); m_pBS->Release(); m_pDevData->data = NULL; m_pBS = NULL; } return MediaPacket::Recycle(); } BOOL VideoPacket::IsBufferDone ( void ) { FX_ENTRY ("VdPckt::IsBufferDone") if (m_hDev) { if (m_dwState & DP_FLAG_VIDEO) { //LOOKLOOK RP - what does this need to do? #if 1 return TRUE; #else ~~~ return (((VIDEOINOUTHDR *) m_pDevHdr)->dwFlags & WHDR_DONE); #endif } } return FALSE; } HRESULT VideoPacket::MakeSilence ( void ) { // create white noise!!! FX_ENTRY ("VdPckt::MakeSilence") if (m_pDevFmt) { if (m_pDevData) { // Don't need to do anything, what's on screen should do it. CopyPreviousBuf ((VIDEOFORMATEX *) m_pDevFmt, (PBYTE) m_pDevData->data, (ULONG) m_pDevData->length); } } _SetState(MP_STATE_RESET); return DPR_SUCCESS; } HRESULT VideoPacket::GetSignalStrength ( PDWORD pdwMaxStrength ) { FX_ENTRY ("VdPckt::GetSignalStrength") // For now send each and every frame. // But you should consider sending only the frames if they // are really different of the previously sent one. // This will save quite some bandwidth when there is no or // very little activity in the video frames. return DPR_NOT_YET_IMPLEMENTED; } HRESULT VideoPacket::Interpolate ( MediaPacket * pPrev, MediaPacket * pNext) { HRESULT hr = DPR_SUCCESS; DPHANDLE hPrevDev; NETBUF *pPrevDevData; PVOID pPrevDevHdr; VIDEOFORMATEX *pPrevpfDev; VIDEOFORMATEX *pNextpfDev; NETBUF *pNextDevData; PVOID pNextDevHdr; FX_ENTRY ("VdPckt::Interpolate") DEBUGMSG (ZONE_AP, ("%s: can't interpolate\r\n", _fx_)); hr = DPR_INVALID_HANDLE; return hr; } HRESULT VideoPacket::Open ( UINT uType, DPHANDLE hdl ) // called by RxStream or TxStream { HRESULT hr = DPR_SUCCESS; MMRESULT mmr; FX_ENTRY ("VdPckt::Open") switch (uType) { #ifdef PREP_HDR_PER_CONV case MP_TYPE_RECVSTRMCONV: m_hStrmConv = hdl; break; #endif case MP_TYPE_STREAMCONV: if ((m_hStrmConv = hdl) != NULL) { if (m_dwState & DP_FLAG_VCM) { // initialize the header ZeroMemory (m_pStrmConvHdr, sizeof (VCMSTREAMHEADER)); ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbStruct = sizeof (VCMSTREAMHEADER); ((VCMSTREAMHEADER *) m_pStrmConvHdr)->fdwStatus = 0; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->dwUser = 0; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->dwSrcUser = 0; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLengthUsed = 0; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->dwDstUser = 0; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLengthUsed = 0; if (m_pNetData && m_pRawData) { if (m_dwState & DP_FLAG_SEND) { if (m_pRawData->data) { ((VCMSTREAMHEADER *) m_pStrmConvHdr)->pbSrc = m_pRawData->data; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLength = m_pRawData->length; } else { // don't have a static raw buffer, so let vcmStreamPrepareHeader // lock the net buffer twice ((VCMSTREAMHEADER *) m_pStrmConvHdr)->pbSrc = m_pNetData->data; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLength = m_pNetData->length; } ((VCMSTREAMHEADER *) m_pStrmConvHdr)->pbDst = m_pNetData->data; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLength = m_pNetData->length; } else if (m_dwState & DP_FLAG_RECV) { ((VCMSTREAMHEADER *) m_pStrmConvHdr)->pbSrc = m_pNetData->data; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLength = m_pNetData->length; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->pbDst = m_pRawData->data; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbDstLength = m_pRawData->length; } // prepare the header mmr = vcmStreamPrepareHeader ((HVCMSTREAM) m_hStrmConv, (VCMSTREAMHEADER *) m_pStrmConvHdr, 0); if (mmr != MMSYSERR_NOERROR) { DEBUGMSG (ZONE_AP, ("%s: vcmStreamPrepareHeader failed, mmr=%ld\r\n", _fx_, (ULONG) mmr)); hr = DPR_CANT_PREPARE_HEADER; goto MyExit; } m_fStrmPrepared = TRUE; } else m_fStrmPrepared = FALSE; } else { hr = DPR_INVALID_PLATFORM; goto MyExit; } } break; case MP_TYPE_DEV: if ((m_hDev = hdl) != NULL) { if (m_dwState & DP_FLAG_VIDEO) { if (m_dwState & DP_FLAG_SEND) { g_videoin_prepare++; } else if (m_dwState & DP_FLAG_RECV) { g_videoout_prepare++; } else { hr = DPR_INVALID_PARAMETER; goto MyExit; } m_fDevPrepared = TRUE; } else { hr = DPR_INVALID_PLATFORM; goto MyExit; } } else { hr = DPR_INVALID_HANDLE; goto MyExit; } break; default: hr = DPR_INVALID_PARAMETER; goto MyExit; } MyExit: return hr; } HRESULT VideoPacket::Close ( UINT uType ) // called by RxStream or TxStream { HRESULT hr = DPR_SUCCESS; MMRESULT mmr; FX_ENTRY ("VdPckt::Close") switch (uType) { case MP_TYPE_RECVSTRMCONV: case MP_TYPE_STREAMCONV: if (m_hStrmConv) { if (m_dwState & DP_FLAG_VCM) { if (m_fStrmPrepared) { // unprepare the header if ((m_dwState & DP_FLAG_SEND) && !m_pRawData->data) { // don't have a static raw buffer, so let vcmStreamUnprepareHeader // unlock the net buffer twice to unwind what Open did ((VCMSTREAMHEADER *) m_pStrmConvHdr)->pbSrc = m_pNetData->data; ((VCMSTREAMHEADER *) m_pStrmConvHdr)->cbSrcLength = m_pNetData->length; } mmr = vcmStreamUnprepareHeader ((HVCMSTREAM) m_hStrmConv, (VCMSTREAMHEADER *) m_pStrmConvHdr, 0); m_fStrmPrepared = FALSE; // don't care about any error if (mmr != MMSYSERR_NOERROR) { DEBUGMSG (ZONE_AP, ("%s: vcmStreamUnprepareHeader failed, mmr=%ld\r\n", _fx_, (ULONG) mmr)); hr = DPR_CANT_UNPREPARE_HEADER; goto MyExit; } } } if (uType == MP_TYPE_STREAMCONV) m_hStrmConv = NULL; } break; case MP_TYPE_DEV: if (m_hDev) { if (m_fDevPrepared) { if (m_dwState & DP_FLAG_SEND) { g_videoin_prepare--; } else if (m_dwState & DP_FLAG_RECV) { g_videoout_prepare--; } else { hr = DPR_INVALID_PARAMETER; goto MyExit; } m_fDevPrepared = FALSE; // don't care about any error } m_hDev = NULL; } else { hr = DPR_INVALID_HANDLE; goto MyExit; } break; default: hr = DPR_INVALID_PARAMETER; goto MyExit; } MyExit: return hr; } void VideoPacket::WriteToFile (MMIODEST *pmmioDest) { MMRESULT mmr; long dwDataLength; FX_ENTRY ("VdPckt::WriteToFile") #ifdef need_video_file_io // BUGBUG - this stuff doesn't work if (dwDataLength = (DWORD)(pmmioDest->dwDataLength + m_pDevData->length) > pmmioDest->dwMaxDataLength ? (DWORD)(pmmioDest->dwMaxDataLength - pmmioDest->dwDataLength) : m_pDevData->length) { if (mmioWrite(pmmioDest->hmmioDst, (char *) m_pDevData->data, dwDataLength) != (LONG)m_pDevData->length) mmr = MMSYSERR_ERROR; else pmmioDest->dwDataLength += dwDataLength; if ((mmr == MMSYSERR_ERROR) || (pmmioDest->dwDataLength == pmmioDest->dwMaxDataLength)) { mmr = mmioAscend(pmmioDest->hmmioDst, &(pmmioDest->ckDst), 0); mmr = mmioAscend(pmmioDest->hmmioDst, &(pmmioDest->ckDstRIFF), 0); mmr = mmioClose(pmmioDest->hmmioDst, 0); pmmioDest->hmmioDst = NULL; } } #endif } void VideoPacket::ReadFromFile (MMIOSRC *pmmioSrc) { long lNumBytesRead; FX_ENTRY ("VdPckt::ReadFromFile") #ifdef need_video_file_io // BUGBUG - this stuff doesn't work if (((VIDEOINOUTHDR *) m_pDevHdr)->dwBytesUsed) { MyRead: if ((pmmioSrc->dwDataLength + ((VIDEOINOUTHDR *) m_pDevHdr)->dwBytesUsed) <= pmmioSrc->dwMaxDataLength) { lNumBytesRead = mmioRead(pmmioSrc->hmmioSrc, ((VIDEOINOUTHDR *) m_pDevHdr)->pData, ((VIDEOINOUTHDR *) m_pDevHdr)->dwBytesUsed); pmmioSrc->dwDataLength += lNumBytesRead; } else { lNumBytesRead = mmioRead(pmmioSrc->hmmioSrc, ((VIDEOINOUTHDR *) m_pDevHdr)->pData, pmmioSrc->dwMaxDataLength - pmmioSrc->dwDataLength); pmmioSrc->dwDataLength += lNumBytesRead; CopyPreviousBuf ((VIDEOFORMATEX *) m_pDevFmt, (PBYTE) ((VIDEOINOUTHDR *) m_pDevHdr)->pData + lNumBytesRead, ((VIDEOINOUTHDR *) m_pDevHdr)->dwBytesUsed - lNumBytesRead); pmmioSrc->dwDataLength = 0; lNumBytesRead = 0; } if (!lNumBytesRead) { if (pmmioSrc->fLoop && !pmmioSrc->fDisconnectAfterPlayback) { // Reset file pointer to beginning of data mmioAscend(pmmioSrc->hmmioSrc, &(pmmioSrc->ckSrc), 0); if (-1L == mmioSeek(pmmioSrc->hmmioSrc, pmmioSrc->ckSrcRIFF.dwDataOffset + sizeof(FOURCC), SEEK_SET)) { DEBUGMSG (1, ("MediaControl::OpenSrcFile: Couldn't seek in file, mmr=%ld\r\n", (ULONG) 0L)); goto MyMMIOErrorExit2; } pmmioSrc->ckSrc.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(pmmioSrc->hmmioSrc, &(pmmioSrc->ckSrc), &(pmmioSrc->ckSrcRIFF), MMIO_FINDCHUNK)) { DEBUGMSG (1, ("MediaControl::OpenSrcFile: Couldn't locate 'data' chunk, mmr=%ld\r\n", (ULONG) 0L)); goto MyMMIOErrorExit2; } // At this point, the src file is sitting at the very // beginning of its data chunks--so we can read from the src file... goto MyRead; MyMMIOErrorExit2: mmioAscend(pmmioSrc->hmmioSrc, &(pmmioSrc->ckSrcRIFF), 0); mmioClose(pmmioSrc->hmmioSrc, 0); pmmioSrc->hmmioSrc = NULL; } else { mmioAscend(pmmioSrc->hmmioSrc, &(pmmioSrc->ckSrcRIFF), 0); mmioClose(pmmioSrc->hmmioSrc, 0); pmmioSrc->hmmioSrc = NULL; /* Dont want to disconnect the whole connection * TODO: investigate closing the channel if (pmmioSrc->fDisconnectAfterPlayback) pConnection->SetMode(CMT_Disconnect); */ } } } #endif } BOOL VideoPacket::IsSameMediaFormat(PVOID fmt1,PVOID fmt2) { return IsSameFormat(fmt1,fmt2); } // returns length of uncompressed video data in buffer // NOTE: not used yet DWORD VideoPacket::GetDevDataSamples() { // samples == frames for video and we only deal with one frame per pkt for now. return 1; }