📄 winutil.cpp
字号:
{
#ifdef WINUTIL_STUB
STUBRET(FALSE);
#else
return m_bUsingImageAllocator;
#endif // WINUTIL_STUB
}
// We need the media type of the connection so that we can get the BITMAPINFO
// from it. We use that in the calls to draw the image such as StretchDIBits
// and also when updating the colour table held in shared memory DIBSECTIONs
void CDrawImage::NotifyMediaType(CMediaType *pMediaType)
{
#ifdef WINUTIL_STUB
STUBNORET;
#else
m_pMediaType = pMediaType;
#endif // WINUTIL_STUB
}
// We store in this object a cookie maintaining the current palette version.
// Each time a palettised format is changed we increment this value so that
// when we come to draw the images we look at the colour table value they
// have and if less than the current we know to update it. This version is
// only needed and indeed used when working with shared memory DIBSECTIONs
LONG CDrawImage::GetPaletteVersion()
{
#ifdef WINUTIL_STUB
STUBRET(0);
#else
return m_PaletteVersion;
#endif // WINUTIL_STUB
}
// Resets the current palette version number
void CDrawImage::ResetPaletteVersion()
{
#ifdef WINUTIL_STUB
STUBNORET;
#else
m_PaletteVersion = PALETTE_VERSION;
#endif // WINUTIL_STUB
}
// Increment the current palette version
void CDrawImage::IncrementPaletteVersion()
{
#ifdef WINUTIL_STUB
STUBNORET;
#else
m_PaletteVersion++;
#endif // WINUTIL_STUB
}
// Constructor must initialise the base allocator. Each sample we create has a
// palette version cookie on board. When the source filter changes the palette
// during streaming the window object increments an internal cookie counter it
// keeps as well. When it comes to render the samples it looks at the cookie
// values and if they don't match then it knows to update the sample's colour
// table. However we always create samples with a cookie of PALETTE_VERSION
// If there have been multiple format changes and we disconnect and reconnect
// thereby causing the samples to be reallocated we will create them with a
// cookie much lower than the current version, this isn't a problem since it
// will be seen by the window object and the versions will then be updated
CImageAllocator::CImageAllocator(CBaseFilter *pFilter,
TCHAR *pName,
HRESULT *phr) :
CBaseAllocator(pName,NULL,phr)
#ifndef WINUTIL_STUB
, m_pFilter(pFilter)
#endif // WINUTIL_STUB
{
#ifdef WINUTIL_STUB
STUBNORET;
#else
ASSERT(phr);
ASSERT(pFilter);
#endif // WINUTIL_STUB
}
// Check our DIB buffers have been released
#ifdef DEBUG
CImageAllocator::~CImageAllocator()
{
#ifdef WINUTIL_STUB
STUBNORET;
#else
ASSERT(m_bCommitted == FALSE);
#endif // WINUTIL_STUB
}
#endif
// Called from destructor and also from base class to free resources. We work
// our way through the list of media samples deleting the DIBSECTION created
// for each. All samples should be back in our list so there is no chance a
// filter is still using one to write on the display or hold on a pending list
void CImageAllocator::Free()
{
#ifdef WINUTIL_STUB
STUBNORET;
#else
ASSERT(m_lAllocated == m_lFree.GetCount());
#ifndef UNDER_CE
EXECUTE_ASSERT(GdiFlush());
#endif // UNDER_CE
CImageSample *pSample;
DIBDATA *pDibData;
while (m_lFree.GetCount() != 0) {
pSample = (CImageSample *) m_lFree.RemoveHead();
pDibData = pSample->GetDIBData();
EXECUTE_ASSERT(DeleteObject(pDibData->hBitmap));
#ifndef UNDER_CE
EXECUTE_ASSERT(CloseHandle(pDibData->hMapping));
#endif
delete pSample;
}
m_lAllocated = 0;
#endif // WINUTIL_STUB
}
// Prepare the allocator by checking all the input parameters
STDMETHODIMP CImageAllocator::CheckSizes(ALLOCATOR_PROPERTIES *pRequest)
{
#ifdef WINUTIL_STUB
STUBFAIL;
#else
// Check we have a valid connection
if (m_pMediaType == NULL) {
return VFW_E_NOT_CONNECTED;
}
// NOTE We always create a DIB section with the source format type which
// may contain a source palette. When we do the BitBlt drawing operation
// the target display device may contain a different palette (we may not
// have the focus) in which case GDI will do after the palette mapping
BITMAPINFOHEADER *pBmiHeader = GetBitmapInfoHeader (m_pMediaType);
// When we call CreateDIBSection it implicitly maps only enough memory
// for the image as defined by thee BITMAPINFOHEADER. If the user asks
// for an image smaller than this then we reject the call, if they ask
// for an image larger than this then we return what they can have
if ((DWORD) pRequest->cbBuffer < pBmiHeader->biSizeImage) {
return E_INVALIDARG;
}
// Reject buffer prefixes
if (pRequest->cbPrefix > 0) {
return E_INVALIDARG;
}
pRequest->cbBuffer = pBmiHeader->biSizeImage;
return NOERROR;
#endif // WINUTIL_STUB
}
// Agree the number of media sample buffers and their sizes. The base class
// this allocator is derived from allows samples to be aligned only on byte
// boundaries NOTE the buffers are not allocated until the Commit call
STDMETHODIMP CImageAllocator::SetProperties(
ALLOCATOR_PROPERTIES * pRequest,
ALLOCATOR_PROPERTIES * pActual)
{
#ifdef WINUTIL_STUB
STUBFAIL;
#else
ALLOCATOR_PROPERTIES Adjusted = *pRequest;
// Check the parameters fit with the current connection
HRESULT hr = CheckSizes(&Adjusted);
if (FAILED(hr)) {
return hr;
}
return CBaseAllocator::SetProperties(&Adjusted, pActual);
#endif // WINUTIL_STUB
}
// Commit the memory by allocating the agreed number of media samples. For
// each sample we are committed to creating we have a CImageSample object
// that we use to manage it's resources. This is initialised with a DIBDATA
// structure that contains amongst other things the GDI DIBSECTION handle
// We will access the renderer media type during this so we must have locked
// (to prevent the format changing for example). The class overrides Commit
// and Decommit to do this locking (base class Commit in turn calls Alloc)
HRESULT CImageAllocator::Alloc(void)
{
#ifdef WINUTIL_STUB
STUBFAIL;
#else
ASSERT(m_pMediaType);
CImageSample *pSample;
DIBDATA DibData;
// Check the base allocator says it's ok to continue
HRESULT hr = CBaseAllocator::Alloc();
if (FAILED(hr)) {
return hr;
}
// We create a new memory mapped object although we don't map it into our
// address space because GDI does that in CreateDIBSection. It is possible
// that we run out of resources before creating all the samples in which
// case the available sample list is left with those already created
ASSERT(m_lAllocated == 0);
while (m_lAllocated < m_lCount) {
// Create and initialise a shared memory GDI buffer
HRESULT hr = CreateDIB(m_lSize,DibData);
if (FAILED(hr)) {
return hr;
}
// Create the sample object and pass it the DIBDATA
pSample = CreateImageSample(DibData.pBase,m_lSize);
if (pSample == NULL) {
EXECUTE_ASSERT(DeleteObject(DibData.hBitmap));
#ifndef UNDER_CE
EXECUTE_ASSERT(CloseHandle(DibData.hMapping));
#endif
return E_OUTOFMEMORY;
}
// Add the completed sample to the available list
pSample->SetDIBData(&DibData);
m_lFree.Add(pSample);
m_lAllocated++;
}
return NOERROR;
#endif // WINUTIL_STUB
}
// We have a virtual method that allocates the samples so that a derived class
// may override it and allocate more specialised sample objects. So long as it
// derives its samples from CImageSample then all this code will still work ok
CImageSample *CImageAllocator::CreateImageSample(LPBYTE pData,LONG Length)
{
#ifdef WINUTIL_STUB
STUBRET(NULL);
#else
HRESULT hr = NOERROR;
CImageSample *pSample;
// Allocate the new sample and check the return codes
pSample = new CImageSample((CBaseAllocator *) this, // Base class
NAME("Video sample"), // DEBUG name
(HRESULT *) &hr, // Return code
(LPBYTE) pData, // DIB address
(LONG) Length); // Size of DIB
if (pSample == NULL || FAILED(hr)) {
delete pSample;
return NULL;
}
return pSample;
#endif // WINUTIL_STUB
}
// This function allocates a shared memory block for use by the source filter
// generating DIBs for us to render. The memory block is created in shared
// memory so that GDI doesn't have to copy the memory when we do a BitBlt
HRESULT CImageAllocator::CreateDIB(LONG InSize,DIBDATA &DibData)
{
#ifdef WINUTIL_STUB
STUBFAIL;
#else
BITMAPINFO *pbmi; // Format information for pin
BYTE *pBase; // Pointer to the actual image
HANDLE hMapping; // Handle to mapped object
HBITMAP hBitmap; // DIB section bitmap handle
// Create a file mapping object and map into our address space
#ifndef UNDER_CE
hMapping = CreateFileMapping(hMEMORY, // Use system page file
NULL, // No security attributes
PAGE_READWRITE, // Full access to memory
(DWORD) 0, // Less than 4Gb in size
InSize, // Size of buffer
NULL); // No name to section
if (hMapping == NULL) {
DWORD Error = GetLastError();
return HRESULT_FROM_WIN32(Error);
}
#else
hMapping = NULL; // mapping object not supported in CreateDIBSection on CE
#endif
// NOTE We always create a DIB section with the source format type which
// may contain a source palette. When we do the BitBlt drawing operation
// the target display device may contain a different palette (we may not
// have the focus) in which case GDI will do after the palette mapping
pbmi = (BITMAPINFO *) GetBitmapInfoHeader(m_pMediaType);
if (m_pMediaType == NULL) {
DbgBreak("Invalid media type");
}
#ifdef UNDER_CE
BITMAPINFO *pBMI = NULL;
// BUGBUG: we have to do a temp fix here as CE currently doesn't have
// a way to get the BI_BITFIELD bitmasks for the screen from the system
if (pbmi->bmiHeader.biBitCount == 16 || pbmi->bmiHeader.biBitCount == 32)
{
pBMI = (BITMAPINFO *) new BYTE[(sizeof(BITMAPINFOHEADER) + (3 * sizeof(DWORD)))];
if (pBMI)
{
// copy the structure
*pBMI = *pbmi;
// fixup the struct
pBMI->bmiHeader.biCompression = BI_BITFIELDS;
// BUGBUG: angusg
// This is a temp fix to alow video to work on both 555 and 565 devices
// the pbmi structure above should be setup correctly with the bitfields
// but on CE it doesn't seem to be, the real fix would be to make sure
// that the format is setup correctly in the first place.
// Thing may be confused by the fact that on the desktop (Win95/98/NT)
// a bitmapinfo header with biBitCount == 16 and biCompression == BI_RGB
// means a 555 bitmap on CE this is invalid.
HDC hdcDisplay = GetDC(NULL);
ASSERT(hdcDisplay);
HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay,1,1);
if (hbm)
{
DIBSECTION dib;
GetObject(hbm, sizeof(DIBSECTION), &dib);
// get the bitfields if necessary
if (pBMI->bmiHeader.biCompression == BI_BITFIELDS)
{
DWORD *pdw = (DWORD *) (&(pBMI->bmiColors));
// just copy the bit fields if the compatible bmp has the same bit depth...
// Otherwise, just use the ones that came with the mediaformat.
if (pBMI->bmiHeader.biBitCount == dib.dsBmih.biBitCount) {
*pdw++ = (DWORD) dib.dsBitfields[0];
*pdw++ = (DWORD) dib.dsBitfields[1];
*pdw++ = (DWORD) dib.dsBitfields[2];
} else {
DWORD *pOrigBitFields = (DWORD *)(&(pbmi->bmiColors));
*pdw++ = (DWORD) pOrigBitFields[0];
*pdw++ = (DWORD) pOrigBitFields[1];
*pdw++ = (DWORD) pOrigBitFields[2];
}
// we have to do this on CE as it incorrectly returns 3
pBMI->bmiHeader.biClrUsed = 0;
}
DeleteObject(hbm);
}
else
{
ASSERT(TRUE);
// assume 565
pBMI->bmiColors[2].rgbBlue = 0x1F;
pBMI->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -