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
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
00060 CleanupTypeMap(m_mInputTypeMap);
00061
00062 CleanupTypeMap(m_mOutputTypeMap);
00063
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
00080 MEDIA_TYPE_LIST* pInputList = (*it).second;
00081
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
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
00125 typeList.push_back(pMediaType);
00126 }
00127 else
00128 {
00129
00130 MEDIA_TYPE_MAP_ITERATOR it;
00131 it = typeMap.find(nPin);
00132 if (it == m_mInputTypeMap.end())
00133 {
00134
00135 typeMap[nPin] = new MEDIA_TYPE_LIST;
00136 typeMap[nPin]->push_back(pMediaType);
00137 }
00138 else
00139 {
00140
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
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
00170 CheckPointer(ppPin,E_POINTER);
00171 ValidateReadWritePtr(ppPin,sizeof(IPin *));
00172
00173
00174
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
00201 if (*ppPin)
00202 {
00203 (*ppPin)->AddRef();
00204 }
00205 else
00206 {
00207 hr = E_OUTOFMEMORY;
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
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
00235 IncrementPinVersion();
00236 }
00237
00238 HRESULT CMultiIOBaseFilter::CheckInputType( const CMediaType *pMediaType )
00239 {
00240
00241
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
00248 HRESULT hr = FindMediaType(pMediaType, pTypeList);
00249 if (SUCCEEDED(hr))
00250 {
00251 return hr;
00252 }
00253
00254
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
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
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
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
00305
00306
00307 if ((nIndex == (int)(m_vInputPins.size() - 2)) &&
00308 (!m_vInputPins[m_vInputPins.size()-1]->IsConnected()))
00309 {
00310
00311
00312 if (m_vInputPins.size() > InitialNumberOfInputPins())
00313 {
00314 m_vInputPins[m_vInputPins.size()-1]->Release();
00315 m_vInputPins.pop_back();
00316
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
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
00370
00371 AM_SAMPLE2_PROPERTIES* pProps = (AM_SAMPLE2_PROPERTIES*)pProperties;
00372
00373 DWORD dwFlags = 0;
00374
00375
00376
00377
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
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
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
00443 if (direction == PINDIR_INPUT)
00444 {
00445 m_mMediaTypes[nIndex] = *pmt;
00446 }
00447
00448
00449 HRESULT hr = FindMediaType(pmt, &m_vInputTypes);
00450 if (SUCCEEDED(hr))
00451 {
00452 return hr;
00453 }
00454
00455
00456 MEDIA_TYPE_MAP_ITERATOR it;
00457 it = m_mInputTypeMap.find(nIndex);
00458 if (it == m_mInputTypeMap.end())
00459 {
00460
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
00476 const GUID* pType = (pInputTypeList->at(i))->MediaType;
00477 if ((!pType)||((pmt->majortype == *pType) && (pType)))
00478 {
00479
00480 const GUID* pSubtype = (pInputTypeList->at(i))->MediaSubtype;
00481 if ((!pSubtype) || ((pmt->subtype == *pSubtype) && (pSubtype)))
00482 {
00483
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
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 }