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
00050 InitialiseInputTypes();
00051
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
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
00096 if (pmt->majortype == MEDIATYPE_Video)
00097 {
00098
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
00129
00130 HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);
00131 if (FAILED(hr))
00132 {
00133 return hr;
00134 }
00135
00136
00137
00138 ASSERT(pMediaType->formattype == FORMAT_VideoInfo);
00139 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pMediaType->pbFormat;
00140
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
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
00182 ALLOCATOR_PROPERTIES Actual;
00183 HRESULT hr = pAlloc->SetProperties(pProp, &Actual);
00184 if (FAILED(hr))
00185 {
00186 return hr;
00187 }
00188
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
00199 if (mtOut->majortype != MEDIATYPE_Video)
00200 {
00201 return VFW_E_TYPE_NOT_ACCEPTED;
00202 }
00203
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
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
00245 if (m_pCropper)
00246 {
00247
00248
00249 BYTE* pBuffer = new BYTE[m_nOutWidth * m_nOutHeight * m_nBytesPerPixel];
00250
00251
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
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
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
00307 return E_FAIL;
00308 }
00309 }
00310 else
00311 {
00312
00313 return E_FAIL;
00314 }
00315 }