00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "StdAfx.h"
00024 #include <mmintrin.h>
00025 #include "BaseVideoFilter.h"
00026 #include "..\..\..\DSUtil\DSUtil.h"
00027 #include "..\..\..\DSUtil\MediaTypes.h"
00028
00029 #include <initguid.h>
00030 #include "..\..\..\..\include\moreuuids.h"
00031
00032
00033
00034
00035
00036 CBaseVideoFilter::CBaseVideoFilter(TCHAR* pName, LPUNKNOWN lpunk, HRESULT* phr, REFCLSID clsid)
00037 : CTransformFilter(pName, lpunk, clsid)
00038 {
00039 if(phr) *phr = S_OK;
00040
00041 if(!(m_pInput = new CBaseVideoInputPin(NAME("CBaseVideoInputPin"), this, phr, L"Video"))) *phr = E_OUTOFMEMORY;
00042 if(FAILED(*phr)) return;
00043
00044 if(!(m_pOutput = new CBaseVideoOutputPin(NAME("CBaseVideoOutputPin"), this, phr, L"Output"))) *phr = E_OUTOFMEMORY;
00045 if(FAILED(*phr)) {delete m_pInput, m_pInput = NULL; return;}
00046
00047 m_wout = m_win = m_w = 0;
00048 m_hout = m_hin = m_h = 0;
00049 m_arxout = m_arxin = m_arx = 0;
00050 m_aryout = m_aryin = m_ary = 0;
00051 }
00052
00053 CBaseVideoFilter::~CBaseVideoFilter()
00054 {
00055 }
00056
00057 int CBaseVideoFilter::GetPinCount()
00058 {
00059 return 2;
00060 }
00061
00062 CBasePin* CBaseVideoFilter::GetPin(int n)
00063 {
00064 switch(n)
00065 {
00066 case 0: return m_pInput;
00067 case 1: return m_pOutput;
00068 }
00069 return NULL;
00070 }
00071
00072 HRESULT CBaseVideoFilter::Receive(IMediaSample* pIn)
00073 {
00074 _mm_empty();
00075
00076 CAutoLock cAutoLock(&m_csReceive);
00077
00078 HRESULT hr;
00079
00080 AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
00081 if(pProps->dwStreamId != AM_STREAM_MEDIA)
00082 return m_pOutput->Deliver(pIn);
00083
00084 AM_MEDIA_TYPE* pmt;
00085 if(SUCCEEDED(pIn->GetMediaType(&pmt)) && pmt)
00086 {
00087 CMediaType mt(*pmt);
00088 m_pInput->SetMediaType(&mt);
00089 DeleteMediaType(pmt);
00090 }
00091
00092 if(FAILED(hr = Transform(pIn)))
00093 return hr;
00094
00095 return S_OK;
00096 }
00097
00098 HRESULT CBaseVideoFilter::GetDeliveryBuffer(int w, int h, IMediaSample** ppOut)
00099 {
00100 CheckPointer(ppOut, E_POINTER);
00101
00102 HRESULT hr;
00103
00104 if(FAILED(hr = ReconnectOutput(w, h)))
00105 return hr;
00106
00107 if(FAILED(hr = m_pOutput->GetDeliveryBuffer(ppOut, NULL, NULL, 0)))
00108 return hr;
00109
00110 AM_MEDIA_TYPE* pmt;
00111 if(SUCCEEDED((*ppOut)->GetMediaType(&pmt)) && pmt)
00112 {
00113 CMediaType mt = *pmt;
00114 m_pOutput->SetMediaType(&mt);
00115 DeleteMediaType(pmt);
00116 }
00117
00118 (*ppOut)->SetDiscontinuity(FALSE);
00119 (*ppOut)->SetSyncPoint(TRUE);
00120
00121
00122
00123 if(GetCLSID(m_pOutput->GetConnected()) == CLSID_OverlayMixer)
00124 (*ppOut)->SetDiscontinuity(TRUE);
00125
00126 return S_OK;
00127 }
00128
00129 HRESULT CBaseVideoFilter::ReconnectOutput(int w, int h)
00130 {
00131 CMediaType& mt = m_pOutput->CurrentMediaType();
00132
00133 int w_org = m_w;
00134 int h_org = m_h;
00135
00136 bool fForceReconnection = false;
00137 if(w != m_w || h != m_h)
00138 {
00139 fForceReconnection = true;
00140 m_w = w;
00141 m_h = h;
00142 }
00143
00144 HRESULT hr = S_OK;
00145
00146 if(fForceReconnection || m_w != m_wout || m_h != m_hout || m_arx != m_arxout || m_ary != m_aryout)
00147 {
00148 if(GetCLSID(m_pOutput->GetConnected()) == CLSID_VideoRenderer)
00149 {
00150 NotifyEvent(EC_ERRORABORT, 0, 0);
00151 return E_FAIL;
00152 }
00153
00154 BITMAPINFOHEADER* bmi = NULL;
00155
00156 if(mt.formattype == FORMAT_VideoInfo)
00157 {
00158 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.Format();
00159 SetRect(&vih->rcSource, 0, 0, m_w, m_h);
00160 SetRect(&vih->rcTarget, 0, 0, m_w, m_h);
00161 bmi = &vih->bmiHeader;
00162 bmi->biXPelsPerMeter = m_w * m_ary;
00163 bmi->biYPelsPerMeter = m_h * m_arx;
00164 }
00165 else if(mt.formattype == FORMAT_VideoInfo2)
00166 {
00167 VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)mt.Format();
00168 SetRect(&vih->rcSource, 0, 0, m_w, m_h);
00169 SetRect(&vih->rcTarget, 0, 0, m_w, m_h);
00170 bmi = &vih->bmiHeader;
00171 vih->dwPictAspectRatioX = m_arx;
00172 vih->dwPictAspectRatioY = m_ary;
00173 }
00174
00175 bmi->biWidth = m_w;
00176 bmi->biHeight = m_h;
00177 bmi->biSizeImage = m_w*m_h*bmi->biBitCount>>3;
00178
00179 hr = m_pOutput->GetConnected()->QueryAccept(&mt);
00180 ASSERT(SUCCEEDED(hr));
00181 HRESULT hr1 = 0, hr2 = 0;
00182 CComPtr<IMediaSample> pOut;
00183 if(SUCCEEDED(hr1 = m_pOutput->GetConnected()->ReceiveConnection(m_pOutput, &mt))
00184 && SUCCEEDED(hr2 = m_pOutput->GetDeliveryBuffer(&pOut, NULL, NULL, 0)))
00185 {
00186 AM_MEDIA_TYPE* pmt;
00187 if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
00188 {
00189 CMediaType mt = *pmt;
00190 m_pOutput->SetMediaType(&mt);
00191 DeleteMediaType(pmt);
00192 }
00193 else
00194 {
00195 long size = pOut->GetSize();
00196 bmi->biWidth = size / bmi->biHeight * 8 / bmi->biBitCount;
00197 }
00198 }
00199 else
00200 {
00201 m_w = w_org;
00202 m_h = h_org;
00203 return E_FAIL;
00204 }
00205
00206 m_wout = m_w;
00207 m_hout = m_h;
00208 m_arxout = m_arx;
00209 m_aryout = m_ary;
00210
00211
00212 NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(m_w, m_h), 0);
00213
00214 return S_OK;
00215 }
00216
00217 return S_FALSE;
00218 }
00219
00220 HRESULT CBaseVideoFilter::CopyBuffer(BYTE* pOut, BYTE* pIn, int w, int h, int pitchIn, const GUID& subtype)
00221 {
00222 int abs_h = abs(h);
00223 BYTE* pInYUV[3] = {pIn, pIn + pitchIn*abs_h, pIn + pitchIn*abs_h + (pitchIn>>1)*(abs_h>>1)};
00224 return CopyBuffer(pOut, pInYUV, w, h, pitchIn, subtype);
00225 }
00226
00227 HRESULT CBaseVideoFilter::CopyBuffer(BYTE* pOut, BYTE** ppIn, int w, int h, int pitchIn, const GUID& subtype)
00228 {
00229 BITMAPINFOHEADER bihOut;
00230 ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
00231
00232 int pitchOut = 0;
00233
00234 if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
00235 {
00236 pitchOut = bihOut.biWidth*bihOut.biBitCount>>3;
00237
00238 if(bihOut.biHeight > 0)
00239 {
00240 pOut += pitchOut*(h-1);
00241 pitchOut = -pitchOut;
00242 if(h < 0) h = -h;
00243 }
00244 }
00245
00246 if(h < 0)
00247 {
00248 h = -h;
00249 ppIn[0] += pitchIn*(h-1);
00250 ppIn[1] += (pitchIn>>1)*((h>>1)-1);
00251 ppIn[2] += (pitchIn>>1)*((h>>1)-1);
00252 pitchIn = -pitchIn;
00253 }
00254
00255 if(subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV || subtype == MEDIASUBTYPE_YV12)
00256 {
00257 BYTE* pIn = ppIn[0];
00258 BYTE* pInU = ppIn[1];
00259 BYTE* pInV = ppIn[2];
00260
00261 if(subtype == MEDIASUBTYPE_YV12) {BYTE* tmp = pInU; pInU = pInV; pInV = tmp;}
00262
00263 BYTE* pOutU = pOut + bihOut.biWidth*h;
00264 BYTE* pOutV = pOut + bihOut.biWidth*h*5/4;
00265
00266 if(bihOut.biCompression == '21VY') {BYTE* tmp = pOutU; pOutU = pOutV; pOutV = tmp;}
00267
00268 ASSERT(w <= abs(pitchIn));
00269
00270 if(bihOut.biCompression == '2YUY')
00271 {
00272 BitBltFromI420ToYUY2(w, h, pOut, bihOut.biWidth*2, pIn, pInU, pInV, pitchIn);
00273 }
00274 else if(bihOut.biCompression == '024I' || bihOut.biCompression == 'VUYI' || bihOut.biCompression == '21VY')
00275 {
00276 BitBltFromI420ToI420(w, h, pOut, pOutU, pOutV, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
00277 }
00278 else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
00279 {
00280 if(!BitBltFromI420ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, pIn, pInU, pInV, pitchIn))
00281 {
00282 for(DWORD y = 0; y < h; y++, pOut += pitchOut)
00283 memset(pOut, 0, pitchOut);
00284 }
00285 }
00286 }
00287 else if(subtype == MEDIASUBTYPE_YUY2)
00288 {
00289 if(bihOut.biCompression == '2YUY')
00290 {
00291 BitBltFromYUY2ToYUY2(w, h, pOut, bihOut.biWidth*2, ppIn[0], pitchIn);
00292 }
00293 else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
00294 {
00295 if(!BitBltFromYUY2ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, ppIn[0], pitchIn))
00296 {
00297 for(DWORD y = 0; y < h; y++, pOut += pitchOut)
00298 memset(pOut, 0, pitchOut);
00299 }
00300 }
00301 }
00302 else if(subtype == MEDIASUBTYPE_ARGB32 || subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_RGB24 || subtype == MEDIASUBTYPE_RGB565)
00303 {
00304 int sbpp =
00305 subtype == MEDIASUBTYPE_ARGB32 || subtype == MEDIASUBTYPE_RGB32 ? 32 :
00306 subtype == MEDIASUBTYPE_RGB24 ? 24 :
00307 subtype == MEDIASUBTYPE_RGB565 ? 16 : 0;
00308
00309 if(bihOut.biCompression == '2YUY')
00310 {
00311
00312
00313 }
00314 else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
00315 {
00316 if(!BitBltFromRGBToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, ppIn[0], pitchIn, sbpp))
00317 {
00318 for(DWORD y = 0; y < h; y++, pOut += pitchOut)
00319 memset(pOut, 0, pitchOut);
00320 }
00321 }
00322 }
00323 else
00324 {
00325 return VFW_E_TYPE_NOT_ACCEPTED;
00326 }
00327
00328 return S_OK;
00329 }
00330
00331 HRESULT CBaseVideoFilter::CheckInputType(const CMediaType* mtIn)
00332 {
00333 BITMAPINFOHEADER bih;
00334 ExtractBIH(mtIn, &bih);
00335
00336 return mtIn->majortype == MEDIATYPE_Video
00337 && (mtIn->subtype == MEDIASUBTYPE_YV12
00338 || mtIn->subtype == MEDIASUBTYPE_I420
00339 || mtIn->subtype == MEDIASUBTYPE_IYUV
00340 || mtIn->subtype == MEDIASUBTYPE_YUY2
00341 || mtIn->subtype == MEDIASUBTYPE_ARGB32
00342 || mtIn->subtype == MEDIASUBTYPE_RGB32
00343 || mtIn->subtype == MEDIASUBTYPE_RGB24
00344 || mtIn->subtype == MEDIASUBTYPE_RGB565)
00345 && (mtIn->formattype == FORMAT_VideoInfo
00346 || mtIn->formattype == FORMAT_VideoInfo2)
00347 && bih.biHeight > 0
00348 ? S_OK
00349 : VFW_E_TYPE_NOT_ACCEPTED;
00350 }
00351
00352 HRESULT CBaseVideoFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00353 {
00354 if(FAILED(CheckInputType(mtIn)) || mtOut->majortype != MEDIATYPE_Video)
00355 return VFW_E_TYPE_NOT_ACCEPTED;
00356
00357 if(mtIn->majortype == MEDIATYPE_Video
00358 && (mtIn->subtype == MEDIASUBTYPE_YV12
00359 || mtIn->subtype == MEDIASUBTYPE_I420
00360 || mtIn->subtype == MEDIASUBTYPE_IYUV))
00361 {
00362 if(mtOut->subtype != MEDIASUBTYPE_YV12
00363 && mtOut->subtype != MEDIASUBTYPE_I420
00364 && mtOut->subtype != MEDIASUBTYPE_IYUV
00365 && mtOut->subtype != MEDIASUBTYPE_YUY2
00366 && mtOut->subtype != MEDIASUBTYPE_ARGB32
00367 && mtOut->subtype != MEDIASUBTYPE_RGB32
00368 && mtOut->subtype != MEDIASUBTYPE_RGB24
00369 && mtOut->subtype != MEDIASUBTYPE_RGB565)
00370 return VFW_E_TYPE_NOT_ACCEPTED;
00371 }
00372 else if(mtIn->majortype == MEDIATYPE_Video
00373 && (mtIn->subtype == MEDIASUBTYPE_YUY2))
00374 {
00375 if(mtOut->subtype != MEDIASUBTYPE_YUY2
00376 && mtOut->subtype != MEDIASUBTYPE_ARGB32
00377 && mtOut->subtype != MEDIASUBTYPE_RGB32
00378 && mtOut->subtype != MEDIASUBTYPE_RGB24
00379 && mtOut->subtype != MEDIASUBTYPE_RGB565)
00380 return VFW_E_TYPE_NOT_ACCEPTED;
00381 }
00382 else if(mtIn->majortype == MEDIATYPE_Video
00383 && (mtIn->subtype == MEDIASUBTYPE_ARGB32
00384 || mtIn->subtype == MEDIASUBTYPE_RGB32
00385 || mtIn->subtype == MEDIASUBTYPE_RGB24
00386 || mtIn->subtype == MEDIASUBTYPE_RGB565))
00387 {
00388 if(mtOut->subtype != MEDIASUBTYPE_ARGB32
00389 && mtOut->subtype != MEDIASUBTYPE_RGB32
00390 && mtOut->subtype != MEDIASUBTYPE_RGB24
00391 && mtOut->subtype != MEDIASUBTYPE_RGB565)
00392 return VFW_E_TYPE_NOT_ACCEPTED;
00393 }
00394
00395 return S_OK;
00396 }
00397
00398 HRESULT CBaseVideoFilter::CheckOutputType(const CMediaType& mtOut)
00399 {
00400 int wout = 0, hout = 0, arxout = 0, aryout = 0;
00401 return ExtractDim(&mtOut, wout, hout, arxout, aryout)
00402 && m_h == abs((int)hout)
00403 && mtOut.subtype != MEDIASUBTYPE_ARGB32
00404 ? S_OK
00405 : VFW_E_TYPE_NOT_ACCEPTED;
00406 }
00407
00408 HRESULT CBaseVideoFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
00409 {
00410 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00411
00412 BITMAPINFOHEADER bih;
00413 ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
00414
00415 pProperties->cBuffers = 1;
00416 pProperties->cbBuffer = bih.biSizeImage;
00417 pProperties->cbAlign = 1;
00418 pProperties->cbPrefix = 0;
00419
00420 HRESULT hr;
00421 ALLOCATOR_PROPERTIES Actual;
00422 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
00423 return hr;
00424
00425 return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
00426 ? E_FAIL
00427 : NOERROR;
00428 }
00429
00430 HRESULT CBaseVideoFilter::GetMediaType(int iPosition, CMediaType* pmt)
00431 {
00432 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00433
00434 struct {const GUID* subtype; WORD biPlanes, biBitCount; DWORD biCompression;} fmts[] =
00435 {
00436 {&MEDIASUBTYPE_YV12, 3, 12, '21VY'},
00437 {&MEDIASUBTYPE_I420, 3, 12, '024I'},
00438 {&MEDIASUBTYPE_IYUV, 3, 12, 'VUYI'},
00439 {&MEDIASUBTYPE_YUY2, 1, 16, '2YUY'},
00440 {&MEDIASUBTYPE_ARGB32, 1, 32, BI_RGB},
00441 {&MEDIASUBTYPE_RGB32, 1, 32, BI_RGB},
00442 {&MEDIASUBTYPE_RGB24, 1, 24, BI_RGB},
00443 {&MEDIASUBTYPE_RGB565, 1, 16, BI_RGB},
00444 {&MEDIASUBTYPE_RGB555, 1, 16, BI_RGB},
00445 {&MEDIASUBTYPE_ARGB32, 1, 32, BI_BITFIELDS},
00446 {&MEDIASUBTYPE_RGB32, 1, 32, BI_BITFIELDS},
00447 {&MEDIASUBTYPE_RGB24, 1, 24, BI_BITFIELDS},
00448 {&MEDIASUBTYPE_RGB565, 1, 16, BI_BITFIELDS},
00449 {&MEDIASUBTYPE_RGB555, 1, 16, BI_BITFIELDS},
00450 };
00451
00452
00453
00454
00455 bool fFoundDVDNavigator = false;
00456 CComPtr<IBaseFilter> pBF = this;
00457 CComPtr<IPin> pPin = m_pInput;
00458 for(; !fFoundDVDNavigator && (pBF = GetFilterFromPin(GetUpStreamPin(pBF, pPin))); pPin = GetFirstPin(pBF))
00459 fFoundDVDNavigator = GetCLSID(pBF) == CLSID_DVDNavigator;
00460
00461 if(fFoundDVDNavigator || m_pInput->CurrentMediaType().formattype == FORMAT_VideoInfo2)
00462 iPosition = iPosition*2;
00463
00464
00465
00466 if(iPosition < 0) return E_INVALIDARG;
00467 if(iPosition >= 2*countof(fmts)) return VFW_S_NO_MORE_ITEMS;
00468
00469 pmt->majortype = MEDIATYPE_Video;
00470 pmt->subtype = *fmts[iPosition/2].subtype;
00471
00472 int w = m_win, h = m_hin, arx = m_arxin, ary = m_aryin;
00473 GetOutputSize(w, h, arx, ary);
00474
00475 BITMAPINFOHEADER bihOut;
00476 memset(&bihOut, 0, sizeof(bihOut));
00477 bihOut.biSize = sizeof(bihOut);
00478 bihOut.biWidth = w;
00479 bihOut.biHeight = h;
00480 bihOut.biPlanes = fmts[iPosition/2].biPlanes;
00481 bihOut.biBitCount = fmts[iPosition/2].biBitCount;
00482 bihOut.biCompression = fmts[iPosition/2].biCompression;
00483 bihOut.biSizeImage = w*h*bihOut.biBitCount>>3;
00484
00485 if(iPosition&1)
00486 {
00487 pmt->formattype = FORMAT_VideoInfo;
00488 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00489 memset(vih, 0, sizeof(VIDEOINFOHEADER));
00490 vih->bmiHeader = bihOut;
00491 vih->bmiHeader.biXPelsPerMeter = vih->bmiHeader.biWidth * ary;
00492 vih->bmiHeader.biYPelsPerMeter = vih->bmiHeader.biHeight * arx;
00493 }
00494 else
00495 {
00496 pmt->formattype = FORMAT_VideoInfo2;
00497 VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER2));
00498 memset(vih, 0, sizeof(VIDEOINFOHEADER2));
00499 vih->bmiHeader = bihOut;
00500 vih->dwPictAspectRatioX = arx;
00501 vih->dwPictAspectRatioY = ary;
00502 vih->dwCopyProtectFlags &= ~AMCOPYPROTECT_RestrictDuplication;
00503 }
00504
00505 CMediaType& mt = m_pInput->CurrentMediaType();
00506
00507
00508 ((VIDEOINFOHEADER*)pmt->Format())->AvgTimePerFrame = ((VIDEOINFOHEADER*)mt.Format())->AvgTimePerFrame;
00509 ((VIDEOINFOHEADER*)pmt->Format())->dwBitRate = ((VIDEOINFOHEADER*)mt.Format())->dwBitRate;
00510 ((VIDEOINFOHEADER*)pmt->Format())->dwBitErrorRate = ((VIDEOINFOHEADER*)mt.Format())->dwBitErrorRate;
00511
00512 CorrectMediaType(pmt);
00513
00514 return S_OK;
00515 }
00516
00517 HRESULT CBaseVideoFilter::SetMediaType(PIN_DIRECTION dir, const CMediaType* pmt)
00518 {
00519 if(dir == PINDIR_INPUT)
00520 {
00521 m_w = m_h = m_arx = m_ary = 0;
00522 ExtractDim(pmt, m_w, m_h, m_arx, m_ary);
00523 m_win = m_w;
00524 m_hin = m_h;
00525 m_arxin = m_arx;
00526 m_aryin = m_ary;
00527 GetOutputSize(m_w, m_h, m_arx, m_ary);
00528 }
00529 else if(dir == PINDIR_OUTPUT)
00530 {
00531 int wout = 0, hout = 0, arxout = 0, aryout = 0;
00532 ExtractDim(pmt, wout, hout, arxout, aryout);
00533 if(m_w == wout && m_h == hout && m_arx == arxout && m_ary == aryout)
00534 {
00535 m_wout = wout;
00536 m_hout = hout;
00537 m_arxout = arxout;
00538 m_aryout = aryout;
00539 }
00540 }
00541
00542 return __super::SetMediaType(dir, pmt);
00543 }
00544
00545
00546
00547
00548
00549 CBaseVideoInputAllocator::CBaseVideoInputAllocator(HRESULT* phr)
00550 : CMemAllocator(NAME("CBaseVideoInputAllocator"), NULL, phr)
00551 {
00552 if(phr) *phr = S_OK;
00553 }
00554
00555 void CBaseVideoInputAllocator::SetMediaType(const CMediaType& mt)
00556 {
00557 m_mt = mt;
00558 }
00559
00560 STDMETHODIMP CBaseVideoInputAllocator::GetBuffer(IMediaSample** ppBuffer, REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime, DWORD dwFlags)
00561 {
00562 if(!m_bCommitted)
00563 return VFW_E_NOT_COMMITTED;
00564
00565 HRESULT hr = __super::GetBuffer(ppBuffer, pStartTime, pEndTime, dwFlags);
00566
00567 if(SUCCEEDED(hr) && m_mt.majortype != GUID_NULL)
00568 {
00569 (*ppBuffer)->SetMediaType(&m_mt);
00570 m_mt.majortype = GUID_NULL;
00571 }
00572
00573 return hr;
00574 }
00575
00576
00577
00578
00579
00580 CBaseVideoInputPin::CBaseVideoInputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName)
00581 : CTransformInputPin(pObjectName, pFilter, phr, pName)
00582 , m_pAllocator(NULL)
00583 {
00584 }
00585
00586 CBaseVideoInputPin::~CBaseVideoInputPin()
00587 {
00588 delete m_pAllocator;
00589 }
00590
00591 STDMETHODIMP CBaseVideoInputPin::GetAllocator(IMemAllocator** ppAllocator)
00592 {
00593 CheckPointer(ppAllocator, E_POINTER);
00594
00595 if(m_pAllocator == NULL)
00596 {
00597 HRESULT hr = S_OK;
00598 m_pAllocator = new CBaseVideoInputAllocator(&hr);
00599 m_pAllocator->AddRef();
00600 }
00601
00602 (*ppAllocator = m_pAllocator)->AddRef();
00603
00604 return S_OK;
00605 }
00606
00607 STDMETHODIMP CBaseVideoInputPin::ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt)
00608 {
00609 CAutoLock cObjectLock(m_pLock);
00610
00611 if(m_Connected)
00612 {
00613 CMediaType mt(*pmt);
00614
00615 if(FAILED(CheckMediaType(&mt)))
00616 return VFW_E_TYPE_NOT_ACCEPTED;
00617
00618 ALLOCATOR_PROPERTIES props, actual;
00619
00620 CComPtr<IMemAllocator> pMemAllocator;
00621 if(FAILED(GetAllocator(&pMemAllocator))
00622 || FAILED(pMemAllocator->Decommit())
00623 || FAILED(pMemAllocator->GetProperties(&props)))
00624 return E_FAIL;
00625
00626 BITMAPINFOHEADER bih;
00627 if(ExtractBIH(pmt, &bih) && bih.biSizeImage)
00628 props.cbBuffer = bih.biSizeImage;
00629
00630 if(FAILED(pMemAllocator->SetProperties(&props, &actual))
00631 || FAILED(pMemAllocator->Commit())
00632 || props.cbBuffer != actual.cbBuffer)
00633 return E_FAIL;
00634
00635 if(m_pAllocator)
00636 m_pAllocator->SetMediaType(mt);
00637
00638 return SetMediaType(&mt) == S_OK
00639 ? S_OK
00640 : VFW_E_TYPE_NOT_ACCEPTED;
00641 }
00642
00643 return __super::ReceiveConnection(pConnector, pmt);
00644 }
00645
00646
00647
00648
00649
00650 CBaseVideoOutputPin::CBaseVideoOutputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName)
00651 : CTransformOutputPin(pObjectName, pFilter, phr, pName)
00652 {
00653 }
00654
00655 HRESULT CBaseVideoOutputPin::CheckMediaType(const CMediaType* mtOut)
00656 {
00657 if(IsConnected())
00658 {
00659 HRESULT hr = ((CBaseVideoFilter*)m_pFilter)->CheckOutputType(*mtOut);
00660 if(FAILED(hr)) return hr;
00661 }
00662
00663 return __super::CheckMediaType(mtOut);
00664 }