You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
634 lines
21 KiB
634 lines
21 KiB
|
|
/****************************************************************************
|
|
* @doc INTERNAL WDMPIN
|
|
*
|
|
* @module WDMPin.cpp | Include file for <c CWDMPin> class used to access
|
|
* video data on a video streaming pin exposed by the WDM class driver.
|
|
*
|
|
* @comm This code is based on the VfW to WDM mapper code written by
|
|
* FelixA and E-zu Wu. The original code can be found on
|
|
* \\redrum\slmro\proj\wdm10\\src\image\vfw\win9x\raytube.
|
|
*
|
|
* Documentation by George Shaw on kernel streaming can be found in
|
|
* \\popcorn\razzle1\src\spec\ks\ks.doc.
|
|
*
|
|
* WDM streaming capture is discussed by Jay Borseth in
|
|
* \\blues\public\jaybo\WDMVCap.doc.
|
|
***************************************************************************/
|
|
|
|
#include "Precomp.h"
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc void | CWDMPin | CWDMPin | Video pin class constructor.
|
|
*
|
|
* @parm DWORD | dwDeviceID | Capture device ID.
|
|
***************************************************************************/
|
|
CWDMPin::CWDMPin(DWORD dwDeviceID) : CWDMDriver(dwDeviceID)
|
|
{
|
|
m_hKS = (HANDLE)NULL;
|
|
m_fStarted = FALSE;
|
|
m_hKsUserDLL = (HINSTANCE)NULL;
|
|
m_pKsCreatePin = (LPFNKSCREATEPIN)NULL;
|
|
|
|
ZeroMemory(&m_biHdr, sizeof(KS_BITMAPINFOHEADER));
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc void | CWDMPin | ~CWDMPin | Video pin class destructor. Closes
|
|
* the video pin and releases the video buffers allocated.
|
|
***************************************************************************/
|
|
CWDMPin::~CWDMPin()
|
|
{
|
|
FX_ENTRY("CWDMPin::~CWDMPin");
|
|
|
|
DEBUGMSG(ZONE_INIT, ("%s: Destroying the video pin, m_hKS=0x%08lX\r\n", _fx_, m_hKS));
|
|
|
|
// Nuke the video streaming pin
|
|
DestroyPin();
|
|
|
|
// Close the driver
|
|
if (GetDriverHandle())
|
|
CloseDriver();
|
|
|
|
// Release kernel streaming DLL (KSUSER.DLL)
|
|
if (m_hKsUserDLL)
|
|
FreeLibrary(m_hKsUserDLL);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | GetFrame | This function gets a frame from the
|
|
* video streaming pin.
|
|
*
|
|
* @parm LPVIDEOHDR | lpVHdr | Pointer to the destination buffer to receive
|
|
* the video frame and information.
|
|
*
|
|
* @parm PDWORD | pdwBytesUsed | Pointer to the number of bytes used to
|
|
* read the video frame.
|
|
*
|
|
* @rdesc Returns TRUE if successful, or FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::GetFrame(LPVIDEOHDR lpVHdr)
|
|
{
|
|
FX_ENTRY("CWDMPin::GetFrame");
|
|
|
|
ASSERT(lpVHdr && lpVHdr->lpData && GetDriverHandle() && m_hKS && (lpVHdr->dwBufferLength >= m_biHdr.biSizeImage));
|
|
|
|
DWORD bRtn;
|
|
|
|
// Check input params and state
|
|
if (!lpVHdr || !lpVHdr->lpData || !GetDriverHandle() || !m_hKS || (lpVHdr->dwBufferLength < m_biHdr.biSizeImage))
|
|
{
|
|
ERRORMESSAGE(("%s: No buffer, no driver, no PIN connection, or buffer too small\r\n", _fx_));
|
|
goto MyError0;
|
|
}
|
|
|
|
// Put the pin in streaming mode
|
|
if (!Start())
|
|
{
|
|
ERRORMESSAGE(("%s: Cannot set streaming state to KSSTATE_RUN\r\n", _fx_));
|
|
goto MyError0;
|
|
}
|
|
|
|
// Initialize structure to do a read on the video pin
|
|
DWORD cbBytesReturned;
|
|
KS_HEADER_AND_INFO SHGetImage;
|
|
|
|
ZeroMemory(&SHGetImage,sizeof(SHGetImage));
|
|
SHGetImage.StreamHeader.Data = (LPDWORD)lpVHdr->lpData;
|
|
SHGetImage.StreamHeader.Size = sizeof (KS_HEADER_AND_INFO);
|
|
SHGetImage.StreamHeader.FrameExtent = m_biHdr.biSizeImage;
|
|
SHGetImage.FrameInfo.ExtendedHeaderSize = sizeof (KS_FRAME_INFO);
|
|
|
|
// Read a frame on the video pin
|
|
bRtn = DeviceIoControl(m_hKS, IOCTL_KS_READ_STREAM, &SHGetImage, sizeof(SHGetImage), &SHGetImage, sizeof(SHGetImage), &cbBytesReturned);
|
|
|
|
if (!bRtn)
|
|
{
|
|
ERRORMESSAGE(("%s: DevIo rtn (%d), GetLastError=%d. StreamState->STOP\r\n", _fx_, bRtn, GetLastError()));
|
|
|
|
// Stop streaming on the video pin
|
|
Stop();
|
|
|
|
goto MyError0;
|
|
}
|
|
|
|
// Sanity check
|
|
ASSERT(SHGetImage.StreamHeader.FrameExtent >= SHGetImage.StreamHeader.DataUsed);
|
|
if (SHGetImage.StreamHeader.FrameExtent < SHGetImage.StreamHeader.DataUsed)
|
|
{
|
|
ERRORMESSAGE(("%s: We've corrupted memory!\r\n", _fx_));
|
|
goto MyError0;
|
|
}
|
|
|
|
lpVHdr->dwTimeCaptured = timeGetTime();
|
|
lpVHdr->dwBytesUsed = SHGetImage.StreamHeader.DataUsed;
|
|
lpVHdr->dwFlags |= VHDR_KEYFRAME;
|
|
|
|
return TRUE;
|
|
|
|
MyError0:
|
|
if (lpVHdr)
|
|
{
|
|
lpVHdr->dwBytesUsed = 0UL;
|
|
lpVHdr->dwTimeCaptured = timeGetTime();
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | Start | This function puts the video
|
|
* pin in streaming mode.
|
|
*
|
|
* @rdesc Returns TRUE if successful, or FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::Start()
|
|
{
|
|
if (m_fStarted)
|
|
return TRUE;
|
|
|
|
if (SetState(KSSTATE_PAUSE))
|
|
m_fStarted = SetState(KSSTATE_RUN);
|
|
|
|
return m_fStarted;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | Stop | This function stops streaming on the
|
|
* video pin.
|
|
*
|
|
* @rdesc Returns TRUE if successful, or FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::Stop()
|
|
{
|
|
if (m_fStarted)
|
|
{
|
|
if (SetState(KSSTATE_PAUSE))
|
|
if (SetState(KSSTATE_STOP))
|
|
m_fStarted = FALSE;
|
|
}
|
|
|
|
return (BOOL)(m_fStarted == FALSE);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | SetState | This function sets the state of the
|
|
* video streaming pin.
|
|
*
|
|
* @parm KSSTATE | ksState | New state.
|
|
*
|
|
* @rdesc Returns TRUE if successful, or FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::SetState(KSSTATE ksState)
|
|
{
|
|
KSPROPERTY ksProp = {0};
|
|
DWORD cbRet;
|
|
|
|
ksProp.Set = KSPROPSETID_Connection;
|
|
ksProp.Id = KSPROPERTY_CONNECTION_STATE;
|
|
ksProp.Flags = KSPROPERTY_TYPE_SET;
|
|
|
|
return DeviceIoControl(m_hKS, IOCTL_KS_PROPERTY, &ksProp, sizeof(ksProp), &ksState, sizeof(KSSTATE), &cbRet);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | SetState | This function either finds a video
|
|
* data range compatible with the bitamp info header passed in, of the
|
|
* prefered video data range.
|
|
*
|
|
* @parm PKS_BITMAPINFOHEADER | pbiHdr | Bitmap info header to match.
|
|
*
|
|
* @parm BOOL | pfValidMatch | Set to TRUE if a match was found, FALSE
|
|
* otherwise.
|
|
*
|
|
* @rdesc Returns a valid pointer to a <t KS_DATARANGE_VIDEO> structure if
|
|
* successful, or a NULL pointer otherwise.
|
|
*
|
|
* @comm \\redrum\slmro\proj\wdm10\src\dvd\amovie\proxy\filter\ksutil.cpp(207):KsGetMediaTypes(
|
|
***************************************************************************/
|
|
PKS_DATARANGE_VIDEO CWDMPin::FindMatchDataRangeVideo(PKS_BITMAPINFOHEADER pbiHdr, BOOL *pfValidMatch)
|
|
{
|
|
FX_ENTRY("CWDMPin::FindMatchDataRangeVideo");
|
|
|
|
ASSERT(pfValidMatch && pbiHdr);
|
|
|
|
// Check input params and state
|
|
if (!pbiHdr || !pfValidMatch)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad input params\r\n", _fx_));
|
|
return (PKS_DATARANGE_VIDEO)NULL;
|
|
}
|
|
|
|
// Default
|
|
*pfValidMatch = FALSE;
|
|
|
|
PDATA_RANGES pDataRanges = GetDriverSupportedDataRanges();
|
|
|
|
ASSERT(pDataRanges != 0);
|
|
|
|
if (!pDataRanges)
|
|
return (PKS_DATARANGE_VIDEO)NULL;
|
|
|
|
PKS_DATARANGE_VIDEO pSelDRVideo, pDRVideo = &pDataRanges->Data, pFirstDRVideo = 0;
|
|
KS_BITMAPINFOHEADER * pbInfo;
|
|
|
|
// PhilF-: This code assumes that all structures are KS_DATARANGE_VIDEO. This
|
|
// may not be a valid assumption foir palettized data types. Check with JayBo
|
|
for (ULONG i = 0; i < pDataRanges->Count; i++)
|
|
{
|
|
// Meaningless unless it is *_VIDEOINFO
|
|
if (pDRVideo->DataRange.Specifier == KSDATAFORMAT_SPECIFIER_VIDEOINFO)
|
|
{
|
|
// We don't care about TV Tuner like devices
|
|
if (pDRVideo->ConfigCaps.VideoStandard == KS_AnalogVideo_None)
|
|
{
|
|
// Save first useable data range
|
|
if (!pFirstDRVideo)
|
|
pFirstDRVideo = pDRVideo;
|
|
|
|
pbInfo = &((pDRVideo->VideoInfoHeader).bmiHeader);
|
|
|
|
if ( (pbInfo->biBitCount == pbiHdr->biBitCount) && (pbInfo->biCompression == pbiHdr->biCompression) &&
|
|
( (((pDRVideo->ConfigCaps.OutputGranularityX == 0) || (pDRVideo->ConfigCaps.OutputGranularityY == 0))
|
|
&& (pDRVideo->ConfigCaps.InputSize.cx == pbiHdr->biWidth) && (pDRVideo->ConfigCaps.InputSize.cy == pbiHdr->biHeight)) ||
|
|
((pDRVideo->ConfigCaps.MinOutputSize.cx <= pbiHdr->biWidth) && (pbiHdr->biWidth <= pDRVideo->ConfigCaps.MaxOutputSize.cx) &&
|
|
(pDRVideo->ConfigCaps.MinOutputSize.cy <= pbiHdr->biHeight) && (pbiHdr->biHeight <= pDRVideo->ConfigCaps.MaxOutputSize.cy) &&
|
|
((pbiHdr->biWidth % pDRVideo->ConfigCaps.OutputGranularityX) == 0) && ((pbiHdr->biHeight % pDRVideo->ConfigCaps.OutputGranularityY) == 0)) ) )
|
|
{
|
|
*pfValidMatch = TRUE;
|
|
pSelDRVideo = pDRVideo;
|
|
break;
|
|
}
|
|
} // VideoStandard
|
|
} // Specifier
|
|
|
|
pDRVideo++; // Next KS_DATARANGE_VIDEO
|
|
}
|
|
|
|
// If no valid match, use the first range found
|
|
if (!*pfValidMatch)
|
|
pSelDRVideo = pFirstDRVideo;
|
|
|
|
return (pSelDRVideo);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | CreatePin | This function actually creates a
|
|
* video streaming pin on the class driver.
|
|
*
|
|
* @parm PKS_BITMAPINFOHEADER | pbiNewHdr | This pointer to a bitmap info
|
|
* header specifies the format of the video data we want from the pin.
|
|
*
|
|
* @parm DWORD | dwAvgTimePerFrame | This parameter specifies the frame
|
|
* at which we want video frames to be produced on the pin.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::CreatePin(PKS_BITMAPINFOHEADER pbiNewHdr, DWORD dwAvgTimePerFrame)
|
|
{
|
|
FX_ENTRY("CWDMPin::CreatePin");
|
|
|
|
ASSERT(m_pKsCreatePin);
|
|
|
|
PKS_BITMAPINFOHEADER pbiHdr;
|
|
BOOL bMustMatch, bValidMatch;
|
|
#ifdef _DEBUG
|
|
char szFourCC[5] = {0};
|
|
#endif
|
|
|
|
if (pbiNewHdr)
|
|
{
|
|
// We need to find a video data range that matches the bitmap info header passed in
|
|
bMustMatch = TRUE;
|
|
pbiHdr = pbiNewHdr;
|
|
}
|
|
else
|
|
{
|
|
// We'll use the preferred video data range and default bitmap format
|
|
bMustMatch = FALSE;
|
|
pbiHdr = &m_biHdr;
|
|
}
|
|
|
|
PKS_DATARANGE_VIDEO pSelDRVideo = FindMatchDataRangeVideo(pbiHdr, &bValidMatch);
|
|
if (!pSelDRVideo)
|
|
return FALSE;
|
|
|
|
if (bMustMatch && !bValidMatch)
|
|
return FALSE;
|
|
|
|
// If we already have a pin, nuke it
|
|
if (GetPinHandle())
|
|
DestroyPin();
|
|
|
|
// Connect to a new PIN.
|
|
DATAPINCONNECT DataConnect;
|
|
ZeroMemory(&DataConnect, sizeof(DATAPINCONNECT));
|
|
DataConnect.Connect.PinId = 0; // CODEC0 sink
|
|
DataConnect.Connect.PinToHandle = NULL; // no "connect to"
|
|
DataConnect.Connect.Interface.Set = KSINTERFACESETID_Standard;
|
|
DataConnect.Connect.Interface.Id = KSINTERFACE_STANDARD_STREAMING; // STREAMING
|
|
DataConnect.Connect.Medium.Set = KSMEDIUMSETID_Standard;
|
|
DataConnect.Connect.Medium.Id = KSMEDIUM_STANDARD_DEVIO;
|
|
DataConnect.Connect.Priority.PriorityClass = KSPRIORITY_NORMAL;
|
|
DataConnect.Connect.Priority.PrioritySubClass = 1;
|
|
CopyMemory(&(DataConnect.Data.DataFormat), &(pSelDRVideo->DataRange), sizeof(KSDATARANGE));
|
|
CopyMemory(&(DataConnect.Data.VideoInfoHeader), &pSelDRVideo->VideoInfoHeader, sizeof(KS_VIDEOINFOHEADER));
|
|
|
|
// Adjust the image sizes if necessary
|
|
if (bValidMatch)
|
|
{
|
|
DataConnect.Data.VideoInfoHeader.bmiHeader.biWidth = pbiHdr->biWidth;
|
|
DataConnect.Data.VideoInfoHeader.bmiHeader.biHeight = abs(pbiHdr->biHeight); // Support only +biHeight!
|
|
DataConnect.Data.VideoInfoHeader.bmiHeader.biSizeImage = pbiHdr->biSizeImage;
|
|
}
|
|
|
|
// Overwrite the default frame rate if non-zero
|
|
if (dwAvgTimePerFrame > 0)
|
|
DataConnect.Data.VideoInfoHeader.AvgTimePerFrame = (REFERENCE_TIME)dwAvgTimePerFrame;
|
|
|
|
#ifdef _DEBUG
|
|
*((DWORD*)&szFourCC) = DataConnect.Data.VideoInfoHeader.bmiHeader.biCompression;
|
|
#endif
|
|
DEBUGMSG(ZONE_INIT, ("%s: Request image format: FourCC(%s) %d * %d * %d bits = %d bytes\r\n", _fx_, szFourCC, DataConnect.Data.VideoInfoHeader.bmiHeader.biWidth, DataConnect.Data.VideoInfoHeader.bmiHeader.biHeight, DataConnect.Data.VideoInfoHeader.bmiHeader.biBitCount, DataConnect.Data.VideoInfoHeader.bmiHeader.biSizeImage));
|
|
DEBUGMSG(ZONE_INIT, ("%s: Request frame rate: %d fps\r\n", _fx_, 10000000/dwAvgTimePerFrame));
|
|
DEBUGMSG(ZONE_INIT, ("%s: m_hKS was=0x%08lX\r\n", _fx_, m_hKS));
|
|
|
|
#ifndef HIDE_WDM_DEVICES
|
|
DWORD dwErr = (*m_pKsCreatePin)(GetDriverHandle(), (PKSPIN_CONNECT)&DataConnect, GENERIC_READ | GENERIC_WRITE, &m_hKS);
|
|
#else
|
|
DWORD dwErr = 0UL;
|
|
m_hKS = NULL;
|
|
#endif
|
|
|
|
if (dwAvgTimePerFrame != 0)
|
|
{
|
|
DEBUGMSG(ZONE_INIT, ("%s: m_hKS is now=0x%08lX set to stream at %d fps\r\n", _fx_, m_hKS, 10000000/dwAvgTimePerFrame));
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(ZONE_INIT, ("%s: m_hKS is now=0x%08lX\r\n", _fx_, m_hKS));
|
|
}
|
|
|
|
if (dwErr || (m_hKS == NULL))
|
|
{
|
|
ERRORMESSAGE(("%s: KsCreatePin returned 0x%08lX failure and m_hKS=0x%08lX\r\n", _fx_, dwErr, m_hKS));
|
|
|
|
if (m_hKS == INVALID_HANDLE_VALUE)
|
|
{
|
|
m_hKS = (HANDLE)NULL;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Cache the bitmap info header
|
|
CopyMemory(&m_biHdr, &DataConnect.Data.VideoInfoHeader.bmiHeader, sizeof(KS_BITMAPINFOHEADER));
|
|
m_dwAvgTimePerFrame = (DWORD)DataConnect.Data.VideoInfoHeader.AvgTimePerFrame;
|
|
|
|
DEBUGMSG(ZONE_INIT, ("%s: New m_biHdr:\r\n biSize=%ld\r\n biWidth=%ld\r\n biHeight=%ld\r\n biPlanes=%ld\r\n biBitCount=%ld\r\n biCompression=%ld\r\n biSizeImage=%ld\r\n", _fx_, m_biHdr.biSize, m_biHdr.biWidth, m_biHdr.biHeight, m_biHdr.biPlanes, m_biHdr.biBitCount, m_biHdr.biCompression, m_biHdr.biSizeImage));
|
|
DEBUGMSG(ZONE_INIT, ("%s: New m_dwAvgTimePerFrame=%ld (%fd fps)\r\n", _fx_, m_dwAvgTimePerFrame, 10000000/m_dwAvgTimePerFrame));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | DestroyPin | This function nukes a video
|
|
* streaming pin.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::DestroyPin()
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
FX_ENTRY("CWDMPin::DestroyPin");
|
|
|
|
DEBUGMSG(ZONE_INIT, ("%s: Destroy PIN m_hKS=0x%08lX\r\n", _fx_, m_hKS));
|
|
|
|
if (m_hKS)
|
|
{
|
|
Stop();
|
|
|
|
if (!(fRet = CloseHandle(m_hKS)))
|
|
{
|
|
ERRORMESSAGE(("%s: CloseHandle(m_hKS=0x%08lX) failed with GetLastError()=0x%08lX\r\n", _fx_, m_hKS, GetLastError()));
|
|
}
|
|
|
|
m_hKS = NULL;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | SetBitmapInfo | This function sets the video
|
|
* format of video streaming pin.
|
|
*
|
|
* @parm PKS_BITMAPINFOHEADER | pbiHdrNew | This pointer to a bitmap info
|
|
* header specifies the format of the video data we want from the pin.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::SetBitmapInfo(PKS_BITMAPINFOHEADER pbiHdrNew)
|
|
{
|
|
FX_ENTRY("CWDMPin::SetBitmapInfo");
|
|
|
|
// Validate call
|
|
if (!GetDriverHandle())
|
|
{
|
|
ERRORMESSAGE(("%s: Driver hasn't been opened yet\r\n", _fx_));
|
|
return FALSE;
|
|
}
|
|
|
|
DEBUGMSG(ZONE_INIT, ("%s: New pbiHdrNew:\r\n biSize=%ld\r\n biWidth=%ld\r\n biHeight=%ld\r\n biPlanes=%ld\r\n biBitCount=%ld\r\n biCompression=%ld\r\n biSizeImage=%ld\r\n", _fx_, pbiHdrNew->biSize, pbiHdrNew->biWidth, pbiHdrNew->biHeight, pbiHdrNew->biPlanes, pbiHdrNew->biBitCount, pbiHdrNew->biCompression, pbiHdrNew->biSizeImage));
|
|
|
|
// Check if we need to change anything
|
|
if ( GetPinHandle() && (m_biHdr.biHeight == pbiHdrNew->biHeight) && (m_biHdr.biWidth == pbiHdrNew->biWidth) &&
|
|
(m_biHdr.biBitCount == pbiHdrNew->biBitCount) && (m_biHdr.biSizeImage == pbiHdrNew->biSizeImage) &&
|
|
(m_biHdr.biCompression == pbiHdrNew->biCompression) )
|
|
return TRUE;
|
|
else
|
|
return CreatePin(pbiHdrNew, m_dwAvgTimePerFrame);
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | GetBitmapInfo | This function gets the video
|
|
* format of a video streaming pin.
|
|
*
|
|
* @parm PKS_BITMAPINFOHEADER | pbInfo | This parameter points to a bitmap
|
|
* info header structure to receive the video format.
|
|
*
|
|
* @parm WORD | wSize | This parameter specifies the size of the bitmap
|
|
* info header structure.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::GetBitmapInfo(PKS_BITMAPINFOHEADER pbInfo, WORD wSize)
|
|
{
|
|
|
|
FX_ENTRY("CWDMPin::GetBitmapInfo");
|
|
|
|
// Validate call
|
|
if (!m_hKS && !m_biHdr.biSizeImage)
|
|
{
|
|
ERRORMESSAGE(("%s: No existing PIN handle or no available format\r\n", _fx_));
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory(pbInfo, &m_biHdr, wSize);
|
|
|
|
// Support only positive +biHeight.
|
|
if (pbInfo->biHeight < 0)
|
|
{
|
|
pbInfo->biHeight = -pbInfo->biHeight;
|
|
DEBUGMSG(ZONE_INIT, ("%s: Changed biHeight from -%ld to %ld\r\n", _fx_, pbInfo->biHeight, pbInfo->biHeight));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | GetPaletteInfo | This function gets the video
|
|
* palette of a video streaming pin.
|
|
*
|
|
* @parm CAPTUREPALETTE * | pPal | This parameter points to a palette
|
|
* structure to receive the video palette.
|
|
*
|
|
* @parm DWORD | dwcbSize | This parameter specifies the size of the video
|
|
* palette.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::GetPaletteInfo(CAPTUREPALETTE *pPal, DWORD dwcbSize)
|
|
{
|
|
|
|
FX_ENTRY("CWDMPin::GetBitmapInfo");
|
|
|
|
// Validate call
|
|
if (!m_hKS && !m_biHdr.biSizeImage && (m_biHdr.biBitCount > 8))
|
|
{
|
|
ERRORMESSAGE(("%s: No existing PIN handle, no available format, or bad biBitCount\r\n", _fx_));
|
|
return FALSE;
|
|
}
|
|
|
|
// PhilF-: Copy some real bits there
|
|
// CopyMemory(pbInfo, &m_biHdr, wSize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | SetAverageTimePerFrame | This function sets the
|
|
* video frame rate of a video streaming pin.
|
|
*
|
|
* @parm DWORD | dwAvgTimePerFrame | This parameter specifies the rate
|
|
* at which we want video frames to be produced on the pin.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::SetAverageTimePerFrame(DWORD dwNewAvgTimePerFrame)
|
|
{
|
|
FX_ENTRY("CWDMPin::SetAverageTimePerFrame");
|
|
|
|
// Validate call
|
|
if (!GetDriverHandle())
|
|
{
|
|
ERRORMESSAGE(("%s: Driver hasn't been opened yet\r\n", _fx_));
|
|
return FALSE;
|
|
}
|
|
|
|
DEBUGMSG(ZONE_INIT, ("%s: Current frame interval=%d; new frame intercal=%d\r\n", _fx_, m_dwAvgTimePerFrame, dwNewAvgTimePerFrame));
|
|
|
|
if (m_dwAvgTimePerFrame != dwNewAvgTimePerFrame)
|
|
return CreatePin(&m_biHdr, dwNewAvgTimePerFrame);
|
|
else
|
|
{
|
|
DEBUGMSG(ZONE_INIT, ("%s: No need to change frame rate\r\n", _fx_));
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* @doc INTERNAL CWDMPINMETHOD
|
|
*
|
|
* @mfunc BOOL | CWDMPin | OpenDriverAndPin | This function opens the class
|
|
* driver and creates a video streaming pin.
|
|
*
|
|
* @rdesc Returns TRUE is successful, FALSE otherwise.
|
|
***************************************************************************/
|
|
BOOL CWDMPin::OpenDriverAndPin()
|
|
{
|
|
FX_ENTRY("CWDMPin::OpenDriverAndPin");
|
|
|
|
// Load KSUSER.DLL and get a proc address
|
|
if (m_hKsUserDLL = LoadLibrary("KSUSER"))
|
|
{
|
|
if (m_pKsCreatePin = (LPFNKSCREATEPIN)GetProcAddress(m_hKsUserDLL, "KsCreatePin"))
|
|
{
|
|
// Open the class driver
|
|
if (OpenDriver())
|
|
{
|
|
// Create a video streaming pin on the driver
|
|
if (CreatePin((PKS_BITMAPINFOHEADER)NULL))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(ZONE_INIT, ("%s: Pin connection creation failed!\r\n", _fx_));
|
|
|
|
if (GetDriverHandle())
|
|
CloseDriver();
|
|
}
|
|
}
|
|
}
|
|
|
|
FreeLibrary(m_hKsUserDLL);
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
|