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