MultiIOBaseFilter.cpp

Go to the documentation of this file.
00001 
00034 #include "MultiIOBaseFilter.h"
00035 
00036 #include "MultiIOInputPin.h"
00037 #include "MultiIOOutputPin.h"
00038 
00039 #include <atlconv.h>
00040 
00041 #pragma comment(lib, "atls.lib")
00042 
00043 CMultiIOBaseFilter::CMultiIOBaseFilter(TCHAR *pObjectName, LPUNKNOWN lpUnk, CLSID clsid)
00044 : CBaseFilter(pObjectName, lpUnk, &m_csFilter, clsid)
00045 {}
00046 
00047 CMultiIOBaseFilter::~CMultiIOBaseFilter(void)
00048 {
00049         // Release all the COM interfaces
00050         for (int i = 0; i < m_vInputPins.size(); i++)
00051         {
00052                 m_vInputPins[i]->Release();
00053         }
00054         for (int i = 0; i < m_vOutputPins.size(); i++)
00055         {
00056                 m_vOutputPins[i]->Release();
00057         }
00058 
00059         // Clean up input type map
00060         CleanupTypeMap(m_mInputTypeMap);
00061         // Clean up Output type map
00062         CleanupTypeMap(m_mOutputTypeMap);
00063         // Clean up generic types
00064         for (int i = 0; i < m_vInputTypes.size(); i++)
00065         {
00066                 delete m_vInputTypes.at(i);
00067         }
00068         for (int i = 0; i < m_vOutputTypes.size(); i++)
00069         {
00070                 delete m_vOutputTypes.at(i);
00071         }
00072 }
00073 
00074 void CMultiIOBaseFilter::CleanupTypeMap(MEDIA_TYPE_MAP mTypeMap)
00075 {
00076         MEDIA_TYPE_MAP_ITERATOR it;
00077         for (it = mTypeMap.begin(); it != mTypeMap.end(); it++)
00078         {
00079                 //Delete the input type list for that pin
00080                 MEDIA_TYPE_LIST* pInputList = (*it).second;
00081                 //Iterate over list and delete all input types
00082                 for (int i = 0; i < pInputList->size(); i++)
00083                 {
00084                         delete pInputList->at(i);
00085                 }
00086                 delete pInputList;
00087         }
00088         mTypeMap.clear();
00089 }
00090 
00091 
00092 void CMultiIOBaseFilter::Initialise()
00093 {
00094         //Create initial number of inputs/outputs
00095         for (int i = 0; i < InitialNumberOfInputPins(); i++)
00096         {
00097                 CreateInputPin();
00098         }
00099 
00100         for (int i = 0; i < InitialNumberOfOutputPins(); i++)
00101         {
00102                 CreateOutputPin();
00103         }
00104         InitialiseInputTypes();
00105         InitialiseOutputTypes();
00106 }
00107 
00108 void CMultiIOBaseFilter::AddInputType( const GUID* pType, const GUID* pSubType, const GUID* pFormat, int nPin  )
00109 {
00110         CIOMediaType* pMediaType = new CIOMediaType(pType, pSubType, pFormat);
00111         AddMediaType(pMediaType, m_vInputTypes, m_mInputTypeMap, nPin );
00112 }
00113 
00114 void CMultiIOBaseFilter::AddOutputType( const GUID* pType, const GUID* pSubType, const GUID* pFormat, int nPin   )
00115 {
00116         CIOMediaType* pMediaType = new CIOMediaType(pType, pSubType, pFormat);
00117         AddMediaType(pMediaType, m_vOutputTypes, m_mOutputTypeMap, nPin );
00118 }
00119 
00120 void CMultiIOBaseFilter::AddMediaType(CIOMediaType* pMediaType, MEDIA_TYPE_LIST& typeList, MEDIA_TYPE_MAP& typeMap, int nPin  )
00121 {
00122         if (nPin == -1)
00123         {
00124                 // Generic types
00125                 typeList.push_back(pMediaType);
00126         }
00127         else
00128         {
00129                 // Add the mapping of the pin number to the type
00130                 MEDIA_TYPE_MAP_ITERATOR it;
00131                 it = typeMap.find(nPin);
00132                 if (it == m_mInputTypeMap.end())
00133                 {
00134                         //No list for pin, create one
00135                         typeMap[nPin] = new MEDIA_TYPE_LIST;
00136                         typeMap[nPin]->push_back(pMediaType);
00137                 }
00138                 else
00139                 {
00140                         //list already exists for pin
00141                         (*it).second->push_back(pMediaType);
00142                 }
00143         }
00144 }
00145 
00146 int CMultiIOBaseFilter::GetPinCount()
00147 {
00148         return (int)(m_vInputPins.size() + m_vOutputPins.size());
00149 }
00150 
00151 CBasePin * CMultiIOBaseFilter::GetPin( int n )
00152 {
00153         if ((n >= GetPinCount()) || (n < 0))
00154                 return NULL;
00155 
00156         if (n < (int) m_vInputPins.size())
00157         {
00158                 //Return the input pin
00159                 return m_vInputPins[n];
00160         }
00161         else
00162         {
00163                 return m_vOutputPins[n - m_vInputPins.size() ];
00164         }
00165 }
00166 
00167 STDMETHODIMP CMultiIOBaseFilter::FindPin( LPCWSTR Id, IPin **ppPin )
00168 {
00169         //Find pin according to it's name
00170         CheckPointer(ppPin,E_POINTER);
00171         ValidateReadWritePtr(ppPin,sizeof(IPin *));
00172         //Todo: Modify for this MUX: Check what ids this method is called with
00173 
00174         //Parse Id and get string number
00175         USES_CONVERSION;
00176         char* szInput = W2A(Id);
00177         char szTemp[10];
00178         ZeroMemory(szTemp, 10);
00179         memcpy(szTemp, szInput, 5);
00180         szTemp[5] = '\0';
00181         if (strcmp(szTemp, "Input")== 0)
00182         {
00183                 char* szID = szInput + 6;
00184                 int nId = atoi(szID);
00185                 *ppPin = GetPin(nId);
00186         }
00187         else if (0==strcmp(szTemp, "Outpu")) 
00188         {
00189                 char* szID = szInput + 7;
00190                 int nId = atoi(szID);
00191                 *ppPin = GetPin(m_vInputPins.size() + nId);
00192         } 
00193         else 
00194         {
00195                 *ppPin = NULL;
00196                 return VFW_E_NOT_FOUND;
00197         }
00198 
00199         HRESULT hr = NOERROR;
00200         //  AddRef() returned pointer - but GetPin could fail if memory is low.
00201         if (*ppPin) 
00202         {
00203                 (*ppPin)->AddRef();
00204         } 
00205         else 
00206         {
00207                 hr = E_OUTOFMEMORY;  // probably.  There's no pin anyway.
00208         }
00209         return hr;
00210 }
00211 
00212 void CMultiIOBaseFilter::CreateInputPin()
00213 {
00214         HRESULT hr;
00215         USES_CONVERSION;
00216         char buffer[10] = "Input ";
00217         itoa(m_vInputPins.size(), buffer + 6, 10);
00218         CMultiIOInputPin* pInputPin = new CMultiIOInputPin(this, &m_csFilter, &hr, A2W(buffer), m_vInputPins.size());
00219         pInputPin->AddRef();
00220         m_vInputPins.push_back(pInputPin);
00221         // ensure enumerator is refreshed
00222         IncrementPinVersion();  
00223 }
00224 
00225 void CMultiIOBaseFilter::CreateOutputPin()
00226 {
00227         HRESULT hr;
00228         USES_CONVERSION;
00229         char buffer[10] = "Output ";
00230         itoa(m_vOutputPins.size(), buffer + 7, 10);
00231         CMultiIOOutputPin* pOutputPin = new CMultiIOOutputPin(this, &m_csFilter, &hr, A2W(buffer), m_vOutputPins.size());
00232         pOutputPin->AddRef();
00233         m_vOutputPins.push_back(pOutputPin);
00234         // ensure enumerator is refreshed
00235         IncrementPinVersion();  
00236 }
00237 
00238 HRESULT CMultiIOBaseFilter::CheckInputType( const CMediaType *pMediaType )
00239 {
00240         //RG 8/01/2008
00241         //Changing this to check all input types
00242         return FindMediaTypeInLists(pMediaType, &m_vInputTypes, m_mInputTypeMap);
00243 }
00244 
00245 HRESULT CMultiIOBaseFilter::FindMediaTypeInLists(const CMediaType* pMediaType, MEDIA_TYPE_LIST* pTypeList, MEDIA_TYPE_MAP& typeMap)
00246 {
00247         // Search for media type in global list
00248         HRESULT hr = FindMediaType(pMediaType, pTypeList);
00249         if (SUCCEEDED(hr))
00250         {
00251                 return hr;
00252         }
00253 
00254         //We haven't found it: Iterate over all pins own media types
00255         MEDIA_TYPE_MAP_ITERATOR it;
00256         for ( it = typeMap.begin(); it != typeMap.end(); it++)
00257         {
00258                 MEDIA_TYPE_LIST* pTypeList = (*it).second;
00259                 HRESULT hr = FindMediaType(pMediaType, pTypeList);
00260                 if (SUCCEEDED(hr))
00261                 {
00262                         return hr;
00263                 }
00264         }
00265         // We didn't find the type anywhere
00266         return VFW_E_TYPE_NOT_ACCEPTED;
00267 }
00268 
00269 void CMultiIOBaseFilter::OnConnect( int nIndex, RTVC_DIRECTION eDirection )
00270 {
00271         switch (eDirection)
00272         {
00273         case RTVC_IN:
00274                 {
00275                         // if this is the last one, make a new one: taken from Geraint's Mpeg Parser
00276                         if (OnFullCreateMoreInputs())
00277                         {
00278                                 if (nIndex == (int)(m_vInputPins.size()-1))
00279                                 {
00280                                         CreateInputPin();
00281                                 }
00282                         }
00283                         break;
00284                 }
00285         case RTVC_OUT:
00286                 {
00287                         // if this is the last one, make a new one: taken from Geraint's Mpeg Parser
00288                         if (OnFullCreateMoreOutputs())
00289                         {
00290                                 if (nIndex == (int)(m_vOutputPins.size()-1))
00291                                 {
00292                                         CreateOutputPin();
00293                                 }
00294                         }
00295                         break;
00296                 }
00297         }
00298 }
00299 
00300 void CMultiIOBaseFilter::OnDisconnect( int nIndex )
00301 {
00302         if (OnFullCreateMoreInputs())
00303         {
00304                 // if index is the last but one, and
00305                 // the last one is still unconnected, then
00306                 // remove the last one
00307                 if ((nIndex == (int)(m_vInputPins.size() - 2)) &&
00308                         (!m_vInputPins[m_vInputPins.size()-1]->IsConnected()))
00309                 {
00310                         // Now make sure that we can't disconnect more than the initial number of inputs
00311                         // You cannot remove a pin to have less pins than you started with
00312                         if (m_vInputPins.size() > InitialNumberOfInputPins())
00313                         {
00314                                 m_vInputPins[m_vInputPins.size()-1]->Release();
00315                                 m_vInputPins.pop_back();
00316                                 // refresh enumerator
00317                                 IncrementPinVersion();
00318                         }
00319                 }
00320         }
00321 }
00322 
00323 
00324 int CMultiIOBaseFilter::InitialNumberOfInputPins()
00325 {
00326         return 1;
00327 }
00328 
00329 int CMultiIOBaseFilter::InitialNumberOfOutputPins()
00330 {
00331         return 1;
00332 }
00333 
00334 bool CMultiIOBaseFilter::OnFullCreateMoreInputs()
00335 {
00336         return false;
00337 }
00338 
00339 bool CMultiIOBaseFilter::OnFullCreateMoreOutputs()
00340 {
00341         return false;
00342 }
00343 
00345 // Output pin stuff
00346 HRESULT CMultiIOBaseFilter::CheckOutputType( const CMediaType* pMediaType )
00347 {
00348         return FindMediaTypeInLists(pMediaType, &m_vOutputTypes, m_mOutputTypeMap);
00349 }
00350 
00364 HRESULT CMultiIOBaseFilter::InitializeOutputSample( IMediaSample *pSample, IMediaSample **ppOutSample, int nInputIndex, int nOutputIndex )
00365 {
00366         AM_SAMPLE2_PROPERTIES * const pProperties = m_vInputPins[nInputIndex]->SampleProps();
00367 
00368         IMediaSample *pOutSample;
00369         //Let's get rid of the const
00370 
00371         AM_SAMPLE2_PROPERTIES* pProps = (AM_SAMPLE2_PROPERTIES*)pProperties;
00372         // default - times are the same
00373         DWORD dwFlags = 0;
00374         // This will prevent the image renderer from switching us to DirectDraw
00375         // when we can't do it without skipping frames because we're not on a
00376         // keyframe.  If it really has to switch us, it still will, but then we
00377         // will have to wait for the next keyframe
00378         if (!(pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) {
00379                 dwFlags |= AM_GBF_NOTASYNCPOINT;
00380         }
00381 
00382         ASSERT(m_vOutputPins[nOutputIndex]->GetAllocator() != NULL);
00383         HRESULT hr = m_vOutputPins[nOutputIndex]->GetAllocator()->GetBuffer(
00384                 &pOutSample
00385                 , pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID ?
00386                 &pProps->tStart : NULL
00387                 , pProps->dwSampleFlags & AM_SAMPLE_STOPVALID ?
00388                 &pProps->tStop : NULL
00389                 , dwFlags
00390                 );
00391         *ppOutSample = pOutSample;
00392         if (FAILED(hr)) {
00393                 return hr;
00394         }
00395 
00396         ASSERT(pOutSample);
00397         IMediaSample2 *pOutSample2;
00398         if (SUCCEEDED(pOutSample->QueryInterface(IID_IMediaSample2,
00399                 (void **)&pOutSample2))) {
00400                         /*  Modify it */
00401                         AM_SAMPLE2_PROPERTIES OutProps;
00402                         EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties(
00403                                 FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps)
00404                                 ));
00405                         OutProps.dwTypeSpecificFlags = pProps->dwTypeSpecificFlags;
00406                         OutProps.dwSampleFlags =
00407                                 (OutProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) |
00408                                 (pProps->dwSampleFlags & ~AM_SAMPLE_TYPECHANGED);
00409                         OutProps.tStart = pProps->tStart;
00410                         OutProps.tStop  = pProps->tStop;
00411                         OutProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId);
00412                         hr = pOutSample2->SetProperties(
00413                                 FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId),
00414                                 (PBYTE)&OutProps
00415                                 );
00416                         pOutSample2->Release();
00417         } else {
00418                 if (pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) {
00419                         pOutSample->SetTime(&pProps->tStart,
00420                                 &pProps->tStop);
00421                 }
00422                 if (pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT) {
00423                         pOutSample->SetSyncPoint(TRUE);
00424                 }
00425                 if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
00426                         pOutSample->SetDiscontinuity(TRUE);
00427                 }
00428                 // Copy the media times
00429 
00430                 LONGLONG MediaStart, MediaEnd;
00431                 if (pSample->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) {
00432                         pOutSample->SetMediaTime(&MediaStart,&MediaEnd);
00433                 }
00434         }
00435         return S_OK;
00436 }
00437 
00438 HRESULT CMultiIOBaseFilter::SetMediaType( PIN_DIRECTION direction,const CMediaType *pmt, int nIndex )
00439 {
00440         UNREFERENCED_PARAMETER(direction);
00441         UNREFERENCED_PARAMETER(pmt);
00442         //Grip a copy of the media type
00443         if (direction == PINDIR_INPUT)
00444         {
00445                 m_mMediaTypes[nIndex] = *pmt;
00446         }
00447         // Check if pin at position accepts the input type
00448         //First iterate over all common media types
00449         HRESULT hr = FindMediaType(pmt, &m_vInputTypes);
00450         if (SUCCEEDED(hr))
00451         {
00452                 return hr;
00453         }
00454 
00455         //We haven't found it: Iterate over pins own media types
00456         MEDIA_TYPE_MAP_ITERATOR it;
00457         it = m_mInputTypeMap.find(nIndex);
00458         if (it == m_mInputTypeMap.end())
00459         {
00460                 //We couldn't find it, reject the connection
00461                 return E_FAIL;
00462         }
00463         else
00464         {
00465                 MEDIA_TYPE_LIST* pInputTypeList = (*it).second;
00466                 HRESULT hr = FindMediaType(pmt, pInputTypeList);
00467                 return hr;
00468         }
00469 }
00470 
00471 HRESULT CMultiIOBaseFilter::FindMediaType(const CMediaType* pmt, MEDIA_TYPE_LIST* pInputTypeList)
00472 {
00473         for (int i = 0; i < pInputTypeList->size(); i++)
00474         {
00475                 //Compare major type
00476                 const GUID* pType = (pInputTypeList->at(i))->MediaType;
00477                 if ((!pType)||((pmt->majortype == *pType) && (pType)))
00478                 {
00479                         //Compare sub type
00480                         const GUID* pSubtype = (pInputTypeList->at(i))->MediaSubtype;
00481                         if ((!pSubtype) || ((pmt->subtype == *pSubtype) && (pSubtype)))
00482                         {
00483                                 //Compare formats
00484                                 const GUID* pFormat = (pInputTypeList->at(i))->Format;
00485                                 if ((!pFormat) || ((pmt->formattype == *pFormat)&&(pFormat)))
00486                                 {
00487                                         return NOERROR;
00488                                 }
00489                         }
00490                 }
00491         }
00492         return E_FAIL;
00493 }
00494 
00495 // Basic implementation -> Just here for override purposes
00496 STDMETHODIMP CMultiIOBaseFilter::EndOfStream( int nIndex )
00497 {
00498         return S_OK;
00499 }
00500 
00501 STDMETHODIMP CMultiIOBaseFilter::BeginFlush( int nIndex )
00502 {
00503         return S_OK;
00504 }
00505 
00506 STDMETHODIMP CMultiIOBaseFilter::EndFlush( int nIndex )
00507 {
00508         return S_OK;
00509 }
00510 
00511 STDMETHODIMP CMultiIOBaseFilter::NewSegment( REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate, int nIndex )
00512 {
00513         return S_OK;
00514 }

Generated on Fri Mar 13 14:12:38 2009 for RTVC by  doxygen 1.5.3