home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / transip.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-20  |  11.9 KB  |  418 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11.  
  12. // Base class for simple Transform-In-Place filters such as audio
  13.  
  14. #include <streams.h>
  15. #include <measure.h>
  16. #include <transip.h>
  17.  
  18.  
  19. // =================================================================
  20. // Implements the CTransInPlaceFilter class
  21. // =================================================================
  22.  
  23. CTransInPlaceFilter::CTransInPlaceFilter
  24.    ( TCHAR     *pName,
  25.      LPUNKNOWN  pUnk,
  26.      CLSID      clsid,
  27.      HRESULT   *phr
  28.    )
  29.    : CTransformFilter(pName, pUnk, clsid, phr)
  30. {
  31.     ASSERT(phr);
  32. #ifdef PERF
  33.     RegisterPerfId();
  34. #endif //  PERF
  35. }
  36.  
  37.  
  38. // return a non-addrefed CBasePin * for the user to addref if he holds onto it
  39. // for longer than his pointer to us. We create the pins dynamically when they
  40. // are asked for rather than in the constructor. This is because we want to
  41. // give the derived class an oppportunity to return different pin objects
  42.  
  43. // As soon as any pin is needed we create both (this is different from the
  44. // usual transform filter) because enumerators, allocators etc are passed
  45. // through from one pin to another and it becomes very painful if the other
  46. // pin isn't there.
  47.  
  48. CBasePin *
  49. CTransInPlaceFilter::GetPin(int n)
  50. {
  51.     HRESULT hr = S_OK;
  52.  
  53.     // Create an input pin if not already done
  54.  
  55.     if (m_pInput == NULL) {
  56.  
  57.         m_pInput = new CTransInPlaceInputPin( NAME("TransInPlace input pin")
  58.                                             , this        // Owner filter
  59.                                             , &hr         // Result code
  60.                                             , L"Input"    // Pin name
  61.                                             );
  62.  
  63.         // a failed return code should delete the object
  64.  
  65.         if (FAILED(hr) || m_pInput == NULL) {
  66.             delete m_pInput;
  67.             m_pInput = NULL;
  68.         }
  69.     }
  70.  
  71.     // Create an output pin if not already done
  72.  
  73.     if (m_pOutput == NULL) {
  74.  
  75.         m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin")
  76.                                               , this       // Owner filter
  77.                                               , &hr        // Result code
  78.                                               , L"Output"  // Pin name
  79.                                               );
  80.  
  81.         // a failed return code should delete the object
  82.  
  83.         if (FAILED(hr) || m_pOutput == NULL) {
  84.             delete m_pOutput;
  85.             m_pOutput = NULL;
  86.         }
  87.     }
  88.  
  89.     // Return the appropriate pin
  90.  
  91.     ASSERT (n>=0 && n<=1);
  92.     if (n == 0) {
  93.         return m_pInput;
  94.     } else if (n==1) {
  95.         return m_pOutput;
  96.     } else {
  97.         return NULL;
  98.     }
  99. }
  100.  
  101.  
  102.  
  103. HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin)
  104. {
  105.     ASSERT(m_pInput);
  106.     ASSERT(m_pOutput);
  107.  
  108.     // if we are not part of a graph, then don't indirect the pointer
  109.     // this probably prevents use of the filter without a filtergraph
  110.     if (!m_pGraph) {
  111.         return VFW_E_NOT_IN_GRAPH;
  112.     }
  113.  
  114.     // Always reconnect the input to account for buffering changes
  115.  
  116.     if (dir == PINDIR_OUTPUT) {
  117.         if( m_pInput->IsConnected() ) {
  118.             return m_pGraph->Reconnect( m_pInput );
  119.         }
  120.         return NOERROR;
  121.     }
  122.  
  123.     ASSERT(dir == PINDIR_INPUT);
  124.  
  125.     // Reconnect output if necessary
  126.  
  127.     if( m_pOutput->IsConnected() ) {
  128.  
  129.         if (  m_pInput->CurrentMediaType()
  130.            != m_pOutput->CurrentMediaType()
  131.            ) {
  132.             return m_pGraph->Reconnect( m_pOutput );
  133.         }
  134.     }
  135.     return NOERROR;
  136. }
  137.  
  138. // override this to customize the transform process
  139.  
  140. HRESULT
  141. CTransInPlaceFilter::Receive(IMediaSample *pSample)
  142. {
  143.     HRESULT hr;
  144.  
  145.     // Start timing the TransInPlace (if PERF is defined)
  146.     MSR_START(m_idTransInPlace);
  147.  
  148.     // have the derived class transform the data
  149.     hr = Transform(pSample);
  150.  
  151.     // Stop the clock and log it (if PERF is defined)
  152.     MSR_STOP(m_idTransInPlace);
  153.  
  154.     if (FAILED(hr)) {
  155.         DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace")));
  156.         return hr;
  157.     }
  158.  
  159.     // the Transform() function can return S_FALSE to indicate that the
  160.     // sample should not be delivered; we only deliver the sample if it's
  161.     // really S_OK (same as NOERROR, of course.)
  162.     if (hr == NOERROR) {
  163.         hr = m_pOutput->Deliver(pSample);
  164.     } else {
  165.         //  But it would be an error to return this private hack
  166.         //  to the caller ...
  167.         if (S_FALSE == hr) {
  168.             hr = NOERROR;
  169.         }
  170.     }
  171.  
  172.     return hr;
  173. }
  174.  
  175.  
  176.  
  177. // =================================================================
  178. // Implements the CTransInPlaceInputPin class
  179. // =================================================================
  180.  
  181.  
  182. // constructor
  183.  
  184. CTransInPlaceInputPin::CTransInPlaceInputPin
  185.     ( TCHAR               *pObjectName
  186.     , CTransInPlaceFilter *pFilter
  187.     , HRESULT             *phr
  188.     , LPCWSTR              pName
  189.     )
  190.     : CTransformInputPin(pObjectName,
  191.                          pFilter,
  192.                          phr,
  193.                          pName)
  194. {
  195.     DbgLog((LOG_TRACE, 2
  196.            , TEXT("CTransInPlaceInputPin::CTransInPlaceInputPin")));
  197.     m_pTIPFilter = pFilter;
  198. }
  199.  
  200.  
  201. // =================================================================
  202. // Implements IMemInputPin interface
  203. // =================================================================
  204.  
  205.  
  206. STDMETHODIMP CTransInPlaceInputPin::GetAllocator(IMemAllocator ** ppAllocator)
  207. {
  208.     CheckPointer(ppAllocator,E_POINTER);
  209.     ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));
  210.     CAutoLock cObjectLock(m_pLock);
  211.  
  212.     // See if we've already got an allocator
  213.     if (m_pAllocator != NULL) {
  214.         *ppAllocator = m_pAllocator;
  215.         m_pAllocator->AddRef();
  216.         return S_OK;
  217.     }
  218.  
  219.     // We don't actually provide an allocator but the downstream filter's
  220.     // input pin may...
  221.     if(  m_pTIPFilter->m_pOutput->IsConnected() ){
  222.         IMemInputPin *pIMemInputPin;
  223.  
  224.         HRESULT hr = m_pTIPFilter->m_pOutput->GetConnected()
  225.                      ->QueryInterface( IID_IMemInputPin, (void **) &pIMemInputPin );
  226.  
  227.         if( SUCCEEDED( hr ) ){
  228.  
  229.             hr = pIMemInputPin->GetAllocator( ppAllocator );
  230.             pIMemInputPin->Release();
  231.  
  232.             if( SUCCEEDED( hr ) ){
  233.                 // Should be addref'd downstream
  234.                 return hr;
  235.             }
  236.         }
  237.     }
  238.  
  239.     return VFW_E_NO_ALLOCATOR;
  240. }
  241.  
  242.  
  243.  
  244. /* Get told which allocator the upstream output pin is actually going to use */
  245.  
  246. STDMETHODIMP
  247. CTransInPlaceInputPin::NotifyAllocator(
  248.     IMemAllocator * pAllocator,
  249.     BOOL bReadOnly)
  250. {
  251.     CheckPointer(pAllocator,E_POINTER);
  252.     ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
  253.  
  254.     if (bReadOnly) {
  255.         // we are an in-place transform.  We scribble on the buffer.
  256.         // We therefore cannot accept a read only buffer.
  257.         return VFW_E_READ_ONLY;
  258.     }
  259.  
  260.     CAutoLock cObjectLock(m_pLock);
  261.  
  262.     // It's possible that the old and the new are the same thing.
  263.     // AddRef before release ensures that we don't unload the damn thing!
  264.     pAllocator->AddRef();
  265.  
  266.     if( m_pAllocator != NULL )
  267.         m_pAllocator->Release();
  268.  
  269.     m_pAllocator = pAllocator;
  270.  
  271.     // Tell our own output pin as we're all on the same one
  272.     // (That's what Transform In Place means)
  273.     m_pTIPFilter->OutputPin()->NotifyAllocator(pAllocator, bReadOnly);
  274.     return NOERROR;
  275. }
  276.  
  277.  
  278. // EnumMediaTypes
  279. // - pass through to our downstream filter
  280. STDMETHODIMP CTransInPlaceInputPin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
  281. {
  282.     // Can only pass through if connected
  283.     if( !m_pTIPFilter->m_pOutput->IsConnected() )
  284.         return VFW_E_NOT_CONNECTED;
  285.  
  286.     return m_pTIPFilter->m_pOutput->GetConnected()->EnumMediaTypes( ppEnum );
  287. }
  288.  
  289.  
  290. // CheckMediaType
  291. // - agree to anything if not connected,
  292. // otherwise pass through to the downstream filter.
  293. // This assumes that the filter does not change the media type.
  294.  
  295. HRESULT CTransInPlaceInputPin::CheckMediaType(const CMediaType *pmt )
  296. {
  297.     HRESULT hr = m_pTIPFilter->CheckInputType(pmt);
  298.     if (hr!=S_OK) return hr;
  299.  
  300.     if( m_pTIPFilter->m_pOutput->IsConnected() )
  301.         return m_pTIPFilter->m_pOutput->GetConnected()->QueryAccept( pmt );
  302.     else
  303.         return S_OK;
  304. }
  305.  
  306.  
  307. // =================================================================
  308. // Implements the CTransInPlaceOutputPin class
  309. // =================================================================
  310.  
  311.  
  312. // constructor
  313.  
  314. CTransInPlaceOutputPin::CTransInPlaceOutputPin(
  315.     TCHAR *pObjectName,
  316.     CTransInPlaceFilter *pFilter,
  317.     HRESULT * phr,
  318.     LPCWSTR pPinName)
  319.     : CTransformOutputPin( pObjectName
  320.                          , pFilter
  321.                          , phr
  322.                          , pPinName)
  323. {
  324.     DbgLog(( LOG_TRACE, 2
  325.            , TEXT("CTransInPlaceOutputPin::CTransInPlaceOutputPin")));
  326.     m_pTIPFilter = pFilter;
  327.  
  328. }
  329.  
  330.  
  331. // EnumMediaTypes
  332. // - pass through to our upstream filter
  333. STDMETHODIMP CTransInPlaceOutputPin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
  334. {
  335.     // Can only pass through if connected.
  336.     if( ! m_pTIPFilter->m_pInput->IsConnected() )
  337.         return VFW_E_NOT_CONNECTED;
  338.  
  339.     return m_pTIPFilter->m_pInput->GetConnected()->EnumMediaTypes( ppEnum );
  340. }
  341.  
  342.  
  343.  
  344. // CheckMediaType
  345. // - agree to anything if not connected,
  346. // otherwise pass through to the upstream filter.
  347.  
  348. HRESULT CTransInPlaceOutputPin::CheckMediaType(const CMediaType *pmt )
  349. {
  350.  
  351.     // Assumes the type does not change.  That's why we're calling
  352.     // CheckINPUTType here on the OUTPUT pin.
  353.     HRESULT hr = m_pTIPFilter->CheckInputType(pmt);
  354.     if (hr!=S_OK) return hr;
  355.  
  356.     if( m_pTIPFilter->m_pInput->IsConnected() )
  357.         return m_pTIPFilter->m_pInput->GetConnected()->QueryAccept( pmt );
  358.     else
  359.         return S_OK;
  360. }
  361.  
  362.  
  363. /* Decide on an allocator, override this if you want to use your own allocator
  364.    Override DecideBufferSize to call SetProperties. If the input pin fails
  365.    the GetAllocator call then this will construct a CMemAllocator and call
  366.    DecideBufferSize on that, and if that fails then we are completely hosed.
  367.    If the you succeed the DecideBufferSize call, we will notify the input
  368.    pin of the selected allocator. NOTE this is called during Connect() which
  369.    therefore looks after grabbing and locking the object's critical section */
  370.  
  371. HRESULT
  372. CTransInPlaceOutputPin::DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc)
  373. {
  374.     HRESULT hr = NOERROR;
  375.  
  376.     /* Don't even try any new allocators
  377.        We are using the one we already have from our own input pin */
  378.  
  379.     hr = m_pTIPFilter->m_pInput->GetAllocator( &m_pAllocator );
  380.  
  381.     if(FAILED(hr))
  382.         return hr;
  383.  
  384.     ASSERT( m_pAllocator != NULL );
  385.  
  386.     *ppAlloc = m_pAllocator;  // The one our own input pin found
  387.  
  388.     // Tell the downstream input pin
  389.     return pPin->NotifyAllocator(*ppAlloc, FALSE);
  390. }
  391.  
  392.  
  393.  
  394. /* Get told which allocator the output pin is actually going to use */
  395.  
  396. // !!! need to fix up read-only etc.
  397.  
  398. STDMETHODIMP
  399. CTransInPlaceOutputPin::NotifyAllocator(
  400.     IMemAllocator * pAllocator,
  401.     BOOL bReadOnly)
  402. {
  403.     CheckPointer(pAllocator,E_POINTER);
  404.     ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
  405.  
  406.     // It's possible that the old and the new are the same thing.
  407.     // AddRef before release ensures that we don't unload the damn thing!
  408.     pAllocator->AddRef();
  409.  
  410.     if( m_pAllocator != NULL )
  411.         m_pAllocator->Release();
  412.  
  413.     m_pAllocator = pAllocator;
  414.  
  415.     return NOERROR;
  416. }
  417.  
  418.