RGBtoYUV420Filter.cpp

Go to the documentation of this file.
00001 
00034 #include "RGBtoYUV420Filter.h"
00035 
00036 // Media Type
00037 #include <DirectShow/CustomMediaTypes.h>
00038 
00039 // Color converters
00040 #include <Image/RealRGB24toYUV420Converter.h>
00041 #include <Image/RealRGB32toYUV420Converter.h>
00042 
00043 RGBtoYUV420Filter::RGBtoYUV420Filter()
00044 : CCustomBaseFilter(NAME("Meraka RTVC RGB 2 YUV420P Converter"), 0, CLSID_RGBtoYUV420ColorConverter),
00045 m_pConverter(NULL),
00046 m_nSizeYUV(0)
00047 {
00048         //Call the initialise input method to load all acceptable input types for this filter
00049         InitialiseInputTypes();
00050 }
00051 
00052 RGBtoYUV420Filter::~RGBtoYUV420Filter()
00053 {
00054         if (m_pConverter)
00055         {
00056                 delete m_pConverter;
00057                 m_pConverter = NULL;
00058         }
00059 }
00060 
00061 CUnknown * WINAPI RGBtoYUV420Filter::CreateInstance( LPUNKNOWN pUnk, HRESULT *pHr )
00062 {
00063         RGBtoYUV420Filter *pFilter = new RGBtoYUV420Filter();
00064         if (pFilter== NULL) 
00065         {
00066                 *pHr = E_OUTOFMEMORY;
00067         }
00068         return pFilter;
00069 }
00070 
00071 
00072 void RGBtoYUV420Filter::InitialiseInputTypes()
00073 {
00074         // Add standard input types
00075         AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_RGB24, &FORMAT_VideoInfo);
00076         AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_RGB32, &FORMAT_VideoInfo);
00077 }
00078 
00079 HRESULT RGBtoYUV420Filter::SetMediaType( PIN_DIRECTION direction, const CMediaType *pmt )
00080 {
00081         HRESULT hr = CCustomBaseFilter::SetMediaType(direction, pmt);
00082         if (direction == PINDIR_INPUT)
00083         {
00084                 m_nSizeYUV = m_nInPixels >> 2;
00085                 //Determine whether we are connected to a RGB24 or 32 source
00086                 if (pmt->majortype == MEDIATYPE_Video)
00087                 {
00088                         //The converter might already exist if the filter has been connected previously
00089                         if (m_pConverter)
00090                         {
00091                                 delete m_pConverter;
00092                                 m_pConverter = NULL;
00093                         }
00094                         if (pmt->subtype == MEDIASUBTYPE_RGB24)
00095                         {
00096                                 m_pConverter = new RealRGB24toYUV420Converter(m_nInWidth, m_nInHeight);
00097                         }
00098                         else if (pmt->subtype == MEDIASUBTYPE_RGB32)
00099                         {
00100                                 m_pConverter = new RealRGB32toYUV420Converter(m_nInWidth, m_nInHeight);
00101                         }
00102                 }
00103         }
00104         return hr;
00105 }
00106 
00107 HRESULT RGBtoYUV420Filter::GetMediaType( int iPosition, CMediaType *pMediaType )
00108 {
00109         if (iPosition < 0)
00110         {
00111                 return E_INVALIDARG;
00112         }
00113         else if (iPosition == 0)
00114         {
00115                 // Get the input pin's media type and return this as the output media type - we want to retain
00116                 // all the information about the image
00117                 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00118                 if (FAILED(hr))
00119                 {
00120                         return hr;
00121                 }
00122                 // Change the output format to MEDIASUBTYPE_YUV420P 
00123                 pMediaType->SetType(&MEDIATYPE_Video);
00124                 pMediaType->SetSubtype(&MEDIASUBTYPE_YUV420P);
00125                 pMediaType->SetFormatType(&FORMAT_VideoInfo);
00126                 return S_OK;
00127         }
00128         return VFW_S_NO_MORE_ITEMS;
00129 }
00130 
00131 HRESULT RGBtoYUV420Filter::DecideBufferSize( IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp )
00132 {
00133         AM_MEDIA_TYPE mt;
00134         HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
00135         if (FAILED(hr))
00136         {
00137                 return hr;
00138         }
00139         //Make sure that the format type is our custom format
00140         ASSERT(mt.formattype == FORMAT_VideoInfo);
00141         BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
00142         //For YUV: we need to amount of bytes needed to store a frame of YUV 
00143         //(Since our converters are using yuvType pointers for arithmetics we need to take the total * sizeof(yuvType)
00144         int nSizeYUV = (m_nInPixels + (2*m_nSizeYUV)) * sizeof(yuvType);
00145         pProp->cbBuffer = nSizeYUV;
00146         
00147         if (pProp->cbAlign == 0)
00148         {
00149                 pProp->cbAlign = 1;
00150         }
00151         if (pProp->cBuffers == 0)
00152         {
00153                 pProp->cBuffers = 1;
00154         }
00155         // Release the format block.
00156         FreeMediaType(mt);
00157 
00158         // Set allocator properties.
00159         ALLOCATOR_PROPERTIES Actual;
00160         hr = pAlloc->SetProperties(pProp, &Actual);
00161         if (FAILED(hr))
00162         {
00163                 return hr;
00164         }
00165         // Even when it succeeds, check the actual result.
00166         if (pProp->cbBuffer > Actual.cbBuffer) 
00167         {
00168                 return E_FAIL;
00169         }
00170         return S_OK;
00171 }
00172 
00173 DWORD RGBtoYUV420Filter::ApplyTransform( BYTE* pBufferIn, BYTE* pBufferOut )
00174 {
00175         int nTotalSize = 0;
00176         //make sure we were able to initialise our converter
00177         if (m_pConverter)
00178         {
00179                 //Map everything into yuvType pointers
00180                 yuvType* pYUV = NULL;
00181                 pYUV = (yuvType*)pBufferOut;
00182                 if (pYUV)
00183                 {
00184                         nTotalSize = (m_nInPixels + (2*m_nSizeYUV))*sizeof(yuvType);
00185                         //Set pointer offsets into YUV array
00186                         yuvType* pY = pYUV;
00187                         yuvType* pU = pYUV + m_nInPixels;
00188                         yuvType* pV = pU + m_nSizeYUV;
00189                         //Convert to YUV
00190                         m_pConverter->Convert((void*)pBufferIn, (void*)pY, (void*)pU, (void*)pV);
00191                         DbgLog((LOG_TRACE, 0, TEXT("Converted to YUV directly")));
00192                 }
00193                 else
00194                 {
00195                         DbgLog((LOG_TRACE, 0, TEXT("YUV array memory not valid")));
00196                 }
00197         }
00198         else
00199         {
00200                 // Add some kind of user notification
00201                 DbgLog((LOG_TRACE, 0, TEXT("RGB to YUV Converter is not initialised - unable to transform")));
00202                 //m_sLastError = "RGB to YUV Converter is not initialised - unable to transform";
00203         }
00204         return nTotalSize;
00205 }
00206 
00207 HRESULT RGBtoYUV420Filter::CheckTransform( const CMediaType *mtIn, const CMediaType *mtOut )
00208 {
00209         // Check the major type.
00210         if (mtOut->majortype != MEDIATYPE_Video)
00211         {
00212                 return VFW_E_TYPE_NOT_ACCEPTED;
00213         }
00214         // Adding advert media type to this method
00215         if (mtOut->subtype != MEDIASUBTYPE_YUV420P)
00216         {
00217                 return VFW_E_TYPE_NOT_ACCEPTED;
00218         }
00219         if (mtOut->formattype != FORMAT_VideoInfo)
00220         {
00221                 return VFW_E_TYPE_NOT_ACCEPTED;
00222         }
00223         // Everything is good.
00224         return S_OK;
00225 }

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