00001
00002
00003
00004
00005
00006 #include <streams.h>
00007 #include <measure.h>
00008 #include <transip.h>
00009
00010 CTransInPlaceFilter::CTransInPlaceFilter
00011 ( TCHAR *pName,
00012 LPUNKNOWN pUnk,
00013 REFCLSID clsid,
00014 HRESULT *phr,
00015 bool bModifiesData
00016 )
00017 : CTransformFilter(pName, pUnk, clsid),
00018 m_bModifiesData(bModifiesData)
00019 {
00020 #ifdef PERF
00021 RegisterPerfId();
00022 #endif
00023
00024 }
00025
00026 #ifdef UNICODE
00027 CTransInPlaceFilter::CTransInPlaceFilter
00028 ( CHAR *pName,
00029 LPUNKNOWN pUnk,
00030 REFCLSID clsid,
00031 HRESULT *phr,
00032 bool bModifiesData
00033 )
00034 : CTransformFilter(pName, pUnk, clsid),
00035 m_bModifiesData(bModifiesData)
00036 {
00037 #ifdef PERF
00038 RegisterPerfId();
00039 #endif
00040
00041 }
00042 #endif
00043
00044 CBasePin *
00045 CTransInPlaceFilter::GetPin(int n)
00046 {
00047 HRESULT hr = S_OK;
00048
00049
00050
00051 if (m_pInput == NULL) {
00052
00053 m_pInput = new CTransInPlaceInputPin( NAME("TransInPlace input pin")
00054 , this
00055 , &hr
00056 , L"Input"
00057 );
00058
00059
00060 ASSERT(SUCCEEDED(hr));
00061 }
00062
00063
00064
00065 if (m_pInput!=NULL && m_pOutput == NULL) {
00066
00067 m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin")
00068 , this
00069 , &hr
00070 , L"Output"
00071 );
00072
00073
00074
00075 ASSERT(SUCCEEDED(hr));
00076 if (m_pOutput == NULL) {
00077 delete m_pInput;
00078 m_pInput = NULL;
00079 }
00080 }
00081
00082
00083
00084 ASSERT (n>=0 && n<=1);
00085 if (n == 0) {
00086 return m_pInput;
00087 } else if (n==1) {
00088 return m_pOutput;
00089 } else {
00090 return NULL;
00091 }
00092
00093 }
00094
00095 HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin)
00096 {
00097 UNREFERENCED_PARAMETER(pReceivePin);
00098 ASSERT(m_pInput);
00099 ASSERT(m_pOutput);
00100
00101
00102
00103 if (!m_pGraph) {
00104 return VFW_E_NOT_IN_GRAPH;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 if (dir == PINDIR_OUTPUT) {
00118 if( m_pInput->IsConnected() ) {
00119 return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() );
00120 }
00121 return NOERROR;
00122 }
00123
00124 ASSERT(dir == PINDIR_INPUT);
00125
00126
00127
00128 if( m_pOutput->IsConnected() ) {
00129
00130 if ( m_pInput->CurrentMediaType()
00131 != m_pOutput->CurrentMediaType()
00132 ) {
00133 return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() );
00134 }
00135 }
00136 return NOERROR;
00137
00138 }
00139
00140 HRESULT CTransInPlaceFilter::DecideBufferSize
00141 ( IMemAllocator *pAlloc
00142 , ALLOCATOR_PROPERTIES *pProperties
00143 )
00144 {
00145 ALLOCATOR_PROPERTIES Request, Actual;
00146 HRESULT hr;
00147
00148
00149 if (m_pInput->IsConnected()) {
00150
00151
00152
00153 hr = InputPin()->PeekAllocator()->GetProperties(&Request);
00154 if (FAILED(hr)) {
00155
00156 return hr;
00157 }
00158 } else {
00159
00160
00161
00162 ZeroMemory(&Request, sizeof(Request));
00163 Request.cBuffers = 1;
00164 Request.cbBuffer = 1;
00165 }
00166
00167 DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements")));
00168 DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"),
00169 Request.cBuffers, Request.cbBuffer));
00170
00171
00172
00173
00174
00175 pProperties->cBuffers = Request.cBuffers;
00176 pProperties->cbBuffer = Request.cbBuffer;
00177 if (pProperties->cBuffers<=0) {pProperties->cBuffers = 1; }
00178 if (pProperties->cbBuffer<=0) {pProperties->cbBuffer = 1; }
00179 hr = pAlloc->SetProperties(pProperties, &Actual);
00180
00181 if (FAILED(hr)) {
00182 return hr;
00183 }
00184
00185 DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements")));
00186 DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"),
00187 Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign));
00188
00189
00190
00191 if ( (Request.cBuffers > Actual.cBuffers)
00192 || (Request.cbBuffer > Actual.cbBuffer)
00193 || (Request.cbAlign > Actual.cbAlign)
00194 ) {
00195 return E_FAIL;
00196 }
00197 return NOERROR;
00198
00199 }
00200
00201 IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource)
00202 {
00203 IMediaSample * pDest;
00204
00205 HRESULT hr;
00206 REFERENCE_TIME tStart, tStop;
00207 const BOOL bTime = S_OK == pSource->GetTime( &tStart, &tStop);
00208
00209
00210 hr = OutputPin()->PeekAllocator()->GetBuffer(
00211 &pDest
00212 , bTime ? &tStart : NULL
00213 , bTime ? &tStop : NULL
00214 , m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0
00215 );
00216
00217 if (FAILED(hr)) {
00218 return NULL;
00219 }
00220
00221 ASSERT(pDest);
00222 IMediaSample2 *pSample2;
00223 if (SUCCEEDED(pDest->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) {
00224 HRESULT hr = pSample2->SetProperties(
00225 FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer),
00226 (PBYTE)m_pInput->SampleProps());
00227 pSample2->Release();
00228 if (FAILED(hr)) {
00229 pDest->Release();
00230 return NULL;
00231 }
00232 } else {
00233 if (bTime) {
00234 pDest->SetTime(&tStart, &tStop);
00235 }
00236
00237 if (S_OK == pSource->IsSyncPoint()) {
00238 pDest->SetSyncPoint(TRUE);
00239 }
00240 if (S_OK == pSource->IsDiscontinuity() || m_bSampleSkipped) {
00241 pDest->SetDiscontinuity(TRUE);
00242 }
00243 if (S_OK == pSource->IsPreroll()) {
00244 pDest->SetPreroll(TRUE);
00245 }
00246
00247
00248 AM_MEDIA_TYPE *pMediaType;
00249 if (S_OK == pSource->GetMediaType(&pMediaType)) {
00250 pDest->SetMediaType(pMediaType);
00251 DeleteMediaType( pMediaType );
00252 }
00253
00254 }
00255
00256 m_bSampleSkipped = FALSE;
00257
00258
00259 REFERENCE_TIME TimeStart, TimeEnd;
00260 if (pSource->GetMediaTime(&TimeStart,&TimeEnd) == NOERROR) {
00261 pDest->SetMediaTime(&TimeStart,&TimeEnd);
00262 }
00263
00264
00265 {
00266 const long lDataLength = pSource->GetActualDataLength();
00267 pDest->SetActualDataLength(lDataLength);
00268
00269
00270 {
00271 BYTE *pSourceBuffer, *pDestBuffer;
00272 long lSourceSize = pSource->GetSize();
00273 long lDestSize = pDest->GetSize();
00274
00275 ASSERT(lDestSize >= lSourceSize && lDestSize >= lDataLength);
00276
00277 pSource->GetPointer(&pSourceBuffer);
00278 pDest->GetPointer(&pDestBuffer);
00279 ASSERT(lDestSize == 0 || pSourceBuffer != NULL && pDestBuffer != NULL);
00280
00281 CopyMemory( (PVOID) pDestBuffer, (PVOID) pSourceBuffer, lDataLength );
00282 }
00283 }
00284
00285 return pDest;
00286
00287 }
00288
00289 HRESULT
00290 CTransInPlaceFilter::Receive(IMediaSample *pSample)
00291 {
00292
00293 AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
00294 if (pProps->dwStreamId != AM_STREAM_MEDIA) {
00295 return m_pOutput->Deliver(pSample);
00296 }
00297 HRESULT hr;
00298
00299
00300 MSR_START(m_idTransInPlace);
00301
00302 if (UsingDifferentAllocators()) {
00303
00304
00305
00306 pSample = Copy(pSample);
00307
00308 if (pSample==NULL) {
00309 MSR_STOP(m_idTransInPlace);
00310 return E_UNEXPECTED;
00311 }
00312 }
00313
00314
00315 hr = Transform(pSample);
00316
00317
00318 MSR_STOP(m_idTransInPlace);
00319
00320 if (FAILED(hr)) {
00321 DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace")));
00322 if (UsingDifferentAllocators()) {
00323 pSample->Release();
00324 }
00325 return hr;
00326 }
00327
00328
00329
00330
00331 if (hr == NOERROR) {
00332 hr = m_pOutput->Deliver(pSample);
00333 } else {
00334
00335
00336 if (S_FALSE == hr) {
00337
00338
00339
00340
00341 m_bSampleSkipped = TRUE;
00342 if (!m_bQualityChanged) {
00343 NotifyEvent(EC_QUALITY_CHANGE,0,0);
00344 m_bQualityChanged = TRUE;
00345 }
00346 hr = NOERROR;
00347 }
00348 }
00349
00350
00351
00352 if (UsingDifferentAllocators()) {
00353 pSample->Release();
00354 }
00355
00356 return hr;
00357
00358 }
00359
00360 CTransInPlaceInputPin::CTransInPlaceInputPin
00361 ( TCHAR *pObjectName
00362 , CTransInPlaceFilter *pFilter
00363 , HRESULT *phr
00364 , LPCWSTR pName
00365 )
00366 : CTransformInputPin(pObjectName,
00367 pFilter,
00368 phr,
00369 pName)
00370 , m_bReadOnly(FALSE)
00371 , m_pTIPFilter(pFilter)
00372 {
00373 DbgLog((LOG_TRACE, 2
00374 , TEXT("CTransInPlaceInputPin::CTransInPlaceInputPin")));
00375
00376 }
00377
00378 STDMETHODIMP CTransInPlaceInputPin::GetAllocator(IMemAllocator ** ppAllocator)
00379 {
00380 CheckPointer(ppAllocator,E_POINTER);
00381 ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));
00382 CAutoLock cObjectLock(m_pLock);
00383
00384 HRESULT hr;
00385
00386 if ( m_pTIPFilter->m_pOutput->IsConnected() ) {
00387
00388 hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
00389 ->GetAllocator( ppAllocator );
00390 if (SUCCEEDED(hr)) {
00391 m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator );
00392 }
00393 }
00394 else {
00395
00396
00397
00398
00399 hr = CTransformInputPin::GetAllocator( ppAllocator );
00400 }
00401 return hr;
00402
00403 }
00404
00405 STDMETHODIMP
00406 CTransInPlaceInputPin::NotifyAllocator(
00407 IMemAllocator * pAllocator,
00408 BOOL bReadOnly)
00409 {
00410 HRESULT hr;
00411 CheckPointer(pAllocator,E_POINTER);
00412 ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
00413
00414 CAutoLock cObjectLock(m_pLock);
00415
00416 m_bReadOnly = bReadOnly;
00417
00418
00419
00420
00421
00422
00423 if (!m_pTIPFilter->OutputPin()->IsConnected()) {
00424 return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly);
00425 }
00426
00427
00428
00429
00430 if (bReadOnly && m_pTIPFilter->m_bModifiesData) {
00431 IMemAllocator *pOutputAllocator =
00432 m_pTIPFilter->OutputPin()->PeekAllocator();
00433
00434
00435 if (pOutputAllocator == NULL) {
00436 hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()->
00437 GetAllocator(&pOutputAllocator);
00438 if (SUCCEEDED(hr)) {
00439 m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator);
00440 pOutputAllocator->Release();
00441 }
00442 }
00443 if (pAllocator == pOutputAllocator) {
00444 hr = E_FAIL;
00445 } else {
00446
00447 ALLOCATOR_PROPERTIES Props, Actual;
00448 hr = pAllocator->GetProperties(&Props);
00449 if (SUCCEEDED(hr)) {
00450 hr = pOutputAllocator->SetProperties(&Props, &Actual);
00451 }
00452 if (SUCCEEDED(hr)) {
00453 if ( (Props.cBuffers > Actual.cBuffers)
00454 || (Props.cbBuffer > Actual.cbBuffer)
00455 || (Props.cbAlign > Actual.cbAlign)
00456 ) {
00457 hr = E_FAIL;
00458 }
00459 }
00460
00461
00462 if (SUCCEEDED(hr)) {
00463 hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
00464 ->NotifyAllocator( pOutputAllocator, FALSE );
00465 }
00466 }
00467 } else {
00468 hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
00469 ->NotifyAllocator( pAllocator, bReadOnly );
00470 if (SUCCEEDED(hr)) {
00471 m_pTIPFilter->OutputPin()->SetAllocator( pAllocator );
00472 }
00473 }
00474
00475 if (SUCCEEDED(hr)) {
00476
00477
00478
00479 pAllocator->AddRef();
00480
00481 if( m_pAllocator != NULL )
00482 m_pAllocator->Release();
00483
00484 m_pAllocator = pAllocator;
00485 }
00486
00487 return hr;
00488
00489 }
00490
00491 STDMETHODIMP CTransInPlaceInputPin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
00492 {
00493
00494 if( !m_pTIPFilter->m_pOutput->IsConnected() )
00495 return VFW_E_NOT_CONNECTED;
00496
00497 return m_pTIPFilter->m_pOutput->GetConnected()->EnumMediaTypes( ppEnum );
00498
00499 }
00500
00501 HRESULT CTransInPlaceInputPin::CheckMediaType(const CMediaType *pmt )
00502 {
00503 HRESULT hr = m_pTIPFilter->CheckInputType(pmt);
00504 if (hr!=S_OK) return hr;
00505
00506 if( m_pTIPFilter->m_pOutput->IsConnected() )
00507 return m_pTIPFilter->m_pOutput->GetConnected()->QueryAccept( pmt );
00508 else
00509 return S_OK;
00510
00511 }
00512
00513 STDMETHODIMP
00514 CTransInPlaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
00515 {
00516
00517 if( m_pTIPFilter->m_pOutput->IsConnected() )
00518 return m_pTIPFilter->OutputPin()
00519 ->ConnectedIMemInputPin()->GetAllocatorRequirements( pProps );
00520 else
00521 return E_NOTIMPL;
00522
00523 }
00524
00525 CTransInPlaceOutputPin::CTransInPlaceOutputPin(
00526 TCHAR *pObjectName,
00527 CTransInPlaceFilter *pFilter,
00528 HRESULT * phr,
00529 LPCWSTR pPinName)
00530 : CTransformOutputPin( pObjectName
00531 , pFilter
00532 , phr
00533 , pPinName),
00534 m_pTIPFilter(pFilter)
00535 {
00536 DbgLog(( LOG_TRACE, 2
00537 , TEXT("CTransInPlaceOutputPin::CTransInPlaceOutputPin")));
00538
00539 }
00540
00541 STDMETHODIMP CTransInPlaceOutputPin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
00542 {
00543
00544 if( ! m_pTIPFilter->m_pInput->IsConnected() )
00545 return VFW_E_NOT_CONNECTED;
00546
00547 return m_pTIPFilter->m_pInput->GetConnected()->EnumMediaTypes( ppEnum );
00548
00549 }
00550
00551 HRESULT CTransInPlaceOutputPin::CheckMediaType(const CMediaType *pmt )
00552 {
00553
00554
00555
00556 if (m_pTIPFilter->UsingDifferentAllocators() && !m_pFilter->IsStopped()) {
00557 if (*pmt == m_mt) {
00558 return S_OK;
00559 } else {
00560 return VFW_E_TYPE_NOT_ACCEPTED;
00561 }
00562 }
00563
00564
00565
00566 HRESULT hr = m_pTIPFilter->CheckInputType(pmt);
00567 if (hr!=S_OK) return hr;
00568
00569 if( m_pTIPFilter->m_pInput->IsConnected() )
00570 return m_pTIPFilter->m_pInput->GetConnected()->QueryAccept( pmt );
00571 else
00572 return S_OK;
00573
00574 }
00575
00576 HRESULT
00577 CTransInPlaceOutputPin::DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc)
00578 {
00579
00580 return S_OK;
00581 }
00582
00583 void
00584 CTransInPlaceOutputPin::SetAllocator(IMemAllocator * pAllocator)
00585 {
00586 pAllocator->AddRef();
00587 if (m_pAllocator) {
00588 m_pAllocator->Release();
00589 }
00590 m_pAllocator = pAllocator;
00591 }