ScaleFilter.cpp

Go to the documentation of this file.
00001 
00034 #include "stdafx.h"
00035 
00036 // Meraka includes
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         //Call the initialize input method to load all acceptable input types for this filter
00049         InitialiseInputTypes();
00050         // Init parameters
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                 //Set defaults
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                 //Determine whether we are connected to a RGB24 or 32 source
00095                 if (pmt->majortype == MEDIATYPE_Video)
00096                 {
00097                         //The scaler might already exist if the filter has been connected previously
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                 // Get the input pin's media type and return this as the output media type - we want to retain
00127                 // all the information about the image
00128                 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00129                 if (FAILED(hr))
00130                 {
00131                         return hr;
00132                 }
00133 
00134                 // Get the bitmap info header and adapt the cropped 
00135                 //make sure that it's a video info header
00136                 ASSERT(pMediaType->formattype == FORMAT_VideoInfo);
00137                 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pMediaType->pbFormat;
00138                 //Now we need to calculate the size of the output image
00139                 BITMAPINFOHEADER* pBi = &(pVih->bmiHeader);
00140                 
00141                 // Set height
00142                 pBi->biHeight = m_nOutHeight;
00143                 ASSERT(pBi->biHeight > 0);
00144 
00145                 // Set width
00146                 pBi->biWidth = m_nOutWidth;
00147                 ASSERT(pBi->biWidth > 0);
00148                 // Set size
00149                 pBi->biSizeImage = pBi->biWidth * pBi->biHeight * BYTES_PER_PIXEL_RGB24;
00150                 pMediaType->lSampleSize = pBi->biSizeImage;
00151 
00152                 // Adjust recs
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         // Leaving this var so that we can cater for RGB32 at a later stage
00171         pProp->cbBuffer = m_nOutPixels * m_nBytesPerPixel;
00172         if (m_nBytesPerPixel == BYTES_PER_PIXEL_YUV420P)
00173         {
00174                 //Adjust the buffer requirements for our custom format
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         // Set allocator properties.
00188         ALLOCATOR_PROPERTIES Actual;
00189         HRESULT hr = pAlloc->SetProperties(pProp, &Actual);
00190         if (FAILED(hr)) 
00191         {
00192                 return hr;
00193         }
00194         // Even when it succeeds, check the actual result.
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         //Make sure the input and output types are related
00205         if (mtOut->majortype != MEDIATYPE_Video)
00206         {
00207                 return VFW_E_TYPE_NOT_ACCEPTED;
00208         }
00209         //Subtypes
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         // Video format
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         // For now, one cannot set any parameters once the output has been connected -> this will affect the buffersize
00236         if (m_pOutput)
00237         {
00238                 if (m_pOutput->IsConnected())
00239                 {
00240                         return E_FAIL;
00241                 }
00242         }
00243 
00244         // TODO: get rid of enum or get rid of string!!!!
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         //make sure we were able to initialize our converter
00260         if (m_pScaler)
00261         {
00262                 //Call scaling conversion code
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         // Update the number of out pixels
00279         m_nOutPixels = m_nOutWidth * m_nOutHeight;
00280         return S_OK;
00281 }

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