CropFilter.cpp

Go to the documentation of this file.
00001 
00035 #include "CropFilter.h"
00036 
00037 #include <DirectShow/CommonDefs.h>
00038 
00039 #include <Image/PicCropperRGB24Impl.h>
00040 #include <Image/PicCropperRGB32Impl.h>
00041 
00042 CCropFilter::CCropFilter()
00043 : CCustomBaseFilter(NAME("Meraka RTVC Crop Filter"), 0, CLSID_CropFilter),
00044         m_pCropper(NULL),
00045         m_nBytesPerPixel(BYTES_PER_PIXEL_RGB24),
00046         m_nStride(0),
00047         m_nPadding(0)
00048 {
00049         //Call the initialise input method to load all acceptable input types for this filter
00050         InitialiseInputTypes();
00051         // Init parameters
00052         initParameters();
00053 }
00054 
00055 CCropFilter::~CCropFilter()
00056 {
00057         if (m_pCropper)
00058         {
00059                 delete m_pCropper;
00060                 m_pCropper = NULL;
00061         }
00062 }
00063 
00064 CUnknown * WINAPI CCropFilter::CreateInstance( LPUNKNOWN pUnk, HRESULT *pHr )
00065 {
00066         CCropFilter *pFilter = new CCropFilter();
00067         if (pFilter== NULL) 
00068         {
00069                 *pHr = E_OUTOFMEMORY;
00070         }
00071         return pFilter;
00072 }
00073 
00074 
00075 void CCropFilter::InitialiseInputTypes()
00076 {
00077         AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_RGB24, &FORMAT_VideoInfo);
00078         AddInputType(&MEDIATYPE_Video, &MEDIASUBTYPE_RGB32, &FORMAT_VideoInfo);
00079 }
00080 
00081 HRESULT CCropFilter::SetMediaType( PIN_DIRECTION direction, const CMediaType *pmt )
00082 {
00083         HRESULT hr = CCustomBaseFilter::SetMediaType(direction, pmt);
00084         if (direction == PINDIR_INPUT)
00085         {
00086                 //Set defaults and make sure that the target dimensions are valid
00087                 if ((m_nOutWidth == 0)||(m_nOutWidth > m_nInWidth))
00088                 {
00089                         m_nOutWidth = m_nInWidth;
00090                 }
00091                 if ((m_nOutHeight == 0)||(m_nOutHeight > m_nInHeight))
00092                 {
00093                         m_nOutHeight = m_nInHeight;
00094                 }
00095                 //Determine whether we are connected to a RGB24 or 32 source
00096                 if (pmt->majortype == MEDIATYPE_Video)
00097                 {
00098                         //The converter might already exist if the filter has been connected previously
00099                         if (m_pCropper)
00100                         {
00101                                 delete m_pCropper;
00102                                 m_pCropper = NULL;
00103                         }
00104                         if (pmt->subtype == MEDIASUBTYPE_RGB24)
00105                         {
00106                                 m_pCropper = new PicCropperRGB24Impl();
00107                                 m_nBytesPerPixel = BYTES_PER_PIXEL_RGB24;
00108                         }
00109                         else if (pmt->subtype == MEDIASUBTYPE_RGB32)
00110                         {
00111                                 m_pCropper = new PicCropperRGB32Impl();
00112                                 m_nBytesPerPixel = BYTES_PER_PIXEL_RGB32;
00113                         }
00114                 }
00115                 RecalculateFilterParameters();
00116         }
00117         return hr;
00118 }
00119 
00120 HRESULT CCropFilter::GetMediaType( int iPosition, CMediaType *pMediaType )
00121 {
00122         if (iPosition < 0)
00123         {
00124                 return E_INVALIDARG;
00125         }
00126         else if (iPosition == 0)
00127         {
00128                 // Get the input pin's media type and return this as the output media type - we want to retain
00129                 // all the information about the image
00130                 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00131                 if (FAILED(hr))
00132                 {
00133                         return hr;
00134                 }
00135                 
00136                 // Get the bitmap info header and adapt the cropped 
00137                 //make sure that it's a video info header
00138                 ASSERT(pMediaType->formattype == FORMAT_VideoInfo);
00139                 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pMediaType->pbFormat;
00140                 //Now we need to calculate the size of the output image
00141                 BITMAPINFOHEADER* pBi = &(pVih->bmiHeader);
00142                 
00143                 pBi->biHeight = m_nOutHeight;
00144                 ASSERT(pBi->biHeight > 0);
00145 
00146                 pBi->biWidth = m_nOutWidth;
00147                 ASSERT(pBi->biWidth > 0);
00148                 pBi->biSizeImage = pBi->biWidth * pBi->biHeight * m_nBytesPerPixel;
00149 
00150                 pVih->rcSource.top = 0;
00151                 pVih->rcSource.left = 0;
00152                 pVih->rcSource.right = pBi->biWidth;
00153                 pVih->rcSource.bottom = pBi->biHeight;
00154 
00155                 pVih->rcTarget.top = 0;
00156                 pVih->rcTarget.left = 0;
00157                 pVih->rcTarget.right = pBi->biWidth;
00158                 pVih->rcTarget.bottom = pBi->biHeight;
00159 
00160                 pMediaType->lSampleSize = pBi->biSizeImage;
00161 
00162                 return S_OK;
00163         }
00164         return VFW_S_NO_MORE_ITEMS;
00165 }
00166 
00167 HRESULT CCropFilter::DecideBufferSize( IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp )
00168 {
00169         // Adding padding to take stride into account
00170         pProp->cbBuffer = (m_nOutWidth + m_nPadding) * m_nOutHeight * m_nBytesPerPixel;
00171 
00172         if (pProp->cbAlign == 0)
00173         {
00174                 pProp->cbAlign = 1;
00175         }
00176         if (pProp->cBuffers == 0)
00177         {
00178                 pProp->cBuffers = 1;
00179         }
00180         
00181         // Set allocator properties.
00182         ALLOCATOR_PROPERTIES Actual;
00183         HRESULT hr = pAlloc->SetProperties(pProp, &Actual);
00184         if (FAILED(hr)) 
00185         {
00186                 return hr;
00187         }
00188         // Even when it succeeds, check the actual result.
00189         if (pProp->cbBuffer > Actual.cbBuffer) 
00190         {
00191                 return E_FAIL;
00192         }
00193         return S_OK;
00194 }
00195 
00196 HRESULT CCropFilter::CheckTransform( const CMediaType *mtIn, const CMediaType *mtOut )
00197 {
00198         //Make sure the input and output types are related
00199         if (mtOut->majortype != MEDIATYPE_Video)
00200         {
00201                 return VFW_E_TYPE_NOT_ACCEPTED;
00202         }
00203         // RG: 27/08/2008 Bug FIX: Resulted in incorrect image in VMR9
00204         if (!
00205                 ((mtIn->subtype == MEDIASUBTYPE_RGB24)&&(mtOut->subtype == MEDIASUBTYPE_RGB24))
00206                 ||
00207                 ((mtIn->subtype == MEDIASUBTYPE_RGB32)&&(mtOut->subtype == MEDIASUBTYPE_RGB32))
00208                 )
00209         {
00210                 return VFW_E_TYPE_NOT_ACCEPTED;
00211         }
00212         if (mtOut->formattype != FORMAT_VideoInfo)
00213         {
00214                 return VFW_E_TYPE_NOT_ACCEPTED;
00215         }
00216         return S_OK;
00217 }
00218 
00219 STDMETHODIMP CCropFilter::SetParameter( const char* type, const char* value )
00220 {
00221         // For now, one cannot set any parameters once the output has been connected -> this will affect the buffer size
00222         if (m_pOutput)
00223         {
00224                 if (m_pOutput->IsConnected())
00225                 {
00226                         return E_FAIL;
00227                 }
00228         }
00229 
00230         if (SUCCEEDED(CSettingsInterface::SetParameter(type, value)))
00231         {
00232                 RecalculateFilterParameters();
00233                 return S_OK;
00234         }
00235         else
00236         {
00237                 return E_FAIL;
00238         }
00239 }
00240 
00241 DWORD CCropFilter::ApplyTransform( BYTE* pBufferIn, BYTE* pBufferOut )
00242 {
00243         int nTotalSize = 0;
00244         //make sure we were able to initialise our converter
00245         if (m_pCropper)
00246         {
00247                 // Create temp buffer for crop
00248                 // TODO: Add stride parameter for crop class to avoid this extra mem alloc
00249                 BYTE* pBuffer = new BYTE[m_nOutWidth * m_nOutHeight * m_nBytesPerPixel];
00250 
00251                 //Call cropping conversion code
00252                 m_pCropper->SetInDimensions(m_nInWidth, m_nInHeight);
00253                 m_pCropper->SetOutDimensions(m_nOutWidth, m_nOutHeight);
00254                 m_pCropper->SetCrop(m_nLeftCrop, m_nRightCrop, m_nTopCrop, m_nBottomCrop);
00255                 m_pCropper->Crop((void*)pBufferIn, (void*)pBuffer);
00256                 
00257                 // Copy the cropped image with stride padding
00258                 BYTE* pFrom = pBuffer;
00259                 BYTE* pTo = pBufferOut;
00260 
00261                 int nBytesPerLine = m_nOutWidth * m_nBytesPerPixel;
00262                 for (size_t i = 0; i < m_nOutHeight; i++)
00263                 {
00264                         memcpy(pTo, pFrom, nBytesPerLine);
00265                         pFrom += nBytesPerLine;
00266                         pTo += nBytesPerLine;
00267                         for (size_t j = 0; j < m_nPadding; j++)
00268                         {
00269                                 *pTo = 0;
00270                                 pTo++;
00271                         }
00272                 }
00273                 nTotalSize = (m_nOutWidth + m_nPadding) * m_nOutHeight * m_nBytesPerPixel;
00274                 delete[] pBuffer;
00275         }
00276         else
00277         {
00278                 DbgLog((LOG_TRACE, 0, TEXT("TestCropper: Cropper is not initialised - unable to transform")));
00279         }
00280         return nTotalSize;
00281 }
00282 
00283 void CCropFilter::RecalculateFilterParameters()
00284 {
00285         //Set defaults and make sure that the target dimensions are valid
00286         m_nOutWidth = m_nInWidth - m_nLeftCrop - m_nRightCrop;
00287         m_nOutHeight = m_nInHeight - m_nTopCrop - m_nBottomCrop;
00288         m_nOutPixels = m_nOutWidth * m_nOutHeight;
00289         m_nStride =  (m_nOutWidth * (m_nBitCount / 8) + 3) & ~3;
00290         m_nPadding = m_nStride - (m_nBytesPerPixel * m_nOutWidth);
00291 
00292 }
00293 
00294 HRESULT CCropFilter::SetCropIfValid( int nTotalDimensionImage, int nNewCrop, int& nOldCrop, int nOppositeCrop  )
00295 {
00296         if (nNewCrop >= 0)
00297         {
00298                 if (nTotalDimensionImage - nOppositeCrop - nNewCrop > 0)
00299                 {
00300                         nOldCrop = nNewCrop;
00301                         RecalculateFilterParameters();
00302                         return S_OK;
00303                 }
00304                 else
00305                 {
00306                         // Fail: Total crop exceeds image dimension
00307                         return E_FAIL;
00308                 }
00309         }
00310         else
00311         {
00312                 // negative value
00313                 return E_FAIL;
00314         }
00315 }

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