- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# BaseVideoFilter.cpp

    00001
    00002 /*
    00003  *      Copyright (C) 2003-2005 Gabest
    00004  *      http://www.gabest.org
    00005  *
    00006  *  This Program is free software; you can redistribute it and/or modify
    00007  *  it under the terms of the GNU General Public License as published by
    00008  *  the Free Software Foundation; either version 2, or (at your option)
    00009  *  any later version.
    00010  *
    00011  *  This Program is distributed in the hope that it will be useful,
    00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00014  *  GNU General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU General Public License
    00017  *  along with GNU Make; see the file COPYING.  If not, write to
    00018  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00019  *  http://www.gnu.org/copyleft/gpl.html
    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 // CBaseVideoFilter
    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(); // just for safety
    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         // FIXME: hell knows why but without this the overlay mixer starts very skippy
    00122         // (don't enable this for other renderers, the old for example will go crazy if you do)
    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)); // should better not fail, after all "mt" is the current media type, just with a different resolution
    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 // stupid overlay mixer won't let us know the new pitch...
    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                 // some renderers don't send this
    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                         // TODO
    00312                         // BitBltFromRGBToYUY2();
    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         // this will make sure we won't connect to the old renderer in dvd mode
    00453         // that renderer can't switch the format dynamically
    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; // hehe
    00503         }
    00504
    00505         CMediaType& mt = m_pInput->CurrentMediaType();
    00506
    00507         // these fields have the same field offset in all four structs
    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 // CBaseVideoInputAllocator
    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 // CBaseVideoInputPin
    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 // CBaseVideoOutputPin
    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 }