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

📄 winutil.cpp

📁 包裝ffmpeg中的codecs成為DirectShow中的transform filter
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    if (pRequest->cbPrefix > 0) {
        return E_INVALIDARG;
    }

    pRequest->cbBuffer = pVideoInfo->bmiHeader.biSizeImage;
    return NOERROR;
}


// 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)
{
    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);
}


// 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)
{
    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));
            EXECUTE_ASSERT(CloseHandle(DibData.hMapping));
            return E_OUTOFMEMORY;
        }

        // Add the completed sample to the available list

        pSample->SetDIBData(&DibData);
        m_lFree.Add(pSample);
        m_lAllocated++;
    }
    return NOERROR;
}


// 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)
{
    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;
}


// 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)
{
    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

    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 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
    }

    // 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 *) HEADER(m_pMediaType->Format());
    if (m_pMediaType == NULL) {
        DbgBreak("Invalid media type");
    }

    hBitmap = CreateDIBSection((HDC) NULL,          // NO device context
                               pbmi,                // Format information
                               DIB_RGB_COLORS,      // Use the palette
                               (VOID **) &pBase,    // Pointer to image data
                               hMapping,            // Mapped memory handle
                               (DWORD) 0);          // Offset into memory

    if (hBitmap == NULL || pBase == NULL) {
        EXECUTE_ASSERT(CloseHandle(hMapping));
        DWORD Error = GetLastError();
        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
    }

    // Initialise the DIB information structure

    DibData.hBitmap = hBitmap;
    DibData.hMapping = hMapping;
    DibData.pBase = pBase;
    DibData.PaletteVersion = PALETTE_VERSION;
    GetObject(hBitmap,sizeof(DIBSECTION),(VOID *)&DibData.DibSection);

    return NOERROR;
}


// We use the media type during the DIBSECTION creation

void CImageAllocator::NotifyMediaType(CMediaType *pMediaType)
{
    m_pMediaType = pMediaType;
}


// Overriden to increment the owning object's reference count

STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingAddRef()
{
    return m_pFilter->AddRef();
}


// Overriden to decrement the owning object's reference count

STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingRelease()
{
    return m_pFilter->Release();
}


// If you derive a class from CMediaSample that has to transport specialised
// member variables and entry points then there are three alternate solutions
// The first is to create a memory buffer larger than actually required by the
// sample and store your information either at the beginning of it or at the
// end, the former being moderately safer allowing for misbehaving transform
// filters. You then adjust the buffer address when you create the base media
// sample. This has the disadvantage of breaking up the memory allocated to
// the samples into separate blocks. The second solution is to implement a
// class derived from CMediaSample and support additional interface(s) that
// convey your private data. This means defining a custom interface. The final
// alternative is to create a class that inherits from CMediaSample and adds
// the private data structures, when you get an IMediaSample in your Receive()
// call check to see if your allocator is being used, and if it is then cast
// the IMediaSample into one of your objects. Additional checks can be made
// to ensure the sample's this pointer is known to be one of your own objects

CImageSample::CImageSample(CBaseAllocator *pAllocator,
                           TCHAR *pName,
                           HRESULT *phr,
                           LPBYTE pBuffer,
                           LONG length) :
    CMediaSample(pName,pAllocator,phr,pBuffer,length),
    m_bInit(FALSE)
{
    ASSERT(pAllocator);
    ASSERT(pBuffer);
}


// Set the shared memory DIB information

void CImageSample::SetDIBData(DIBDATA *pDibData)
{
    ASSERT(pDibData);
    m_DibData = *pDibData;
    m_bInit = TRUE;
}


// Retrieve the shared memory DIB data

DIBDATA *CImageSample::GetDIBData()
{
    ASSERT(m_bInit == TRUE);
    return &m_DibData;
}


// This class handles the creation of a palette. It is fairly specialist and
// is intended to simplify palette management for video renderer filters. It
// is for this reason that the constructor requires three other objects with
// which it interacts, namely a base media filter, a base window and a base
// drawing object although the base window or the draw object may be NULL to
// ignore that part of us. We try not to create and install palettes unless
// absolutely necessary as they typically require WM_PALETTECHANGED messages
// to be sent to every window thread in the system which is very expensive

CImagePalette::CImagePalette(CBaseFilter *pBaseFilter,
                             CBaseWindow *pBaseWindow,
                             CDrawImage *pDrawImage) :
    m_pBaseWindow(pBaseWindow),
    m_pFilter(pBaseFilter),
    m_pDrawImage(pDrawImage),
    m_hPalette(NULL)
{
    ASSERT(m_pFilter);
}


// Destructor

#ifdef DEBUG
CImagePalette::~CImagePalette()
{
    ASSERT(m_hPalette == NULL);
}
#endif


// We allow dynamic format changes of the palette but rather than change the
// palette every time we call this to work out whether an update is required.
// If the original type didn't use a palette and the new one does (or vica
// versa) then we return TRUE. If neither formats use a palette we'll return
// FALSE. If both formats use a palette we compare their colours and return
// FALSE if they match. This therefore short circuits palette creation unless
// absolutely necessary since installing palettes is an expensive operation

BOOL CImagePalette::ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,
                                 const VIDEOINFOHEADER *pOldInfo)
{
    // We may not have a current format yet

    if (pOldInfo == NULL) {
        return TRUE;
    }

    // Do both formats not require a palette

    if (ContainsPalette(pNewInfo) == FALSE) {
        if (ContainsPalette(pOldInfo) == FALSE) {
            return FALSE;
        }
    }

    // Compare the colours to see if they match

    DWORD VideoEntries = pNewInfo->bmiHeader.biClrUsed;
    if (ContainsPalette(pNewInfo) == TRUE)
        if (ContainsPalette(pOldInfo) == TRUE)
            if (pOldInfo->bmiHeader.biClrUsed == VideoEntries)
                if (pOldInfo->bmiHeader.biClrUsed > 0)
                    if (memcmp((PVOID) GetBitmapPalette(pNewInfo),
                               (PVOID) GetBitmapPalette(pOldInfo),
                               VideoEntries * sizeof(RGBQUAD)) == 0) {

                        return FALSE;
                    }
    return TRUE;
}


// This is normally called when the input pin type is set to install a palette
// We will typically be called from two different places. The first is when we
// have negotiated a palettised media type after connection, the other is when
// we receive a new type during processing with an updated palette in which
// case we must remove and release the resources held by the current palette

// We can be passed an optional device name if we wish to prepare a palette
// for a specific monitor on a multi monitor system

HRESULT CImagePalette::PreparePalette(const CMediaType *pmtNew,
                                      const CMediaType *pmtOld,
				      LPSTR szDevice)
{
    const VIDEOINFOHEADER *pNewInfo = (VIDEOINFOHEADER *) pmtNew->Format();
    const VIDEOINFOHEADER *pOldInfo = (VIDEOINFOHEADER *) pmtOld->Format();
    ASSERT(pNewInfo);

    // This is an performance optimisation, when we get a media type we check
    // to see if the format requires a palette change. If either we need one
    // when previously we didn't or vica versa then this returns TRUE, if we
    // previously needed a palette and we do now it compares their colours

    if (ShouldUpdate(pNewInfo,pOldInfo) == FALSE) {
        NOTE("No update needed");
        return S_FALSE;
    }

    // We must notify the filter graph that the application may have changed
    // the palette although in practice we don't bother checking to see if it
    // is really different. If it tries to get the palette either the window
    // or renderer lock will ensure it doesn't get in until we are finished

    RemovePalette();
    m_pFilter->NotifyEvent(EC_PALETTE_CHANGED,0,0);

    // Do we need a palette for the new format

    if (ContainsPalette(pNewInfo) == FALSE) {
        NOTE("New has no palette");
        return S_FALSE;
    }

    if (m_pBaseWindow) {
        m_pBaseWindow->LockPaletteLock();
    }

    // If we're changing the palette on the fly then we increment our palette
    // cookie which is compared against the cookie also stored in all of our
    // DIBSECTION media samples. If they don't match when we come to draw it
    // then we know the sample is out of date and we'll update it's palette

    NOTE("Making new colour palette");
    m_hPalette = MakePalette(pNewInfo, szDevice);
    ASSERT(m_hPalette != NULL);

    if (m_pBaseWindow) {
        m_pBaseWindow->UnlockPaletteLock();
    }

    // The window in which the new palette is to be realised may be a NULL
    // pointer to signal that no window is in use, if so we don't call it
    // Some

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -