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 }

Generated on Tue Dec 13 14:47:26 2005 for guliverkli by  doxygen 1.4.5