00001
00034 #include "RGBtoYUV420Filter.h"
00035
00036
00037 #include <DirectShow/CustomMediaTypes.h>
00038
00039
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
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
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
00086 if (pmt->majortype == MEDIATYPE_Video)
00087 {
00088
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
00116
00117 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00118 if (FAILED(hr))
00119 {
00120 return hr;
00121 }
00122
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
00140 ASSERT(mt.formattype == FORMAT_VideoInfo);
00141 BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
00142
00143
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
00156 FreeMediaType(mt);
00157
00158
00159 ALLOCATOR_PROPERTIES Actual;
00160 hr = pAlloc->SetProperties(pProp, &Actual);
00161 if (FAILED(hr))
00162 {
00163 return hr;
00164 }
00165
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
00177 if (m_pConverter)
00178 {
00179
00180 yuvType* pYUV = NULL;
00181 pYUV = (yuvType*)pBufferOut;
00182 if (pYUV)
00183 {
00184 nTotalSize = (m_nInPixels + (2*m_nSizeYUV))*sizeof(yuvType);
00185
00186 yuvType* pY = pYUV;
00187 yuvType* pU = pYUV + m_nInPixels;
00188 yuvType* pV = pU + m_nSizeYUV;
00189
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
00201 DbgLog((LOG_TRACE, 0, TEXT("RGB to YUV Converter is not initialised - unable to transform")));
00202
00203 }
00204 return nTotalSize;
00205 }
00206
00207 HRESULT RGBtoYUV420Filter::CheckTransform( const CMediaType *mtIn, const CMediaType *mtOut )
00208 {
00209
00210 if (mtOut->majortype != MEDIATYPE_Video)
00211 {
00212 return VFW_E_TYPE_NOT_ACCEPTED;
00213 }
00214
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
00224 return S_OK;
00225 }