Tee.cpp

Go to the documentation of this file.
00001 
00034 #include "stdafx.h"
00035 
00036 // STL
00037 #include <cassert>
00038 
00039 // Meraka includes
00040 #include "Tee.h"
00041 
00042 CRtvcTee::CRtvcTee() 
00043         :CMultiIOBaseFilter(NAME("Meraka RTVC Tee Filter"), 0, CLSID_RtvcTee)
00044 {
00045         //Hack virtual method of subclass can't be called from base class contructor, hence must be called in child contructor
00046         Initialise();
00047 }
00048 
00049 CRtvcTee::~CRtvcTee()
00050 {;}
00051 
00052 CUnknown * WINAPI CRtvcTee::CreateInstance( LPUNKNOWN pUnk, HRESULT *pHr )
00053 {
00054         CRtvcTee *pFilter = new CRtvcTee();
00055         if (pFilter== NULL) 
00056         {
00057                 *pHr = E_OUTOFMEMORY;
00058         }
00059         return pFilter;
00060 }
00061 
00062 HRESULT CRtvcTee::Receive( IMediaSample *pSample, int nIndex )
00063 {
00064         ASSERT(nIndex >= 0);
00065         ASSERT (nIndex < m_vInputPins.size());
00066         ASSERT(pSample);
00067 
00068         HRESULT hr;
00069         if (nIndex == 0)
00070         {
00071                 //We have a live stream - display it
00072                 CAutoLock lck(&m_csReceive);
00073                 AM_SAMPLE2_PROPERTIES * const pProps = m_vInputPins[0]->SampleProps();
00074                 if (pProps->dwStreamId != AM_STREAM_MEDIA) {
00075                         return m_vInputPins[0]->Receive(pSample);
00076                 }
00077 
00078                 // Copy the input sample to all outputs
00079                 for (size_t i = 0;  i < m_vOutputPins.size(); i++)
00080                 {
00081                         if (m_vOutputPins[i]->IsConnected())
00082                         {
00083                                 IMediaSample * pOutSample;
00084                                 // Set up the output sample
00085                                 hr = InitializeOutputSample(pSample, &pOutSample, nIndex, i);
00086 
00087                                 if (FAILED(hr)) {
00088                                         return hr;
00089                                 }
00090 
00091                                 // Start timing the transform (if PERF is defined)
00092                                 MSR_START(m_idTransform);
00093 
00094                                 // Get pointers to the underlying buffers.
00095                                 BYTE *pBufferIn  = NULL;
00096                                 BYTE *pBufferOut = NULL;
00097 
00098                                 if (pSample)
00099                                 {
00100                                         HRESULT hr = pSample->GetPointer(&pBufferIn);
00101                                         if (FAILED(hr))
00102                                         {
00103                                                 return hr;
00104                                         }
00105                                 }
00106 
00107                                 if (pOutSample)
00108                                 {
00109                                         HRESULT hr = pOutSample->GetPointer(&pBufferOut);
00110                                         if (FAILED(hr))
00111                                         {
00112                                                 return hr;
00113                                         }
00114                                 }
00115 
00116                                 // Process the data.
00117                                 int nSize = pSample->GetActualDataLength();
00118                                 memcpy(pBufferOut, pBufferIn, nSize);
00119 
00120                                 pOutSample->SetActualDataLength(nSize);
00121                                 pOutSample->SetSyncPoint(TRUE);
00122 
00123                                 // Stop the clock and log it (if PERF is defined)
00124                                 MSR_STOP(m_idTransform);
00125 
00126                                 if (FAILED(hr)) {
00127                                         DbgLog((LOG_TRACE,1,TEXT("Error from transform")));
00128                                 } 
00129                                 else 
00130                                 {
00131                                         // the Transform() function can return S_FALSE to indicate that the
00132                                         // sample should not be delivered; we only deliver the sample if it's
00133                                         // really S_OK (same as NOERROR, of course.)
00134                                         if (hr == NOERROR) 
00135                                         {
00136                                                 hr = m_vOutputPins[i]->Deliver(pOutSample);
00137                                                 //m_bSampleSkipped = FALSE;     // last thing no longer dropped
00138                                         } 
00139                                         else 
00140                                         {
00141                                                 // S_FALSE returned from Transform is a PRIVATE agreement
00142                                                 // We should return NOERROR from Receive() in this cause because returning S_FALSE
00143                                                 // from Receive() means that this is the end of the stream and no more data should
00144                                                 // be sent.
00145                                                 if (S_FALSE == hr) 
00146                                                 {
00147                                                         //  Release the sample before calling notify to avoid
00148                                                         //  deadlocks if the sample holds a lock on the system
00149                                                         //  such as DirectDraw buffers do
00150                                                         pOutSample->Release();
00151                                                         /*m_bSampleSkipped = TRUE;
00152                                                         if (!m_bQualityChanged) {
00153                                                         NotifyEvent(EC_QUALITY_CHANGE,0,0);
00154                                                         m_bQualityChanged = TRUE;
00155                                                         }*/
00156                                                         return NOERROR;
00157                                                 }
00158                                         }
00159                                 }
00160                                 // release the output buffer. If the connected pin still needs it,
00161                                 // it will have addrefed it itself.
00162                                 pOutSample->Release();
00163                         }
00164                 }
00165                 return hr;
00166         }
00167         else
00168         {
00169                 // There are only two possible indexes for this multiplexer
00170                 return E_INVALIDARG;
00171         }
00172 }
00173 
00174 void CRtvcTee::InitialiseInputTypes()
00175 {
00176         AddInputType(NULL, NULL, NULL);
00177 }
00178 
00179 void CRtvcTee::InitialiseOutputTypes()
00180 {
00181         AddOutputType(NULL, NULL, NULL);
00182 }
00183 
00184 HRESULT CRtvcTee::DecideBufferSize( IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pRequestProperties, int m_nIndex )
00185 {
00186         // Get media type of the output pin
00187         AM_MEDIA_TYPE mt;
00188         HRESULT hr = m_vInputPins[0]->ConnectionMediaType(&mt);
00189         if (FAILED(hr))
00190         {
00191                 return hr;
00192         } 
00193 
00194         // This simple tee will only cater for the following types
00195         assert(mt.formattype == FORMAT_VideoInfo || mt.formattype == FORMAT_WaveFormatEx);
00196         if(mt.formattype == FORMAT_VideoInfo)
00197         {
00198                 BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
00199                 pRequestProperties->cbBuffer = DIBSIZE(*pbmi);
00200         }
00201         else if (mt.formattype == FORMAT_WaveFormatEx)
00202         {
00203                 WAVEFORMATEX *pWavHeader = (WAVEFORMATEX*)mt.pbFormat;
00204                 pRequestProperties->cbBuffer = pWavHeader->nSamplesPerSec * pWavHeader->nChannels * (pWavHeader->wBitsPerSample >> 3);
00205         }
00206 
00207         if (pRequestProperties->cbAlign == 0)
00208         {
00209                 pRequestProperties->cbAlign = 1;
00210         }
00211         if (pRequestProperties->cBuffers == 0)
00212         {
00213                 pRequestProperties->cBuffers = 1;
00214         }
00215         // Release the format block.
00216         FreeMediaType(mt);
00217 
00218         // Set allocator properties.
00219         ALLOCATOR_PROPERTIES Actual;
00220         hr = pAlloc->SetProperties(pRequestProperties, &Actual);
00221         if (FAILED(hr)) 
00222         {
00223                 return hr;
00224         }
00225         // Even when it succeeds, check the actual result.
00226         if (pRequestProperties->cbBuffer > Actual.cbBuffer) 
00227         {
00228                 return E_FAIL;
00229         }
00230         return S_OK;
00231 }
00232 
00233 HRESULT CRtvcTee::GetMediaType( int iPosition, CMediaType* pMediaType, int nOutputPinIndex )
00234 {
00235         if (iPosition < 0)
00236         {
00237                 return E_INVALIDARG;
00238         }
00239         else if (iPosition == 0)
00240         {
00241                 return m_vInputPins[0]->ConnectionMediaType(pMediaType);
00242         }
00243         return VFW_S_NO_MORE_ITEMS;
00244 }
00245 
00246 HRESULT CRtvcTee::CheckOutputType( const CMediaType* pMediaType )
00247 {
00248         AM_MEDIA_TYPE mediaType;
00249         HRESULT hr = m_vInputPins[0]->ConnectionMediaType(&mediaType);
00250         if ((*pMediaType->Type() == mediaType.majortype) &&
00251                 (*pMediaType->Subtype() == mediaType.subtype) &&
00252                 (*pMediaType->FormatType() == mediaType.formattype)
00253                 )
00254         {
00255                 return S_OK;
00256         }
00257         else
00258         {
00259                 return VFW_E_TYPE_NOT_ACCEPTED;
00260         }
00261 }

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