home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================;
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
- //
- // Contrast
- //
- // A Transform filter that alters the contrast of a video
- // image as it passes through
-
- #include <windows.h>
- #include <streams.h>
-
- #include <initguid.h>
- #include <olectl.h>
- #include <olectlid.h>
-
- #include "contuids.h"
- #include "icontrst.h"
- #include "contprop.h"
- #include "contrast.h"
-
- // setup data
-
- AMOVIESETUP_MEDIATYPE sudPinTypes = { &MEDIATYPE_Video // clsMajorType
- , &MEDIASUBTYPE_NULL } ; // clsMinorType
-
- AMOVIESETUP_PIN psudPins[] = { { L"Input" // strName
- , FALSE // bRendered
- , FALSE // bOutput
- , FALSE // bZero
- , FALSE // bMany
- , &CLSID_NULL // clsConnectsToFilter
- , L"Output" // strConnectsToPin
- , 1 // nTypes
- , &sudPinTypes } // lpTypes
- , { L"Output" // strName
- , FALSE // bRendered
- , TRUE // bOutput
- , FALSE // bZero
- , FALSE // bMany
- , &CLSID_NULL // clsConnectsToFilter
- , L"Input" // strConnectsToPin
- , 1 // nTypes
- , &sudPinTypes } }; // lpTypes
-
-
- AMOVIESETUP_FILTER sudContrast = { &CLSID_Contrast // clsID
- , L"Video Contrast" // strName
- , MERIT_DO_NOT_USE // dwMerit
- , 2 // nPins
- , psudPins }; // lpPin
-
-
-
- // COM Global table of objects in this dll
- CFactoryTemplate g_Templates[2] = {
-
- {L"Video Contrast", &CLSID_Contrast, CContrast::CreateInstance},
- {L"Video Contrast Property Page", &CLSID_ContrastPropertyPage, CContrastProperties::CreateInstance}
- };
- // Count of objects listed in g_cTemplates
- int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
-
-
- //
- // CContrast::Constructor
- //
- CContrast::CContrast(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
- : CTransformFilter(tszName, punk, CLSID_Contrast, phr)
- , m_DefaultContrastLevel(0)
- , m_ContrastLevel(m_DefaultContrastLevel)
- , m_PrevLevel(m_ContrastLevel)
- , m_lBufferRequest(1) {
-
- }
-
-
- //
- // CreateInstance
- //
- // Provide the way for COM to create a CContrast object
- CUnknown *CContrast::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {
-
- CContrast *pNewObject = new CContrast(NAME("Contrast Transform Filter"), punk, phr);
- if (pNewObject == NULL) {
- *phr = E_OUTOFMEMORY;
- }
-
- return pNewObject;
-
- }
-
-
- //
- // GetSetupData
- //
- LPAMOVIESETUP_FILTER CContrast::GetSetupData()
- {
- return &sudContrast;
- }
-
- //
- // NonDelegatingQueryInterface
- //
- // Reveals IContrast & ISpecifyPropertyPages
- STDMETHODIMP CContrast::NonDelegatingQueryInterface(REFIID riid, void ** ppv) {
-
- if (riid == IID_IContrast) {
- return GetInterface((IContrast *) this, ppv);
- }
- else if (riid == IID_ISpecifyPropertyPages) {
- return GetInterface((ISpecifyPropertyPages *) this, ppv);
- }
- else {
- return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
- }
- }
-
-
- //
- // Transform
- //
- // Copy the input sample into thee output sample. Then transform
- // the output sample 'in place'.
- HRESULT CContrast::Transform(IMediaSample *pIn, IMediaSample *pOut) {
-
- HRESULT hr = Copy(pIn, pOut);
- if (FAILED(hr)) {
- return hr;
- }
-
- return Transform(pOut);
- }
-
-
- //
- // Copy
- //
- // make Dest an identical copy of Source
- HRESULT CContrast::Copy(IMediaSample *pSource, IMediaSample *pDest) const {
-
- {
- // Copy the sample data
-
- BYTE *pSourceBuffer, *pDestBuffer;
- long lSourceSize = pSource->GetActualDataLength();
- long lDestSize = pDest->GetSize();
-
- ASSERT(lDestSize >= lSourceSize);
-
- pSource->GetPointer(&pSourceBuffer);
- pDest->GetPointer(&pDestBuffer);
-
- CopyMemory( (PVOID) pDestBuffer
- , (PVOID) pSourceBuffer
- , lSourceSize
- );
- }
- {
- // Copy the sample times
-
- REFERENCE_TIME TimeStart, TimeEnd;
- if (NOERROR == pSource->GetTime(&TimeStart, &TimeEnd)) {
- pDest->SetTime(&TimeStart, &TimeEnd);
- }
-
- LONGLONG MediaStart, MediaEnd;
- if (pSource->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) {
- pDest->SetMediaTime(&MediaStart,&MediaEnd);
- }
- }
- {
- // Copy the Sync point property
-
- HRESULT hr = pSource->IsSyncPoint();
- if (hr == S_OK) {
- pDest->SetSyncPoint(TRUE);
- }
- else if (hr == S_FALSE) {
- pDest->SetSyncPoint(FALSE);
- }
- else { // an unexpected error has occured...
- return E_UNEXPECTED;
- }
- }
- {
- // Copy the media type
-
- AM_MEDIA_TYPE *pMediaType;
- pSource->GetMediaType(&pMediaType);
- pDest->SetMediaType(pMediaType);
- DeleteMediaType(pMediaType);
- }
- {
- // Copy the preroll property
-
- HRESULT hr = pSource->IsPreroll();
- if (hr == S_OK) {
- pDest->SetPreroll(TRUE);
- }
- else if (hr == S_FALSE) {
- pDest->SetPreroll(FALSE);
- }
- else { // an unexpected error has occured...
- return E_UNEXPECTED;
- }
- }
- {
- // Copy the discontinuity property
-
- HRESULT hr = pSource->IsDiscontinuity();
- if (hr == S_OK) {
- pDest->SetDiscontinuity(TRUE);
- }
- else if (hr == S_FALSE) {
- pDest->SetDiscontinuity(FALSE);
- }
- else { // an unexpected error has occured...
- return E_UNEXPECTED;
- }
- }
- {
- // Copy the actual data length
-
- long lDataLength = pSource->GetActualDataLength();
- pDest->SetActualDataLength(lDataLength);
- }
-
- return NOERROR;
- }
-
-
- //
- // Transform
- //
- // 'In place' adjust the contrast of this sample
- HRESULT CContrast::Transform(IMediaSample *pMediaSample) {
-
- signed char ContrastLevel;
- {
- CAutoLock l(&m_ContrastLock);
-
- ContrastLevel = m_ContrastLevel; // take a copy, so we dont hold the lock
- // for the whole transform. Also ensures
- // we use the same level throughout this frame!
- }
-
- AM_MEDIA_TYPE *pAdjustedType = NULL;
-
- pMediaSample->GetMediaType(&pAdjustedType);
- if (pAdjustedType != NULL) { // an upstream filter has changed the type
- if (CheckInputType(&CMediaType(*pAdjustedType)) == S_OK) { // we can handle the change
-
- m_pInput->CurrentMediaType() = *pAdjustedType;
- CoTaskMemFree(pAdjustedType);
-
- }
- else {
- CoTaskMemFree(pAdjustedType);
- return E_FAIL;
- }
- }
-
-
- if ( (pAdjustedType != NULL) // an upstream filter has changed the type
- || (m_PrevLevel != ContrastLevel) // the user has changed the type
- ) { // do transform
-
- CMediaType AdjustedType((AM_MEDIA_TYPE) m_pInput->CurrentMediaType());
-
- HRESULT hr = Transform(&AdjustedType, ContrastLevel);
- if (hr == S_OK) { // a format change was performed - inform downstream filters.
- pMediaSample->SetMediaType(&AdjustedType);
- m_PrevLevel = ContrastLevel;
- }
- else {
- return hr;
- }
- }
-
- return NOERROR;
- }
-
-
- //
- // CheckInputType
- //
- // check the input type is OK.
- // return an error otherwise
- HRESULT CContrast::CheckInputType(const CMediaType *mtIn) {
-
- // check this is a VIDEOINFO type
- if (*mtIn->FormatType() != FORMAT_VideoInfo) {
- return E_INVALIDARG;
- }
-
- if (CanChangeContrastLevel(mtIn)) {
- return NOERROR;
- }
- else {
- return E_FAIL;
- }
- }
-
-
- //
- // CheckTransform
- //
- // If these types are OK as input and output (I can transform them
- // and they are the same) return NOERROR. Otherwise return an
- // error code
- HRESULT CContrast::CheckTransform(const CMediaType *mtIn,
- const CMediaType *mtOut)
- {
- if (CanChangeContrastLevel(mtIn) == TRUE) {
- VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
- VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
- if (memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0) {
- return NOERROR;
- }
- }
- return E_FAIL;
- }
-
-
- //
- // DecideBufferSize
- //
- // Tell the output pin's allocator what size buffers we
- // require. Can only do this when the input is connected
- HRESULT CContrast::DecideBufferSize(IMemAllocator *pAlloc,
- ALLOCATOR_PROPERTIES *pProperties)
- {
- if (!m_pInput->IsConnected()) {
- return E_UNEXPECTED;
- }
-
- ASSERT(pAlloc);
- ASSERT(pProperties);
- HRESULT hr = NOERROR;
-
- pProperties->cBuffers = 1;
- pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
-
- ASSERT(pProperties->cbBuffer);
-
- // If we don't have fixed sized samples we must guess some size
-
- if (!m_pInput->CurrentMediaType().bFixedSizeSamples) {
- if (pProperties->cbBuffer < 100000) {
- // nothing more than a guess!!
- pProperties->cbBuffer = 100000;
- }
- }
-
- // Ask the allocator to reserve us some sample memory, NOTE the function
- // can succeed (that is return NOERROR) but still not have allocated the
- // memory that we requested, so we must check we got whatever we wanted
-
- ALLOCATOR_PROPERTIES Actual;
- hr = pAlloc->SetProperties(pProperties,&Actual);
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT( Actual.cBuffers == 1 );
-
- if (pProperties->cBuffers > Actual.cBuffers ||
- pProperties->cbBuffer > Actual.cbBuffer) {
- return E_FAIL;
- }
- return NOERROR;
- }
-
-
- //
- // GetMediaType
- //
- // I support 1 type, namely the type of the input pin. This
- // is only available if my input is connected.
- HRESULT CContrast::GetMediaType(int iPosition, CMediaType *pMediaType) {
-
- if (m_pInput->IsConnected()) {
- if (iPosition<0) {
- return E_INVALIDARG;
- }
- if (iPosition>0) {
- return VFW_S_NO_MORE_ITEMS;
- }
-
- *pMediaType = m_pInput->CurrentMediaType();
-
- return NOERROR;
- }
- else {
- return E_UNEXPECTED;
- }
- }
-
-
-
- //
- // --- IContrast ---
- //
-
-
- //
- // get_ContrastLevel
- //
- STDMETHODIMP CContrast::get_ContrastLevel(signed char *ContrastLevel) {
-
- CAutoLock l(&m_ContrastLock);
-
- *ContrastLevel = m_ContrastLevel;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_ContrastLevel: %d"), *ContrastLevel));
-
- return NOERROR;
- }
-
-
- //
- // put_ContrastLevel
- //
- STDMETHODIMP CContrast::put_ContrastLevel(signed char ContrastLevel, unsigned long ChangeTime) {
-
- CAutoLock l(&m_ContrastLock);
-
- m_ContrastLevel = ContrastLevel;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_ContrastLevel: %x, (time: %x)"), m_ContrastLevel, ChangeTime));
-
- return NOERROR;
- }
-
-
- //
- // put_DefaultContrastLevel
- //
- STDMETHODIMP CContrast::put_DefaultContrastLevel(void) {
-
- CAutoLock l(&m_ContrastLock);
-
- DbgLog((LOG_TRACE, 1, TEXT("put_DefaultContrastLevel")));
-
- m_ContrastLevel = m_DefaultContrastLevel;
-
- return NOERROR;
- }
-
-
- //
- // --- ISpecifyPropertyPages ---
- //
-
-
- //
- // GetPages
- //
- // Returns the clsid's of the property pages we support
- STDMETHODIMP CContrast::GetPages(CAUUID *pPages) {
-
- pPages->cElems = 1;
- pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
- if (pPages->pElems == NULL) {
- return E_OUTOFMEMORY;
- }
- *(pPages->pElems) = CLSID_ContrastPropertyPage;
-
- return NOERROR;
- }
-
-
- //
- // CanChangeContrastLevel
- //
- // Check if this is a paletised format
- BOOL CContrast::CanChangeContrastLevel(const CMediaType *pMediaType) const {
-
- if ( (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video))
- && (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB8))
- ) {
-
- // I think I can process this format (8 bit palettised)
- // So do a quick sanity check on the palette info
-
- VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->Format();
-
- return ( (pvi->bmiHeader.biClrUsed > 0) // there is a palette
- && (pvi->bmiHeader.biBitCount == 8) // media type & videoinfo agree
- );
- }
- else { // cant process this
- return FALSE;
- }
- }
-
-
- //
- // TransformMediaType
- //
- // Adjust the palette entries of pType to reflect the specified contrast level
- HRESULT CContrast::Transform(AM_MEDIA_TYPE *pType, const signed char ContrastLevel) const {
-
- VIDEOINFO *pvi = (VIDEOINFO *) pType->pbFormat;
-
- if (ContrastLevel >= 0) {
- int Low = 0 + m_ContrastLevel;
- int High = 255 - m_ContrastLevel;
- float Grad = ((float)(High - Low)) / 255;
-
- for (UINT i = 0; i < pvi->bmiHeader.biClrUsed; i++) {
-
- IncreaseContrast(&pvi->bmiColors[i], Low, High, Grad);
- }
- }
- else {
- float Grad = 255 / (255 + (float) ContrastLevel + (float) ContrastLevel);
-
- for (UINT i = 0; i < pvi->bmiHeader.biClrUsed; i++) {
-
- DecreaseContrast(&pvi->bmiColors[i], ContrastLevel, Grad);
- }
- }
-
- return NOERROR;
- }
-
-
-
- //
- // ChangeContrast
- //
- // Adjust the contrast of this palette element
- inline
- void CContrast::IncreaseContrast(RGBQUAD *pElem, const int Low, const int High, const float Grad) const {
-
- IncreaseContrast(&pElem->rgbRed, Low, High, Grad);
- IncreaseContrast(&pElem->rgbGreen, Low, High, Grad);
- IncreaseContrast(&pElem->rgbBlue, Low, High, Grad);
- }
-
-
- //
- // ChangeContrast
- //
- // Change this byte's contrast
- inline
- void CContrast::IncreaseContrast(BYTE *pByte, const int Low, const int High, const float Grad) const {
-
- if (*pByte <= Low) {
- *pByte = 0;
- }
- else if ( ( Low < *pByte )
- && ( *pByte < High )
- ) {
- *pByte = (BYTE)( (*pByte - Low) / Grad);
- }
- else { // pElem->rgbGreen >= High
- *pByte = 255;
- }
- }
-
-
- //
- // DecreaseContrast
- //
- // Adjust the contrast of this palette element
- inline
- void CContrast::DecreaseContrast(RGBQUAD *pElem, const int Level, const float Grad) const {
-
- DecreaseContrast(&pElem->rgbRed, Level, Grad);
- DecreaseContrast(&pElem->rgbGreen, Level, Grad);
- DecreaseContrast(&pElem->rgbBlue, Level, Grad);
- }
-
-
- //
- // DecreaseContrast
- //
- // Use different maths to calculate the 'decreasing contrast' line
- inline
- void CContrast::DecreaseContrast(BYTE *pByte, const int Level, const float Grad) const {
-
- ASSERT(Grad != 0.0);
-
- *pByte = (BYTE) ( ((int) (*pByte / Grad)) - Level);
- }
-
-
- /******************************Public*Routine******************************\
- * exported entry points for registration and
- * unregistration (in this case they only call
- * through to default implmentations).
- *
- *
- *
- * History:
- *
- \**************************************************************************/
- HRESULT
- DllRegisterServer()
- {
- return AMovieDllRegisterServer();
- }
-
- HRESULT
- DllUnregisterServer()
- {
- return AMovieDllUnregisterServer();
- }
-
-