569 lines
13 KiB
C++
569 lines
13 KiB
C++
|
|
#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;
|
|
}
|
|
|