00001
00034 #include "stdafx.h"
00035
00036
00037 #include "ScaleFilter.h"
00038
00039 #include <DirectShow/CustomMediaTypes.h>
00040 #include <Image/PicScalerRGB24Impl.h>
00041 #include <Image/PicScalerYUV420PImpl.h>
00042
00043 CScaleFilter::CScaleFilter()
00044 : CCustomBaseFilter(NAME("Meraka RTVC Scale Filter"), 0, CLSID_ScaleFilter),
00045 m_pScaler(NULL),
00046 m_nBytesPerPixel(BYTES_PER_PIXEL_RGB24)
00047 {
00048
00049 InitialiseInputTypes();
00050
00051 initParameters();
00052 }
00053
00054 CScaleFilter::~CScaleFilter()
00055 {
00056 if (m_pScaler)
00057 {
00058 delete m_pScaler;
00059 m_pScaler = NULL;
00060 }
00061 }
00062
00063 CUnknown * WINAPI CScaleFilter::CreateInstance( LPUNKNOWN pUnk, HRESULT *pHr )
00064 {
00065 CScaleFilter *pFilter = new CScaleFilter();
00066 if (pFilter== NULL)
00067 {
00068 *pHr = E_OUTOFMEMORY;
00069 }
00070 return pFilter;
00071 }
00072
00073
00074 void CScaleFilter::InitialiseInputTypes()
00075 {
00076 AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_RGB24, &FORMAT_VideoInfo);
00077 AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_YUV420P, &FORMAT_VideoInfo);
00078 }
00079
00080 HRESULT CScaleFilter::SetMediaType( PIN_DIRECTION direction, const CMediaType *pmt )
00081 {
00082 HRESULT hr = CCustomBaseFilter::SetMediaType(direction, pmt);
00083 if (direction == PINDIR_INPUT)
00084 {
00085
00086 if (m_nOutWidth == 0)
00087 {
00088 m_nOutWidth = m_nInWidth;
00089 }
00090 if (m_nOutHeight == 0)
00091 {
00092 m_nOutHeight = m_nInHeight;
00093 }
00094
00095 if (pmt->majortype == MEDIATYPE_Video)
00096 {
00097
00098 if (m_pScaler)
00099 {
00100 delete m_pScaler;
00101 m_pScaler = NULL;
00102 }
00103 if (pmt->subtype == MEDIASUBTYPE_RGB24)
00104 {
00105 m_pScaler = new PicScalerRGB24Impl();
00106 m_nBytesPerPixel = BYTES_PER_PIXEL_RGB24;
00107 }
00108 else if (pmt->subtype == MEDIASUBTYPE_YUV420P)
00109 {
00110 m_pScaler = new PicScalerYUV420PImpl();
00111 m_nBytesPerPixel = BYTES_PER_PIXEL_YUV420P;
00112 }
00113 }
00114 }
00115 return hr;
00116 }
00117
00118 HRESULT CScaleFilter::GetMediaType( int iPosition, CMediaType *pMediaType )
00119 {
00120 if (iPosition < 0)
00121 {
00122 return E_INVALIDARG;
00123 }
00124 else if (iPosition == 0)
00125 {
00126
00127
00128 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00129 if (FAILED(hr))
00130 {
00131 return hr;
00132 }
00133
00134
00135
00136 ASSERT(pMediaType->formattype == FORMAT_VideoInfo);
00137 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pMediaType->pbFormat;
00138
00139 BITMAPINFOHEADER* pBi = &(pVih->bmiHeader);
00140
00141
00142 pBi->biHeight = m_nOutHeight;
00143 ASSERT(pBi->biHeight > 0);
00144
00145
00146 pBi->biWidth = m_nOutWidth;
00147 ASSERT(pBi->biWidth > 0);
00148
00149 pBi->biSizeImage = pBi->biWidth * pBi->biHeight * BYTES_PER_PIXEL_RGB24;
00150 pMediaType->lSampleSize = pBi->biSizeImage;
00151
00152
00153 pVih->rcSource.top = 0;
00154 pVih->rcSource.left = 0;
00155 pVih->rcSource.right = pBi->biWidth;
00156 pVih->rcSource.bottom = pBi->biHeight;
00157
00158 pVih->rcTarget.top = 0;
00159 pVih->rcTarget.left = 0;
00160 pVih->rcTarget.right = pBi->biWidth;
00161 pVih->rcTarget.bottom = pBi->biHeight;
00162
00163 return S_OK;
00164 }
00165 return VFW_S_NO_MORE_ITEMS;
00166 }
00167
00168 HRESULT CScaleFilter::DecideBufferSize( IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp )
00169 {
00170
00171 pProp->cbBuffer = m_nOutPixels * m_nBytesPerPixel;
00172 if (m_nBytesPerPixel == BYTES_PER_PIXEL_YUV420P)
00173 {
00174
00175 pProp->cbBuffer *= sizeof(yuvType);
00176 }
00177
00178 if (pProp->cbAlign == 0)
00179 {
00180 pProp->cbAlign = 1;
00181 }
00182 if (pProp->cBuffers == 0)
00183 {
00184 pProp->cBuffers = 1;
00185 }
00186
00187
00188 ALLOCATOR_PROPERTIES Actual;
00189 HRESULT hr = pAlloc->SetProperties(pProp, &Actual);
00190 if (FAILED(hr))
00191 {
00192 return hr;
00193 }
00194
00195 if (pProp->cbBuffer > Actual.cbBuffer)
00196 {
00197 return E_FAIL;
00198 }
00199 return S_OK;
00200 }
00201
00202 HRESULT CScaleFilter::CheckTransform( const CMediaType *mtIn, const CMediaType *mtOut )
00203 {
00204
00205 if (mtOut->majortype != MEDIATYPE_Video)
00206 {
00207 return VFW_E_TYPE_NOT_ACCEPTED;
00208 }
00209
00210 if (mtIn->subtype == MEDIASUBTYPE_RGB24)
00211 {
00212 if (mtOut->subtype != MEDIASUBTYPE_RGB24)
00213 {
00214 return VFW_E_TYPE_NOT_ACCEPTED;
00215 }
00216 }
00217 if (mtIn->subtype == MEDIASUBTYPE_YUV420P)
00218 {
00219 if (mtOut->subtype != MEDIASUBTYPE_YUV420P)
00220 {
00221 return VFW_E_TYPE_NOT_ACCEPTED;
00222 }
00223 }
00224
00225 if (mtOut->formattype != FORMAT_VideoInfo)
00226 {
00227 return VFW_E_TYPE_NOT_ACCEPTED;
00228 }
00229 return S_OK;
00230 }
00231
00232
00233 STDMETHODIMP CScaleFilter::SetParameter( const char* type, const char* value )
00234 {
00235
00236 if (m_pOutput)
00237 {
00238 if (m_pOutput->IsConnected())
00239 {
00240 return E_FAIL;
00241 }
00242 }
00243
00244
00245 if (SUCCEEDED(CSettingsInterface::SetParameter(type, value)))
00246 {
00247 m_nOutPixels = m_nOutWidth * m_nOutHeight;
00248 return S_OK;
00249 }
00250 else
00251 {
00252 return E_FAIL;
00253 }
00254 }
00255
00256 DWORD CScaleFilter::ApplyTransform( BYTE* pBufferIn, BYTE* pBufferOut )
00257 {
00258 int nTotalSize = 0;
00259
00260 if (m_pScaler)
00261 {
00262
00263 m_pScaler->SetInDimensions(m_nInWidth, m_nInHeight);
00264 m_pScaler->SetOutDimensions(m_nOutWidth, m_nOutHeight);
00265 m_pScaler->Scale((void*)pBufferOut, (void*)pBufferIn);
00266 nTotalSize = m_nOutWidth * m_nOutHeight * m_nBytesPerPixel;
00267 }
00268 else
00269 {
00270 DbgLog((LOG_TRACE, 0, TEXT("Scaler is not initialised - unable to transform")));
00271 }
00272 return nTotalSize;
00273 }
00274
00275
00276 HRESULT CScaleFilter::RecalculateFilterParameters()
00277 {
00278
00279 m_nOutPixels = m_nOutWidth * m_nOutHeight;
00280 return S_OK;
00281 }