sync with trunk r46493
[reactos.git] / 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 #ifdef KSPROXY_TRACE
1989 WCHAR Buffer[100];
1990 swprintf(Buffer, L"COutputPin::CreatePinHandle failed with %lx\n", hr);
1991 OutputDebugStringW(Buffer);
1992 #endif
1993 return hr;
1994 }
1995
1996 if (!m_InterfaceHandler)
1997 {
1998 // now load the IKsInterfaceHandler plugin
1999 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
2000 if (FAILED(hr))
2001 {
2002 // failed to load interface handler plugin
2003 CoTaskMemFree(MediumList);
2004 CoTaskMemFree(InterfaceList);
2005
2006 return hr;
2007 }
2008
2009 // now set the pin
2010 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
2011 if (FAILED(hr))
2012 {
2013 // failed to load interface handler plugin
2014 InterfaceHandler->Release();
2015 CoTaskMemFree(MediumList);
2016 CoTaskMemFree(InterfaceList);
2017 return hr;
2018 }
2019
2020 // store interface handler
2021 m_InterfaceHandler = InterfaceHandler;
2022 }
2023 }
2024 else
2025 {
2026 #ifdef KSPROXY_TRACE
2027 WCHAR Buffer[100];
2028 swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
2029 OutputDebugStringW(Buffer);
2030 DebugBreak();
2031 #endif
2032
2033 hr = E_FAIL;
2034 }
2035
2036 // free medium / interface / dataformat
2037 CoTaskMemFree(MediumList);
2038 CoTaskMemFree(InterfaceList);
2039
2040 return hr;
2041 }
2042
2043 HRESULT
2044 STDMETHODCALLTYPE
2045 COutputPin::CreatePinHandle(
2046 PKSPIN_MEDIUM Medium,
2047 PKSPIN_INTERFACE Interface,
2048 const AM_MEDIA_TYPE *pmt)
2049 {
2050 PKSPIN_CONNECT PinConnect;
2051 PKSDATAFORMAT DataFormat;
2052 ULONG Length;
2053 HRESULT hr;
2054 HANDLE hFilter;
2055 IKsObject * KsObjectParent;
2056
2057 //KSALLOCATOR_FRAMING Framing;
2058 //KSPROPERTY Property;
2059 //ULONG BytesReturned;
2060
2061 if (m_hPin != INVALID_HANDLE_VALUE)
2062 {
2063 // pin already exists
2064 //CloseHandle(m_hPin);
2065 //m_hPin = INVALID_HANDLE_VALUE;
2066 return S_OK;
2067 }
2068
2069
2070 // calc format size
2071 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
2072
2073 // allocate pin connect
2074 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
2075 if (!PinConnect)
2076 {
2077 // failed
2078 return E_OUTOFMEMORY;
2079 }
2080
2081 // setup request
2082 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
2083 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
2084 PinConnect->PinId = m_PinId;
2085 PinConnect->PinToHandle = NULL;
2086 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
2087 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
2088
2089 // get dataformat offset
2090 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
2091
2092 // copy data format
2093 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
2094 DataFormat->Flags = 0;
2095 DataFormat->SampleSize = pmt->lSampleSize;
2096 DataFormat->Reserved = 0;
2097 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
2098 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
2099 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
2100
2101 if (pmt->cbFormat)
2102 {
2103 // copy extended format
2104 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
2105 }
2106
2107 // get IKsObject interface
2108 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
2109 if (FAILED(hr))
2110 return hr;
2111
2112 // get parent filter handle
2113 hFilter = KsObjectParent->KsGetObjectHandle();
2114
2115 // release IKsObject
2116 KsObjectParent->Release();
2117
2118 if (!hFilter)
2119 return E_HANDLE;
2120
2121 // create pin
2122 hr = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
2123
2124 if (SUCCEEDED(hr))
2125 {
2126 // store current interface / medium
2127 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
2128 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
2129 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
2130
2131 #ifdef KSPROXY_TRACE
2132 LPOLESTR pMajor, pSub, pFormat;
2133 StringFromIID(m_MediaFormat.majortype, &pMajor);
2134 StringFromIID(m_MediaFormat.subtype , &pSub);
2135 StringFromIID(m_MediaFormat.formattype, &pFormat);
2136 WCHAR Buffer[200];
2137 swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
2138 CoTaskMemFree(pMajor);
2139 CoTaskMemFree(pSub);
2140 CoTaskMemFree(pFormat);
2141 OutputDebugStringW(Buffer);
2142 #endif
2143
2144 if (pmt->cbFormat)
2145 {
2146 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
2147 if (!m_MediaFormat.pbFormat)
2148 {
2149 CoTaskMemFree(PinConnect);
2150 m_MediaFormat.pbFormat = NULL;
2151 m_MediaFormat.cbFormat = 0;
2152 return E_OUTOFMEMORY;
2153 }
2154 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
2155 }
2156 #if 0
2157 Property.Set = KSPROPSETID_Connection;
2158 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
2159 Property.Flags = KSPROPERTY_TYPE_GET;
2160
2161 ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING));
2162 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
2163 if (SUCCEEDED(hr))
2164 {
2165 m_Properties.cbAlign = (Framing.FileAlignment + 1);
2166 m_Properties.cbBuffer = Framing.FrameSize;
2167 m_Properties.cbPrefix = 0; //FIXME
2168 m_Properties.cBuffers = Framing.Frames;
2169 }
2170 hr = S_OK;
2171 #endif
2172
2173 if (FAILED(InitializeIOThread()))
2174 {
2175 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
2176 DebugBreak();
2177 }
2178
2179 LPGUID pGuid;
2180 ULONG NumGuids = 0;
2181
2182 // get all supported sets
2183 hr = GetSupportedSets(&pGuid, &NumGuids);
2184 if (FAILED(hr))
2185 {
2186 #ifdef KSPROXY_TRACE
2187 OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
2188 DebugBreak();
2189 #endif
2190 return hr;
2191 }
2192
2193 // load all proxy plugins
2194 hr = LoadProxyPlugins(pGuid, NumGuids);
2195 if (FAILED(hr))
2196 {
2197 #ifdef KSPROXY_TRACE
2198 OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
2199 DebugBreak();
2200 #endif
2201 return hr;
2202 }
2203
2204 // free sets
2205 CoTaskMemFree(pGuid);
2206
2207
2208 //TODO
2209 // connect pin pipes
2210
2211 }
2212 // free pin connect
2213 CoTaskMemFree(PinConnect);
2214
2215 return hr;
2216 }
2217
2218 HRESULT
2219 STDMETHODCALLTYPE
2220 COutputPin::GetSupportedSets(
2221 LPGUID * pOutGuid,
2222 PULONG NumGuids)
2223 {
2224 KSPROPERTY Property;
2225 LPGUID pGuid;
2226 ULONG NumProperty = 0;
2227 ULONG NumMethods = 0;
2228 ULONG NumEvents = 0;
2229 ULONG Length;
2230 ULONG BytesReturned;
2231 HRESULT hr;
2232
2233 Property.Set = GUID_NULL;
2234 Property.Id = 0;
2235 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
2236
2237 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
2238 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
2239 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
2240
2241 Length = NumProperty + NumMethods + NumEvents;
2242
2243 assert(Length);
2244
2245 // allocate guid buffer
2246 pGuid = (LPGUID)CoTaskMemAlloc(Length);
2247 if (!pGuid)
2248 {
2249 // failed
2250 return E_OUTOFMEMORY;
2251 }
2252
2253 NumProperty /= sizeof(GUID);
2254 NumMethods /= sizeof(GUID);
2255 NumEvents /= sizeof(GUID);
2256
2257 // get all properties
2258 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
2259 if (FAILED(hr))
2260 {
2261 CoTaskMemFree(pGuid);
2262 return E_FAIL;
2263 }
2264 Length -= BytesReturned;
2265
2266 // get all methods
2267 if (Length && NumMethods)
2268 {
2269 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
2270 if (FAILED(hr))
2271 {
2272 CoTaskMemFree(pGuid);
2273 return E_FAIL;
2274 }
2275 Length -= BytesReturned;
2276 }
2277
2278 // get all events
2279 if (Length && NumEvents)
2280 {
2281 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
2282 if (FAILED(hr))
2283 {
2284 CoTaskMemFree(pGuid);
2285 return E_FAIL;
2286 }
2287 Length -= BytesReturned;
2288 }
2289
2290 #ifdef KSPROXY_TRACE
2291 WCHAR Buffer[200];
2292 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
2293 OutputDebugStringW(Buffer);
2294 #endif
2295
2296 *pOutGuid = pGuid;
2297 *NumGuids = NumProperty+NumEvents+NumMethods;
2298 return S_OK;
2299 }
2300
2301 HRESULT
2302 STDMETHODCALLTYPE
2303 COutputPin::LoadProxyPlugins(
2304 LPGUID pGuids,
2305 ULONG NumGuids)
2306 {
2307 ULONG Index;
2308 LPOLESTR pStr;
2309 HKEY hKey, hSubKey;
2310 HRESULT hr;
2311 IUnknown * pUnknown;
2312
2313 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
2314 {
2315 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
2316 return E_FAIL;
2317 }
2318
2319 // enumerate all sets
2320 for(Index = 0; Index < NumGuids; Index++)
2321 {
2322 // convert to string
2323 hr = StringFromCLSID(pGuids[Index], &pStr);
2324 if (FAILED(hr))
2325 return E_FAIL;
2326
2327 // now try open class key
2328 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
2329 {
2330 // no plugin for that set exists
2331 CoTaskMemFree(pStr);
2332 continue;
2333 }
2334
2335 // try load plugin
2336 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
2337 if (SUCCEEDED(hr))
2338 {
2339 // store plugin
2340 m_Plugins.push_back(pUnknown);
2341 DebugBreak();
2342 }
2343 // close key
2344 RegCloseKey(hSubKey);
2345 }
2346
2347 // close media interfaces key
2348 RegCloseKey(hKey);
2349 return S_OK;
2350 }
2351
2352
2353 HRESULT
2354 WINAPI
2355 COutputPin::IoProcessRoutine()
2356 {
2357 IMediaSample *Sample;
2358 LONG SampleCount;
2359 HRESULT hr;
2360 PKSSTREAM_SEGMENT StreamSegment;
2361 HANDLE hEvent;
2362 IMediaSample * Samples[1];
2363
2364 #ifdef KSPROXY_TRACE
2365 WCHAR Buffer[200];
2366 #endif
2367
2368 // first wait for the start event to signal
2369 WaitForSingleObject(m_hStartEvent, INFINITE);
2370
2371 assert(m_InterfaceHandler);
2372 do
2373 {
2374 if (m_StopInProgress)
2375 {
2376 // stop io thread
2377 break;
2378 }
2379
2380 assert(m_State == KSSTATE_RUN);
2381 assert(m_MemAllocator);
2382
2383 // get buffer
2384 hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT);
2385
2386 if (FAILED(hr))
2387 {
2388 WaitForSingleObject(m_hBufferAvailable, INFINITE);
2389 // now retry again
2390 continue;
2391 }
2392
2393 // fill buffer
2394 SampleCount = 1;
2395 Samples[0] = Sample;
2396
2397 Sample->SetTime(NULL, NULL);
2398 hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
2399 Samples,
2400 &SampleCount,
2401 KsIoOperation_Read,
2402 &StreamSegment);
2403 if (FAILED(hr) || !StreamSegment)
2404 {
2405 #ifdef KSPROXY_TRACE
2406 swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr);
2407 OutputDebugStringW(Buffer);
2408 #endif
2409 break;
2410 }
2411
2412 // get completion event
2413 hEvent = StreamSegment->CompletionEvent;
2414
2415 // wait for i/o completion
2416 WaitForSingleObject(hEvent, INFINITE);
2417
2418 // perform completion
2419 m_InterfaceHandler->KsCompleteIo(StreamSegment);
2420
2421 // close completion event
2422 CloseHandle(hEvent);
2423
2424 if (SUCCEEDED(hr))
2425 {
2426 assert(m_MemInputPin);
2427
2428 // now deliver the sample
2429 hr = m_MemInputPin->Receive(Sample);
2430
2431 #ifdef KSPROXY_TRACE
2432 swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator);
2433 OutputDebugStringW(Buffer);
2434 #endif
2435
2436 if (FAILED(hr))
2437 break;
2438
2439 Sample = NULL;
2440 }
2441 }while(TRUE);
2442
2443 // signal end of i/o thread
2444 SetEvent(m_hStopEvent);
2445
2446 m_IoThreadStarted = false;
2447
2448 return NOERROR;
2449 }
2450
2451 DWORD
2452 WINAPI
2453 COutputPin_IoThreadStartup(
2454 LPVOID lpParameter)
2455 {
2456 COutputPin * Pin = (COutputPin*)lpParameter;
2457 assert(Pin);
2458
2459 return Pin->IoProcessRoutine();
2460 }
2461
2462
2463 HRESULT
2464 WINAPI
2465 COutputPin::InitializeIOThread()
2466 {
2467 HANDLE hThread;
2468
2469 if (m_IoThreadStarted)
2470 return NOERROR;
2471
2472 if (!m_hStartEvent)
2473 m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2474
2475 if (!m_hStartEvent)
2476 return E_OUTOFMEMORY;
2477
2478 if (!m_hStopEvent)
2479 m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2480
2481 if (!m_hStopEvent)
2482 return E_OUTOFMEMORY;
2483
2484 if (!m_hBufferAvailable)
2485 m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL);
2486
2487 if (!m_hBufferAvailable)
2488 return E_OUTOFMEMORY;
2489
2490 m_StopInProgress = false;
2491 m_IoThreadStarted = true;
2492
2493 // now create the startup thread
2494 hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL);
2495 if (!hThread)
2496 return E_OUTOFMEMORY;
2497
2498
2499 // close thread handle
2500 CloseHandle(hThread);
2501 return NOERROR;
2502 }
2503
2504 HRESULT
2505 STDMETHODCALLTYPE
2506 COutputPin_SetState(
2507 IPin * Pin,
2508 KSSTATE State)
2509 {
2510 HRESULT hr = S_OK;
2511 KSPROPERTY Property;
2512 KSSTATE CurState;
2513 ULONG BytesReturned;
2514 COutputPin * pPin = (COutputPin*)Pin;
2515
2516 #ifdef KSPROXY_TRACE
2517 WCHAR Buffer[200];
2518 #endif
2519
2520 Property.Set = KSPROPSETID_Connection;
2521 Property.Id = KSPROPERTY_CONNECTION_STATE;
2522 Property.Flags = KSPROPERTY_TYPE_SET;
2523
2524 EnterCriticalSection(&pPin->m_Lock);
2525
2526 if (pPin->m_State <= State)
2527 {
2528 if (pPin->m_State == KSSTATE_STOP)
2529 {
2530 hr = pPin->InitializeIOThread();
2531 if (FAILED(hr))
2532 {
2533 // failed to initialize I/O thread
2534 #ifdef KSPROXY_TRACE
2535 OutputDebugStringW(L"Failed to initialize I/O Thread\n");
2536 #endif
2537 LeaveCriticalSection(&pPin->m_Lock);
2538 return hr;
2539 }
2540 CurState = KSSTATE_ACQUIRE;
2541 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2542
2543 #ifdef KSPROXY_TRACE
2544 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
2545 OutputDebugStringW(Buffer);
2546 #endif
2547
2548 if (FAILED(hr))
2549 {
2550 LeaveCriticalSection(&pPin->m_Lock);
2551 return hr;
2552 }
2553
2554 pPin->m_State = CurState;
2555
2556 if (pPin->m_State == State)
2557 {
2558 LeaveCriticalSection(&pPin->m_Lock);
2559 return hr;
2560 }
2561 }
2562 if (pPin->m_State == KSSTATE_ACQUIRE)
2563 {
2564 CurState = KSSTATE_PAUSE;
2565 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2566
2567 #ifdef KSPROXY_TRACE
2568 swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
2569 OutputDebugStringW(Buffer);
2570 #endif
2571
2572 if (FAILED(hr))
2573 {
2574 LeaveCriticalSection(&pPin->m_Lock);
2575 return hr;
2576 }
2577
2578 pPin->m_State = CurState;
2579
2580 if (pPin->m_State == State)
2581 {
2582 LeaveCriticalSection(&pPin->m_Lock);
2583 return hr;
2584 }
2585 }
2586 if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE)
2587 {
2588 CurState = KSSTATE_RUN;
2589 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2590
2591 #ifdef KSPROXY_TRACE
2592 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr);
2593 OutputDebugStringW(Buffer);
2594 #endif
2595
2596 if (SUCCEEDED(hr))
2597 {
2598 pPin->m_State = CurState;
2599 // signal start event
2600 SetEvent(pPin->m_hStartEvent);
2601 }
2602 }
2603
2604 LeaveCriticalSection(&pPin->m_Lock);
2605 return hr;
2606 }
2607 else
2608 {
2609 if (pPin->m_State == KSSTATE_RUN)
2610 {
2611 // setting pending stop flag
2612 pPin->m_StopInProgress = true;
2613
2614 // release any waiting threads
2615 SetEvent(pPin->m_hBufferAvailable);
2616
2617 // wait until i/o thread is done
2618 WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
2619
2620 CurState = KSSTATE_PAUSE;
2621 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2622
2623 #ifdef KSPROXY_TRACE
2624 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
2625 OutputDebugStringW(Buffer);
2626 #endif
2627
2628 if (FAILED(hr))
2629 {
2630 LeaveCriticalSection(&pPin->m_Lock);
2631 return hr;
2632 }
2633
2634 pPin->m_State = CurState;
2635
2636 if (FAILED(hr))
2637 {
2638 LeaveCriticalSection(&pPin->m_Lock);
2639 return hr;
2640 }
2641 }
2642 if (pPin->m_State == KSSTATE_PAUSE)
2643 {
2644 CurState = KSSTATE_ACQUIRE;
2645 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2646
2647 #ifdef KSPROXY_TRACE
2648 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
2649 OutputDebugStringW(Buffer);
2650 #endif
2651
2652 if (FAILED(hr))
2653 {
2654 LeaveCriticalSection(&pPin->m_Lock);
2655 return hr;
2656 }
2657
2658 pPin->m_State = CurState;
2659
2660 if (pPin->m_State == State)
2661 {
2662 LeaveCriticalSection(&pPin->m_Lock);
2663 return hr;
2664 }
2665 }
2666
2667 CloseHandle(pPin->m_hStopEvent);
2668 CloseHandle(pPin->m_hStartEvent);
2669 CloseHandle(pPin->m_hBufferAvailable);
2670
2671 /* close event handles */
2672 pPin->m_hStopEvent = NULL;
2673 pPin->m_hStartEvent = NULL;
2674 pPin->m_hBufferAvailable = NULL;
2675
2676 CurState = KSSTATE_STOP;
2677 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2678
2679 #ifdef KSPROXY_TRACE
2680 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr);
2681 OutputDebugStringW(Buffer);
2682 #endif
2683
2684 if (SUCCEEDED(hr))
2685 {
2686 // store state
2687 pPin->m_State = CurState;
2688 }
2689
2690 // unset pending stop flag
2691 pPin->m_StopInProgress = false;
2692
2693 LeaveCriticalSection(&pPin->m_Lock);
2694 return hr;
2695 }
2696 }
2697
2698 HRESULT
2699 WINAPI
2700 COutputPin_Constructor(
2701 IBaseFilter * ParentFilter,
2702 LPCWSTR PinName,
2703 ULONG PinId,
2704 KSPIN_COMMUNICATION Communication,
2705 REFIID riid,
2706 LPVOID * ppv)
2707 {
2708 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
2709
2710 if (!handler)
2711 return E_OUTOFMEMORY;
2712
2713 if (FAILED(handler->QueryInterface(riid, ppv)))
2714 {
2715 /* not supported */
2716 delete handler;
2717 return E_NOINTERFACE;
2718 }
2719
2720 return S_OK;
2721 }