⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winutil.cpp

📁 basic class basic classbasic class
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
#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 + -