[KSPROXY]
[reactos.git] / reactos / dll / directx / ksproxy / output_pin.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/output_pin.cpp
5 * PURPOSE: OutputPin of Proxy Filter
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 class COutputPin : public IPin,
12 public IKsObject,
13 public IKsPropertySet,
14 public IStreamBuilder,
15 public IKsPinFactory,
16 public ISpecifyPropertyPages,
17 public IKsPinEx,
18 public IKsPinPipe,
19 public IKsControl,
20 public IKsAggregateControl,
21 public IQualityControl,
22 public IMediaSeeking,
23 public IAMBufferNegotiation,
24 public IAMStreamConfig,
25 public IMemAllocatorNotifyCallbackTemp
26
27 {
28 public:
29 typedef std::vector<IUnknown *>ProxyPluginVector;
30
31 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
32
33 STDMETHODIMP_(ULONG) AddRef()
34 {
35 InterlockedIncrement(&m_Ref);
36 return m_Ref;
37 }
38 STDMETHODIMP_(ULONG) Release()
39 {
40 InterlockedDecrement(&m_Ref);
41 if (!m_Ref)
42 {
43 //delete this;
44 return 0;
45 }
46 return m_Ref;
47 }
48
49 //IKsPin
50 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
51 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
52 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
53 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
54 HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
55 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
56 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
57 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
58 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
59 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
60 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
61 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
62 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
63 // IKsPinEx
64 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
65
66 //IKsPinPipe
67 HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
68 HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
69 IPin* STDMETHODCALLTYPE KsGetConnectedPin();
70 IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
71 HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
72 ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
73 HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
74 GUID STDMETHODCALLTYPE KsGetPinBusCache();
75 HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
76 PWCHAR STDMETHODCALLTYPE KsGetPinName();
77 PWCHAR STDMETHODCALLTYPE KsGetFilterName();
78
79 //IPin methods
80 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
81 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
82 HRESULT STDMETHODCALLTYPE Disconnect();
83 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
84 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
85 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
86 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
87 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
88 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
89 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
90 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
91 HRESULT STDMETHODCALLTYPE EndOfStream();
92 HRESULT STDMETHODCALLTYPE BeginFlush();
93 HRESULT STDMETHODCALLTYPE EndFlush();
94 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
95
96 // ISpecifyPropertyPages
97 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
98
99 //IKsObject methods
100 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
101
102 //IKsPropertySet
103 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
104 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
105 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
106
107 //IKsControl
108 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
109 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
110 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
111
112 //IStreamBuilder
113 HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
114 HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
115
116 //IKsPinFactory
117 HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
118
119 //IKsAggregateControl
120 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
121 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
122
123 //IQualityControl
124 HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q);
125 HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
126
127 //IMediaSeeking
128 HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
129 HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
130 HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
131 HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
132 HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
133 HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
134 HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
135 HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
136 HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
137 HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
138 HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
139 HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
140 HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
141 HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
142 HRESULT STDMETHODCALLTYPE SetRate(double dRate);
143 HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
144 HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
145
146 //IAMBufferNegotiation
147 HRESULT STDMETHODCALLTYPE SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop);
148 HRESULT STDMETHODCALLTYPE GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop);
149
150 //IAMStreamConfig
151 HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt);
152 HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt);
153 HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize);
154 HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC);
155
156 //IMemAllocatorNotifyCallbackTemp
157 HRESULT STDMETHODCALLTYPE NotifyRelease();
158
159 //---------------------------------------------------------------
160 COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication);
161 virtual ~COutputPin();
162 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
163 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
164 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
165 HRESULT WINAPI IoProcessRoutine();
166 HRESULT WINAPI InitializeIOThread();
167 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
168 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
169
170 friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter);
171 friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State);
172
173 protected:
174 LONG m_Ref;
175 IBaseFilter * m_ParentFilter;
176 LPCWSTR m_PinName;
177 HANDLE m_hPin;
178 ULONG m_PinId;
179 IPin * m_Pin;
180 IKsAllocatorEx * m_KsAllocatorEx;
181 ULONG m_PipeAllocatorFlag;
182 BOOL m_bPinBusCacheInitialized;
183 GUID m_PinBusCache;
184 LPWSTR m_FilterName;
185 FRAMING_PROP m_FramingProp[4];
186 PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
187
188 IMemAllocator * m_MemAllocator;
189 IMemInputPin * m_MemInputPin;
190 LONG m_IoCount;
191 KSPIN_COMMUNICATION m_Communication;
192 KSPIN_INTERFACE m_Interface;
193 KSPIN_MEDIUM m_Medium;
194 AM_MEDIA_TYPE m_MediaFormat;
195 ALLOCATOR_PROPERTIES m_Properties;
196 IKsInterfaceHandler * m_InterfaceHandler;
197
198 HANDLE m_hStartEvent;
199 HANDLE m_hBufferAvailable;
200 HANDLE m_hStopEvent;
201 BOOL m_StopInProgress;
202 BOOL m_IoThreadStarted;
203
204 KSSTATE m_State;
205 CRITICAL_SECTION m_Lock;
206
207 ProxyPluginVector m_Plugins;
208 };
209
210 COutputPin::~COutputPin()
211 {
212 }
213
214 COutputPin::COutputPin(
215 IBaseFilter * ParentFilter,
216 LPCWSTR PinName,
217 ULONG PinId,
218 KSPIN_COMMUNICATION Communication) : m_Ref(0),
219 m_ParentFilter(ParentFilter),
220 m_PinName(PinName),
221 m_hPin(INVALID_HANDLE_VALUE),
222 m_PinId(PinId),
223 m_Pin(0),
224 m_KsAllocatorEx(0),
225 m_PipeAllocatorFlag(0),
226 m_bPinBusCacheInitialized(0),
227 m_FilterName(0),
228 m_MemAllocator(0),
229 m_MemInputPin(0),
230 m_IoCount(0),
231 m_Communication(Communication),
232 m_InterfaceHandler(0),
233 m_hStartEvent(0),
234 m_hBufferAvailable(0),
235 m_hStopEvent(0),
236 m_StopInProgress(0),
237 m_IoThreadStarted(0),
238 m_State(KSSTATE_STOP),
239 m_Plugins()
240 {
241 HRESULT hr;
242 IKsObject * KsObjectParent;
243
244 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
245 assert(hr == S_OK);
246
247 ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
248 ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
249
250 hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId);
251 assert(hr == S_OK);
252
253 InitializeCriticalSection(&m_Lock);
254
255 KsObjectParent->Release();
256 };
257
258 HRESULT
259 STDMETHODCALLTYPE
260 COutputPin::QueryInterface(
261 IN REFIID refiid,
262 OUT PVOID* Output)
263 {
264 *Output = NULL;
265 if (IsEqualGUID(refiid, IID_IUnknown) ||
266 IsEqualGUID(refiid, IID_IPin))
267 {
268 #ifdef KSPROXY_TRACE
269 OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n");
270 #endif
271 *Output = PVOID(this);
272 reinterpret_cast<IUnknown*>(*Output)->AddRef();
273 return NOERROR;
274 }
275 else if (IsEqualGUID(refiid, IID_IKsObject))
276 {
277 if (m_hPin == INVALID_HANDLE_VALUE)
278 {
279 HRESULT hr = CreatePin(&m_MediaFormat);
280 if (FAILED(hr))
281 return hr;
282 }
283 #ifdef KSPROXY_TRACE
284 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
285 #endif
286 *Output = (IKsObject*)(this);
287 reinterpret_cast<IKsObject*>(*Output)->AddRef();
288 return NOERROR;
289 }
290 else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx))
291 {
292 *Output = (IKsPinEx*)(this);
293 reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
294 return NOERROR;
295 }
296 else if (IsEqualGUID(refiid, IID_IKsPinPipe))
297 {
298 *Output = (IKsPinPipe*)(this);
299 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
300 return NOERROR;
301 }
302 else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
303 {
304 *Output = (IKsAggregateControl*)(this);
305 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
306 return NOERROR;
307 }
308 else if (IsEqualGUID(refiid, IID_IQualityControl))
309 {
310 *Output = (IQualityControl*)(this);
311 reinterpret_cast<IQualityControl*>(*Output)->AddRef();
312 return NOERROR;
313 }
314 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
315 {
316 if (m_hPin == INVALID_HANDLE_VALUE)
317 {
318 HRESULT hr = CreatePin(&m_MediaFormat);
319 if (FAILED(hr))
320 return hr;
321 }
322 #ifdef KSPROXY_TRACE
323 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
324 #endif
325 *Output = (IKsPropertySet*)(this);
326 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
327 return NOERROR;
328 }
329 else if (IsEqualGUID(refiid, IID_IKsControl))
330 {
331 #ifdef KSPROXY_TRACE
332 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");
333 #endif
334 *Output = (IKsControl*)(this);
335 reinterpret_cast<IKsControl*>(*Output)->AddRef();
336 return NOERROR;
337 }
338 #if 0
339 else if (IsEqualGUID(refiid, IID_IStreamBuilder))
340 {
341 *Output = (IStreamBuilder*)(this);
342 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
343 return NOERROR;
344 }
345 #endif
346 else if (IsEqualGUID(refiid, IID_IKsPinFactory))
347 {
348 #ifdef KSPROXY_TRACE
349 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");
350 #endif
351 *Output = (IKsPinFactory*)(this);
352 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
353 return NOERROR;
354 }
355 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
356 {
357 #ifdef KSPROXY_TRACE
358 OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");
359 #endif
360 *Output = (ISpecifyPropertyPages*)(this);
361 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
362 return NOERROR;
363 }
364 else if (IsEqualGUID(refiid, IID_IMediaSeeking))
365 {
366 *Output = (IMediaSeeking*)(this);
367 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
368 return NOERROR;
369 }
370 else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation))
371 {
372 *Output = (IAMBufferNegotiation*)(this);
373 reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef();
374 return NOERROR;
375 }
376 else if (IsEqualGUID(refiid, IID_IAMStreamConfig))
377 {
378 *Output = (IAMStreamConfig*)(this);
379 reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef();
380 return NOERROR;
381 }
382 else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp))
383 {
384 *Output = (IMemAllocatorNotifyCallbackTemp*)(this);
385 reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef();
386 return NOERROR;
387 }
388
389 #ifdef KSPROXY_TRACE
390 WCHAR Buffer[MAX_PATH];
391 LPOLESTR lpstr;
392 StringFromCLSID(refiid, &lpstr);
393 swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName);
394 OutputDebugStringW(Buffer);
395 CoTaskMemFree(lpstr);
396 #endif
397
398 return E_NOINTERFACE;
399 }
400
401 //-------------------------------------------------------------------
402 // IAMBufferNegotiation interface
403 //
404 HRESULT
405 STDMETHODCALLTYPE
406 COutputPin::SuggestAllocatorProperties(
407 const ALLOCATOR_PROPERTIES *pprop)
408 {
409 #ifdef KSPROXY_TRACE
410 OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n");
411 #endif
412
413 if (m_Pin)
414 {
415 // pin is already connected
416 return VFW_E_ALREADY_CONNECTED;
417 }
418
419 CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES));
420 return NOERROR;
421 }
422
423 HRESULT
424 STDMETHODCALLTYPE
425 COutputPin::GetAllocatorProperties(
426 ALLOCATOR_PROPERTIES *pprop)
427 {
428 #ifdef KSPROXY_TRACE
429 OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n");
430 #endif
431
432 if (!m_Pin)
433 {
434 // you should call this method AFTER you connected
435 return E_UNEXPECTED;
436 }
437
438 if (!m_KsAllocatorEx)
439 {
440 // something went wrong while creating the allocator
441 return E_FAIL;
442 }
443
444 CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES));
445 return NOERROR;
446 }
447
448 //-------------------------------------------------------------------
449 // IAMStreamConfig interface
450 //
451 HRESULT
452 STDMETHODCALLTYPE
453 COutputPin::SetFormat(
454 AM_MEDIA_TYPE *pmt)
455 {
456 #ifdef KSPROXY_TRACE
457 OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n");
458 #endif
459 return E_NOTIMPL;
460 }
461
462 HRESULT
463 STDMETHODCALLTYPE
464 COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt)
465 {
466 #ifdef KSPROXY_TRACE
467 OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n");
468 #endif
469 return E_NOTIMPL;
470 }
471
472 HRESULT
473 STDMETHODCALLTYPE
474 COutputPin::GetNumberOfCapabilities(
475 int *piCount,
476 int *piSize)
477 {
478 #ifdef KSPROXY_TRACE
479 OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n");
480 #endif
481 return E_NOTIMPL;
482 }
483
484 HRESULT
485 STDMETHODCALLTYPE
486 COutputPin::GetStreamCaps(
487 int iIndex,
488 AM_MEDIA_TYPE **ppmt,
489 BYTE *pSCC)
490 {
491 #ifdef KSPROXY_TRACE
492 OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n");
493 #endif
494 return E_NOTIMPL;
495 }
496
497 //-------------------------------------------------------------------
498 // IMemAllocatorNotifyCallbackTemp interface
499 //
500 HRESULT
501 STDMETHODCALLTYPE
502 COutputPin::NotifyRelease()
503 {
504 #ifdef KSPROXY_TRACE
505 OutputDebugStringW(L"COutputPin::NotifyRelease\n");
506 #endif
507
508 // notify thread of new available sample
509 SetEvent(m_hBufferAvailable);
510
511 return NOERROR;
512 }
513
514 //-------------------------------------------------------------------
515 // IMediaSeeking interface
516 //
517 HRESULT
518 STDMETHODCALLTYPE
519 COutputPin::GetCapabilities(
520 DWORD *pCapabilities)
521 {
522 IMediaSeeking * FilterMediaSeeking;
523 HRESULT hr;
524
525 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
526 if (FAILED(hr))
527 return hr;
528
529 hr = FilterMediaSeeking->GetCapabilities(pCapabilities);
530
531 FilterMediaSeeking->Release();
532 return hr;
533 }
534
535 HRESULT
536 STDMETHODCALLTYPE
537 COutputPin::CheckCapabilities(
538 DWORD *pCapabilities)
539 {
540 IMediaSeeking * FilterMediaSeeking;
541 HRESULT hr;
542
543 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
544 if (FAILED(hr))
545 return hr;
546
547 hr = FilterMediaSeeking->CheckCapabilities(pCapabilities);
548
549 FilterMediaSeeking->Release();
550 return hr;
551 }
552
553 HRESULT
554 STDMETHODCALLTYPE
555 COutputPin::IsFormatSupported(
556 const GUID *pFormat)
557 {
558 IMediaSeeking * FilterMediaSeeking;
559 HRESULT hr;
560
561 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
562 if (FAILED(hr))
563 return hr;
564
565 hr = FilterMediaSeeking->IsFormatSupported(pFormat);
566
567 FilterMediaSeeking->Release();
568 return hr;
569 }
570
571 HRESULT
572 STDMETHODCALLTYPE
573 COutputPin::QueryPreferredFormat(
574 GUID *pFormat)
575 {
576 IMediaSeeking * FilterMediaSeeking;
577 HRESULT hr;
578
579 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
580 if (FAILED(hr))
581 return hr;
582
583 hr = FilterMediaSeeking->QueryPreferredFormat(pFormat);
584
585 FilterMediaSeeking->Release();
586 return hr;
587 }
588
589 HRESULT
590 STDMETHODCALLTYPE
591 COutputPin::GetTimeFormat(
592 GUID *pFormat)
593 {
594 IMediaSeeking * FilterMediaSeeking;
595 HRESULT hr;
596
597 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
598 if (FAILED(hr))
599 return hr;
600
601 hr = FilterMediaSeeking->GetTimeFormat(pFormat);
602
603 FilterMediaSeeking->Release();
604 return hr;
605 }
606
607 HRESULT
608 STDMETHODCALLTYPE
609 COutputPin::IsUsingTimeFormat(
610 const GUID *pFormat)
611 {
612 IMediaSeeking * FilterMediaSeeking;
613 HRESULT hr;
614
615 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
616 if (FAILED(hr))
617 return hr;
618
619 hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat);
620
621 FilterMediaSeeking->Release();
622 return hr;
623 }
624
625 HRESULT
626 STDMETHODCALLTYPE
627 COutputPin::SetTimeFormat(
628 const GUID *pFormat)
629 {
630 IMediaSeeking * FilterMediaSeeking;
631 HRESULT hr;
632
633 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
634 if (FAILED(hr))
635 return hr;
636
637 hr = FilterMediaSeeking->SetTimeFormat(pFormat);
638
639 FilterMediaSeeking->Release();
640 return hr;
641 }
642
643 HRESULT
644 STDMETHODCALLTYPE
645 COutputPin::GetDuration(
646 LONGLONG *pDuration)
647 {
648 IMediaSeeking * FilterMediaSeeking;
649 HRESULT hr;
650
651 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
652 if (FAILED(hr))
653 return hr;
654
655 hr = FilterMediaSeeking->GetDuration(pDuration);
656
657 FilterMediaSeeking->Release();
658 return hr;
659 }
660
661 HRESULT
662 STDMETHODCALLTYPE
663 COutputPin::GetStopPosition(
664 LONGLONG *pStop)
665 {
666 IMediaSeeking * FilterMediaSeeking;
667 HRESULT hr;
668
669 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
670 if (FAILED(hr))
671 return hr;
672
673 hr = FilterMediaSeeking->GetStopPosition(pStop);
674
675 FilterMediaSeeking->Release();
676 return hr;
677 }
678
679
680 HRESULT
681 STDMETHODCALLTYPE
682 COutputPin::GetCurrentPosition(
683 LONGLONG *pCurrent)
684 {
685 IMediaSeeking * FilterMediaSeeking;
686 HRESULT hr;
687
688 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
689 if (FAILED(hr))
690 return hr;
691
692 hr = FilterMediaSeeking->GetCurrentPosition(pCurrent);
693
694 FilterMediaSeeking->Release();
695 return hr;
696 }
697
698 HRESULT
699 STDMETHODCALLTYPE
700 COutputPin::ConvertTimeFormat(
701 LONGLONG *pTarget,
702 const GUID *pTargetFormat,
703 LONGLONG Source,
704 const GUID *pSourceFormat)
705 {
706 IMediaSeeking * FilterMediaSeeking;
707 HRESULT hr;
708
709 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
710 if (FAILED(hr))
711 return hr;
712
713 hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
714
715 FilterMediaSeeking->Release();
716 return hr;
717 }
718
719 HRESULT
720 STDMETHODCALLTYPE
721 COutputPin::SetPositions(
722 LONGLONG *pCurrent,
723 DWORD dwCurrentFlags,
724 LONGLONG *pStop,
725 DWORD dwStopFlags)
726 {
727 IMediaSeeking * FilterMediaSeeking;
728 HRESULT hr;
729
730 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
731 if (FAILED(hr))
732 return hr;
733
734 hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
735
736 FilterMediaSeeking->Release();
737 return hr;
738 }
739
740 HRESULT
741 STDMETHODCALLTYPE
742 COutputPin::GetPositions(
743 LONGLONG *pCurrent,
744 LONGLONG *pStop)
745 {
746 IMediaSeeking * FilterMediaSeeking;
747 HRESULT hr;
748
749 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
750 if (FAILED(hr))
751 return hr;
752
753 hr = FilterMediaSeeking->GetPositions(pCurrent, pStop);
754
755 FilterMediaSeeking->Release();
756 return hr;
757 }
758
759 HRESULT
760 STDMETHODCALLTYPE
761 COutputPin::GetAvailable(
762 LONGLONG *pEarliest,
763 LONGLONG *pLatest)
764 {
765 IMediaSeeking * FilterMediaSeeking;
766 HRESULT hr;
767
768 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
769 if (FAILED(hr))
770 return hr;
771
772 hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest);
773
774 FilterMediaSeeking->Release();
775 return hr;
776 }
777
778 HRESULT
779 STDMETHODCALLTYPE
780 COutputPin::SetRate(
781 double dRate)
782 {
783 IMediaSeeking * FilterMediaSeeking;
784 HRESULT hr;
785
786 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
787 if (FAILED(hr))
788 return hr;
789
790 hr = FilterMediaSeeking->SetRate(dRate);
791
792 FilterMediaSeeking->Release();
793 return hr;
794 }
795
796 HRESULT
797 STDMETHODCALLTYPE
798 COutputPin::GetRate(
799 double *pdRate)
800 {
801 IMediaSeeking * FilterMediaSeeking;
802 HRESULT hr;
803
804 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
805 if (FAILED(hr))
806 return hr;
807
808 hr = FilterMediaSeeking->GetRate(pdRate);
809
810 FilterMediaSeeking->Release();
811 return hr;
812 }
813
814 HRESULT
815 STDMETHODCALLTYPE
816 COutputPin::GetPreroll(
817 LONGLONG *pllPreroll)
818 {
819 IMediaSeeking * FilterMediaSeeking;
820 HRESULT hr;
821
822 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
823 if (FAILED(hr))
824 return hr;
825
826 hr = FilterMediaSeeking->GetPreroll(pllPreroll);
827
828 FilterMediaSeeking->Release();
829 return hr;
830 }
831
832 //-------------------------------------------------------------------
833 // IQualityControl interface
834 //
835 HRESULT
836 STDMETHODCALLTYPE
837 COutputPin::Notify(
838 IBaseFilter *pSelf,
839 Quality q)
840 {
841 #ifdef KSPROXY_TRACE
842 OutputDebugStringW(L"COutputPin::Notify NotImplemented\n");
843 #endif
844 return E_NOTIMPL;
845 }
846
847 HRESULT
848 STDMETHODCALLTYPE
849 COutputPin::SetSink(
850 IQualityControl *piqc)
851 {
852 #ifdef KSPROXY_TRACE
853 OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n");
854 #endif
855 return E_NOTIMPL;
856 }
857
858
859 //-------------------------------------------------------------------
860 // IKsAggregateControl interface
861 //
862 HRESULT
863 STDMETHODCALLTYPE
864 COutputPin::KsAddAggregate(
865 IN REFGUID AggregateClass)
866 {
867 #ifdef KSPROXY_TRACE
868 OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n");
869 #endif
870 return E_NOTIMPL;
871 }
872
873 HRESULT
874 STDMETHODCALLTYPE
875 COutputPin::KsRemoveAggregate(
876 REFGUID AggregateClass)
877 {
878 #ifdef KSPROXY_TRACE
879 OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n");
880 #endif
881 return E_NOTIMPL;
882 }
883
884
885 //-------------------------------------------------------------------
886 // IKsPin
887 //
888
889 HRESULT
890 STDMETHODCALLTYPE
891 COutputPin::KsQueryMediums(
892 PKSMULTIPLE_ITEM* MediumList)
893 {
894 HRESULT hr;
895 HANDLE hFilter;
896 IKsObject * KsObjectParent;
897
898 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
899 if (FAILED(hr))
900 return E_NOINTERFACE;
901
902 hFilter = KsObjectParent->KsGetObjectHandle();
903
904 if (hFilter)
905 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
906 else
907 hr = E_HANDLE;
908
909 KsObjectParent->Release();
910
911 return hr;
912 }
913
914 HRESULT
915 STDMETHODCALLTYPE
916 COutputPin::KsQueryInterfaces(
917 PKSMULTIPLE_ITEM* InterfaceList)
918 {
919 HRESULT hr;
920 HANDLE hFilter;
921 IKsObject * KsObjectParent;
922
923 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
924 if (FAILED(hr))
925 return hr;
926
927 hFilter = KsObjectParent->KsGetObjectHandle();
928
929 if (hFilter)
930 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
931 else
932 hr = E_HANDLE;
933
934 KsObjectParent->Release();
935
936 return hr;
937 }
938
939 HRESULT
940 STDMETHODCALLTYPE
941 COutputPin::KsCreateSinkPinHandle(
942 KSPIN_INTERFACE& Interface,
943 KSPIN_MEDIUM& Medium)
944 {
945 #ifdef KSPROXY_TRACE
946 OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n");
947 #endif
948 return E_NOTIMPL;
949 }
950
951 HRESULT
952 STDMETHODCALLTYPE
953 COutputPin::KsGetCurrentCommunication(
954 KSPIN_COMMUNICATION *Communication,
955 KSPIN_INTERFACE *Interface,
956 KSPIN_MEDIUM *Medium)
957 {
958 if (Communication)
959 {
960 *Communication = m_Communication;
961 }
962
963 if (Interface)
964 {
965 if (!m_hPin)
966 return VFW_E_NOT_CONNECTED;
967
968 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
969 }
970
971 if (Medium)
972 {
973 if (!m_hPin)
974 return VFW_E_NOT_CONNECTED;
975
976 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
977 }
978 return NOERROR;
979 }
980
981 HRESULT
982 STDMETHODCALLTYPE
983 COutputPin::KsPropagateAcquire()
984 {
985 KSPROPERTY Property;
986 KSSTATE State;
987 ULONG BytesReturned;
988 HRESULT hr;
989
990 #ifdef KSPROXY_TRACE
991 OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n");
992 #endif
993
994 assert(m_hPin != INVALID_HANDLE_VALUE);
995
996 Property.Set = KSPROPSETID_Connection;
997 Property.Id = KSPROPERTY_CONNECTION_STATE;
998 Property.Flags = KSPROPERTY_TYPE_SET;
999
1000 State = KSSTATE_ACQUIRE;
1001
1002 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
1003 if (SUCCEEDED(hr))
1004 {
1005 m_State = State;
1006 }
1007
1008 //TODO
1009 //propagate to connected pin on the pipe
1010
1011 return hr;
1012 }
1013
1014 HRESULT
1015 STDMETHODCALLTYPE
1016 COutputPin::KsDeliver(
1017 IMediaSample* Sample,
1018 ULONG Flags)
1019 {
1020 return E_FAIL;
1021 }
1022
1023 HRESULT
1024 STDMETHODCALLTYPE
1025 COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
1026 {
1027 return NOERROR;
1028 }
1029
1030 IMemAllocator *
1031 STDMETHODCALLTYPE
1032 COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
1033 {
1034 if (Operation == KsPeekOperation_AddRef)
1035 {
1036 // add reference on allocator
1037 m_MemAllocator->AddRef();
1038 }
1039
1040 return m_MemAllocator;
1041 }
1042
1043 HRESULT
1044 STDMETHODCALLTYPE
1045 COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
1046 {
1047 if (MemAllocator)
1048 {
1049 MemAllocator->AddRef();
1050 }
1051
1052 if (m_MemAllocator)
1053 {
1054 m_MemAllocator->Release();
1055 }
1056
1057 m_MemAllocator = MemAllocator;
1058 return NOERROR;
1059 }
1060
1061 HRESULT
1062 STDMETHODCALLTYPE
1063 COutputPin::KsRenegotiateAllocator()
1064 {
1065 return E_FAIL;
1066 }
1067
1068 LONG
1069 STDMETHODCALLTYPE
1070 COutputPin::KsIncrementPendingIoCount()
1071 {
1072 return InterlockedIncrement((volatile LONG*)&m_IoCount);
1073 }
1074
1075 LONG
1076 STDMETHODCALLTYPE
1077 COutputPin::KsDecrementPendingIoCount()
1078 {
1079 return InterlockedDecrement((volatile LONG*)&m_IoCount);
1080 }
1081
1082 HRESULT
1083 STDMETHODCALLTYPE
1084 COutputPin::KsQualityNotify(
1085 ULONG Proportion,
1086 REFERENCE_TIME TimeDelta)
1087 {
1088 #ifdef KSPROXY_TRACE
1089 OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n");
1090 #endif
1091 return E_NOTIMPL;
1092 }
1093
1094 //-------------------------------------------------------------------
1095 // IKsPinEx
1096 //
1097
1098 VOID
1099 STDMETHODCALLTYPE
1100 COutputPin::KsNotifyError(
1101 IMediaSample* Sample,
1102 HRESULT hr)
1103 {
1104 #ifdef KSPROXY_TRACE
1105 OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n");
1106 #endif
1107 }
1108
1109
1110 //-------------------------------------------------------------------
1111 // IKsPinPipe
1112 //
1113
1114 HRESULT
1115 STDMETHODCALLTYPE
1116 COutputPin::KsGetPinFramingCache(
1117 PKSALLOCATOR_FRAMING_EX *FramingEx,
1118 PFRAMING_PROP FramingProp,
1119 FRAMING_CACHE_OPS Option)
1120 {
1121 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
1122 {
1123 // invalid argument
1124 return E_INVALIDARG;
1125 }
1126
1127 // get framing properties
1128 *FramingProp = m_FramingProp[Option];
1129 *FramingEx = m_FramingEx[Option];
1130
1131 return NOERROR;
1132 }
1133
1134 HRESULT
1135 STDMETHODCALLTYPE
1136 COutputPin::KsSetPinFramingCache(
1137 PKSALLOCATOR_FRAMING_EX FramingEx,
1138 PFRAMING_PROP FramingProp,
1139 FRAMING_CACHE_OPS Option)
1140 {
1141 ULONG Index;
1142 ULONG RefCount = 0;
1143
1144 if (m_FramingEx[Option])
1145 {
1146 for(Index = 1; Index < 4; Index++)
1147 {
1148 if (m_FramingEx[Index] == m_FramingEx[Option])
1149 RefCount++;
1150 }
1151
1152 if (RefCount == 1)
1153 {
1154 // existing framing is only used once
1155 CoTaskMemFree(m_FramingEx[Option]);
1156 }
1157 }
1158
1159 // store framing
1160 m_FramingEx[Option] = FramingEx;
1161 m_FramingProp[Option] = *FramingProp;
1162
1163 return S_OK;
1164 }
1165
1166 IPin*
1167 STDMETHODCALLTYPE
1168 COutputPin::KsGetConnectedPin()
1169 {
1170 return m_Pin;
1171 }
1172
1173 IKsAllocatorEx*
1174 STDMETHODCALLTYPE
1175 COutputPin::KsGetPipe(
1176 KSPEEKOPERATION Operation)
1177 {
1178 if (Operation == KsPeekOperation_AddRef)
1179 {
1180 if (m_KsAllocatorEx)
1181 m_KsAllocatorEx->AddRef();
1182 }
1183 return m_KsAllocatorEx;
1184 }
1185
1186 HRESULT
1187 STDMETHODCALLTYPE
1188 COutputPin::KsSetPipe(
1189 IKsAllocatorEx *KsAllocator)
1190 {
1191 if (KsAllocator)
1192 KsAllocator->AddRef();
1193
1194 if (m_KsAllocatorEx)
1195 m_KsAllocatorEx->Release();
1196
1197 m_KsAllocatorEx = KsAllocator;
1198 return NOERROR;
1199 }
1200
1201 ULONG
1202 STDMETHODCALLTYPE
1203 COutputPin::KsGetPipeAllocatorFlag()
1204 {
1205 return m_PipeAllocatorFlag;
1206 }
1207
1208
1209 HRESULT
1210 STDMETHODCALLTYPE
1211 COutputPin::KsSetPipeAllocatorFlag(
1212 ULONG Flag)
1213 {
1214 m_PipeAllocatorFlag = Flag;
1215 return NOERROR;
1216 }
1217
1218 GUID
1219 STDMETHODCALLTYPE
1220 COutputPin::KsGetPinBusCache()
1221 {
1222 if (!m_bPinBusCacheInitialized)
1223 {
1224 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
1225 m_bPinBusCacheInitialized = TRUE;
1226 }
1227
1228 return m_PinBusCache;
1229 }
1230
1231 HRESULT
1232 STDMETHODCALLTYPE
1233 COutputPin::KsSetPinBusCache(
1234 GUID Bus)
1235 {
1236 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
1237 return NOERROR;
1238 }
1239
1240 PWCHAR
1241 STDMETHODCALLTYPE
1242 COutputPin::KsGetPinName()
1243 {
1244 return (PWCHAR)m_PinName;
1245 }
1246
1247
1248 PWCHAR
1249 STDMETHODCALLTYPE
1250 COutputPin::KsGetFilterName()
1251 {
1252 return m_FilterName;
1253 }
1254
1255 //-------------------------------------------------------------------
1256 // ISpecifyPropertyPages
1257 //
1258
1259 HRESULT
1260 STDMETHODCALLTYPE
1261 COutputPin::GetPages(CAUUID *pPages)
1262 {
1263 #ifdef KSPROXY_TRACE
1264 OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
1265 #endif
1266
1267 if (!pPages)
1268 return E_POINTER;
1269
1270 pPages->cElems = 0;
1271 pPages->pElems = NULL;
1272
1273 return S_OK;
1274 }
1275
1276 //-------------------------------------------------------------------
1277 // IKsPinFactory
1278 //
1279
1280 HRESULT
1281 STDMETHODCALLTYPE
1282 COutputPin::KsPinFactory(
1283 ULONG* PinFactory)
1284 {
1285 #ifdef KSPROXY_TRACE
1286 OutputDebugStringW(L"COutputPin::KsPinFactory\n");
1287 #endif
1288
1289 *PinFactory = m_PinId;
1290 return S_OK;
1291 }
1292
1293
1294 //-------------------------------------------------------------------
1295 // IStreamBuilder
1296 //
1297
1298 HRESULT
1299 STDMETHODCALLTYPE
1300 COutputPin::Render(
1301 IPin *ppinOut,
1302 IGraphBuilder *pGraph)
1303 {
1304 #ifdef KSPROXY_TRACE
1305 OutputDebugStringW(L"COutputPin::Render\n");
1306 #endif
1307 return S_OK;
1308 }
1309
1310 HRESULT
1311 STDMETHODCALLTYPE
1312 COutputPin::Backout(
1313 IPin *ppinOut,
1314 IGraphBuilder *pGraph)
1315 {
1316 #ifdef KSPROXY_TRACE
1317 OutputDebugStringW(L"COutputPin::Backout\n");
1318 #endif
1319
1320 return S_OK;
1321 }
1322 //-------------------------------------------------------------------
1323 // IKsObject
1324 //
1325 HANDLE
1326 STDMETHODCALLTYPE
1327 COutputPin::KsGetObjectHandle()
1328 {
1329 #ifdef KSPROXY_TRACE
1330 OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");
1331 #endif
1332
1333 assert(m_hPin != INVALID_HANDLE_VALUE);
1334 return m_hPin;
1335 }
1336
1337 //-------------------------------------------------------------------
1338 // IKsControl
1339 //
1340 HRESULT
1341 STDMETHODCALLTYPE
1342 COutputPin::KsProperty(
1343 PKSPROPERTY Property,
1344 ULONG PropertyLength,
1345 LPVOID PropertyData,
1346 ULONG DataLength,
1347 ULONG* BytesReturned)
1348 {
1349 HRESULT hr;
1350
1351 assert(m_hPin != INVALID_HANDLE_VALUE);
1352
1353 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
1354 #ifdef KSPROXY_TRACE
1355 WCHAR Buffer[100];
1356 LPOLESTR pstr;
1357 StringFromCLSID(Property->Set, &pstr);
1358 swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr);
1359 OutputDebugStringW(Buffer);
1360 #endif
1361
1362 return hr;
1363 }
1364
1365 HRESULT
1366 STDMETHODCALLTYPE
1367 COutputPin::KsMethod(
1368 PKSMETHOD Method,
1369 ULONG MethodLength,
1370 LPVOID MethodData,
1371 ULONG DataLength,
1372 ULONG* BytesReturned)
1373 {
1374 assert(m_hPin != INVALID_HANDLE_VALUE);
1375 #ifdef KSPROXY_TRACE
1376 OutputDebugStringW(L"COutputPin::KsMethod\n");
1377 #endif
1378 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
1379 }
1380
1381 HRESULT
1382 STDMETHODCALLTYPE
1383 COutputPin::KsEvent(
1384 PKSEVENT Event,
1385 ULONG EventLength,
1386 LPVOID EventData,
1387 ULONG DataLength,
1388 ULONG* BytesReturned)
1389 {
1390 assert(m_hPin != INVALID_HANDLE_VALUE);
1391
1392 #ifdef KSPROXY_TRACE
1393 OutputDebugStringW(L"COutputPin::KsEvent\n");
1394 #endif
1395
1396 if (EventLength)
1397 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
1398 else
1399 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
1400 }
1401
1402
1403 //-------------------------------------------------------------------
1404 // IKsPropertySet
1405 //
1406 HRESULT
1407 STDMETHODCALLTYPE
1408 COutputPin::Set(
1409 REFGUID guidPropSet,
1410 DWORD dwPropID,
1411 LPVOID pInstanceData,
1412 DWORD cbInstanceData,
1413 LPVOID pPropData,
1414 DWORD cbPropData)
1415 {
1416 ULONG BytesReturned;
1417
1418 if (cbInstanceData)
1419 {
1420 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1421 if (!Property)
1422 return E_OUTOFMEMORY;
1423
1424 Property->Set = guidPropSet;
1425 Property->Id = dwPropID;
1426 Property->Flags = KSPROPERTY_TYPE_SET;
1427
1428 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1429
1430 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1431 CoTaskMemFree(Property);
1432 return hr;
1433 }
1434 else
1435 {
1436 KSPROPERTY Property;
1437
1438 Property.Set = guidPropSet;
1439 Property.Id = dwPropID;
1440 Property.Flags = KSPROPERTY_TYPE_SET;
1441
1442 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1443 return hr;
1444 }
1445 }
1446
1447 HRESULT
1448 STDMETHODCALLTYPE
1449 COutputPin::Get(
1450 REFGUID guidPropSet,
1451 DWORD dwPropID,
1452 LPVOID pInstanceData,
1453 DWORD cbInstanceData,
1454 LPVOID pPropData,
1455 DWORD cbPropData,
1456 DWORD *pcbReturned)
1457 {
1458 ULONG BytesReturned;
1459
1460 if (cbInstanceData)
1461 {
1462 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1463 if (!Property)
1464 return E_OUTOFMEMORY;
1465
1466 Property->Set = guidPropSet;
1467 Property->Id = dwPropID;
1468 Property->Flags = KSPROPERTY_TYPE_GET;
1469
1470 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1471
1472 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1473 CoTaskMemFree(Property);
1474 return hr;
1475 }
1476 else
1477 {
1478 KSPROPERTY Property;
1479
1480 Property.Set = guidPropSet;
1481 Property.Id = dwPropID;
1482 Property.Flags = KSPROPERTY_TYPE_GET;
1483
1484 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1485 return hr;
1486 }
1487 }
1488
1489 HRESULT
1490 STDMETHODCALLTYPE
1491 COutputPin::QuerySupported(
1492 REFGUID guidPropSet,
1493 DWORD dwPropID,
1494 DWORD *pTypeSupport)
1495 {
1496 KSPROPERTY Property;
1497 ULONG BytesReturned;
1498
1499 #ifdef KSPROXY_TRACE
1500 OutputDebugStringW(L"COutputPin::QuerySupported\n");
1501 #endif
1502
1503 Property.Set = guidPropSet;
1504 Property.Id = dwPropID;
1505 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1506
1507 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1508 }
1509
1510
1511 //-------------------------------------------------------------------
1512 // IPin interface
1513 //
1514 HRESULT
1515 STDMETHODCALLTYPE
1516 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1517 {
1518 HRESULT hr;
1519 ALLOCATOR_PROPERTIES Properties;
1520 IMemAllocatorCallbackTemp *pMemCallback;
1521
1522 #ifdef KSPROXY_TRACE
1523 WCHAR Buffer[200];
1524 OutputDebugStringW(L"COutputPin::Connect called\n");
1525 #endif
1526
1527 if (pmt)
1528 {
1529 hr = pReceivePin->QueryAccept(pmt);
1530 if (FAILED(hr))
1531 return hr;
1532 }
1533 else
1534 {
1535 // query accept
1536 hr = pReceivePin->QueryAccept(&m_MediaFormat);
1537 if (FAILED(hr))
1538 return hr;
1539
1540 pmt = &m_MediaFormat;
1541 }
1542
1543 // query for IMemInput interface
1544 hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin);
1545 if (FAILED(hr))
1546 {
1547 #ifdef KSPROXY_TRACE
1548 OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");
1549 #endif
1550
1551 DebugBreak();
1552 return hr;
1553 }
1554
1555 // get input pin allocator properties
1556 ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES));
1557 m_MemInputPin->GetAllocatorRequirements(&Properties);
1558
1559 //FIXME determine allocator properties
1560 Properties.cBuffers = 32;
1561 Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size
1562 Properties.cbAlign = 4;
1563
1564 // get input pin allocator
1565 #if 0
1566 hr = m_MemInputPin->GetAllocator(&m_MemAllocator);
1567 if (SUCCEEDED(hr))
1568 {
1569 // set allocator properties
1570 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties);
1571 if (FAILED(hr))
1572 m_MemAllocator->Release();
1573 }
1574 #endif
1575
1576 if (1)
1577 {
1578 hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator);
1579 if (FAILED(hr))
1580 return hr;
1581
1582 // set allocator properties
1583 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties);
1584 if (FAILED(hr))
1585 {
1586 #ifdef KSPROXY_TRACE
1587 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr);
1588 OutputDebugStringW(Buffer);
1589 #endif
1590 m_MemAllocator->Release();
1591 m_MemInputPin->Release();
1592 return hr;
1593 }
1594 }
1595
1596 // commit property changes
1597 hr = m_MemAllocator->Commit();
1598 if (FAILED(hr))
1599 {
1600 #ifdef KSPROXY_TRACE
1601 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr);
1602 OutputDebugStringW(Buffer);
1603 #endif
1604 m_MemAllocator->Release();
1605 m_MemInputPin->Release();
1606 return hr;
1607 }
1608
1609 // get callback interface
1610 hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback);
1611 if (FAILED(hr))
1612 {
1613 #ifdef KSPROXY_TRACE
1614 swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr);
1615 OutputDebugStringW(Buffer);
1616 #endif
1617 m_MemAllocator->Release();
1618 m_MemInputPin->Release();
1619 return hr;
1620 }
1621
1622 // set notification routine
1623 hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this);
1624
1625 // release IMemAllocatorNotifyCallbackTemp interface
1626 pMemCallback->Release();
1627
1628 if (FAILED(hr))
1629 {
1630 #ifdef KSPROXY_TRACE
1631 swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr);
1632 OutputDebugStringW(Buffer);
1633 #endif
1634 m_MemAllocator->Release();
1635 m_MemInputPin->Release();
1636 return hr;
1637 }
1638
1639 // now set allocator
1640 hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE);
1641 if (FAILED(hr))
1642 {
1643 #ifdef KSPROXY_TRACE
1644 swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr);
1645 OutputDebugStringW(Buffer);
1646 #endif
1647 m_MemAllocator->Release();
1648 m_MemInputPin->Release();
1649 return hr;
1650 }
1651
1652 if (!m_hPin)
1653 {
1654 //FIXME create pin handle
1655 assert(0);
1656 }
1657
1658 // receive connection;
1659 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
1660 if (SUCCEEDED(hr))
1661 {
1662 // increment reference count
1663 pReceivePin->AddRef();
1664 m_Pin = pReceivePin;
1665 #ifdef KSPROXY_TRACE
1666 OutputDebugStringW(L"COutputPin::Connect success\n");
1667 #endif
1668 }
1669 else
1670 {
1671 m_MemInputPin->Release();
1672 m_MemAllocator->Release();
1673 }
1674
1675 return hr;
1676 }
1677
1678 HRESULT
1679 STDMETHODCALLTYPE
1680 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1681 {
1682 return E_UNEXPECTED;
1683 }
1684 HRESULT
1685 STDMETHODCALLTYPE
1686 COutputPin::Disconnect( void)
1687 {
1688 #ifdef KSPROXY_TRACE
1689 OutputDebugStringW(L"COutputPin::Disconnect\n");
1690 #endif
1691
1692 if (!m_Pin)
1693 {
1694 // pin was not connected
1695 return S_FALSE;
1696 }
1697
1698 //FIXME
1699 //check if filter is active
1700
1701 m_Pin->Release();
1702 m_Pin = NULL;
1703 m_MemInputPin->Release();
1704 m_MemAllocator->Release();
1705
1706 CloseHandle(m_hPin);
1707 m_hPin = INVALID_HANDLE_VALUE;
1708
1709 #ifdef KSPROXY_TRACE
1710 OutputDebugStringW(L"COutputPin::Disconnect\n");
1711 #endif
1712 return S_OK;
1713 }
1714 HRESULT
1715 STDMETHODCALLTYPE
1716 COutputPin::ConnectedTo(IPin **pPin)
1717 {
1718 #ifdef KSPROXY_TRACE
1719 OutputDebugStringW(L"COutputPin::ConnectedTo\n");
1720 #endif
1721
1722 if (!pPin)
1723 return E_POINTER;
1724
1725 if (m_Pin)
1726 {
1727 // increment reference count
1728 m_Pin->AddRef();
1729 *pPin = m_Pin;
1730 return S_OK;
1731 }
1732
1733 *pPin = NULL;
1734 return VFW_E_NOT_CONNECTED;
1735 }
1736 HRESULT
1737 STDMETHODCALLTYPE
1738 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1739 {
1740 #ifdef KSPROXY_TRACE
1741 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");
1742 #endif
1743
1744 return E_NOTIMPL;
1745 }
1746 HRESULT
1747 STDMETHODCALLTYPE
1748 COutputPin::QueryPinInfo(PIN_INFO *pInfo)
1749 {
1750 wcscpy(pInfo->achName, m_PinName);
1751 pInfo->dir = PINDIR_OUTPUT;
1752 pInfo->pFilter = m_ParentFilter;
1753 m_ParentFilter->AddRef();
1754
1755 return S_OK;
1756 }
1757 HRESULT
1758 STDMETHODCALLTYPE
1759 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1760 {
1761 if (pPinDir)
1762 {
1763 *pPinDir = PINDIR_OUTPUT;
1764 return S_OK;
1765 }
1766
1767 return E_POINTER;
1768 }
1769 HRESULT
1770 STDMETHODCALLTYPE
1771 COutputPin::QueryId(LPWSTR *Id)
1772 {
1773 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1774 if (!*Id)
1775 return E_OUTOFMEMORY;
1776
1777 wcscpy(*Id, m_PinName);
1778 return S_OK;
1779 }
1780 HRESULT
1781 STDMETHODCALLTYPE
1782 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
1783 {
1784 #ifdef KSPROXY_TRACE
1785 OutputDebugStringW(L"COutputPin::QueryAccept called\n");
1786 #endif
1787
1788 return E_NOTIMPL;
1789 }
1790 HRESULT
1791 STDMETHODCALLTYPE
1792 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1793 {
1794 HRESULT hr;
1795 ULONG MediaTypeCount = 0, Index;
1796 AM_MEDIA_TYPE * MediaTypes;
1797 HANDLE hFilter;
1798 IKsObject * KsObjectParent;
1799
1800 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1801 if (FAILED(hr))
1802 return hr;
1803
1804 // get parent filter handle
1805 hFilter = KsObjectParent->KsGetObjectHandle();
1806
1807 // release IKsObject
1808 KsObjectParent->Release();
1809
1810 // query media type count
1811 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1812 if (FAILED(hr) || !MediaTypeCount)
1813 {
1814 return hr;
1815 }
1816
1817 // allocate media types
1818 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1819 if (!MediaTypes)
1820 {
1821 // not enough memory
1822 return E_OUTOFMEMORY;
1823 }
1824
1825 // zero media types
1826 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1827
1828 for(Index = 0; Index < MediaTypeCount; Index++)
1829 {
1830 // get media type
1831 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1832 if (FAILED(hr))
1833 {
1834 // failed
1835 CoTaskMemFree(MediaTypes);
1836 return hr;
1837 }
1838 }
1839
1840 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1841 }
1842 HRESULT
1843 STDMETHODCALLTYPE
1844 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1845 {
1846 return E_NOTIMPL;
1847 }
1848 HRESULT
1849 STDMETHODCALLTYPE
1850 COutputPin::EndOfStream( void)
1851 {
1852 /* should be called only on input pins */
1853 return E_UNEXPECTED;
1854 }
1855 HRESULT
1856 STDMETHODCALLTYPE
1857 COutputPin::BeginFlush( void)
1858 {
1859 /* should be called only on input pins */
1860 return E_UNEXPECTED;
1861 }
1862 HRESULT
1863 STDMETHODCALLTYPE
1864 COutputPin::EndFlush( void)
1865 {
1866 /* should be called only on input pins */
1867 return E_UNEXPECTED;
1868 }
1869 HRESULT
1870 STDMETHODCALLTYPE
1871 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1872 {
1873 if (!m_Pin)
1874 {
1875 // we are not connected
1876 return VFW_E_NOT_CONNECTED;
1877 }
1878
1879 return m_Pin->NewSegment(tStart, tStop, dRate);
1880 }
1881
1882 //-------------------------------------------------------------------
1883 HRESULT
1884 STDMETHODCALLTYPE
1885 COutputPin::CheckFormat(
1886 const AM_MEDIA_TYPE *pmt)
1887 {
1888 PKSMULTIPLE_ITEM MultipleItem;
1889 PKSDATAFORMAT DataFormat;
1890 HRESULT hr;
1891 IKsObject * KsObjectParent;
1892 HANDLE hFilter;
1893
1894 if (!pmt)
1895 return E_POINTER;
1896
1897 // get IKsObject interface
1898 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1899 if (FAILED(hr))
1900 return hr;
1901
1902 // get parent filter handle
1903 hFilter = KsObjectParent->KsGetObjectHandle();
1904
1905 // release IKsObject
1906 KsObjectParent->Release();
1907
1908 if (!hFilter)
1909 return E_HANDLE;
1910
1911
1912 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1913 if (FAILED(hr))
1914 return S_FALSE;
1915
1916 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1917 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1918 {
1919 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1920 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1921 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1922 {
1923 // format is supported
1924 CoTaskMemFree(MultipleItem);
1925 return S_OK;
1926 }
1927 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1928 }
1929 //format is not supported
1930 CoTaskMemFree(MultipleItem);
1931 return S_FALSE;
1932 }
1933
1934 HRESULT
1935 STDMETHODCALLTYPE
1936 COutputPin::CreatePin(
1937 const AM_MEDIA_TYPE *pmt)
1938 {
1939 PKSMULTIPLE_ITEM MediumList;
1940 PKSMULTIPLE_ITEM InterfaceList;
1941 PKSPIN_MEDIUM Medium;
1942 PKSPIN_INTERFACE Interface;
1943 IKsInterfaceHandler * InterfaceHandler;
1944 HRESULT hr;
1945
1946 // query for pin medium
1947 hr = KsQueryMediums(&MediumList);
1948 if (FAILED(hr))
1949 return hr;
1950
1951 // query for pin interface
1952 hr = KsQueryInterfaces(&InterfaceList);
1953 if (FAILED(hr))
1954 {
1955 // failed
1956 CoTaskMemFree(MediumList);
1957 return hr;
1958 }
1959
1960 if (MediumList->Count)
1961 {
1962 //use first available medium
1963 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1964 }
1965 else
1966 {
1967 // default to standard medium
1968 Medium = &StandardPinMedium;
1969 }
1970
1971 if (InterfaceList->Count)
1972 {
1973 //use first available interface
1974 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1975 }
1976 else
1977 {
1978 // default to standard interface
1979 Interface = &StandardPinInterface;
1980 }
1981
1982 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1983 {
1984 // now create pin
1985 hr = CreatePinHandle(Medium, Interface, pmt);
1986 if (FAILED(hr))
1987 {
1988 m_InterfaceHandler->Release();
1989 m_InterfaceHandler = InterfaceHandler;
1990 }
1991
1992 if (!m_InterfaceHandler)
1993 {
1994 // now load the IKsInterfaceHandler plugin
1995 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1996 if (FAILED(hr))
1997 {
1998 // failed to load interface handler plugin
1999 CoTaskMemFree(MediumList);
2000 CoTaskMemFree(InterfaceList);
2001
2002 return hr;
2003 }
2004
2005 // now set the pin
2006 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
2007 if (FAILED(hr))
2008 {
2009 // failed to load interface handler plugin
2010 InterfaceHandler->Release();
2011 CoTaskMemFree(MediumList);
2012 CoTaskMemFree(InterfaceList);
2013 return hr;
2014 }
2015
2016 // store interface handler
2017 m_InterfaceHandler = InterfaceHandler;
2018 }
2019 }
2020 else
2021 {
2022 #ifdef KSPROXY_TRACE
2023 WCHAR Buffer[100];
2024 swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
2025 OutputDebugStringW(Buffer);
2026 DebugBreak();
2027 #endif
2028
2029 hr = E_FAIL;
2030 }
2031
2032 // free medium / interface / dataformat
2033 CoTaskMemFree(MediumList);
2034 CoTaskMemFree(InterfaceList);
2035
2036 return hr;
2037 }
2038
2039 HRESULT
2040 STDMETHODCALLTYPE
2041 COutputPin::CreatePinHandle(
2042 PKSPIN_MEDIUM Medium,
2043 PKSPIN_INTERFACE Interface,
2044 const AM_MEDIA_TYPE *pmt)
2045 {
2046 PKSPIN_CONNECT PinConnect;
2047 PKSDATAFORMAT DataFormat;
2048 ULONG Length;
2049 HRESULT hr;
2050 HANDLE hFilter;
2051 IKsObject * KsObjectParent;
2052
2053 //KSALLOCATOR_FRAMING Framing;
2054 //KSPROPERTY Property;
2055 //ULONG BytesReturned;
2056
2057 if (m_hPin != INVALID_HANDLE_VALUE)
2058 {
2059 // pin already exists
2060 //CloseHandle(m_hPin);
2061 //m_hPin = INVALID_HANDLE_VALUE;
2062 return S_OK;
2063 }
2064
2065
2066 // calc format size
2067 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
2068
2069 // allocate pin connect
2070 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
2071 if (!PinConnect)
2072 {
2073 // failed
2074 return E_OUTOFMEMORY;
2075 }
2076
2077 // setup request
2078 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
2079 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
2080 PinConnect->PinId = m_PinId;
2081 PinConnect->PinToHandle = NULL;
2082 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
2083 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
2084
2085 // get dataformat offset
2086 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
2087
2088 // copy data format
2089 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
2090 DataFormat->Flags = 0;
2091 DataFormat->SampleSize = pmt->lSampleSize;
2092 DataFormat->Reserved = 0;
2093 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
2094 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
2095 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
2096
2097 if (pmt->cbFormat)
2098 {
2099 // copy extended format
2100 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
2101 }
2102
2103 // get IKsObject interface
2104 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
2105 if (FAILED(hr))
2106 return hr;
2107
2108 // get parent filter handle
2109 hFilter = KsObjectParent->KsGetObjectHandle();
2110
2111 // release IKsObject
2112 KsObjectParent->Release();
2113
2114 if (!hFilter)
2115 return E_HANDLE;
2116
2117 // create pin
2118 hr = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
2119
2120 if (SUCCEEDED(hr))
2121 {
2122 // store current interface / medium
2123 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
2124 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
2125 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
2126
2127 #ifdef KSPROXY_TRACE
2128 LPOLESTR pMajor, pSub, pFormat;
2129 StringFromIID(m_MediaFormat.majortype, &pMajor);
2130 StringFromIID(m_MediaFormat.subtype , &pSub);
2131 StringFromIID(m_MediaFormat.formattype, &pFormat);
2132 WCHAR Buffer[200];
2133 swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
2134 CoTaskMemFree(pMajor);
2135 CoTaskMemFree(pSub);
2136 CoTaskMemFree(pFormat);
2137 OutputDebugStringW(Buffer);
2138 #endif
2139
2140 if (pmt->cbFormat)
2141 {
2142 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
2143 if (!m_MediaFormat.pbFormat)
2144 {
2145 CoTaskMemFree(PinConnect);
2146 m_MediaFormat.pbFormat = NULL;
2147 m_MediaFormat.cbFormat = 0;
2148 return E_OUTOFMEMORY;
2149 }
2150 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
2151 }
2152 #if 0
2153 Property.Set = KSPROPSETID_Connection;
2154 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
2155 Property.Flags = KSPROPERTY_TYPE_GET;
2156
2157 ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING));
2158 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
2159 if (SUCCEEDED(hr))
2160 {
2161 m_Properties.cbAlign = (Framing.FileAlignment + 1);
2162 m_Properties.cbBuffer = Framing.FrameSize;
2163 m_Properties.cbPrefix = 0; //FIXME
2164 m_Properties.cBuffers = Framing.Frames;
2165 }
2166 hr = S_OK;
2167 #endif
2168
2169 if (FAILED(InitializeIOThread()))
2170 {
2171 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
2172 DebugBreak();
2173 }
2174
2175 LPGUID pGuid;
2176 ULONG NumGuids = 0;
2177
2178 // get all supported sets
2179 hr = GetSupportedSets(&pGuid, &NumGuids);
2180 if (FAILED(hr))
2181 {
2182 #ifdef KSPROXY_TRACE
2183 OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
2184 #endif
2185 return hr;
2186 }
2187
2188 // load all proxy plugins
2189 hr = LoadProxyPlugins(pGuid, NumGuids);
2190 if (FAILED(hr))
2191 {
2192 #ifdef KSPROXY_TRACE
2193 OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
2194 #endif
2195 return hr;
2196 }
2197
2198 // free sets
2199 CoTaskMemFree(pGuid);
2200
2201
2202 //TODO
2203 // connect pin pipes
2204
2205 }
2206 // free pin connect
2207 CoTaskMemFree(PinConnect);
2208
2209 return hr;
2210 }
2211
2212 HRESULT
2213 STDMETHODCALLTYPE
2214 COutputPin::GetSupportedSets(
2215 LPGUID * pOutGuid,
2216 PULONG NumGuids)
2217 {
2218 KSPROPERTY Property;
2219 LPGUID pGuid;
2220 ULONG NumProperty = 0;
2221 ULONG NumMethods = 0;
2222 ULONG NumEvents = 0;
2223 ULONG Length;
2224 ULONG BytesReturned;
2225 HRESULT hr;
2226
2227 Property.Set = GUID_NULL;
2228 Property.Id = 0;
2229 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
2230
2231 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
2232 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
2233 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
2234
2235 Length = NumProperty + NumMethods + NumEvents;
2236
2237 // allocate guid buffer
2238 pGuid = (LPGUID)CoTaskMemAlloc(Length);
2239 if (!pGuid)
2240 {
2241 // failed
2242 return E_OUTOFMEMORY;
2243 }
2244
2245 NumProperty /= sizeof(GUID);
2246 NumMethods /= sizeof(GUID);
2247 NumEvents /= sizeof(GUID);
2248
2249 // get all properties
2250 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
2251 if (FAILED(hr))
2252 {
2253 CoTaskMemFree(pGuid);
2254 return E_FAIL;
2255 }
2256 Length -= BytesReturned;
2257
2258 // get all methods
2259 if (Length)
2260 {
2261 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
2262 if (FAILED(hr))
2263 {
2264 CoTaskMemFree(pGuid);
2265 return E_FAIL;
2266 }
2267 Length -= BytesReturned;
2268 }
2269
2270 // get all events
2271 if (Length)
2272 {
2273 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
2274 if (FAILED(hr))
2275 {
2276 CoTaskMemFree(pGuid);
2277 return E_FAIL;
2278 }
2279 Length -= BytesReturned;
2280 }
2281
2282 #ifdef KSPROXY_TRACE
2283 WCHAR Buffer[200];
2284 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
2285 OutputDebugStringW(Buffer);
2286 #endif
2287
2288 *pOutGuid = pGuid;
2289 *NumGuids = NumProperty+NumEvents+NumMethods;
2290 return S_OK;
2291 }
2292
2293 HRESULT
2294 STDMETHODCALLTYPE
2295 COutputPin::LoadProxyPlugins(
2296 LPGUID pGuids,
2297 ULONG NumGuids)
2298 {
2299 ULONG Index;
2300 LPOLESTR pStr;
2301 HKEY hKey, hSubKey;
2302 HRESULT hr;
2303 IUnknown * pUnknown;
2304
2305 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
2306 {
2307 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
2308 return E_FAIL;
2309 }
2310
2311 // enumerate all sets
2312 for(Index = 0; Index < NumGuids; Index++)
2313 {
2314 // convert to string
2315 hr = StringFromCLSID(pGuids[Index], &pStr);
2316 if (FAILED(hr))
2317 return E_FAIL;
2318
2319 // now try open class key
2320 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
2321 {
2322 // no plugin for that set exists
2323 CoTaskMemFree(pStr);
2324 continue;
2325 }
2326
2327 // try load plugin
2328 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
2329 if (SUCCEEDED(hr))
2330 {
2331 // store plugin
2332 m_Plugins.push_back(pUnknown);
2333 }
2334 // close key
2335 RegCloseKey(hSubKey);
2336 }
2337
2338 // close media interfaces key
2339 RegCloseKey(hKey);
2340 return S_OK;
2341 }
2342
2343
2344 HRESULT
2345 WINAPI
2346 COutputPin::IoProcessRoutine()
2347 {
2348 IMediaSample *Sample;
2349 LONG SampleCount;
2350 HRESULT hr;
2351 PKSSTREAM_SEGMENT StreamSegment;
2352 HANDLE hEvent;
2353 IMediaSample * Samples[1];
2354
2355 #ifdef KSPROXY_TRACE
2356 WCHAR Buffer[200];
2357 #endif
2358
2359 // first wait for the start event to signal
2360 WaitForSingleObject(m_hStartEvent, INFINITE);
2361
2362 assert(m_InterfaceHandler);
2363 do
2364 {
2365 if (m_StopInProgress)
2366 {
2367 // stop io thread
2368 break;
2369 }
2370
2371 assert(m_State == KSSTATE_RUN);
2372 assert(m_MemAllocator);
2373
2374 // get buffer
2375 hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT);
2376
2377 if (FAILED(hr))
2378 {
2379 WaitForSingleObject(m_hBufferAvailable, INFINITE);
2380 // now retry again
2381 continue;
2382 }
2383
2384 // fill buffer
2385 SampleCount = 1;
2386 Samples[0] = Sample;
2387
2388 Sample->SetTime(NULL, NULL);
2389 hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
2390 Samples,
2391 &SampleCount,
2392 KsIoOperation_Read,
2393 &StreamSegment);
2394 if (FAILED(hr) || !StreamSegment)
2395 {
2396 #ifdef KSPROXY_TRACE
2397 swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr);
2398 OutputDebugStringW(Buffer);
2399 #endif
2400 break;
2401 }
2402
2403 // get completion event
2404 hEvent = StreamSegment->CompletionEvent;
2405
2406 // wait for i/o completion
2407 WaitForSingleObject(hEvent, INFINITE);
2408
2409 // perform completion
2410 m_InterfaceHandler->KsCompleteIo(StreamSegment);
2411
2412 // close completion event
2413 CloseHandle(hEvent);
2414
2415 if (SUCCEEDED(hr))
2416 {
2417 assert(m_MemInputPin);
2418
2419 // now deliver the sample
2420 hr = m_MemInputPin->Receive(Sample);
2421
2422 #ifdef KSPROXY_TRACE
2423 swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator);
2424 OutputDebugStringW(Buffer);
2425 #endif
2426
2427 if (FAILED(hr))
2428 break;
2429
2430 Sample = NULL;
2431 }
2432 }while(TRUE);
2433
2434 // signal end of i/o thread
2435 SetEvent(m_hStopEvent);
2436
2437 m_IoThreadStarted = false;
2438
2439 return NOERROR;
2440 }
2441
2442 DWORD
2443 WINAPI
2444 COutputPin_IoThreadStartup(
2445 LPVOID lpParameter)
2446 {
2447 COutputPin * Pin = (COutputPin*)lpParameter;
2448 assert(Pin);
2449
2450 return Pin->IoProcessRoutine();
2451 }
2452
2453
2454 HRESULT
2455 WINAPI
2456 COutputPin::InitializeIOThread()
2457 {
2458 HANDLE hThread;
2459
2460 if (m_IoThreadStarted)
2461 return NOERROR;
2462
2463 if (!m_hStartEvent)
2464 m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2465
2466 if (!m_hStartEvent)
2467 return E_OUTOFMEMORY;
2468
2469 if (!m_hStopEvent)
2470 m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2471
2472 if (!m_hStopEvent)
2473 return E_OUTOFMEMORY;
2474
2475 if (!m_hBufferAvailable)
2476 m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL);
2477
2478 if (!m_hBufferAvailable)
2479 return E_OUTOFMEMORY;
2480
2481 m_StopInProgress = false;
2482 m_IoThreadStarted = true;
2483
2484 // now create the startup thread
2485 hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL);
2486 if (!hThread)
2487 return E_OUTOFMEMORY;
2488
2489
2490 // close thread handle
2491 CloseHandle(hThread);
2492 return NOERROR;
2493 }
2494
2495 HRESULT
2496 STDMETHODCALLTYPE
2497 COutputPin_SetState(
2498 IPin * Pin,
2499 KSSTATE State)
2500 {
2501 HRESULT hr = S_OK;
2502 KSPROPERTY Property;
2503 KSSTATE CurState;
2504 ULONG BytesReturned;
2505 COutputPin * pPin = (COutputPin*)Pin;
2506
2507 #ifdef KSPROXY_TRACE
2508 WCHAR Buffer[200];
2509 #endif
2510
2511 Property.Set = KSPROPSETID_Connection;
2512 Property.Id = KSPROPERTY_CONNECTION_STATE;
2513 Property.Flags = KSPROPERTY_TYPE_SET;
2514
2515 EnterCriticalSection(&pPin->m_Lock);
2516
2517 if (pPin->m_State <= State)
2518 {
2519 if (pPin->m_State == KSSTATE_STOP)
2520 {
2521 hr = pPin->InitializeIOThread();
2522 if (FAILED(hr))
2523 {
2524 // failed to initialize I/O thread
2525 #ifdef KSPROXY_TRACE
2526 OutputDebugStringW(L"Failed to initialize I/O Thread\n");
2527 #endif
2528 LeaveCriticalSection(&pPin->m_Lock);
2529 return hr;
2530 }
2531 CurState = KSSTATE_ACQUIRE;
2532 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2533
2534 #ifdef KSPROXY_TRACE
2535 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
2536 OutputDebugStringW(Buffer);
2537 #endif
2538
2539 if (FAILED(hr))
2540 {
2541 LeaveCriticalSection(&pPin->m_Lock);
2542 return hr;
2543 }
2544
2545 pPin->m_State = CurState;
2546
2547 if (pPin->m_State == State)
2548 {
2549 LeaveCriticalSection(&pPin->m_Lock);
2550 return hr;
2551 }
2552 }
2553 if (pPin->m_State == KSSTATE_ACQUIRE)
2554 {
2555 CurState = KSSTATE_PAUSE;
2556 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2557
2558 #ifdef KSPROXY_TRACE
2559 swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
2560 OutputDebugStringW(Buffer);
2561 #endif
2562
2563 if (FAILED(hr))
2564 {
2565 LeaveCriticalSection(&pPin->m_Lock);
2566 return hr;
2567 }
2568
2569 pPin->m_State = CurState;
2570
2571 if (pPin->m_State == State)
2572 {
2573 LeaveCriticalSection(&pPin->m_Lock);
2574 return hr;
2575 }
2576 }
2577 if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE)
2578 {
2579 CurState = KSSTATE_RUN;
2580 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2581
2582 #ifdef KSPROXY_TRACE
2583 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr);
2584 OutputDebugStringW(Buffer);
2585 #endif
2586
2587 if (SUCCEEDED(hr))
2588 {
2589 pPin->m_State = CurState;
2590 // signal start event
2591 SetEvent(pPin->m_hStartEvent);
2592 }
2593 }
2594
2595 LeaveCriticalSection(&pPin->m_Lock);
2596 return hr;
2597 }
2598 else
2599 {
2600 if (pPin->m_State == KSSTATE_RUN)
2601 {
2602 // setting pending stop flag
2603 pPin->m_StopInProgress = true;
2604
2605 // release any waiting threads
2606 SetEvent(pPin->m_hBufferAvailable);
2607
2608 // wait until i/o thread is done
2609 WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
2610
2611 CurState = KSSTATE_PAUSE;
2612 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2613
2614 #ifdef KSPROXY_TRACE
2615 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
2616 OutputDebugStringW(Buffer);
2617 #endif
2618
2619 if (FAILED(hr))
2620 {
2621 LeaveCriticalSection(&pPin->m_Lock);
2622 return hr;
2623 }
2624
2625 pPin->m_State = CurState;
2626
2627 if (FAILED(hr))
2628 {
2629 LeaveCriticalSection(&pPin->m_Lock);
2630 return hr;
2631 }
2632 }
2633 if (pPin->m_State == KSSTATE_PAUSE)
2634 {
2635 CurState = KSSTATE_ACQUIRE;
2636 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2637
2638 #ifdef KSPROXY_TRACE
2639 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
2640 OutputDebugStringW(Buffer);
2641 #endif
2642
2643 if (FAILED(hr))
2644 {
2645 LeaveCriticalSection(&pPin->m_Lock);
2646 return hr;
2647 }
2648
2649 pPin->m_State = CurState;
2650
2651 if (pPin->m_State == State)
2652 {
2653 LeaveCriticalSection(&pPin->m_Lock);
2654 return hr;
2655 }
2656 }
2657
2658 CloseHandle(pPin->m_hStopEvent);
2659 CloseHandle(pPin->m_hStartEvent);
2660 CloseHandle(pPin->m_hBufferAvailable);
2661
2662 /* close event handles */
2663 pPin->m_hStopEvent = NULL;
2664 pPin->m_hStartEvent = NULL;
2665 pPin->m_hBufferAvailable = NULL;
2666
2667 CurState = KSSTATE_STOP;
2668 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2669
2670 #ifdef KSPROXY_TRACE
2671 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr);
2672 OutputDebugStringW(Buffer);
2673 #endif
2674
2675 if (SUCCEEDED(hr))
2676 {
2677 // store state
2678 pPin->m_State = CurState;
2679 }
2680
2681 // unset pending stop flag
2682 pPin->m_StopInProgress = false;
2683
2684 LeaveCriticalSection(&pPin->m_Lock);
2685 return hr;
2686 }
2687 }
2688
2689 HRESULT
2690 WINAPI
2691 COutputPin_Constructor(
2692 IBaseFilter * ParentFilter,
2693 LPCWSTR PinName,
2694 ULONG PinId,
2695 KSPIN_COMMUNICATION Communication,
2696 REFIID riid,
2697 LPVOID * ppv)
2698 {
2699 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
2700
2701 if (!handler)
2702 return E_OUTOFMEMORY;
2703
2704 if (FAILED(handler->QueryInterface(riid, ppv)))
2705 {
2706 /* not supported */
2707 delete handler;
2708 return E_NOINTERFACE;
2709 }
2710
2711 return S_OK;
2712 }