00001 #include "stdafx.h"
00002 #include ".\deinterlacerfilter.h"
00003 #include "..\..\DSUtil\MediaTypes.h"
00004 #include "..\..\..\include\moreuuids.h"
00005
00006 CDeinterlacerFilter::CDeinterlacerFilter(LPUNKNOWN punk, HRESULT* phr)
00007 : CTransformFilter(NAME("CDeinterlacerFilter"), punk, __uuidof(CDeinterlacerFilter))
00008 {
00009 if(phr) *phr = S_OK;
00010 }
00011
00012 HRESULT CDeinterlacerFilter::CheckInputType(const CMediaType* mtIn)
00013 {
00014 BITMAPINFOHEADER bih;
00015 if(!ExtractBIH(mtIn, &bih) || bih.biHeight <= 288)
00016 return E_FAIL;
00017
00018 return mtIn->subtype == MEDIASUBTYPE_YUY2 || mtIn->subtype == MEDIASUBTYPE_UYVY
00019 || mtIn->subtype == MEDIASUBTYPE_I420 || mtIn->subtype == MEDIASUBTYPE_YV12 || mtIn->subtype == MEDIASUBTYPE_IYUV
00020 ? S_OK
00021 : E_FAIL;
00022 }
00023
00024 HRESULT CDeinterlacerFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00025 {
00026 return mtIn->subtype == mtOut->subtype ? S_OK : E_FAIL;
00027 }
00028
00029 HRESULT CDeinterlacerFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
00030 {
00031 HRESULT hr;
00032
00033 AM_MEDIA_TYPE* pmt = NULL;
00034 if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
00035 {
00036 CMediaType mt = *pmt;
00037 m_pOutput->SetMediaType(&mt);
00038 DeleteMediaType(pmt);
00039 }
00040
00041 BYTE* pDataIn = NULL;
00042 if(FAILED(pIn->GetPointer(&pDataIn)) || !pDataIn)
00043 return S_FALSE;
00044
00045 BYTE* pDataOut = NULL;
00046 if(FAILED(hr = pOut->GetPointer(&pDataOut)) || !pDataOut)
00047 return hr;
00048
00049 const CMediaType& mtIn = m_pInput->CurrentMediaType();
00050 const CMediaType& mtOut = m_pOutput->CurrentMediaType();
00051
00052 BITMAPINFOHEADER bihIn, bihOut;
00053 ExtractBIH(&mtIn, &bihIn);
00054 ExtractBIH(&mtOut, &bihOut);
00055
00056 bool fInputFlipped = bihIn.biHeight >= 0 && bihIn.biCompression <= 3;
00057 bool fOutputFlipped = bihOut.biHeight >= 0 && bihOut.biCompression <= 3;
00058 bool fFlip = fInputFlipped != fOutputFlipped;
00059
00060 int bppIn = !(bihIn.biBitCount&7) ? bihIn.biBitCount : 8;
00061 int bppOut = !(bihOut.biBitCount&7) ? bihOut.biBitCount : 8;
00062 int pitchIn = bihIn.biWidth*bppIn>>3;
00063 int pitchOut = bihOut.biWidth*bppOut>>3;
00064 BYTE* pDataOut2 = pDataOut;
00065 if(fFlip) {pDataOut2 += pitchOut*(bihIn.biHeight-1); pitchOut = -pitchOut;}
00066
00067 if(mtIn.subtype == MEDIASUBTYPE_YUY2 || mtIn.subtype == MEDIASUBTYPE_UYVY)
00068 {
00069 DeinterlaceBlend(pDataOut, pDataIn, pitchIn, bihIn.biHeight, pitchOut, pitchIn);
00070 }
00071 else if(mtIn.subtype == MEDIASUBTYPE_I420 || mtIn.subtype == MEDIASUBTYPE_YV12 || mtIn.subtype == MEDIASUBTYPE_IYUV)
00072 {
00073 DeinterlaceBlend(pDataOut, pDataIn, pitchIn, bihIn.biHeight, pitchOut, pitchIn);
00074
00075 int sizeIn = bihIn.biHeight*pitchIn, sizeOut = abs(bihOut.biHeight)*pitchOut;
00076 pitchIn /= 2; pitchOut /= 2;
00077 bihIn.biHeight /= 2;
00078 pDataIn += sizeIn; pDataOut += sizeOut;
00079 DeinterlaceBlend(pDataOut, pDataIn, pitchIn, bihIn.biHeight, pitchOut, pitchIn);
00080
00081 pDataIn += sizeIn/4; pDataOut += sizeOut/4;
00082 DeinterlaceBlend(pDataOut, pDataIn, pitchIn, bihIn.biHeight, pitchOut, pitchIn);
00083 }
00084
00085 return S_OK;
00086 }
00087
00088 HRESULT CDeinterlacerFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
00089 {
00090 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00091
00092 BITMAPINFOHEADER bih;
00093 ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
00094
00095 pProperties->cBuffers = 1;
00096 pProperties->cbBuffer = bih.biSizeImage;
00097 pProperties->cbAlign = 1;
00098 pProperties->cbPrefix = 0;
00099
00100 HRESULT hr;
00101 ALLOCATOR_PROPERTIES Actual;
00102 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
00103 return hr;
00104
00105 return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
00106 ? E_FAIL
00107 : NOERROR;
00108 }
00109
00110 HRESULT CDeinterlacerFilter::GetMediaType(int iPosition, CMediaType* pmt)
00111 {
00112 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00113 if(iPosition < 0) return E_INVALIDARG;
00114 if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
00115 *pmt = m_pInput->CurrentMediaType();
00116 CorrectMediaType(pmt);
00117 return S_OK;
00118 }