YUV420ToRGBFilter.cpp

Go to the documentation of this file.
00001 
00034 #include "YUV420ToRGBFilter.h"
00035 
00036 // Media Types
00037 #include <DirectShow/CustomMediaTypes.h>
00038 
00039 //Color converters
00040 #include <Image/RealYUV420toRGB24Converter.h>
00041 
00042 YUV420toRGBFilter::YUV420toRGBFilter()
00043 : CCustomBaseFilter(NAME("Meraka RTVC YUV420P 2 RGB Converter"), 0, CLSID_YUV420toRGBColorConverter),
00044 m_pConverter(NULL),
00045 m_nSizeUV(0)
00046 {
00047         //Call the initialise input method to load all acceptable input types for this filter
00048         InitialiseInputTypes();
00049         m_pConverter = new RealYUV420toRGB24Converter(m_nInWidth, m_nInHeight);
00050 }
00051 
00052 YUV420toRGBFilter::~YUV420toRGBFilter()
00053 {
00054         if (m_pConverter)
00055         {
00056                 delete m_pConverter;
00057                 m_pConverter = NULL;
00058         }
00059 }
00060 
00061 CUnknown * WINAPI YUV420toRGBFilter::CreateInstance( LPUNKNOWN pUnk, HRESULT *pHr )
00062 {
00063         YUV420toRGBFilter *pFilter = new YUV420toRGBFilter();
00064         if (pFilter== NULL) 
00065         {
00066                 *pHr = E_OUTOFMEMORY;
00067         }
00068         return pFilter;
00069 }
00070 
00071 
00072 void YUV420toRGBFilter::InitialiseInputTypes()
00073 {
00074         AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_YUV420P, &FORMAT_VideoInfo);
00075 }
00076 
00077 
00078 HRESULT YUV420toRGBFilter::SetMediaType( PIN_DIRECTION direction, const CMediaType *pmt )
00079 {
00080         HRESULT hr = CCustomBaseFilter::SetMediaType(direction, pmt);
00081         if (direction == PINDIR_INPUT)
00082         {
00083                 m_nSizeUV = m_nInPixels >> 2;
00084                 m_pConverter->SetDimensions(m_nInWidth, m_nInHeight);
00085         }
00086         return hr;
00087 }
00088 
00089 HRESULT YUV420toRGBFilter::GetMediaType( int iPosition, CMediaType *pMediaType )
00090 {
00091         if (iPosition < 0)
00092         {
00093                 return E_INVALIDARG;
00094         }
00095         else if (iPosition == 0)
00096         {
00097                 // Get the input pin's media type and return this as the output media type - we want to retain
00098                 // all the information about the image
00099                 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00100                 if (FAILED(hr))
00101                 {
00102                         return hr;
00103                 }
00104 
00105                 //Adjust the bitmapinfo header
00106                 BITMAPINFOHEADER *pbmi = HEADER(pMediaType->pbFormat);
00107                 if (pbmi->biBitCount == 32)
00108                 {
00109                         // Set the bit count to 24 since the RBGtoYUV filter also accepts 32 bit but this filter only
00110                         // outputs 24 bit RGB.
00111                         pbmi->biBitCount = 24;
00112                         pbmi->biSizeImage = m_nInPixels * BYTES_PER_PIXEL_RGB24;
00113                 }
00114                 else if (pbmi->biBitCount == 24)
00115                 {
00116                         // We still need to set the size of the out image: the original image might have been scaled
00117                         // So we need to recalculate the size in RGB 24
00118                         pbmi->biSizeImage = m_nInPixels * BYTES_PER_PIXEL_RGB24;
00119                 }
00120                 //Reset the media subtype
00121                 // Change the output format from MEDIASUBTYPE_YUV420P to RGB24
00122                 pMediaType->SetSubtype(&MEDIASUBTYPE_RGB24);
00123                 return S_OK;
00124         }
00125         return VFW_S_NO_MORE_ITEMS;
00126 }
00127 
00128 HRESULT YUV420toRGBFilter::DecideBufferSize( IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp )
00129 {
00130         AM_MEDIA_TYPE mt;
00131         HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
00132         if (FAILED(hr))
00133         {
00134                 return hr;
00135         }
00136         //Make sure that the format type is our custom format
00137         ASSERT(mt.formattype == FORMAT_VideoInfo);
00138         BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
00139         pProp->cbBuffer = DIBSIZE(*pbmi);
00140 
00141         if (pProp->cbAlign == 0)
00142         {
00143                 pProp->cbAlign = 1;
00144         }
00145         if (pProp->cBuffers == 0)
00146         {
00147                 pProp->cBuffers = 1;
00148         }
00149         // Release the format block.
00150         FreeMediaType(mt);
00151 
00152         // Set allocator properties.
00153         ALLOCATOR_PROPERTIES Actual;
00154         hr = pAlloc->SetProperties(pProp, &Actual);
00155         if (FAILED(hr)) 
00156         {
00157                 return hr;
00158         }
00159         // Even when it succeeds, check the actual result.
00160         if (pProp->cbBuffer > Actual.cbBuffer) 
00161         {
00162                 return E_FAIL;
00163         }
00164         return S_OK;
00165 }
00166 
00167 DWORD YUV420toRGBFilter::ApplyTransform( BYTE* pBufferIn, BYTE* pBufferOut )
00168 {
00169         int nRet = 0;
00170         if (m_pConverter)
00171         {
00172                 yuvType* pYUV = NULL;
00173                 pYUV = (yuvType*)pBufferIn;
00174                 if (pYUV)
00175                 {
00176                         //set the Y, U and V pointers to point to the correct positions within the byte array
00177                         yuvType* pY = pYUV;
00178                         yuvType* pU = pYUV + m_nInPixels;
00179                         yuvType* pV = pYUV + m_nInPixels + m_nSizeUV;
00180                         //Convert
00181                         m_pConverter->Convert((void*)pY, (void*)pU, (void*)pV, (void*)pBufferOut);
00182                         DbgLog((LOG_TRACE, 0, TEXT("Converted from YUV420 to RGB Directly")));
00183                         //RGB24 stores 3 Bytes per pixel
00184                         nRet = m_nInPixels * BYTES_PER_PIXEL_RGB24;
00185                 }
00186         }
00187         return nRet;
00188 }
00189 
00190 HRESULT YUV420toRGBFilter::CheckTransform( const CMediaType *mtIn, const CMediaType *mtOut )
00191 {
00192         //Does this also occur when format changes occur such as when changing the renderer size???
00193         long lSize = mtOut->GetSampleSize();
00194 
00195         // Check the major type.
00196         if (mtOut->majortype != MEDIATYPE_Video)
00197         {
00198                 return VFW_E_TYPE_NOT_ACCEPTED;
00199         }
00200         if (mtOut->subtype != MEDIASUBTYPE_RGB24)
00201         {
00202                 return VFW_E_TYPE_NOT_ACCEPTED;
00203         }
00204         if (mtOut->formattype != FORMAT_VideoInfo)
00205         {
00206                 return VFW_E_TYPE_NOT_ACCEPTED;
00207         }
00208         // Everything is good.
00209         return S_OK;
00210 }

Generated on Fri Mar 13 14:12:38 2009 for RTVC by  doxygen 1.5.3