ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

output_pin.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
00004  * FILE:            dll/directx/ksproxy/output_pin.cpp
00005  * PURPOSE:         OutputPin of Proxy Filter
00006  *
00007  * PROGRAMMERS:     Johannes Anderwald (janderwald@reactos.org)
00008  */
00009 #include "precomp.h"
00010 
00011 class COutputPin : public IPin,
00012                    public IKsObject,
00013                    public IKsPropertySet,
00014                    public IStreamBuilder,
00015                    public IKsPinFactory,
00016                    public ISpecifyPropertyPages,
00017                    public IKsPinEx,
00018                    public IKsPinPipe,
00019                    public IKsControl,
00020                    public IKsAggregateControl,
00021                    public IQualityControl,
00022                    public IMediaSeeking,
00023                    public IAMBufferNegotiation,
00024                    public IAMStreamConfig,
00025                    public IMemAllocatorNotifyCallbackTemp
00026 
00027 {
00028 public:
00029     typedef std::vector<IUnknown *>ProxyPluginVector;
00030 
00031     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00032 
00033     STDMETHODIMP_(ULONG) AddRef()
00034     {
00035         InterlockedIncrement(&m_Ref);
00036         return m_Ref;
00037     }
00038     STDMETHODIMP_(ULONG) Release()
00039     {
00040         InterlockedDecrement(&m_Ref);
00041         if (!m_Ref)
00042         {
00043             //delete this;
00044             return 0;
00045         }
00046         return m_Ref;
00047     }
00048 
00049     //IKsPin
00050     HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
00051     HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
00052     HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
00053     HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
00054     HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
00055     HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
00056     HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
00057     IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
00058     HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
00059     HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
00060     LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
00061     LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
00062     HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
00063     // IKsPinEx
00064     VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
00065 
00066     //IKsPinPipe
00067     HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
00068     HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
00069     IPin* STDMETHODCALLTYPE KsGetConnectedPin();
00070     IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
00071     HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
00072     ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
00073     HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
00074     GUID STDMETHODCALLTYPE KsGetPinBusCache();
00075     HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
00076     PWCHAR STDMETHODCALLTYPE KsGetPinName();
00077     PWCHAR STDMETHODCALLTYPE KsGetFilterName();
00078 
00079     //IPin methods
00080     HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
00081     HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
00082     HRESULT STDMETHODCALLTYPE Disconnect();
00083     HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
00084     HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
00085     HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
00086     HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
00087     HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
00088     HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
00089     HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
00090     HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
00091     HRESULT STDMETHODCALLTYPE EndOfStream();
00092     HRESULT STDMETHODCALLTYPE BeginFlush();
00093     HRESULT STDMETHODCALLTYPE EndFlush();
00094     HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
00095 
00096     // ISpecifyPropertyPages
00097     HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
00098 
00099     //IKsObject methods
00100     HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
00101 
00102     //IKsPropertySet
00103     HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
00104     HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
00105     HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
00106 
00107     //IKsControl
00108     HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
00109     HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
00110     HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
00111 
00112     //IStreamBuilder
00113     HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
00114     HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
00115 
00116     //IKsPinFactory
00117     HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
00118 
00119     //IKsAggregateControl
00120     HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
00121     HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
00122 
00123     //IQualityControl
00124     HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q);
00125     HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
00126 
00127     //IMediaSeeking
00128     HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
00129     HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
00130     HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
00131     HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
00132     HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
00133     HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
00134     HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
00135     HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
00136     HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
00137     HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
00138     HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
00139     HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
00140     HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
00141     HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
00142     HRESULT STDMETHODCALLTYPE SetRate(double dRate);
00143     HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
00144     HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
00145 
00146     //IAMBufferNegotiation
00147     HRESULT STDMETHODCALLTYPE SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop);
00148     HRESULT STDMETHODCALLTYPE GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop);
00149 
00150     //IAMStreamConfig
00151     HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt);
00152     HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt);
00153     HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize);
00154     HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC);
00155 
00156     //IMemAllocatorNotifyCallbackTemp
00157     HRESULT STDMETHODCALLTYPE NotifyRelease();
00158 
00159     //---------------------------------------------------------------
00160     COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication);
00161     virtual ~COutputPin();
00162     HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
00163     HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
00164     HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
00165     HRESULT WINAPI IoProcessRoutine();
00166     HRESULT WINAPI InitializeIOThread();
00167     HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
00168     HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
00169 
00170     friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter);
00171     friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State);
00172 
00173 protected:
00174     LONG m_Ref;
00175     IBaseFilter * m_ParentFilter;
00176     LPCWSTR m_PinName;
00177     HANDLE m_hPin;
00178     ULONG m_PinId;
00179     IPin * m_Pin;
00180     IKsAllocatorEx * m_KsAllocatorEx;
00181     ULONG m_PipeAllocatorFlag;
00182     BOOL m_bPinBusCacheInitialized;
00183     GUID m_PinBusCache;
00184     LPWSTR m_FilterName;
00185     FRAMING_PROP m_FramingProp[4];
00186     PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
00187 
00188     IMemAllocator * m_MemAllocator;
00189     IMemInputPin * m_MemInputPin;
00190     LONG m_IoCount;
00191     KSPIN_COMMUNICATION m_Communication;
00192     KSPIN_INTERFACE m_Interface;
00193     KSPIN_MEDIUM m_Medium;
00194     AM_MEDIA_TYPE m_MediaFormat;
00195     ALLOCATOR_PROPERTIES m_Properties;
00196     IKsInterfaceHandler * m_InterfaceHandler;
00197 
00198     HANDLE m_hStartEvent;
00199     HANDLE m_hBufferAvailable;
00200     HANDLE m_hStopEvent;
00201     BOOL m_StopInProgress;
00202     BOOL m_IoThreadStarted;
00203 
00204     KSSTATE m_State;
00205     CRITICAL_SECTION m_Lock;
00206 
00207     ProxyPluginVector m_Plugins;
00208 };
00209 
00210 COutputPin::~COutputPin()
00211 {
00212 }
00213 
00214 COutputPin::COutputPin(
00215     IBaseFilter * ParentFilter,
00216     LPCWSTR PinName,
00217     ULONG PinId,
00218     KSPIN_COMMUNICATION Communication) : m_Ref(0),
00219                                          m_ParentFilter(ParentFilter),
00220                                          m_PinName(PinName),
00221                                          m_hPin(INVALID_HANDLE_VALUE),
00222                                          m_PinId(PinId),
00223                                          m_Pin(0),
00224                                          m_KsAllocatorEx(0),
00225                                          m_PipeAllocatorFlag(0),
00226                                          m_bPinBusCacheInitialized(0),
00227                                          m_FilterName(0),
00228                                          m_MemAllocator(0),
00229                                          m_MemInputPin(0),
00230                                          m_IoCount(0),
00231                                          m_Communication(Communication),
00232                                          m_InterfaceHandler(0),
00233                                          m_hStartEvent(0),
00234                                          m_hBufferAvailable(0),
00235                                          m_hStopEvent(0),
00236                                          m_StopInProgress(0),
00237                                          m_IoThreadStarted(0),
00238                                          m_State(KSSTATE_STOP),
00239                                          m_Plugins()
00240 {
00241     HRESULT hr;
00242     IKsObject * KsObjectParent;
00243 
00244     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
00245     assert(hr == S_OK);
00246 
00247     ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
00248     ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
00249     ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE));
00250 
00251     hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId);
00252 
00253 #ifdef KSPROXY_TRACE
00254     WCHAR Buffer[100];
00255     swprintf(Buffer, L"COutputPin::COutputPin Format %p pbFormat %lu\n", &m_MediaFormat, m_MediaFormat.cbFormat);
00256     OutputDebugStringW(Buffer);
00257 #endif
00258 
00259     assert(hr == S_OK);
00260 
00261     InitializeCriticalSection(&m_Lock);
00262 
00263     KsObjectParent->Release();
00264 };
00265 
00266 HRESULT
00267 STDMETHODCALLTYPE
00268 COutputPin::QueryInterface(
00269     IN  REFIID refiid,
00270     OUT PVOID* Output)
00271 {
00272     *Output = NULL;
00273     if (IsEqualGUID(refiid, IID_IUnknown) ||
00274         IsEqualGUID(refiid, IID_IPin))
00275     {
00276 #ifdef KSPROXY_TRACE
00277         OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n");
00278 #endif
00279         *Output = PVOID(this);
00280         reinterpret_cast<IUnknown*>(*Output)->AddRef();
00281         return NOERROR;
00282     }
00283     else if (IsEqualGUID(refiid, IID_IKsObject))
00284     {
00285         if (m_hPin == INVALID_HANDLE_VALUE)
00286         {
00287             HRESULT hr = CreatePin(&m_MediaFormat);
00288             if (FAILED(hr))
00289                 return hr;
00290         }
00291 #ifdef KSPROXY_TRACE
00292         OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
00293 #endif
00294         *Output = (IKsObject*)(this);
00295         reinterpret_cast<IKsObject*>(*Output)->AddRef();
00296         return NOERROR;
00297     }
00298     else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx))
00299     {
00300         *Output = (IKsPinEx*)(this);
00301         reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
00302         return NOERROR;
00303     }
00304     else if (IsEqualGUID(refiid, IID_IKsPinPipe))
00305     {
00306         *Output = (IKsPinPipe*)(this);
00307         reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
00308         return NOERROR;
00309     }
00310     else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
00311     {
00312         *Output = (IKsAggregateControl*)(this);
00313         reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
00314         return NOERROR;
00315     }
00316     else if (IsEqualGUID(refiid, IID_IQualityControl))
00317     {
00318         *Output = (IQualityControl*)(this);
00319         reinterpret_cast<IQualityControl*>(*Output)->AddRef();
00320         return NOERROR;
00321     }
00322     else if (IsEqualGUID(refiid, IID_IKsPropertySet))
00323     {
00324         if (m_hPin == INVALID_HANDLE_VALUE)
00325         {
00326             HRESULT hr = CreatePin(&m_MediaFormat);
00327             if (FAILED(hr))
00328                 return hr;
00329         }
00330 #ifdef KSPROXY_TRACE
00331         OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
00332 #endif
00333         *Output = (IKsPropertySet*)(this);
00334         reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
00335         return NOERROR;
00336     }
00337     else if (IsEqualGUID(refiid, IID_IKsControl))
00338     {
00339 #ifdef KSPROXY_TRACE
00340         OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");
00341 #endif
00342         *Output = (IKsControl*)(this);
00343         reinterpret_cast<IKsControl*>(*Output)->AddRef();
00344         return NOERROR;
00345     }
00346 #if 0
00347     else if (IsEqualGUID(refiid, IID_IStreamBuilder))
00348     {
00349         *Output = (IStreamBuilder*)(this);
00350         reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
00351         return NOERROR;
00352     }
00353 #endif
00354     else if (IsEqualGUID(refiid, IID_IKsPinFactory))
00355     {
00356 #ifdef KSPROXY_TRACE
00357         OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");
00358 #endif
00359         *Output = (IKsPinFactory*)(this);
00360         reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
00361         return NOERROR;
00362     }
00363     else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
00364     {
00365 #ifdef KSPROXY_TRACE
00366         OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");
00367 #endif
00368         *Output = (ISpecifyPropertyPages*)(this);
00369         reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
00370         return NOERROR;
00371     }
00372     else if (IsEqualGUID(refiid, IID_IMediaSeeking))
00373     {
00374         *Output = (IMediaSeeking*)(this);
00375         reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
00376         return NOERROR;
00377     }
00378     else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation))
00379     {
00380         *Output = (IAMBufferNegotiation*)(this);
00381         reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef();
00382         return NOERROR;
00383     }
00384     else if (IsEqualGUID(refiid, IID_IAMStreamConfig))
00385     {
00386         *Output = (IAMStreamConfig*)(this);
00387         reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef();
00388         return NOERROR;
00389     }
00390     else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp))
00391     {
00392         *Output = (IMemAllocatorNotifyCallbackTemp*)(this);
00393         reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef();
00394         return NOERROR;
00395     }
00396 
00397 #ifdef KSPROXY_TRACE
00398     WCHAR Buffer[MAX_PATH];
00399     LPOLESTR lpstr;
00400     StringFromCLSID(refiid, &lpstr);
00401     swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName);
00402     OutputDebugStringW(Buffer);
00403     CoTaskMemFree(lpstr);
00404 #endif
00405 
00406     return E_NOINTERFACE;
00407 }
00408 
00409 //-------------------------------------------------------------------
00410 // IAMBufferNegotiation interface
00411 //
00412 HRESULT
00413 STDMETHODCALLTYPE
00414 COutputPin::SuggestAllocatorProperties(
00415     const ALLOCATOR_PROPERTIES *pprop)
00416 {
00417 #ifdef KSPROXY_TRACE
00418     OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n");
00419 #endif
00420 
00421     if (m_Pin)
00422     {
00423         // pin is already connected
00424         return VFW_E_ALREADY_CONNECTED;
00425     }
00426 
00427     CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES));
00428     return NOERROR;
00429 }
00430 
00431 HRESULT
00432 STDMETHODCALLTYPE
00433 COutputPin::GetAllocatorProperties(
00434     ALLOCATOR_PROPERTIES *pprop)
00435 {
00436 #ifdef KSPROXY_TRACE
00437     OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n");
00438 #endif
00439 
00440     if (!m_Pin)
00441     {
00442         // you should call this method AFTER you connected
00443         return E_UNEXPECTED;
00444     }
00445 
00446     if (!m_KsAllocatorEx)
00447     {
00448         // something went wrong while creating the allocator
00449         return E_FAIL;
00450     }
00451 
00452     CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES));
00453     return NOERROR;
00454 }
00455 
00456 //-------------------------------------------------------------------
00457 // IAMStreamConfig interface
00458 //
00459 HRESULT
00460 STDMETHODCALLTYPE
00461 COutputPin::SetFormat(
00462     AM_MEDIA_TYPE *pmt)
00463 {
00464 #ifdef KSPROXY_TRACE
00465     OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n");
00466 #endif
00467     return E_NOTIMPL;
00468 }
00469 
00470 HRESULT
00471 STDMETHODCALLTYPE
00472 COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt)
00473 {
00474 #ifdef KSPROXY_TRACE
00475     OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n");
00476 #endif
00477     return E_NOTIMPL;
00478 }
00479 
00480 HRESULT
00481 STDMETHODCALLTYPE
00482 COutputPin::GetNumberOfCapabilities(
00483     int *piCount,
00484     int *piSize)
00485 {
00486 #ifdef KSPROXY_TRACE
00487     OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n");
00488 #endif
00489     return E_NOTIMPL;
00490 }
00491 
00492 HRESULT
00493 STDMETHODCALLTYPE
00494 COutputPin::GetStreamCaps(
00495     int iIndex,
00496     AM_MEDIA_TYPE **ppmt,
00497     BYTE *pSCC)
00498 {
00499 #ifdef KSPROXY_TRACE
00500     OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n");
00501 #endif
00502     return E_NOTIMPL;
00503 }
00504 
00505 //-------------------------------------------------------------------
00506 // IMemAllocatorNotifyCallbackTemp interface
00507 //
00508 HRESULT
00509 STDMETHODCALLTYPE
00510 COutputPin::NotifyRelease()
00511 {
00512 #ifdef KSPROXY_TRACE
00513     OutputDebugStringW(L"COutputPin::NotifyRelease\n");
00514 #endif
00515 
00516     // notify thread of new available sample
00517     SetEvent(m_hBufferAvailable);
00518 
00519     return NOERROR;
00520 }
00521 
00522 //-------------------------------------------------------------------
00523 // IMediaSeeking interface
00524 //
00525 HRESULT
00526 STDMETHODCALLTYPE
00527 COutputPin::GetCapabilities(
00528     DWORD *pCapabilities)
00529 {
00530     IMediaSeeking * FilterMediaSeeking;
00531     HRESULT hr;
00532 
00533     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00534     if (FAILED(hr))
00535         return hr;
00536 
00537     hr = FilterMediaSeeking->GetCapabilities(pCapabilities);
00538 
00539     FilterMediaSeeking->Release();
00540     return hr;
00541 }
00542 
00543 HRESULT
00544 STDMETHODCALLTYPE
00545 COutputPin::CheckCapabilities(
00546     DWORD *pCapabilities)
00547 {
00548     IMediaSeeking * FilterMediaSeeking;
00549     HRESULT hr;
00550 
00551     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00552     if (FAILED(hr))
00553         return hr;
00554 
00555     hr = FilterMediaSeeking->CheckCapabilities(pCapabilities);
00556 
00557     FilterMediaSeeking->Release();
00558     return hr;
00559 }
00560 
00561 HRESULT
00562 STDMETHODCALLTYPE
00563 COutputPin::IsFormatSupported(
00564     const GUID *pFormat)
00565 {
00566     IMediaSeeking * FilterMediaSeeking;
00567     HRESULT hr;
00568 
00569     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00570     if (FAILED(hr))
00571         return hr;
00572 
00573     hr = FilterMediaSeeking->IsFormatSupported(pFormat);
00574 
00575     FilterMediaSeeking->Release();
00576     return hr;
00577 }
00578 
00579 HRESULT
00580 STDMETHODCALLTYPE
00581 COutputPin::QueryPreferredFormat(
00582     GUID *pFormat)
00583 {
00584     IMediaSeeking * FilterMediaSeeking;
00585     HRESULT hr;
00586 
00587     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00588     if (FAILED(hr))
00589         return hr;
00590 
00591     hr = FilterMediaSeeking->QueryPreferredFormat(pFormat);
00592 
00593     FilterMediaSeeking->Release();
00594     return hr;
00595 }
00596 
00597 HRESULT
00598 STDMETHODCALLTYPE
00599 COutputPin::GetTimeFormat(
00600     GUID *pFormat)
00601 {
00602     IMediaSeeking * FilterMediaSeeking;
00603     HRESULT hr;
00604 
00605     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00606     if (FAILED(hr))
00607         return hr;
00608 
00609     hr = FilterMediaSeeking->GetTimeFormat(pFormat);
00610 
00611     FilterMediaSeeking->Release();
00612     return hr;
00613 }
00614 
00615 HRESULT
00616 STDMETHODCALLTYPE
00617 COutputPin::IsUsingTimeFormat(
00618     const GUID *pFormat)
00619 {
00620     IMediaSeeking * FilterMediaSeeking;
00621     HRESULT hr;
00622 
00623     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00624     if (FAILED(hr))
00625         return hr;
00626 
00627     hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat);
00628 
00629     FilterMediaSeeking->Release();
00630     return hr;
00631 }
00632 
00633 HRESULT
00634 STDMETHODCALLTYPE
00635 COutputPin::SetTimeFormat(
00636     const GUID *pFormat)
00637 {
00638     IMediaSeeking * FilterMediaSeeking;
00639     HRESULT hr;
00640 
00641     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00642     if (FAILED(hr))
00643         return hr;
00644 
00645     hr = FilterMediaSeeking->SetTimeFormat(pFormat);
00646 
00647     FilterMediaSeeking->Release();
00648     return hr;
00649 }
00650 
00651 HRESULT
00652 STDMETHODCALLTYPE
00653 COutputPin::GetDuration(
00654     LONGLONG *pDuration)
00655 {
00656     IMediaSeeking * FilterMediaSeeking;
00657     HRESULT hr;
00658 
00659     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00660     if (FAILED(hr))
00661         return hr;
00662 
00663     hr = FilterMediaSeeking->GetDuration(pDuration);
00664 
00665     FilterMediaSeeking->Release();
00666     return hr;
00667 }
00668 
00669 HRESULT
00670 STDMETHODCALLTYPE
00671 COutputPin::GetStopPosition(
00672     LONGLONG *pStop)
00673 {
00674     IMediaSeeking * FilterMediaSeeking;
00675     HRESULT hr;
00676 
00677     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00678     if (FAILED(hr))
00679         return hr;
00680 
00681     hr = FilterMediaSeeking->GetStopPosition(pStop);
00682 
00683     FilterMediaSeeking->Release();
00684     return hr;
00685 }
00686 
00687 
00688 HRESULT
00689 STDMETHODCALLTYPE
00690 COutputPin::GetCurrentPosition(
00691     LONGLONG *pCurrent)
00692 {
00693     IMediaSeeking * FilterMediaSeeking;
00694     HRESULT hr;
00695 
00696     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00697     if (FAILED(hr))
00698         return hr;
00699 
00700     hr = FilterMediaSeeking->GetCurrentPosition(pCurrent);
00701 
00702     FilterMediaSeeking->Release();
00703     return hr;
00704 }
00705 
00706 HRESULT
00707 STDMETHODCALLTYPE
00708 COutputPin::ConvertTimeFormat(
00709     LONGLONG *pTarget,
00710     const GUID *pTargetFormat,
00711     LONGLONG Source,
00712     const GUID *pSourceFormat)
00713 {
00714     IMediaSeeking * FilterMediaSeeking;
00715     HRESULT hr;
00716 
00717     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00718     if (FAILED(hr))
00719         return hr;
00720 
00721     hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
00722 
00723     FilterMediaSeeking->Release();
00724     return hr;
00725 }
00726 
00727 HRESULT
00728 STDMETHODCALLTYPE
00729 COutputPin::SetPositions(
00730     LONGLONG *pCurrent,
00731     DWORD dwCurrentFlags,
00732     LONGLONG *pStop,
00733     DWORD dwStopFlags)
00734 {
00735     IMediaSeeking * FilterMediaSeeking;
00736     HRESULT hr;
00737 
00738     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00739     if (FAILED(hr))
00740         return hr;
00741 
00742     hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
00743 
00744     FilterMediaSeeking->Release();
00745     return hr;
00746 }
00747 
00748 HRESULT
00749 STDMETHODCALLTYPE
00750 COutputPin::GetPositions(
00751     LONGLONG *pCurrent,
00752     LONGLONG *pStop)
00753 {
00754     IMediaSeeking * FilterMediaSeeking;
00755     HRESULT hr;
00756 
00757     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00758     if (FAILED(hr))
00759         return hr;
00760 
00761     hr = FilterMediaSeeking->GetPositions(pCurrent, pStop);
00762 
00763     FilterMediaSeeking->Release();
00764     return hr;
00765 }
00766 
00767 HRESULT
00768 STDMETHODCALLTYPE
00769 COutputPin::GetAvailable(
00770     LONGLONG *pEarliest,
00771     LONGLONG *pLatest)
00772 {
00773     IMediaSeeking * FilterMediaSeeking;
00774     HRESULT hr;
00775 
00776     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00777     if (FAILED(hr))
00778         return hr;
00779 
00780     hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest);
00781 
00782     FilterMediaSeeking->Release();
00783     return hr;
00784 }
00785 
00786 HRESULT
00787 STDMETHODCALLTYPE
00788 COutputPin::SetRate(
00789     double dRate)
00790 {
00791     IMediaSeeking * FilterMediaSeeking;
00792     HRESULT hr;
00793 
00794     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00795     if (FAILED(hr))
00796         return hr;
00797 
00798     hr = FilterMediaSeeking->SetRate(dRate);
00799 
00800     FilterMediaSeeking->Release();
00801     return hr;
00802 }
00803 
00804 HRESULT
00805 STDMETHODCALLTYPE
00806 COutputPin::GetRate(
00807     double *pdRate)
00808 {
00809     IMediaSeeking * FilterMediaSeeking;
00810     HRESULT hr;
00811 
00812     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00813     if (FAILED(hr))
00814         return hr;
00815 
00816     hr = FilterMediaSeeking->GetRate(pdRate);
00817 
00818     FilterMediaSeeking->Release();
00819     return hr;
00820 }
00821 
00822 HRESULT
00823 STDMETHODCALLTYPE
00824 COutputPin::GetPreroll(
00825     LONGLONG *pllPreroll)
00826 {
00827     IMediaSeeking * FilterMediaSeeking;
00828     HRESULT hr;
00829 
00830     hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
00831     if (FAILED(hr))
00832         return hr;
00833 
00834     hr = FilterMediaSeeking->GetPreroll(pllPreroll);
00835 
00836     FilterMediaSeeking->Release();
00837     return hr;
00838 }
00839 
00840 //-------------------------------------------------------------------
00841 // IQualityControl interface
00842 //
00843 HRESULT
00844 STDMETHODCALLTYPE
00845 COutputPin::Notify(
00846     IBaseFilter *pSelf,
00847     Quality q)
00848 {
00849 #ifdef KSPROXY_TRACE
00850     OutputDebugStringW(L"COutputPin::Notify NotImplemented\n");
00851 #endif
00852     return E_NOTIMPL;
00853 }
00854 
00855 HRESULT
00856 STDMETHODCALLTYPE
00857 COutputPin::SetSink(
00858     IQualityControl *piqc)
00859 {
00860 #ifdef KSPROXY_TRACE
00861     OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n");
00862 #endif
00863     return E_NOTIMPL;
00864 }
00865 
00866 
00867 //-------------------------------------------------------------------
00868 // IKsAggregateControl interface
00869 //
00870 HRESULT
00871 STDMETHODCALLTYPE
00872 COutputPin::KsAddAggregate(
00873     IN REFGUID AggregateClass)
00874 {
00875 #ifdef KSPROXY_TRACE
00876     OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n");
00877 #endif
00878     return E_NOTIMPL;
00879 }
00880 
00881 HRESULT
00882 STDMETHODCALLTYPE
00883 COutputPin::KsRemoveAggregate(
00884     REFGUID AggregateClass)
00885 {
00886 #ifdef KSPROXY_TRACE
00887     OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n");
00888 #endif
00889     return E_NOTIMPL;
00890 }
00891 
00892 
00893 //-------------------------------------------------------------------
00894 // IKsPin
00895 //
00896 
00897 HRESULT
00898 STDMETHODCALLTYPE
00899 COutputPin::KsQueryMediums(
00900     PKSMULTIPLE_ITEM* MediumList)
00901 {
00902     HRESULT hr;
00903     HANDLE hFilter;
00904     IKsObject * KsObjectParent;
00905 
00906     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
00907     if (FAILED(hr))
00908         return E_NOINTERFACE;
00909 
00910     hFilter = KsObjectParent->KsGetObjectHandle();
00911 
00912     if (hFilter)
00913         hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
00914     else
00915         hr = E_HANDLE;
00916 
00917     KsObjectParent->Release();
00918 
00919     return hr;
00920 }
00921 
00922 HRESULT
00923 STDMETHODCALLTYPE
00924 COutputPin::KsQueryInterfaces(
00925     PKSMULTIPLE_ITEM* InterfaceList)
00926 {
00927     HRESULT hr;
00928     HANDLE hFilter;
00929     IKsObject * KsObjectParent;
00930 
00931     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
00932     if (FAILED(hr))
00933         return hr;
00934 
00935     hFilter = KsObjectParent->KsGetObjectHandle();
00936 
00937     if (hFilter)
00938         hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
00939     else
00940         hr = E_HANDLE;
00941 
00942     KsObjectParent->Release();
00943 
00944     return hr;
00945 }
00946 
00947 HRESULT
00948 STDMETHODCALLTYPE
00949 COutputPin::KsCreateSinkPinHandle(
00950     KSPIN_INTERFACE& Interface,
00951     KSPIN_MEDIUM& Medium)
00952 {
00953 #ifdef KSPROXY_TRACE
00954     OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n");
00955 #endif
00956     return E_NOTIMPL;
00957 }
00958 
00959 HRESULT
00960 STDMETHODCALLTYPE
00961 COutputPin::KsGetCurrentCommunication(
00962     KSPIN_COMMUNICATION *Communication,
00963     KSPIN_INTERFACE *Interface,
00964     KSPIN_MEDIUM *Medium)
00965 {
00966     if (Communication)
00967     {
00968         *Communication = m_Communication;
00969     }
00970 
00971     if (Interface)
00972     {
00973         if (!m_hPin)
00974             return VFW_E_NOT_CONNECTED;
00975 
00976         CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
00977     }
00978 
00979     if (Medium)
00980     {
00981         if (!m_hPin)
00982             return VFW_E_NOT_CONNECTED;
00983 
00984         CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
00985     }
00986     return NOERROR;
00987 }
00988 
00989 HRESULT
00990 STDMETHODCALLTYPE
00991 COutputPin::KsPropagateAcquire()
00992 {
00993     KSPROPERTY Property;
00994     KSSTATE State;
00995     ULONG BytesReturned;
00996     HRESULT hr;
00997 
00998 #ifdef KSPROXY_TRACE
00999     OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n");
01000 #endif
01001 
01002     assert(m_hPin != INVALID_HANDLE_VALUE);
01003 
01004     Property.Set = KSPROPSETID_Connection;
01005     Property.Id = KSPROPERTY_CONNECTION_STATE;
01006     Property.Flags = KSPROPERTY_TYPE_SET;
01007 
01008     State = KSSTATE_ACQUIRE;
01009 
01010     hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
01011     if (SUCCEEDED(hr))
01012     {
01013         m_State = State;
01014     }
01015 
01016     //TODO
01017     //propagate to connected pin on the pipe
01018 
01019     return hr;
01020 }
01021 
01022 HRESULT
01023 STDMETHODCALLTYPE
01024 COutputPin::KsDeliver(
01025     IMediaSample* Sample,
01026     ULONG Flags)
01027 {
01028     return E_FAIL;
01029 }
01030 
01031 HRESULT
01032 STDMETHODCALLTYPE
01033 COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
01034 {
01035     return NOERROR;
01036 }
01037 
01038 IMemAllocator *
01039 STDMETHODCALLTYPE
01040 COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
01041 {
01042     if (Operation == KsPeekOperation_AddRef)
01043     {
01044         // add reference on allocator
01045         m_MemAllocator->AddRef();
01046     }
01047 
01048     return m_MemAllocator;
01049 }
01050 
01051 HRESULT
01052 STDMETHODCALLTYPE
01053 COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
01054 {
01055     if (MemAllocator)
01056     {
01057         MemAllocator->AddRef();
01058     }
01059 
01060     if (m_MemAllocator)
01061     {
01062         m_MemAllocator->Release();
01063     }
01064 
01065     m_MemAllocator = MemAllocator;
01066     return NOERROR;
01067 }
01068 
01069 HRESULT
01070 STDMETHODCALLTYPE
01071 COutputPin::KsRenegotiateAllocator()
01072 {
01073     return E_FAIL;
01074 }
01075 
01076 LONG
01077 STDMETHODCALLTYPE
01078 COutputPin::KsIncrementPendingIoCount()
01079 {
01080     return InterlockedIncrement((volatile LONG*)&m_IoCount);
01081 }
01082 
01083 LONG
01084 STDMETHODCALLTYPE
01085 COutputPin::KsDecrementPendingIoCount()
01086 {
01087     return InterlockedDecrement((volatile LONG*)&m_IoCount);
01088 }
01089 
01090 HRESULT
01091 STDMETHODCALLTYPE
01092 COutputPin::KsQualityNotify(
01093     ULONG Proportion,
01094     REFERENCE_TIME TimeDelta)
01095 {
01096 #ifdef KSPROXY_TRACE
01097     OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n");
01098 #endif
01099     return E_NOTIMPL;
01100 }
01101 
01102 //-------------------------------------------------------------------
01103 // IKsPinEx
01104 //
01105 
01106 VOID
01107 STDMETHODCALLTYPE
01108 COutputPin::KsNotifyError(
01109     IMediaSample* Sample,
01110     HRESULT hr)
01111 {
01112 #ifdef KSPROXY_TRACE
01113     OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n");
01114 #endif
01115 }
01116 
01117 
01118 //-------------------------------------------------------------------
01119 // IKsPinPipe
01120 //
01121 
01122 HRESULT
01123 STDMETHODCALLTYPE
01124 COutputPin::KsGetPinFramingCache(
01125     PKSALLOCATOR_FRAMING_EX *FramingEx,
01126     PFRAMING_PROP FramingProp,
01127     FRAMING_CACHE_OPS Option)
01128 {
01129     if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
01130     {
01131         // invalid argument
01132         return E_INVALIDARG;
01133     }
01134 
01135     // get framing properties
01136     *FramingProp = m_FramingProp[Option];
01137     *FramingEx = m_FramingEx[Option];
01138 
01139     return NOERROR;
01140 }
01141 
01142 HRESULT
01143 STDMETHODCALLTYPE
01144 COutputPin::KsSetPinFramingCache(
01145     PKSALLOCATOR_FRAMING_EX FramingEx,
01146     PFRAMING_PROP FramingProp,
01147     FRAMING_CACHE_OPS Option)
01148 {
01149     ULONG Index;
01150     ULONG RefCount = 0;
01151 
01152     if (m_FramingEx[Option])
01153     {
01154         for(Index = 1; Index < 4; Index++)
01155         {
01156             if (m_FramingEx[Index] == m_FramingEx[Option])
01157                 RefCount++;
01158         }
01159 
01160         if (RefCount == 1)
01161         {
01162             // existing framing is only used once
01163             CoTaskMemFree(m_FramingEx[Option]);
01164         }
01165     }
01166 
01167     // store framing
01168     m_FramingEx[Option] = FramingEx;
01169     m_FramingProp[Option] = *FramingProp;
01170 
01171     return S_OK;
01172 }
01173 
01174 IPin*
01175 STDMETHODCALLTYPE
01176 COutputPin::KsGetConnectedPin()
01177 {
01178     return m_Pin;
01179 }
01180 
01181 IKsAllocatorEx*
01182 STDMETHODCALLTYPE
01183 COutputPin::KsGetPipe(
01184     KSPEEKOPERATION Operation)
01185 {
01186     if (Operation == KsPeekOperation_AddRef)
01187     {
01188         if (m_KsAllocatorEx)
01189             m_KsAllocatorEx->AddRef();
01190     }
01191     return m_KsAllocatorEx;
01192 }
01193 
01194 HRESULT
01195 STDMETHODCALLTYPE
01196 COutputPin::KsSetPipe(
01197     IKsAllocatorEx *KsAllocator)
01198 {
01199     if (KsAllocator)
01200         KsAllocator->AddRef();
01201 
01202     if (m_KsAllocatorEx)
01203         m_KsAllocatorEx->Release();
01204 
01205     m_KsAllocatorEx = KsAllocator;
01206     return NOERROR;
01207 }
01208 
01209 ULONG
01210 STDMETHODCALLTYPE
01211 COutputPin::KsGetPipeAllocatorFlag()
01212 {
01213     return m_PipeAllocatorFlag;
01214 }
01215 
01216 
01217 HRESULT
01218 STDMETHODCALLTYPE
01219 COutputPin::KsSetPipeAllocatorFlag(
01220     ULONG Flag)
01221 {
01222     m_PipeAllocatorFlag = Flag;
01223     return NOERROR;
01224 }
01225 
01226 GUID
01227 STDMETHODCALLTYPE
01228 COutputPin::KsGetPinBusCache()
01229 {
01230     if (!m_bPinBusCacheInitialized)
01231     {
01232         CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
01233         m_bPinBusCacheInitialized = TRUE;
01234     }
01235 
01236     return m_PinBusCache;
01237 }
01238 
01239 HRESULT
01240 STDMETHODCALLTYPE
01241 COutputPin::KsSetPinBusCache(
01242     GUID Bus)
01243 {
01244     CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
01245     return NOERROR;
01246 }
01247 
01248 PWCHAR
01249 STDMETHODCALLTYPE
01250 COutputPin::KsGetPinName()
01251 {
01252     return (PWCHAR)m_PinName;
01253 }
01254 
01255 
01256 PWCHAR
01257 STDMETHODCALLTYPE
01258 COutputPin::KsGetFilterName()
01259 {
01260     return m_FilterName;
01261 }
01262 
01263 //-------------------------------------------------------------------
01264 // ISpecifyPropertyPages
01265 //
01266 
01267 HRESULT
01268 STDMETHODCALLTYPE
01269 COutputPin::GetPages(CAUUID *pPages)
01270 {
01271 #ifdef KSPROXY_TRACE
01272     OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
01273 #endif
01274 
01275     if (!pPages)
01276         return E_POINTER;
01277 
01278     pPages->cElems = 0;
01279     pPages->pElems = NULL;
01280 
01281     return S_OK;
01282 }
01283 
01284 //-------------------------------------------------------------------
01285 // IKsPinFactory
01286 //
01287 
01288 HRESULT
01289 STDMETHODCALLTYPE
01290 COutputPin::KsPinFactory(
01291     ULONG* PinFactory)
01292 {
01293 #ifdef KSPROXY_TRACE
01294     OutputDebugStringW(L"COutputPin::KsPinFactory\n");
01295 #endif
01296 
01297     *PinFactory = m_PinId;
01298     return S_OK;
01299 }
01300 
01301 
01302 //-------------------------------------------------------------------
01303 // IStreamBuilder
01304 //
01305 
01306 HRESULT
01307 STDMETHODCALLTYPE
01308 COutputPin::Render(
01309     IPin *ppinOut,
01310     IGraphBuilder *pGraph)
01311 {
01312 #ifdef KSPROXY_TRACE
01313     OutputDebugStringW(L"COutputPin::Render\n");
01314 #endif
01315     return S_OK;
01316 }
01317 
01318 HRESULT
01319 STDMETHODCALLTYPE
01320 COutputPin::Backout(
01321     IPin *ppinOut,
01322     IGraphBuilder *pGraph)
01323 {
01324 #ifdef KSPROXY_TRACE
01325     OutputDebugStringW(L"COutputPin::Backout\n");
01326 #endif
01327 
01328     return S_OK;
01329 }
01330 //-------------------------------------------------------------------
01331 // IKsObject
01332 //
01333 HANDLE
01334 STDMETHODCALLTYPE
01335 COutputPin::KsGetObjectHandle()
01336 {
01337 #ifdef KSPROXY_TRACE
01338     OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");
01339 #endif
01340 
01341     assert(m_hPin != INVALID_HANDLE_VALUE);
01342     return m_hPin;
01343 }
01344 
01345 //-------------------------------------------------------------------
01346 // IKsControl
01347 //
01348 HRESULT
01349 STDMETHODCALLTYPE
01350 COutputPin::KsProperty(
01351     PKSPROPERTY Property,
01352     ULONG PropertyLength,
01353     LPVOID PropertyData,
01354     ULONG DataLength,
01355     ULONG* BytesReturned)
01356 {
01357     HRESULT hr;
01358 
01359     assert(m_hPin != INVALID_HANDLE_VALUE);
01360 
01361     hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
01362 #ifdef KSPROXY_TRACE
01363     WCHAR Buffer[100];
01364     LPOLESTR pstr;
01365     StringFromCLSID(Property->Set, &pstr);
01366     swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr);
01367     OutputDebugStringW(Buffer);
01368 #endif
01369 
01370     return hr;
01371 }
01372 
01373 HRESULT
01374 STDMETHODCALLTYPE
01375 COutputPin::KsMethod(
01376     PKSMETHOD Method,
01377     ULONG MethodLength,
01378     LPVOID MethodData,
01379     ULONG DataLength,
01380     ULONG* BytesReturned)
01381 {
01382     assert(m_hPin != INVALID_HANDLE_VALUE);
01383 #ifdef KSPROXY_TRACE
01384     OutputDebugStringW(L"COutputPin::KsMethod\n");
01385 #endif
01386     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
01387 }
01388 
01389 HRESULT
01390 STDMETHODCALLTYPE
01391 COutputPin::KsEvent(
01392     PKSEVENT Event,
01393     ULONG EventLength,
01394     LPVOID EventData,
01395     ULONG DataLength,
01396     ULONG* BytesReturned)
01397 {
01398     assert(m_hPin != INVALID_HANDLE_VALUE);
01399 
01400 #ifdef KSPROXY_TRACE
01401     OutputDebugStringW(L"COutputPin::KsEvent\n");
01402 #endif
01403 
01404     if (EventLength)
01405         return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
01406     else
01407         return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
01408 }
01409 
01410 
01411 //-------------------------------------------------------------------
01412 // IKsPropertySet
01413 //
01414 HRESULT
01415 STDMETHODCALLTYPE
01416 COutputPin::Set(
01417     REFGUID guidPropSet,
01418     DWORD dwPropID,
01419     LPVOID pInstanceData,
01420     DWORD cbInstanceData,
01421     LPVOID pPropData,
01422     DWORD cbPropData)
01423 {
01424     ULONG BytesReturned;
01425 
01426     if (cbInstanceData)
01427     {
01428         PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
01429         if (!Property)
01430             return E_OUTOFMEMORY;
01431 
01432         Property->Set = guidPropSet;
01433         Property->Id = dwPropID;
01434         Property->Flags = KSPROPERTY_TYPE_SET;
01435 
01436         CopyMemory((Property+1), pInstanceData, cbInstanceData);
01437 
01438         HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
01439         CoTaskMemFree(Property);
01440         return hr;
01441     }
01442     else
01443     {
01444         KSPROPERTY Property;
01445 
01446         Property.Set = guidPropSet;
01447         Property.Id = dwPropID;
01448         Property.Flags = KSPROPERTY_TYPE_SET;
01449 
01450         HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
01451         return hr;
01452     }
01453 }
01454 
01455 HRESULT
01456 STDMETHODCALLTYPE
01457 COutputPin::Get(
01458     REFGUID guidPropSet,
01459     DWORD dwPropID,
01460     LPVOID pInstanceData,
01461     DWORD cbInstanceData,
01462     LPVOID pPropData,
01463     DWORD cbPropData,
01464     DWORD *pcbReturned)
01465 {
01466     ULONG BytesReturned;
01467 
01468     if (cbInstanceData)
01469     {
01470         PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
01471         if (!Property)
01472             return E_OUTOFMEMORY;
01473 
01474         Property->Set = guidPropSet;
01475         Property->Id = dwPropID;
01476         Property->Flags = KSPROPERTY_TYPE_GET;
01477 
01478         CopyMemory((Property+1), pInstanceData, cbInstanceData);
01479 
01480         HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
01481         CoTaskMemFree(Property);
01482         return hr;
01483     }
01484     else
01485     {
01486         KSPROPERTY Property;
01487 
01488         Property.Set = guidPropSet;
01489         Property.Id = dwPropID;
01490         Property.Flags = KSPROPERTY_TYPE_GET;
01491 
01492         HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
01493         return hr;
01494     }
01495 }
01496 
01497 HRESULT
01498 STDMETHODCALLTYPE
01499 COutputPin::QuerySupported(
01500     REFGUID guidPropSet,
01501     DWORD dwPropID,
01502     DWORD *pTypeSupport)
01503 {
01504     KSPROPERTY Property;
01505     ULONG BytesReturned;
01506 
01507 #ifdef KSPROXY_TRACE
01508     OutputDebugStringW(L"COutputPin::QuerySupported\n");
01509 #endif
01510 
01511     Property.Set = guidPropSet;
01512     Property.Id = dwPropID;
01513     Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
01514 
01515     return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
01516 }
01517 
01518 
01519 //-------------------------------------------------------------------
01520 // IPin interface
01521 //
01522 HRESULT
01523 STDMETHODCALLTYPE
01524 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
01525 {
01526     HRESULT hr;
01527     ALLOCATOR_PROPERTIES Properties;
01528     IMemAllocatorCallbackTemp *pMemCallback;
01529     LPGUID pGuid;
01530     ULONG NumGuids = 0;
01531 
01532 #ifdef KSPROXY_TRACE
01533     WCHAR Buffer[200];
01534     OutputDebugStringW(L"COutputPin::Connect called\n");
01535 #endif
01536 
01537     if (pmt)
01538     {
01539         hr = pReceivePin->QueryAccept(pmt);
01540         if (FAILED(hr))
01541             return hr;
01542     }
01543     else
01544     {
01545         // query accept
01546         hr = pReceivePin->QueryAccept(&m_MediaFormat);
01547         if (FAILED(hr))
01548             return hr;
01549 
01550          pmt = &m_MediaFormat;
01551     }
01552 
01553     if (m_hPin == INVALID_HANDLE_VALUE)
01554     {
01555         hr = CreatePin(pmt);
01556         if (FAILED(hr))
01557         {
01558 #ifdef KSPROXY_TRACE
01559             swprintf(Buffer, L"COutputPin::Connect CreatePin handle failed with %lx\n", hr);
01560             OutputDebugStringW(Buffer);
01561 #endif
01562             return hr;
01563         }
01564     }
01565 
01566 
01567     // query for IMemInput interface
01568     hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin);
01569     if (FAILED(hr))
01570     {
01571 #ifdef KSPROXY_TRACE
01572         OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");
01573 #endif
01574 
01575         return hr;
01576     }
01577 
01578     // get input pin allocator properties
01579     ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES));
01580     m_MemInputPin->GetAllocatorRequirements(&Properties);
01581 
01582     //FIXME determine allocator properties
01583     Properties.cBuffers = 32;
01584     Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size
01585     Properties.cbAlign = 4;
01586 
01587     // get input pin allocator
01588 #if 0
01589     hr = m_MemInputPin->GetAllocator(&m_MemAllocator);
01590     if (SUCCEEDED(hr))
01591     {
01592         // set allocator properties
01593         hr = m_MemAllocator->SetProperties(&Properties, &m_Properties);
01594         if (FAILED(hr))
01595             m_MemAllocator->Release();
01596     }
01597 #endif
01598 
01599     if (1)
01600     {
01601         hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator);
01602         if (FAILED(hr))
01603             return hr;
01604 
01605         // set allocator properties
01606         hr = m_MemAllocator->SetProperties(&Properties, &m_Properties);
01607         if (FAILED(hr))
01608         {
01609 #ifdef KSPROXY_TRACE
01610             swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr);
01611             OutputDebugStringW(Buffer);
01612 #endif
01613             m_MemAllocator->Release();
01614             m_MemInputPin->Release();
01615             return hr;
01616         }
01617     }
01618 
01619     // commit property changes
01620     hr = m_MemAllocator->Commit();
01621     if (FAILED(hr))
01622     {
01623 #ifdef KSPROXY_TRACE
01624         swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr);
01625         OutputDebugStringW(Buffer);
01626 #endif
01627         m_MemAllocator->Release();
01628         m_MemInputPin->Release();
01629         return hr;
01630     }
01631 
01632     // get callback interface
01633     hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback);
01634     if (FAILED(hr))
01635     {
01636 #ifdef KSPROXY_TRACE
01637         swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr);
01638         OutputDebugStringW(Buffer);
01639 #endif
01640         m_MemAllocator->Release();
01641         m_MemInputPin->Release();
01642         return hr;
01643     }
01644 
01645     // set notification routine
01646     hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this);
01647 
01648     // release IMemAllocatorNotifyCallbackTemp interface
01649     pMemCallback->Release();
01650 
01651     if (FAILED(hr))
01652     {
01653 #ifdef KSPROXY_TRACE
01654         swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr);
01655         OutputDebugStringW(Buffer);
01656 #endif
01657         m_MemAllocator->Release();
01658         m_MemInputPin->Release();
01659         return hr;
01660     }
01661 
01662     // now set allocator
01663     hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE);
01664     if (FAILED(hr))
01665     {
01666 #ifdef KSPROXY_TRACE
01667         swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr);
01668         OutputDebugStringW(Buffer);
01669 #endif
01670         m_MemAllocator->Release();
01671         m_MemInputPin->Release();
01672         return hr;
01673     }
01674 
01675 
01676     assert(m_hPin != INVALID_HANDLE_VALUE);
01677 
01678     // get all supported sets
01679     if (m_Plugins.size() == 0)
01680     {
01681         if (GetSupportedSets(&pGuid, &NumGuids))
01682         {
01683             // load all proxy plugins
01684             if (FAILED(LoadProxyPlugins(pGuid, NumGuids)));
01685             {
01686 #ifdef KSPROXY_TRACE
01687                 OutputDebugStringW(L"COutputPin::Connect LoadProxyPlugins failed\n");
01688 #endif
01689             }
01690             // free sets
01691             CoTaskMemFree(pGuid);
01692         }
01693     }
01694 
01695     // receive connection;
01696     hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
01697     if (SUCCEEDED(hr))
01698     {
01699         // increment reference count
01700         pReceivePin->AddRef();
01701         m_Pin = pReceivePin;
01702 #ifdef KSPROXY_TRACE
01703         OutputDebugStringW(L"COutputPin::Connect success\n");
01704 #endif
01705     }
01706     else
01707     {
01708         m_MemInputPin->Release();
01709         m_MemAllocator->Release();
01710     }
01711 
01712     return hr;
01713 }
01714 
01715 HRESULT
01716 STDMETHODCALLTYPE
01717 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
01718 {
01719     return E_UNEXPECTED;
01720 }
01721 HRESULT
01722 STDMETHODCALLTYPE
01723 COutputPin::Disconnect( void)
01724 {
01725 #ifdef KSPROXY_TRACE
01726    OutputDebugStringW(L"COutputPin::Disconnect\n");
01727 #endif
01728 
01729     if (!m_Pin)
01730     {
01731         // pin was not connected
01732         return S_FALSE;
01733     }
01734 
01735     //FIXME
01736     //check if filter is active
01737 
01738     m_Pin->Release();
01739     m_Pin = NULL;
01740     m_MemInputPin->Release();
01741     m_MemAllocator->Release();
01742 
01743     CloseHandle(m_hPin);
01744     m_hPin = INVALID_HANDLE_VALUE;
01745 
01746 #ifdef KSPROXY_TRACE
01747     OutputDebugStringW(L"COutputPin::Disconnect\n");
01748 #endif
01749     return S_OK;
01750 }
01751 HRESULT
01752 STDMETHODCALLTYPE
01753 COutputPin::ConnectedTo(IPin **pPin)
01754 {
01755 #ifdef KSPROXY_TRACE
01756    OutputDebugStringW(L"COutputPin::ConnectedTo\n");
01757 #endif
01758 
01759     if (!pPin)
01760         return E_POINTER;
01761 
01762     if (m_Pin)
01763     {
01764         // increment reference count
01765         m_Pin->AddRef();
01766         *pPin = m_Pin;
01767         return S_OK;
01768     }
01769 
01770     *pPin = NULL;
01771     return VFW_E_NOT_CONNECTED;
01772 }
01773 HRESULT
01774 STDMETHODCALLTYPE
01775 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
01776 {
01777 #ifdef KSPROXY_TRACE
01778     OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");
01779 #endif
01780 
01781     return E_NOTIMPL;
01782 }
01783 HRESULT
01784 STDMETHODCALLTYPE
01785 COutputPin::QueryPinInfo(PIN_INFO *pInfo)
01786 {
01787     wcscpy(pInfo->achName, m_PinName);
01788     pInfo->dir = PINDIR_OUTPUT;
01789     pInfo->pFilter = m_ParentFilter;
01790     m_ParentFilter->AddRef();
01791 
01792     return S_OK;
01793 }
01794 HRESULT
01795 STDMETHODCALLTYPE
01796 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
01797 {
01798     if (pPinDir)
01799     {
01800         *pPinDir = PINDIR_OUTPUT;
01801         return S_OK;
01802     }
01803 
01804     return E_POINTER;
01805 }
01806 HRESULT
01807 STDMETHODCALLTYPE
01808 COutputPin::QueryId(LPWSTR *Id)
01809 {
01810     *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
01811     if (!*Id)
01812         return E_OUTOFMEMORY;
01813 
01814     wcscpy(*Id, m_PinName);
01815     return S_OK;
01816 }
01817 HRESULT
01818 STDMETHODCALLTYPE
01819 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
01820 {
01821 #ifdef KSPROXY_TRACE
01822     OutputDebugStringW(L"COutputPin::QueryAccept called\n");
01823 #endif
01824 
01825     return E_NOTIMPL;
01826 }
01827 HRESULT
01828 STDMETHODCALLTYPE
01829 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
01830 {
01831     HRESULT hr;
01832     ULONG MediaTypeCount = 0, Index;
01833     AM_MEDIA_TYPE * MediaTypes;
01834     HANDLE hFilter;
01835     IKsObject * KsObjectParent;
01836 
01837     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
01838     if (FAILED(hr))
01839         return hr;
01840 
01841     // get parent filter handle
01842     hFilter = KsObjectParent->KsGetObjectHandle();
01843 
01844     // release IKsObject
01845     KsObjectParent->Release();
01846 
01847     // query media type count
01848     hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
01849     if (FAILED(hr) || !MediaTypeCount)
01850     {
01851         return hr;
01852     }
01853 
01854     // allocate media types
01855     MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
01856     if (!MediaTypes)
01857     {
01858         // not enough memory
01859         return E_OUTOFMEMORY;
01860     }
01861 
01862     // zero media types
01863     ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
01864 
01865     for(Index = 0; Index < MediaTypeCount; Index++)
01866     {
01867         // get media type
01868         hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
01869         if (FAILED(hr))
01870         {
01871             // failed
01872             CoTaskMemFree(MediaTypes);
01873             return hr;
01874         }
01875     }
01876 
01877     return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
01878 }
01879 HRESULT
01880 STDMETHODCALLTYPE
01881 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
01882 {
01883     return E_NOTIMPL;
01884 }
01885 HRESULT
01886 STDMETHODCALLTYPE
01887 COutputPin::EndOfStream( void)
01888 {
01889     /* should be called only on input pins */
01890     return E_UNEXPECTED;
01891 }
01892 HRESULT
01893 STDMETHODCALLTYPE
01894 COutputPin::BeginFlush( void)
01895 {
01896     /* should be called only on input pins */
01897     return E_UNEXPECTED;
01898 }
01899 HRESULT
01900 STDMETHODCALLTYPE
01901 COutputPin::EndFlush( void)
01902 {
01903     /* should be called only on input pins */
01904     return E_UNEXPECTED;
01905 }
01906 HRESULT
01907 STDMETHODCALLTYPE
01908 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
01909 {
01910     if (!m_Pin)
01911     {
01912         // we are not connected
01913         return VFW_E_NOT_CONNECTED;
01914     }
01915 
01916     return m_Pin->NewSegment(tStart, tStop, dRate);
01917 }
01918 
01919 //-------------------------------------------------------------------
01920 HRESULT
01921 STDMETHODCALLTYPE
01922 COutputPin::CheckFormat(
01923     const AM_MEDIA_TYPE *pmt)
01924 {
01925     PKSMULTIPLE_ITEM MultipleItem;
01926     PKSDATAFORMAT DataFormat;
01927     HRESULT hr;
01928     IKsObject * KsObjectParent;
01929     HANDLE hFilter;
01930 
01931     if (!pmt)
01932         return E_POINTER;
01933 
01934     // get IKsObject interface
01935     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
01936     if (FAILED(hr))
01937         return hr;
01938 
01939     // get parent filter handle
01940     hFilter = KsObjectParent->KsGetObjectHandle();
01941 
01942     // release IKsObject
01943     KsObjectParent->Release();
01944 
01945     if (!hFilter)
01946         return E_HANDLE;
01947 
01948 
01949     hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
01950     if (FAILED(hr))
01951         return S_FALSE;
01952 
01953     DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
01954     for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
01955     {
01956         if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
01957             IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
01958             IsEqualGUID(pmt->formattype, DataFormat->Specifier))
01959         {
01960             // format is supported
01961             CoTaskMemFree(MultipleItem);
01962             return S_OK;
01963         }
01964         DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
01965     }
01966     //format is not supported
01967     CoTaskMemFree(MultipleItem);
01968     return S_FALSE;
01969 }
01970 
01971 HRESULT
01972 STDMETHODCALLTYPE
01973 COutputPin::CreatePin(
01974     const AM_MEDIA_TYPE *pmt)
01975 {
01976     PKSMULTIPLE_ITEM MediumList;
01977     PKSMULTIPLE_ITEM InterfaceList;
01978     PKSPIN_MEDIUM Medium;
01979     PKSPIN_INTERFACE Interface;
01980     IKsInterfaceHandler * InterfaceHandler;
01981     HRESULT hr;
01982 
01983     // query for pin medium
01984     hr = KsQueryMediums(&MediumList);
01985     if (FAILED(hr))
01986     {
01987 #ifdef KSPROXY_TRACE
01988         WCHAR Buffer[100];
01989         swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr);
01990         OutputDebugStringW(Buffer);
01991 #endif
01992         return hr;
01993     }
01994 
01995     // query for pin interface
01996     hr = KsQueryInterfaces(&InterfaceList);
01997     if (FAILED(hr))
01998     {
01999         // failed
02000 #ifdef KSPROXY_TRACE
02001         WCHAR Buffer[100];
02002         swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr);
02003         OutputDebugStringW(Buffer);
02004 #endif
02005 
02006         CoTaskMemFree(MediumList);
02007         return hr;
02008     }
02009 
02010     if (MediumList->Count)
02011     {
02012         //use first available medium
02013         Medium = (PKSPIN_MEDIUM)(MediumList + 1);
02014     }
02015     else
02016     {
02017         // default to standard medium
02018         Medium = &StandardPinMedium;
02019     }
02020 
02021     if (InterfaceList->Count)
02022     {
02023         //use first available interface
02024         Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
02025     }
02026     else
02027     {
02028         // default to standard interface
02029         Interface = &StandardPinInterface;
02030     }
02031 
02032     if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
02033     {
02034         // now create pin
02035         hr = CreatePinHandle(Medium, Interface, pmt);
02036         if (FAILED(hr))
02037         {
02038 #ifdef KSPROXY_TRACE
02039             WCHAR Buffer[100];
02040             swprintf(Buffer, L"COutputPin::CreatePinHandle failed with %lx\n", hr);
02041             OutputDebugStringW(Buffer);
02042 #endif
02043             return hr;
02044         }
02045 
02046         if (!m_InterfaceHandler)
02047         {
02048             // now load the IKsInterfaceHandler plugin
02049             hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
02050             if (FAILED(hr))
02051             {
02052                 // failed to load interface handler plugin
02053                 CoTaskMemFree(MediumList);
02054                 CoTaskMemFree(InterfaceList);
02055 
02056 #ifdef KSPROXY_TRACE
02057                 WCHAR Buffer[100];
02058                 swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr);
02059                 OutputDebugStringW(Buffer);
02060 #endif
02061 
02062                 return hr;
02063             }
02064 
02065             // now set the pin
02066             hr = InterfaceHandler->KsSetPin((IKsPin*)this);
02067             if (FAILED(hr))
02068             {
02069                 // failed to initialize interface handler plugin
02070 #ifdef KSPROXY_TRACE
02071                 WCHAR Buffer[100];
02072                 swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr);
02073                 OutputDebugStringW(Buffer);
02074 #endif
02075                 InterfaceHandler->Release();
02076                 CoTaskMemFree(MediumList);
02077                 CoTaskMemFree(InterfaceList);
02078                 return hr;
02079             }
02080 
02081             // store interface handler
02082             m_InterfaceHandler = InterfaceHandler;
02083         }
02084     }
02085     else
02086     {
02087 #ifdef KSPROXY_TRACE
02088         WCHAR Buffer[100];
02089         swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
02090         OutputDebugStringW(Buffer);
02091 #endif
02092 
02093         hr = E_FAIL;
02094     }
02095 
02096     // free medium / interface / dataformat
02097     CoTaskMemFree(MediumList);
02098     CoTaskMemFree(InterfaceList);
02099 
02100 #ifdef KSPROXY_TRACE
02101     WCHAR Buffer[100];
02102     swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr);
02103     OutputDebugStringW(Buffer);
02104 #endif
02105 
02106     return hr;
02107 }
02108 
02109 HRESULT
02110 STDMETHODCALLTYPE
02111 COutputPin::CreatePinHandle(
02112     PKSPIN_MEDIUM Medium,
02113     PKSPIN_INTERFACE Interface,
02114     const AM_MEDIA_TYPE *pmt)
02115 {
02116     PKSPIN_CONNECT PinConnect;
02117     PKSDATAFORMAT DataFormat;
02118     ULONG Length;
02119     HRESULT hr;
02120     HANDLE hFilter;
02121     IKsObject * KsObjectParent;
02122 
02123     //KSALLOCATOR_FRAMING Framing;
02124     //KSPROPERTY Property;
02125     //ULONG BytesReturned;
02126 
02127     OutputDebugStringW(L"COutputPin::CreatePinHandle\n");
02128 
02129     if (m_hPin != INVALID_HANDLE_VALUE)
02130     {
02131         // pin already exists
02132         //CloseHandle(m_hPin);
02133         //m_hPin = INVALID_HANDLE_VALUE;
02134         OutputDebugStringW(L"COutputPin::CreatePinHandle pin already exists\n");
02135         return S_OK;
02136     }
02137 
02138 
02139     // calc format size
02140     Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
02141 
02142     // allocate pin connect
02143     PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
02144     if (!PinConnect)
02145     {
02146         // failed
02147         OutputDebugStringW(L"COutputPin::CreatePinHandle out of memory\n");
02148         return E_OUTOFMEMORY;
02149     }
02150         OutputDebugStringW(L"COutputPin::CreatePinHandle copy pinconnect\n");
02151     // setup request
02152     CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
02153     CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
02154     PinConnect->PinId = m_PinId;
02155     PinConnect->PinToHandle = NULL;
02156     PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
02157     PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
02158 
02159     // get dataformat offset
02160     DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
02161         OutputDebugStringW(L"COutputPin::CreatePinHandle copy format\n");
02162     // copy data format
02163     DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
02164     DataFormat->Flags = 0;
02165     DataFormat->SampleSize = pmt->lSampleSize;
02166     DataFormat->Reserved = 0;
02167     CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
02168     CopyMemory(&DataFormat->SubFormat,  &pmt->subtype, sizeof(GUID));
02169     CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
02170 
02171     if (pmt->cbFormat)
02172     {
02173         // copy extended format
02174         WCHAR Buffer[100];
02175         swprintf(Buffer, L"COutputPin::CreatePinHandle copy format %p pbFormat %lu\n", pmt, pmt->cbFormat);
02176         OutputDebugStringW(Buffer);
02177         CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
02178     }
02179 
02180     // get IKsObject interface
02181     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
02182     if (FAILED(hr))
02183     {
02184         OutputDebugStringW(L"COutputPin::CreatePinHandle no IID_IKsObject interface\n");
02185         return hr;
02186     }
02187 
02188     // get parent filter handle
02189     hFilter = KsObjectParent->KsGetObjectHandle();
02190 
02191     // release IKsObject
02192     KsObjectParent->Release();
02193 
02194     if (!hFilter)
02195     {
02196         OutputDebugStringW(L"COutputPin::CreatePinHandle no filter handle\n");
02197         return E_HANDLE;
02198     }
02199 
02200     OutputDebugStringW(L"COutputPin::CreatePinHandle before creating pin\n");
02201     // create pin
02202     DWORD dwError = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
02203 
02204     if (dwError == ERROR_SUCCESS)
02205     {
02206         OutputDebugStringW(L"COutputPin::CreatePinHandle created pin\n");
02207 
02208         // store current interface / medium
02209         CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
02210         CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
02211         CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
02212 
02213 #ifdef KSPROXY_TRACE
02214         LPOLESTR pMajor, pSub, pFormat;
02215         StringFromIID(m_MediaFormat.majortype, &pMajor);
02216         StringFromIID(m_MediaFormat.subtype , &pSub);
02217         StringFromIID(m_MediaFormat.formattype, &pFormat);
02218         WCHAR Buffer[200];
02219         swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
02220         CoTaskMemFree(pMajor);
02221         CoTaskMemFree(pSub);
02222         CoTaskMemFree(pFormat);
02223         OutputDebugStringW(Buffer);
02224 #endif
02225 
02226         if (pmt->cbFormat)
02227         {
02228             m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
02229             if (!m_MediaFormat.pbFormat)
02230             {
02231                 CoTaskMemFree(PinConnect);
02232                 m_MediaFormat.pbFormat = NULL;
02233                 m_MediaFormat.cbFormat = 0;
02234                 return E_OUTOFMEMORY;
02235             }
02236             CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
02237         }
02238 #if 0
02239         Property.Set = KSPROPSETID_Connection;
02240         Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
02241         Property.Flags = KSPROPERTY_TYPE_GET;
02242 
02243         ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING));
02244         hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
02245         if (SUCCEEDED(hr))
02246         {
02247             m_Properties.cbAlign = (Framing.FileAlignment + 1);
02248             m_Properties.cbBuffer = Framing.FrameSize;
02249             m_Properties.cbPrefix = 0; //FIXME
02250             m_Properties.cBuffers = Framing.Frames;
02251         }
02252         hr = S_OK;
02253 #endif
02254 
02255         if (FAILED(InitializeIOThread()))
02256         {
02257             OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
02258         }
02259 
02260         //TODO
02261         // connect pin pipes
02262 
02263     }
02264     else
02265         OutputDebugStringW(L"COutputPin::CreatePinHandle failed to create pin\n");
02266     // free pin connect
02267      CoTaskMemFree(PinConnect);
02268 
02269     return hr;
02270 }
02271 
02272 HRESULT
02273 STDMETHODCALLTYPE
02274 COutputPin::GetSupportedSets(
02275     LPGUID * pOutGuid,
02276     PULONG NumGuids)
02277 {
02278     KSPROPERTY Property;
02279     LPGUID pGuid;
02280     ULONG NumProperty = 0;
02281     ULONG NumMethods = 0;
02282     ULONG NumEvents = 0;
02283     ULONG Length;
02284     ULONG BytesReturned;
02285     HRESULT hr;
02286 
02287     Property.Set = GUID_NULL;
02288     Property.Id = 0;
02289     Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
02290 
02291     KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
02292     KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
02293     KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
02294 
02295     Length = NumProperty + NumMethods + NumEvents;
02296 
02297     assert(Length);
02298 
02299     // allocate guid buffer
02300     pGuid = (LPGUID)CoTaskMemAlloc(Length);
02301     if (!pGuid)
02302     {
02303         // failed
02304         return E_OUTOFMEMORY;
02305     }
02306 
02307     NumProperty /= sizeof(GUID);
02308     NumMethods /= sizeof(GUID);
02309     NumEvents /= sizeof(GUID);
02310 
02311     // get all properties
02312     hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
02313     if (FAILED(hr))
02314     {
02315         CoTaskMemFree(pGuid);
02316         return E_FAIL;
02317     }
02318     Length -= BytesReturned;
02319 
02320     // get all methods
02321     if (Length && NumMethods)
02322     {
02323         hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
02324         if (FAILED(hr))
02325         {
02326             CoTaskMemFree(pGuid);
02327             return E_FAIL;
02328         }
02329         Length -= BytesReturned;
02330     }
02331 
02332     // get all events
02333     if (Length && NumEvents)
02334     {
02335         hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
02336         if (FAILED(hr))
02337         {
02338             CoTaskMemFree(pGuid);
02339             return E_FAIL;
02340         }
02341         Length -= BytesReturned;
02342     }
02343 
02344 #ifdef KSPROXY_TRACE
02345     WCHAR Buffer[200];
02346     swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
02347     OutputDebugStringW(Buffer);
02348 #endif
02349 
02350     *pOutGuid = pGuid;
02351     *NumGuids = NumProperty+NumEvents+NumMethods;
02352     return S_OK;
02353 }
02354 
02355 HRESULT
02356 STDMETHODCALLTYPE
02357 COutputPin::LoadProxyPlugins(
02358     LPGUID pGuids,
02359     ULONG NumGuids)
02360 {
02361     ULONG Index;
02362     LPOLESTR pStr;
02363     HKEY hKey, hSubKey;
02364     HRESULT hr;
02365     IUnknown * pUnknown;
02366 
02367     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
02368     {
02369         OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
02370         return E_FAIL;
02371     }
02372 
02373     // enumerate all sets
02374     for(Index = 0; Index < NumGuids; Index++)
02375     {
02376         // convert to string
02377         hr = StringFromCLSID(pGuids[Index], &pStr);
02378         if (FAILED(hr))
02379             return E_FAIL;
02380 
02381         // now try open class key
02382         if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
02383         {
02384             // no plugin for that set exists
02385             CoTaskMemFree(pStr);
02386             continue;
02387         }
02388 
02389         // try load plugin
02390         hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
02391         if (SUCCEEDED(hr))
02392         {
02393             // store plugin
02394             m_Plugins.push_back(pUnknown);
02395         }
02396         // close key
02397         RegCloseKey(hSubKey);
02398     }
02399 
02400     // close media interfaces key
02401     RegCloseKey(hKey);
02402     return S_OK;
02403 }
02404 
02405 
02406 HRESULT
02407 WINAPI
02408 COutputPin::IoProcessRoutine()
02409 {
02410     IMediaSample *Sample;
02411     LONG SampleCount;
02412     HRESULT hr;
02413     PKSSTREAM_SEGMENT * StreamSegment;
02414     HANDLE hEvent;
02415     IMediaSample ** Samples;
02416     LONG NumHandles;
02417     DWORD dwStatus;
02418 
02419 #ifdef KSPROXY_TRACE
02420     WCHAR Buffer[200];
02421 #endif
02422 
02423     NumHandles = m_Properties.cBuffers / 2;
02424 
02425     if (!NumHandles)
02426         NumHandles = 8;
02427 
02428     assert(NumHandles);
02429 
02430     //allocate stream segment array
02431     StreamSegment = (PKSSTREAM_SEGMENT*)CoTaskMemAlloc(sizeof(PVOID) * NumHandles);
02432     if (!StreamSegment)
02433     {
02434         OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n");
02435         return E_FAIL;
02436     }
02437 
02438     // allocate handle array
02439     Samples = (IMediaSample**)CoTaskMemAlloc(sizeof(IMediaSample*) * NumHandles);
02440     if (!Samples)
02441     {
02442         OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n");
02443         return E_FAIL;
02444     }
02445 
02446     // zero handles array
02447     ZeroMemory(StreamSegment, sizeof(PVOID) * NumHandles);
02448     ZeroMemory(Samples, sizeof(IMediaSample*) * NumHandles);
02449 
02450     // first wait for the start event to signal
02451     WaitForSingleObject(m_hStartEvent, INFINITE);
02452 
02453     m_IoCount = 0;
02454 
02455     assert(m_InterfaceHandler);
02456     do
02457     {
02458         if (m_StopInProgress)
02459         {
02460             // stop io thread
02461             break;
02462         }
02463 
02464         assert(m_State == KSSTATE_RUN);
02465         assert(m_MemAllocator);
02466 
02467         // get buffer
02468         hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT);
02469 
02470         if (FAILED(hr))
02471         {
02472             WaitForSingleObject(m_hBufferAvailable, INFINITE);
02473             // now retry again
02474             continue;
02475         }
02476 
02477         // fill buffer
02478         SampleCount = 1;
02479         Samples[m_IoCount] = Sample;
02480 
02481         Sample->SetTime(NULL, NULL);
02482         hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
02483                                                        &Samples[m_IoCount],
02484                                                        &SampleCount,
02485                                                        KsIoOperation_Read,
02486                                                        &StreamSegment[m_IoCount]);
02487         if (FAILED(hr) || !StreamSegment)
02488         {
02489 #ifdef KSPROXY_TRACE
02490             swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr);
02491             OutputDebugStringW(Buffer);
02492 #endif
02493             break;
02494         }
02495 
02496         // interface handle should increment pending i/o count
02497         assert(m_IoCount >= 1);
02498 
02499         swprintf(Buffer, L"COutputPin::IoProcessRoutine m_IoCount %lu NumHandles %lu\n", m_IoCount, NumHandles);
02500         OutputDebugStringW(Buffer);
02501 
02502         if (m_IoCount != NumHandles)
02503             continue;
02504 
02505         // get completion handle
02506         hEvent = StreamSegment[0]->CompletionEvent;
02507 
02508         // wait for i/o completion
02509         dwStatus = WaitForSingleObject(hEvent, INFINITE);
02510 
02511         swprintf(Buffer, L"COutputPin::IoProcessRoutine dwStatus %lx Error %lx NumHandles %lu\n", dwStatus, GetLastError(), NumHandles);
02512         OutputDebugStringW(Buffer);
02513 
02514         // perform completion
02515         m_InterfaceHandler->KsCompleteIo(StreamSegment[0]);
02516 
02517         // close completion event
02518         CloseHandle(hEvent);
02519 
02520         if (SUCCEEDED(hr))
02521         {
02522             assert(m_MemInputPin);
02523 
02524             // now deliver the sample
02525             hr = m_MemInputPin->Receive(Samples[0]);
02526 
02527 #ifdef KSPROXY_TRACE
02528             swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator);
02529             OutputDebugStringW(Buffer);
02530 #endif
02531 
02532              if (FAILED(hr))
02533                  break;
02534 
02535             Sample = NULL;
02536         }
02537 
02538         //circular stream segment array
02539         RtlMoveMemory(StreamSegment, &StreamSegment[1], sizeof(PVOID) * (NumHandles - 1));
02540         RtlMoveMemory(Samples, &Samples[1], sizeof(IMediaSample*) * (NumHandles - 1));
02541 
02542     }while(TRUE);
02543 
02544     // signal end of i/o thread
02545     SetEvent(m_hStopEvent);
02546 
02547     m_IoThreadStarted = false;
02548 
02549     return NOERROR;
02550 }
02551 
02552 DWORD
02553 WINAPI
02554 COutputPin_IoThreadStartup(
02555     LPVOID lpParameter)
02556 {
02557     COutputPin * Pin = (COutputPin*)lpParameter;
02558     assert(Pin);
02559 
02560     return Pin->IoProcessRoutine();
02561 }
02562 
02563 
02564 HRESULT
02565 WINAPI
02566 COutputPin::InitializeIOThread()
02567 {
02568     HANDLE hThread;
02569 
02570     if (m_IoThreadStarted)
02571         return NOERROR;
02572 
02573     if (!m_hStartEvent)
02574         m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
02575 
02576     if (!m_hStartEvent)
02577         return E_OUTOFMEMORY;
02578 
02579     if (!m_hStopEvent)
02580         m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
02581 
02582     if (!m_hStopEvent)
02583         return E_OUTOFMEMORY;
02584 
02585     if (!m_hBufferAvailable)
02586         m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL);
02587 
02588     if (!m_hBufferAvailable)
02589         return E_OUTOFMEMORY;
02590 
02591     m_StopInProgress = false;
02592     m_IoThreadStarted = true;
02593 
02594     // now create the startup thread
02595     hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL);
02596     if (!hThread)
02597         return E_OUTOFMEMORY;
02598 
02599 
02600     // close thread handle
02601     CloseHandle(hThread);
02602     return NOERROR;
02603 }
02604 
02605 HRESULT
02606 STDMETHODCALLTYPE
02607 COutputPin_SetState(
02608     IPin * Pin,
02609     KSSTATE State)
02610 {
02611     HRESULT hr = S_OK;
02612     KSPROPERTY Property;
02613     KSSTATE CurState;
02614     ULONG BytesReturned;
02615     COutputPin * pPin = (COutputPin*)Pin;
02616 
02617 #ifdef KSPROXY_TRACE
02618     WCHAR Buffer[200];
02619 #endif
02620 
02621     Property.Set = KSPROPSETID_Connection;
02622     Property.Id = KSPROPERTY_CONNECTION_STATE;
02623     Property.Flags = KSPROPERTY_TYPE_SET;
02624 
02625     EnterCriticalSection(&pPin->m_Lock);
02626 
02627     if (pPin->m_State <= State)
02628     {
02629         if (pPin->m_State == KSSTATE_STOP)
02630         {
02631             hr = pPin->InitializeIOThread();
02632             if (FAILED(hr))
02633             {
02634                 // failed to initialize I/O thread
02635 #ifdef KSPROXY_TRACE
02636                 OutputDebugStringW(L"Failed to initialize I/O Thread\n");
02637 #endif
02638                 LeaveCriticalSection(&pPin->m_Lock);
02639                 return hr;
02640             }
02641             CurState = KSSTATE_ACQUIRE;
02642             hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
02643 
02644 #ifdef KSPROXY_TRACE
02645             swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
02646             OutputDebugStringW(Buffer);
02647 #endif
02648 
02649             if (FAILED(hr))
02650             {
02651                 LeaveCriticalSection(&pPin->m_Lock);
02652                 return hr;
02653             }
02654 
02655             pPin->m_State = CurState;
02656 
02657             if (pPin->m_State == State)
02658             {
02659                 LeaveCriticalSection(&pPin->m_Lock);
02660                 return hr;
02661             }
02662         }
02663         if (pPin->m_State == KSSTATE_ACQUIRE)
02664         {
02665             CurState = KSSTATE_PAUSE;
02666             hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
02667 
02668 #ifdef KSPROXY_TRACE
02669             swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
02670             OutputDebugStringW(Buffer);
02671 #endif
02672 
02673             if (FAILED(hr))
02674             {
02675                 LeaveCriticalSection(&pPin->m_Lock);
02676                 return hr;
02677             }
02678 
02679             pPin->m_State = CurState;
02680 
02681             if (pPin->m_State == State)
02682             {
02683                 LeaveCriticalSection(&pPin->m_Lock);
02684                 return hr;
02685             }
02686         }
02687         if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE)
02688         {
02689             CurState = KSSTATE_RUN;
02690             hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
02691 
02692 #ifdef KSPROXY_TRACE
02693             swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr);
02694             OutputDebugStringW(Buffer);
02695 #endif
02696 
02697             if (SUCCEEDED(hr))
02698             {
02699                 pPin->m_State = CurState;
02700                 // signal start event
02701                 SetEvent(pPin->m_hStartEvent);
02702             }
02703         }
02704 
02705         LeaveCriticalSection(&pPin->m_Lock);
02706         return hr;
02707     }
02708     else
02709     {
02710         if (pPin->m_State == KSSTATE_RUN)
02711         {
02712             // setting pending stop flag
02713             pPin->m_StopInProgress = true;
02714 
02715             // release any waiting threads
02716             SetEvent(pPin->m_hBufferAvailable);
02717 
02718             // wait until i/o thread is done
02719             WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
02720 
02721             CurState = KSSTATE_PAUSE;
02722             hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
02723 
02724 #ifdef KSPROXY_TRACE
02725             swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
02726             OutputDebugStringW(Buffer);
02727 #endif
02728 
02729             if (FAILED(hr))
02730             {
02731                 LeaveCriticalSection(&pPin->m_Lock);
02732                 return hr;
02733             }
02734 
02735             pPin->m_State = CurState;
02736 
02737             if (FAILED(hr))
02738             {
02739                 LeaveCriticalSection(&pPin->m_Lock);
02740                 return hr;
02741             }
02742         }
02743         if (pPin->m_State == KSSTATE_PAUSE)
02744         {
02745             CurState = KSSTATE_ACQUIRE;
02746             hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
02747 
02748 #ifdef KSPROXY_TRACE
02749             swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
02750             OutputDebugStringW(Buffer);
02751 #endif
02752 
02753             if (FAILED(hr))
02754             {
02755                 LeaveCriticalSection(&pPin->m_Lock);
02756                 return hr;
02757             }
02758 
02759             pPin->m_State = CurState;
02760 
02761             if (pPin->m_State == State)
02762             {
02763                 LeaveCriticalSection(&pPin->m_Lock);
02764                 return hr;
02765             }
02766         }
02767 
02768         CloseHandle(pPin->m_hStopEvent);
02769         CloseHandle(pPin->m_hStartEvent);
02770         CloseHandle(pPin->m_hBufferAvailable);
02771 
02772         /* close event handles */
02773         pPin->m_hStopEvent = NULL;
02774         pPin->m_hStartEvent = NULL;
02775         pPin->m_hBufferAvailable = NULL;
02776 
02777         CurState = KSSTATE_STOP;
02778         hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
02779 
02780 #ifdef KSPROXY_TRACE
02781         swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr);
02782         OutputDebugStringW(Buffer);
02783 #endif
02784 
02785         if (SUCCEEDED(hr))
02786         {
02787             // store state
02788             pPin->m_State = CurState;
02789         }
02790 
02791         // unset pending stop flag
02792         pPin->m_StopInProgress = false;
02793 
02794         LeaveCriticalSection(&pPin->m_Lock);
02795         return hr;
02796     }
02797 }
02798 
02799 HRESULT
02800 WINAPI
02801 COutputPin_Constructor(
02802     IBaseFilter * ParentFilter,
02803     LPCWSTR PinName,
02804     ULONG PinId,
02805     KSPIN_COMMUNICATION Communication,
02806     REFIID riid,
02807     LPVOID * ppv)
02808 {
02809     COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
02810 
02811     if (!handler)
02812         return E_OUTOFMEMORY;
02813 
02814     if (FAILED(handler->QueryInterface(riid, ppv)))
02815     {
02816         /* not supported */
02817         delete handler;
02818         return E_NOINTERFACE;
02819     }
02820 
02821     return S_OK;
02822 }

Generated on Sun May 27 2012 04:21:52 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.