[QUARTZ]
[reactos.git] / reactos / dll / directx / ksproxy / input_pin.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/input_pin.cpp
5 * PURPOSE: InputPin of Proxy Filter
6 *
7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 const GUID IID_IKsPinPipe = {0xe539cd90, 0xa8b4, 0x11d1, {0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}};
12 const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
13
14 KSPIN_INTERFACE StandardPinInterface =
15 {
16 {STATIC_KSINTERFACESETID_Standard},
17 KSINTERFACE_STANDARD_STREAMING,
18 0
19 };
20
21 KSPIN_MEDIUM StandardPinMedium =
22 {
23 {STATIC_KSMEDIUMSETID_Standard},
24 KSMEDIUM_TYPE_ANYINSTANCE,
25 0
26 };
27
28 class CInputPin : public IPin,
29 public IKsPropertySet,
30 public IKsControl,
31 public IKsObject,
32 public IKsPinEx,
33 public IMemInputPin,
34 public IKsPinPipe,
35 public IKsPinFactory,
36 public IStreamBuilder,
37 public IKsAggregateControl,
38 public IQualityControl,
39 public ISpecifyPropertyPages
40 {
41 public:
42 typedef std::vector<IUnknown *>ProxyPluginVector;
43
44 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
45
46 STDMETHODIMP_(ULONG) AddRef()
47 {
48 InterlockedIncrement(&m_Ref);
49 return m_Ref;
50 }
51 STDMETHODIMP_(ULONG) Release()
52 {
53 InterlockedDecrement(&m_Ref);
54 if (!m_Ref)
55 {
56 delete this;
57 return 0;
58 }
59 return m_Ref;
60 }
61
62 //IKsPinPipe
63 HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
64 HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
65 IPin* STDMETHODCALLTYPE KsGetConnectedPin();
66 IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
67 HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
68 ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
69 HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
70 GUID STDMETHODCALLTYPE KsGetPinBusCache();
71 HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
72 PWCHAR STDMETHODCALLTYPE KsGetPinName();
73 PWCHAR STDMETHODCALLTYPE KsGetFilterName();
74
75 //IPin methods
76 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
77 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
78 HRESULT STDMETHODCALLTYPE Disconnect();
79 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
80 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
81 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
82 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
83 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
84 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
85 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
86 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
87 HRESULT STDMETHODCALLTYPE EndOfStream();
88 HRESULT STDMETHODCALLTYPE BeginFlush();
89 HRESULT STDMETHODCALLTYPE EndFlush();
90 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
91
92 // ISpecifyPropertyPages
93 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
94
95 //IKsObject methods
96 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
97
98 //IKsPropertySet
99 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
100 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
101 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
102
103 //IKsControl
104 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
105 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
106 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
107
108 //IKsPin
109 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
110 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
111 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
112 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
113 HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
114 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
115 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
116 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
117 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
118 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
119 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
120 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
121 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
122 // IKsPinEx
123 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
124
125 //IMemInputPin
126 HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
127 HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
128 HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
129 HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
130 HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
131 HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void);
132
133 //IKsPinFactory
134 HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
135
136 //IStreamBuilder
137 HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
138 HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
139
140 //IKsAggregateControl
141 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
142 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
143
144 //IQualityControl
145 HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q);
146 HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
147
148 //---------------------------------------------------------------
149 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
150 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
151 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
152 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
153 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
154 CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication);
155 virtual ~CInputPin(){};
156
157 protected:
158 LONG m_Ref;
159 IBaseFilter * m_ParentFilter;
160 LPCWSTR m_PinName;
161 HANDLE m_hPin;
162 ULONG m_PinId;
163 IMemAllocator * m_MemAllocator;
164 LONG m_IoCount;
165 KSPIN_COMMUNICATION m_Communication;
166 KSPIN_INTERFACE m_Interface;
167 KSPIN_MEDIUM m_Medium;
168 AM_MEDIA_TYPE m_MediaFormat;
169 IPin * m_Pin;
170 BOOL m_ReadOnly;
171 IKsInterfaceHandler * m_InterfaceHandler;
172 IKsAllocatorEx * m_KsAllocatorEx;
173 ULONG m_PipeAllocatorFlag;
174 BOOL m_bPinBusCacheInitialized;
175 GUID m_PinBusCache;
176 LPWSTR m_FilterName;
177 FRAMING_PROP m_FramingProp[4];
178 PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
179 ProxyPluginVector m_Plugins;
180 };
181
182 CInputPin::CInputPin(
183 IBaseFilter * ParentFilter,
184 LPCWSTR PinName,
185 ULONG PinId,
186 KSPIN_COMMUNICATION Communication) : m_Ref(0),
187 m_ParentFilter(ParentFilter),
188 m_PinName(PinName),
189 m_hPin(INVALID_HANDLE_VALUE),
190 m_PinId(PinId),
191 m_MemAllocator(0),
192 m_IoCount(0),
193 m_Communication(Communication),
194 m_Pin(0),
195 m_ReadOnly(0),
196 m_InterfaceHandler(0),
197 m_KsAllocatorEx(0),
198 m_PipeAllocatorFlag(0),
199 m_bPinBusCacheInitialized(0),
200 m_FilterName(0),
201 m_Plugins()
202 {
203 ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
204 ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
205
206 HRESULT hr;
207 IKsObject * KsObjectParent;
208 HANDLE hFilter;
209
210 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
211 assert(hr == S_OK);
212
213 hFilter = KsObjectParent->KsGetObjectHandle();
214 assert(hFilter);
215
216 KsObjectParent->Release();
217
218
219 ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE));
220 hr = KsGetMediaType(0, &m_MediaFormat, hFilter, m_PinId);
221 assert(hr == S_OK);
222 }
223
224 HRESULT
225 STDMETHODCALLTYPE
226 CInputPin::QueryInterface(
227 IN REFIID refiid,
228 OUT PVOID* Output)
229 {
230 WCHAR Buffer[100];
231
232 *Output = NULL;
233
234 if (IsEqualGUID(refiid, IID_IUnknown) ||
235 IsEqualGUID(refiid, IID_IPin))
236 {
237 *Output = PVOID(this);
238 reinterpret_cast<IUnknown*>(*Output)->AddRef();
239 return NOERROR;
240 }
241 else if (IsEqualGUID(refiid, IID_IMemInputPin))
242 {
243 if (m_hPin == INVALID_HANDLE_VALUE)
244 {
245 HRESULT hr = CreatePin(&m_MediaFormat);
246 if (FAILED(hr))
247 return hr;
248 }
249
250 *Output = (IMemInputPin*)(this);
251 reinterpret_cast<IMemInputPin*>(*Output)->AddRef();
252 return NOERROR;
253 }
254 else if (IsEqualGUID(refiid, IID_IKsObject))
255 {
256 *Output = (IKsObject*)(this);
257 reinterpret_cast<IKsObject*>(*Output)->AddRef();
258 return NOERROR;
259 }
260 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
261 {
262 if (m_hPin == INVALID_HANDLE_VALUE)
263 {
264 HRESULT hr = CreatePin(&m_MediaFormat);
265 if (FAILED(hr))
266 return hr;
267 }
268
269 *Output = (IKsPropertySet*)(this);
270 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
271 return NOERROR;
272 }
273 else if (IsEqualGUID(refiid, IID_IKsControl))
274 {
275 *Output = (IKsControl*)(this);
276 reinterpret_cast<IKsControl*>(*Output)->AddRef();
277 return NOERROR;
278 }
279 else if (IsEqualGUID(refiid, IID_IKsPin) ||
280 IsEqualGUID(refiid, IID_IKsPinEx))
281 {
282 *Output = (IKsPinEx*)(this);
283 reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
284 return NOERROR;
285 }
286 else if (IsEqualGUID(refiid, IID_IKsPinPipe))
287 {
288 *Output = (IKsPinPipe*)(this);
289 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
290 return NOERROR;
291 }
292 else if (IsEqualGUID(refiid, IID_IKsPinFactory))
293 {
294 *Output = (IKsPinFactory*)(this);
295 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
296 return NOERROR;
297 }
298 #if 0
299 else if (IsEqualGUID(refiid, IID_IStreamBuilder))
300 {
301 *Output = (IStreamBuilder*)(this);
302 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
303 return NOERROR;
304 }
305 #endif
306 else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
307 {
308 *Output = (IKsAggregateControl*)(this);
309 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
310 return NOERROR;
311 }
312 else if (IsEqualGUID(refiid, IID_IQualityControl))
313 {
314 *Output = (IQualityControl*)(this);
315 reinterpret_cast<IQualityControl*>(*Output)->AddRef();
316 return NOERROR;
317 }
318 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
319 {
320 *Output = (ISpecifyPropertyPages*)(this);
321 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
322 return NOERROR;
323 }
324
325 LPOLESTR lpstr;
326 StringFromCLSID(refiid, &lpstr);
327 swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr);
328 OutputDebugStringW(Buffer);
329 CoTaskMemFree(lpstr);
330
331 return E_NOINTERFACE;
332 }
333 //-------------------------------------------------------------------
334 // IQualityControl interface
335 //
336 HRESULT
337 STDMETHODCALLTYPE
338 CInputPin::Notify(
339 IBaseFilter *pSelf,
340 Quality q)
341 {
342 #ifdef KSPROXY_TRACE
343 OutputDebugStringW(L"CInputPin::Notify NotImplemented\n");
344 #endif
345
346 return E_NOTIMPL;
347 }
348
349 HRESULT
350 STDMETHODCALLTYPE
351 CInputPin::SetSink(
352 IQualityControl *piqc)
353 {
354 #ifdef KSPROXY_TRACE
355 OutputDebugStringW(L"CInputPin::SetSink NotImplemented\n");
356 #endif
357
358 return E_NOTIMPL;
359 }
360
361
362 //-------------------------------------------------------------------
363 // IKsAggregateControl interface
364 //
365 HRESULT
366 STDMETHODCALLTYPE
367 CInputPin::KsAddAggregate(
368 IN REFGUID AggregateClass)
369 {
370 #ifdef KSPROXY_TRACE
371 OutputDebugStringW(L"CInputPin::KsAddAggregate NotImplemented\n");
372 #endif
373
374 return E_NOTIMPL;
375 }
376
377 HRESULT
378 STDMETHODCALLTYPE
379 CInputPin::KsRemoveAggregate(
380 REFGUID AggregateClass)
381 {
382 #ifdef KSPROXY_TRACE
383 OutputDebugStringW(L"CInputPin::KsRemoveAggregate NotImplemented\n");
384 #endif
385
386 return E_NOTIMPL;
387 }
388
389 //-------------------------------------------------------------------
390 // IStreamBuilder
391 //
392
393 HRESULT
394 STDMETHODCALLTYPE
395 CInputPin::Render(
396 IPin *ppinOut,
397 IGraphBuilder *pGraph)
398 {
399 OutputDebugStringW(L"CInputPin::Render\n");
400 return S_OK;
401 }
402
403 HRESULT
404 STDMETHODCALLTYPE
405 CInputPin::Backout(
406 IPin *ppinOut,
407 IGraphBuilder *pGraph)
408 {
409 #ifdef KSPROXY_TRACE
410 OutputDebugStringW(L"CInputPin::Backout\n");
411 #endif
412
413 return S_OK;
414 }
415
416 //-------------------------------------------------------------------
417 // IKsPinFactory
418 //
419
420 HRESULT
421 STDMETHODCALLTYPE
422 CInputPin::KsPinFactory(
423 ULONG* PinFactory)
424 {
425 #ifdef KSPROXY_TRACE
426 OutputDebugStringW(L"CInputPin::KsPinFactory\n");
427 #endif
428
429 *PinFactory = m_PinId;
430 return S_OK;
431 }
432
433 //-------------------------------------------------------------------
434 // IKsPinPipe
435 //
436
437 HRESULT
438 STDMETHODCALLTYPE
439 CInputPin::KsGetPinFramingCache(
440 PKSALLOCATOR_FRAMING_EX *FramingEx,
441 PFRAMING_PROP FramingProp,
442 FRAMING_CACHE_OPS Option)
443 {
444 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
445 {
446 // invalid argument
447 return E_INVALIDARG;
448 }
449
450 // get framing properties
451 *FramingProp = m_FramingProp[Option];
452 *FramingEx = m_FramingEx[Option];
453
454 return NOERROR;
455 }
456
457 HRESULT
458 STDMETHODCALLTYPE
459 CInputPin::KsSetPinFramingCache(
460 PKSALLOCATOR_FRAMING_EX FramingEx,
461 PFRAMING_PROP FramingProp,
462 FRAMING_CACHE_OPS Option)
463 {
464 ULONG Index;
465 ULONG RefCount = 0;
466
467 if (m_FramingEx[Option])
468 {
469 for(Index = 1; Index < 4; Index++)
470 {
471 if (m_FramingEx[Index] == m_FramingEx[Option])
472 RefCount++;
473 }
474
475 if (RefCount == 1)
476 {
477 // existing framing is only used once
478 CoTaskMemFree(m_FramingEx[Option]);
479 }
480 }
481
482 // store framing
483 m_FramingEx[Option] = FramingEx;
484 m_FramingProp[Option] = *FramingProp;
485
486 return S_OK;
487 }
488
489 IPin*
490 STDMETHODCALLTYPE
491 CInputPin::KsGetConnectedPin()
492 {
493 return m_Pin;
494 }
495
496 IKsAllocatorEx*
497 STDMETHODCALLTYPE
498 CInputPin::KsGetPipe(
499 KSPEEKOPERATION Operation)
500 {
501 if (Operation == KsPeekOperation_AddRef)
502 {
503 if (m_KsAllocatorEx)
504 m_KsAllocatorEx->AddRef();
505 }
506 return m_KsAllocatorEx;
507 }
508
509 HRESULT
510 STDMETHODCALLTYPE
511 CInputPin::KsSetPipe(
512 IKsAllocatorEx *KsAllocator)
513 {
514 if (KsAllocator)
515 KsAllocator->AddRef();
516
517 if (m_KsAllocatorEx)
518 m_KsAllocatorEx->Release();
519
520 m_KsAllocatorEx = KsAllocator;
521 return NOERROR;
522 }
523
524 ULONG
525 STDMETHODCALLTYPE
526 CInputPin::KsGetPipeAllocatorFlag()
527 {
528 return m_PipeAllocatorFlag;
529 }
530
531
532 HRESULT
533 STDMETHODCALLTYPE
534 CInputPin::KsSetPipeAllocatorFlag(
535 ULONG Flag)
536 {
537 m_PipeAllocatorFlag = Flag;
538 return NOERROR;
539 }
540
541 GUID
542 STDMETHODCALLTYPE
543 CInputPin::KsGetPinBusCache()
544 {
545 if (!m_bPinBusCacheInitialized)
546 {
547 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
548 m_bPinBusCacheInitialized = TRUE;
549 }
550
551 return m_PinBusCache;
552 }
553
554 HRESULT
555 STDMETHODCALLTYPE
556 CInputPin::KsSetPinBusCache(
557 GUID Bus)
558 {
559 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
560 return NOERROR;
561 }
562
563 PWCHAR
564 STDMETHODCALLTYPE
565 CInputPin::KsGetPinName()
566 {
567 return (PWCHAR)m_PinName;
568 }
569
570
571 PWCHAR
572 STDMETHODCALLTYPE
573 CInputPin::KsGetFilterName()
574 {
575 return m_FilterName;
576 }
577
578 //-------------------------------------------------------------------
579 // ISpecifyPropertyPages
580 //
581
582 HRESULT
583 STDMETHODCALLTYPE
584 CInputPin::GetPages(CAUUID *pPages)
585 {
586 if (!pPages)
587 return E_POINTER;
588
589 pPages->cElems = 0;
590 pPages->pElems = NULL;
591
592 return S_OK;
593 }
594
595 //-------------------------------------------------------------------
596 // IMemInputPin
597 //
598
599
600 HRESULT
601 STDMETHODCALLTYPE
602 CInputPin::GetAllocator(IMemAllocator **ppAllocator)
603 {
604 #ifdef KSPROXY_TRACE
605 OutputDebugStringW(L"CInputPin::GetAllocator\n");
606 #endif
607
608 return VFW_E_NO_ALLOCATOR;
609 }
610
611 HRESULT
612 STDMETHODCALLTYPE
613 CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
614 {
615 HRESULT hr;
616 ALLOCATOR_PROPERTIES Properties;
617
618 hr = pAllocator->GetProperties(&Properties);
619
620 #ifdef KSPROXY_TRACE
621 WCHAR Buffer[100];
622 swprintf(Buffer, L"CInputPin::NotifyAllocator hr %lx bReadOnly, %u cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", hr, bReadOnly, Properties.cbAlign, Properties.cbBuffer, Properties.cbPrefix, Properties.cBuffers);
623 OutputDebugStringW(Buffer);
624 #endif
625
626 if (pAllocator)
627 {
628 pAllocator->AddRef();
629 }
630
631 if (m_MemAllocator)
632 {
633 m_MemAllocator->Release();
634 }
635
636 m_MemAllocator = pAllocator;
637 m_ReadOnly = bReadOnly;
638 return NOERROR;
639 }
640
641 HRESULT
642 STDMETHODCALLTYPE
643 CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
644 {
645 KSALLOCATOR_FRAMING Framing;
646 KSPROPERTY Property;
647 HRESULT hr;
648 ULONG BytesReturned;
649
650 Property.Set = KSPROPSETID_Connection;
651 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
652 Property.Flags = KSPROPERTY_TYPE_SET;
653
654 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
655 if (SUCCEEDED(hr))
656 {
657 pProps->cBuffers = Framing.Frames;
658 pProps->cbBuffer = Framing.FrameSize;
659 pProps->cbAlign = Framing.FileAlignment;
660 pProps->cbPrefix = 0;
661 }
662 else
663 hr = E_NOTIMPL;
664
665 #ifdef KSPROXY_TRACE
666 WCHAR Buffer[100];
667 swprintf(Buffer, L"CInputPin::GetAllocatorRequirements hr %lx m_hPin %p cBuffers %u cbBuffer %u cbAlign %u cbPrefix %u\n", hr, m_hPin, pProps->cBuffers, pProps->cbBuffer, pProps->cbAlign, pProps->cbPrefix);
668 OutputDebugStringW(Buffer);
669 #endif
670
671 return hr;
672 }
673
674 HRESULT
675 STDMETHODCALLTYPE
676 CInputPin::Receive(IMediaSample *pSample)
677 {
678 #ifdef KSPROXY_TRACE
679 OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
680 #endif
681
682 return E_NOTIMPL;
683 }
684
685 HRESULT
686 STDMETHODCALLTYPE
687 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
688 {
689 #ifdef KSPROXY_TRACE
690 OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
691 #endif
692
693 return E_NOTIMPL;
694 }
695
696 HRESULT
697 STDMETHODCALLTYPE
698 CInputPin::ReceiveCanBlock( void)
699 {
700 #ifdef KSPROXY_TRACE
701 OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
702 #endif
703
704 return S_FALSE;
705 }
706
707 //-------------------------------------------------------------------
708 // IKsPin
709 //
710
711 HRESULT
712 STDMETHODCALLTYPE
713 CInputPin::KsQueryMediums(
714 PKSMULTIPLE_ITEM* MediumList)
715 {
716 HRESULT hr;
717 IKsObject * KsObjectParent;
718 HANDLE hFilter;
719
720 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
721 if (FAILED(hr))
722 return hr;
723
724 hFilter = KsObjectParent->KsGetObjectHandle();
725
726 KsObjectParent->Release();
727
728 if (!hFilter)
729 return E_HANDLE;
730
731 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
732 }
733
734 HRESULT
735 STDMETHODCALLTYPE
736 CInputPin::KsQueryInterfaces(
737 PKSMULTIPLE_ITEM* InterfaceList)
738 {
739 HRESULT hr;
740 IKsObject * KsObjectParent;
741 HANDLE hFilter;
742
743 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
744 if (FAILED(hr))
745 return hr;
746
747 hFilter = KsObjectParent->KsGetObjectHandle();
748
749 KsObjectParent->Release();
750
751 if (!hFilter)
752 return E_HANDLE;
753
754 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
755 }
756
757 HRESULT
758 STDMETHODCALLTYPE
759 CInputPin::KsCreateSinkPinHandle(
760 KSPIN_INTERFACE& Interface,
761 KSPIN_MEDIUM& Medium)
762 {
763 return CreatePin(&m_MediaFormat);
764 }
765
766 HRESULT
767 STDMETHODCALLTYPE
768 CInputPin::KsGetCurrentCommunication(
769 KSPIN_COMMUNICATION *Communication,
770 KSPIN_INTERFACE *Interface,
771 KSPIN_MEDIUM *Medium)
772 {
773 if (Communication)
774 {
775 *Communication = m_Communication;
776 }
777
778 if (Interface)
779 {
780 if (!m_hPin)
781 return VFW_E_NOT_CONNECTED;
782
783 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
784 }
785
786 if (Medium)
787 {
788 if (!m_hPin)
789 return VFW_E_NOT_CONNECTED;
790
791 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
792 }
793 return NOERROR;
794 }
795
796 HRESULT
797 STDMETHODCALLTYPE
798 CInputPin::KsPropagateAcquire()
799 {
800 KSPROPERTY Property;
801 KSSTATE State;
802 ULONG BytesReturned;
803 HRESULT hr;
804
805 assert(m_hPin != INVALID_HANDLE_VALUE);
806
807 Property.Set = KSPROPSETID_Connection;
808 Property.Id = KSPROPERTY_CONNECTION_STATE;
809 Property.Flags = KSPROPERTY_TYPE_SET;
810
811 State = KSSTATE_ACQUIRE;
812
813 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
814
815 //TODO
816 //propagate to connected pin on the pipe
817
818 return hr;
819 }
820
821 HRESULT
822 STDMETHODCALLTYPE
823 CInputPin::KsDeliver(
824 IMediaSample* Sample,
825 ULONG Flags)
826 {
827 return E_FAIL;
828 }
829
830 HRESULT
831 STDMETHODCALLTYPE
832 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
833 {
834 return NOERROR;
835 }
836
837 IMemAllocator *
838 STDMETHODCALLTYPE
839 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
840 {
841 if (Operation == KsPeekOperation_AddRef)
842 {
843 // add reference on allocator
844 m_MemAllocator->AddRef();
845 }
846
847 return m_MemAllocator;
848 }
849
850 HRESULT
851 STDMETHODCALLTYPE
852 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
853 {
854
855 if (MemAllocator)
856 {
857 MemAllocator->AddRef();
858 }
859
860 if (m_MemAllocator)
861 {
862 m_MemAllocator->Release();
863 }
864
865 m_MemAllocator = MemAllocator;
866 return NOERROR;
867 }
868
869 HRESULT
870 STDMETHODCALLTYPE
871 CInputPin::KsRenegotiateAllocator()
872 {
873 return E_FAIL;
874 }
875
876 LONG
877 STDMETHODCALLTYPE
878 CInputPin::KsIncrementPendingIoCount()
879 {
880 return InterlockedIncrement((volatile LONG*)&m_IoCount);
881 }
882
883 LONG
884 STDMETHODCALLTYPE
885 CInputPin::KsDecrementPendingIoCount()
886 {
887 return InterlockedDecrement((volatile LONG*)&m_IoCount);
888 }
889
890 HRESULT
891 STDMETHODCALLTYPE
892 CInputPin::KsQualityNotify(
893 ULONG Proportion,
894 REFERENCE_TIME TimeDelta)
895 {
896 #ifdef KSPROXY_TRACE
897 OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
898 #endif
899
900 return E_NOTIMPL;
901 }
902
903 //-------------------------------------------------------------------
904 // IKsPinEx
905 //
906
907 VOID
908 STDMETHODCALLTYPE
909 CInputPin::KsNotifyError(
910 IMediaSample* Sample,
911 HRESULT hr)
912 {
913 #ifdef KSPROXY_TRACE
914 OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n");
915 #endif
916 }
917
918
919 //-------------------------------------------------------------------
920 // IKsControl
921 //
922 HRESULT
923 STDMETHODCALLTYPE
924 CInputPin::KsProperty(
925 PKSPROPERTY Property,
926 ULONG PropertyLength,
927 LPVOID PropertyData,
928 ULONG DataLength,
929 ULONG* BytesReturned)
930 {
931 assert(m_hPin != INVALID_HANDLE_VALUE);
932 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
933 }
934
935 HRESULT
936 STDMETHODCALLTYPE
937 CInputPin::KsMethod(
938 PKSMETHOD Method,
939 ULONG MethodLength,
940 LPVOID MethodData,
941 ULONG DataLength,
942 ULONG* BytesReturned)
943 {
944 assert(m_hPin != INVALID_HANDLE_VALUE);
945 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
946 }
947
948 HRESULT
949 STDMETHODCALLTYPE
950 CInputPin::KsEvent(
951 PKSEVENT Event,
952 ULONG EventLength,
953 LPVOID EventData,
954 ULONG DataLength,
955 ULONG* BytesReturned)
956 {
957 assert(m_hPin != INVALID_HANDLE_VALUE);
958
959 if (EventLength)
960 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
961 else
962 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
963 }
964
965
966 //-------------------------------------------------------------------
967 // IKsPropertySet
968 //
969 HRESULT
970 STDMETHODCALLTYPE
971 CInputPin::Set(
972 REFGUID guidPropSet,
973 DWORD dwPropID,
974 LPVOID pInstanceData,
975 DWORD cbInstanceData,
976 LPVOID pPropData,
977 DWORD cbPropData)
978 {
979 ULONG BytesReturned;
980
981 if (cbInstanceData)
982 {
983 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
984 if (!Property)
985 return E_OUTOFMEMORY;
986
987 Property->Set = guidPropSet;
988 Property->Id = dwPropID;
989 Property->Flags = KSPROPERTY_TYPE_SET;
990
991 CopyMemory((Property+1), pInstanceData, cbInstanceData);
992
993 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
994 CoTaskMemFree(Property);
995 return hr;
996 }
997 else
998 {
999 KSPROPERTY Property;
1000
1001 Property.Set = guidPropSet;
1002 Property.Id = dwPropID;
1003 Property.Flags = KSPROPERTY_TYPE_SET;
1004
1005 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1006 return hr;
1007 }
1008 }
1009
1010 HRESULT
1011 STDMETHODCALLTYPE
1012 CInputPin::Get(
1013 REFGUID guidPropSet,
1014 DWORD dwPropID,
1015 LPVOID pInstanceData,
1016 DWORD cbInstanceData,
1017 LPVOID pPropData,
1018 DWORD cbPropData,
1019 DWORD *pcbReturned)
1020 {
1021 ULONG BytesReturned;
1022
1023 if (cbInstanceData)
1024 {
1025 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1026 if (!Property)
1027 return E_OUTOFMEMORY;
1028
1029 Property->Set = guidPropSet;
1030 Property->Id = dwPropID;
1031 Property->Flags = KSPROPERTY_TYPE_GET;
1032
1033 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1034
1035 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1036 CoTaskMemFree(Property);
1037 return hr;
1038 }
1039 else
1040 {
1041 KSPROPERTY Property;
1042
1043 Property.Set = guidPropSet;
1044 Property.Id = dwPropID;
1045 Property.Flags = KSPROPERTY_TYPE_GET;
1046
1047 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1048 return hr;
1049 }
1050 }
1051
1052 HRESULT
1053 STDMETHODCALLTYPE
1054 CInputPin::QuerySupported(
1055 REFGUID guidPropSet,
1056 DWORD dwPropID,
1057 DWORD *pTypeSupport)
1058 {
1059 KSPROPERTY Property;
1060 ULONG BytesReturned;
1061
1062 Property.Set = guidPropSet;
1063 Property.Id = dwPropID;
1064 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1065
1066 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1067 }
1068
1069
1070 //-------------------------------------------------------------------
1071 // IKsObject
1072 //
1073 HANDLE
1074 STDMETHODCALLTYPE
1075 CInputPin::KsGetObjectHandle()
1076 {
1077 assert(m_hPin);
1078 return m_hPin;
1079 }
1080
1081 //-------------------------------------------------------------------
1082 // IPin interface
1083 //
1084 HRESULT
1085 STDMETHODCALLTYPE
1086 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1087 {
1088 #ifdef KSPROXY_TRACE
1089 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
1090 #endif
1091 return NOERROR;
1092 }
1093
1094 HRESULT
1095 STDMETHODCALLTYPE
1096 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1097 {
1098 HRESULT hr;
1099
1100 if (m_Pin)
1101 {
1102 // already connected
1103 return VFW_E_ALREADY_CONNECTED;
1104 }
1105
1106 // first check format
1107 hr = CheckFormat(pmt);
1108 if (FAILED(hr))
1109 {
1110 // format is not supported
1111 return hr;
1112 }
1113
1114 hr = CreatePin(pmt);
1115 if (FAILED(hr))
1116 {
1117 return hr;
1118 }
1119
1120 m_Pin = pConnector;
1121 m_Pin->AddRef();
1122
1123 return S_OK;
1124 }
1125 HRESULT
1126 STDMETHODCALLTYPE
1127 CInputPin::Disconnect( void)
1128 {
1129 if (!m_Pin)
1130 {
1131 // pin was not connected
1132 return S_FALSE;
1133 }
1134
1135 //FIXME
1136 //check if filter is active
1137
1138 m_Pin->Release();
1139 m_Pin = NULL;
1140
1141 #ifdef KSPROXY_TRACE
1142 OutputDebugStringW(L"CInputPin::Disconnect\n");
1143 #endif
1144
1145 return S_OK;
1146 }
1147 HRESULT
1148 STDMETHODCALLTYPE
1149 CInputPin::ConnectedTo(IPin **pPin)
1150 {
1151 if (!pPin)
1152 return E_POINTER;
1153
1154 if (m_Pin)
1155 {
1156 // increment reference count
1157 m_Pin->AddRef();
1158 *pPin = m_Pin;
1159 return S_OK;
1160 }
1161
1162 *pPin = NULL;
1163 return VFW_E_NOT_CONNECTED;
1164 }
1165 HRESULT
1166 STDMETHODCALLTYPE
1167 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1168 {
1169 if (!m_Pin)
1170 return VFW_E_NOT_CONNECTED;
1171
1172 #ifdef KSPROXY_TRACE
1173 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
1174 #endif
1175
1176 return E_NOTIMPL;
1177 }
1178 HRESULT
1179 STDMETHODCALLTYPE
1180 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
1181 {
1182 wcscpy(pInfo->achName, m_PinName);
1183 pInfo->dir = PINDIR_INPUT;
1184 pInfo->pFilter = m_ParentFilter;
1185 m_ParentFilter->AddRef();
1186
1187 return S_OK;
1188 }
1189 HRESULT
1190 STDMETHODCALLTYPE
1191 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1192 {
1193 if (pPinDir)
1194 {
1195 *pPinDir = PINDIR_INPUT;
1196 return S_OK;
1197 }
1198
1199 return E_POINTER;
1200 }
1201 HRESULT
1202 STDMETHODCALLTYPE
1203 CInputPin::QueryId(LPWSTR *Id)
1204 {
1205 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1206 if (!*Id)
1207 return E_OUTOFMEMORY;
1208
1209 wcscpy(*Id, m_PinName);
1210 return S_OK;
1211 }
1212
1213 HRESULT
1214 STDMETHODCALLTYPE
1215 CInputPin::QueryAccept(
1216 const AM_MEDIA_TYPE *pmt)
1217 {
1218 return CheckFormat(pmt);
1219 }
1220 HRESULT
1221 STDMETHODCALLTYPE
1222 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1223 {
1224 HRESULT hr;
1225 ULONG MediaTypeCount = 0, Index;
1226 AM_MEDIA_TYPE * MediaTypes;
1227 IKsObject * KsObjectParent;
1228 HANDLE hFilter;
1229
1230 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1231 if (FAILED(hr))
1232 return hr;
1233
1234 hFilter = KsObjectParent->KsGetObjectHandle();
1235
1236 KsObjectParent->Release();
1237
1238 if (!hFilter)
1239 return E_HANDLE;
1240
1241
1242 // query media type count
1243 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1244 if (FAILED(hr) || !MediaTypeCount)
1245 return hr;
1246
1247 // allocate media types
1248 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1249 if (!MediaTypes)
1250 {
1251 // not enough memory
1252 return E_OUTOFMEMORY;
1253 }
1254
1255 // zero media types
1256 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1257
1258 for(Index = 0; Index < MediaTypeCount; Index++)
1259 {
1260 // get media type
1261 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1262 if (FAILED(hr))
1263 {
1264 // failed
1265 CoTaskMemFree(MediaTypes);
1266 return hr;
1267 }
1268 }
1269
1270 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1271 }
1272
1273 HRESULT
1274 STDMETHODCALLTYPE
1275 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1276 {
1277 #ifdef KSPROXY_TRACE
1278 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
1279 #endif
1280 return E_NOTIMPL;
1281 }
1282 HRESULT
1283 STDMETHODCALLTYPE
1284 CInputPin::EndOfStream( void)
1285 {
1286 #ifdef KSPROXY_TRACE
1287 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
1288 #endif
1289 return E_NOTIMPL;
1290 }
1291 HRESULT
1292 STDMETHODCALLTYPE
1293 CInputPin::BeginFlush( void)
1294 {
1295 #ifdef KSPROXY_TRACE
1296 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
1297 #endif
1298 return E_NOTIMPL;
1299 }
1300 HRESULT
1301 STDMETHODCALLTYPE
1302 CInputPin::EndFlush( void)
1303 {
1304 #ifdef KSPROXY_TRACE
1305 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
1306 #endif
1307 return E_NOTIMPL;
1308 }
1309 HRESULT
1310 STDMETHODCALLTYPE
1311 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1312 {
1313 #ifdef KSPROXY_TRACE
1314 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
1315 #endif
1316 return E_NOTIMPL;
1317 }
1318
1319
1320 //-------------------------------------------------------------------
1321 HRESULT
1322 STDMETHODCALLTYPE
1323 CInputPin::CheckFormat(
1324 const AM_MEDIA_TYPE *pmt)
1325 {
1326 PKSMULTIPLE_ITEM MultipleItem;
1327 PKSDATAFORMAT DataFormat;
1328 HRESULT hr;
1329 IKsObject * KsObjectParent;
1330 HANDLE hFilter;
1331
1332 if (!pmt)
1333 return E_POINTER;
1334
1335 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1336 if (FAILED(hr))
1337 return hr;
1338
1339 hFilter = KsObjectParent->KsGetObjectHandle();
1340
1341 KsObjectParent->Release();
1342
1343 if (!hFilter)
1344 return E_HANDLE;
1345
1346
1347 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1348 if (FAILED(hr))
1349 return S_FALSE;
1350
1351 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1352 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1353 {
1354 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1355 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1356 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1357 {
1358 // format is supported
1359 CoTaskMemFree(MultipleItem);
1360 #ifdef KSPROXY_TRACE
1361 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
1362 #endif
1363 return S_OK;
1364 }
1365 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1366 }
1367 //format is not supported
1368 CoTaskMemFree(MultipleItem);
1369 return S_FALSE;
1370 }
1371
1372 HRESULT
1373 STDMETHODCALLTYPE
1374 CInputPin::CreatePin(
1375 const AM_MEDIA_TYPE *pmt)
1376 {
1377 PKSMULTIPLE_ITEM MediumList;
1378 PKSMULTIPLE_ITEM InterfaceList;
1379 PKSPIN_MEDIUM Medium;
1380 PKSPIN_INTERFACE Interface;
1381 IKsInterfaceHandler * InterfaceHandler;
1382 HRESULT hr;
1383
1384 // query for pin medium
1385 hr = KsQueryMediums(&MediumList);
1386 if (FAILED(hr))
1387 return hr;
1388
1389 // query for pin interface
1390 hr = KsQueryInterfaces(&InterfaceList);
1391 if (FAILED(hr))
1392 {
1393 // failed
1394 CoTaskMemFree(MediumList);
1395 return hr;
1396 }
1397
1398 if (MediumList->Count)
1399 {
1400 //use first available medium
1401 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1402 }
1403 else
1404 {
1405 // default to standard medium
1406 Medium = &StandardPinMedium;
1407 }
1408
1409 if (InterfaceList->Count)
1410 {
1411 //use first available interface
1412 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1413 }
1414 else
1415 {
1416 // default to standard interface
1417 Interface = &StandardPinInterface;
1418 }
1419
1420 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1421 {
1422 if (!m_InterfaceHandler)
1423 {
1424 // now load the IKsInterfaceHandler plugin
1425 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1426 if (FAILED(hr))
1427 {
1428 // failed to load interface handler plugin
1429 #ifdef KSPROXY_TRACE
1430 OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
1431 #endif
1432 CoTaskMemFree(MediumList);
1433 CoTaskMemFree(InterfaceList);
1434
1435 return hr;
1436 }
1437
1438 // now set the pin
1439 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
1440 if (FAILED(hr))
1441 {
1442 // failed to load interface handler plugin
1443 #ifdef KSPROXY_TRACE
1444 OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
1445 #endif
1446 InterfaceHandler->Release();
1447 CoTaskMemFree(MediumList);
1448 CoTaskMemFree(InterfaceList);
1449 return hr;
1450 }
1451
1452 // store interface handler
1453 m_InterfaceHandler = InterfaceHandler;
1454 }
1455
1456 // now create pin
1457 hr = CreatePinHandle(Medium, Interface, pmt);
1458 if (FAILED(hr))
1459 {
1460 m_InterfaceHandler->Release();
1461 m_InterfaceHandler = InterfaceHandler;
1462 }
1463 }
1464 else
1465 {
1466 #ifdef KSPROXY_TRACE
1467 WCHAR Buffer[100];
1468 swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
1469 OutputDebugStringW(Buffer);
1470 #endif
1471 hr = E_FAIL;
1472 }
1473
1474 // free medium / interface / dataformat
1475 CoTaskMemFree(MediumList);
1476 CoTaskMemFree(InterfaceList);
1477
1478 return hr;
1479 }
1480
1481 HRESULT
1482 STDMETHODCALLTYPE
1483 CInputPin::CreatePinHandle(
1484 PKSPIN_MEDIUM Medium,
1485 PKSPIN_INTERFACE Interface,
1486 const AM_MEDIA_TYPE *pmt)
1487 {
1488 PKSPIN_CONNECT PinConnect;
1489 PKSDATAFORMAT DataFormat;
1490 ULONG Length;
1491 HRESULT hr;
1492 IKsObject * KsObjectParent;
1493 HANDLE hFilter;
1494
1495 if (!pmt)
1496 return E_POINTER;
1497
1498 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1499 if (FAILED(hr))
1500 return hr;
1501
1502 hFilter = KsObjectParent->KsGetObjectHandle();
1503
1504 KsObjectParent->Release();
1505
1506 if (!hFilter)
1507 return E_HANDLE;
1508
1509
1510 if (m_hPin != INVALID_HANDLE_VALUE)
1511 {
1512 // pin already exists
1513 //CloseHandle(m_hPin);
1514 //m_hPin = INVALID_HANDLE_VALUE;
1515 return S_OK;
1516 }
1517
1518
1519 // calc format size
1520 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
1521
1522 // allocate pin connect
1523 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
1524 if (!PinConnect)
1525 {
1526 // failed
1527 return E_OUTOFMEMORY;
1528 }
1529
1530 // setup request
1531 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1532 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1533 PinConnect->PinId = m_PinId;
1534 PinConnect->PinToHandle = NULL;
1535 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1536 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1537
1538 // get dataformat offset
1539 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1540
1541 // copy data format
1542 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1543 DataFormat->Flags = 0;
1544 DataFormat->SampleSize = pmt->lSampleSize;
1545 DataFormat->Reserved = 0;
1546 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1547 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
1548 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1549
1550 if (pmt->cbFormat)
1551 {
1552 // copy extended format
1553 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1554 }
1555
1556 // create pin
1557 hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1558
1559 if (SUCCEEDED(hr))
1560 {
1561 // store current interface / medium
1562 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
1563 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
1564 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
1565
1566 #ifdef KSPROXY_TRACE
1567 LPOLESTR pMajor, pSub, pFormat;
1568 StringFromIID(m_MediaFormat.majortype, &pMajor);
1569 StringFromIID(m_MediaFormat.subtype , &pSub);
1570 StringFromIID(m_MediaFormat.formattype, &pFormat);
1571
1572 WCHAR Buffer[200];
1573 swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
1574 CoTaskMemFree(pMajor);
1575 CoTaskMemFree(pSub);
1576 CoTaskMemFree(pFormat);
1577 OutputDebugStringW(Buffer);
1578 #endif
1579
1580 if (pmt->cbFormat)
1581 {
1582 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
1583 if (!m_MediaFormat.pbFormat)
1584 {
1585 CoTaskMemFree(PinConnect);
1586 m_MediaFormat.pbFormat = NULL;
1587 m_MediaFormat.cbFormat = 0;
1588 return E_OUTOFMEMORY;
1589 }
1590 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
1591 }
1592
1593 LPGUID pGuid;
1594 ULONG NumGuids = 0;
1595
1596 // get all supported sets
1597 hr = GetSupportedSets(&pGuid, &NumGuids);
1598 if (FAILED(hr))
1599 {
1600 #ifdef KSPROXY_TRACE
1601 OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
1602 #endif
1603 return hr;
1604 }
1605
1606 // load all proxy plugins
1607 hr = LoadProxyPlugins(pGuid, NumGuids);
1608 if (FAILED(hr))
1609 {
1610 #ifdef KSPROXY_TRACE
1611 OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
1612 #endif
1613 return hr;
1614 }
1615
1616 // free sets
1617 CoTaskMemFree(pGuid);
1618
1619
1620 //TODO
1621 // connect pin pipes
1622
1623 }
1624
1625 // free pin connect
1626 CoTaskMemFree(PinConnect);
1627
1628 return hr;
1629 }
1630
1631 HRESULT
1632 STDMETHODCALLTYPE
1633 CInputPin::GetSupportedSets(
1634 LPGUID * pOutGuid,
1635 PULONG NumGuids)
1636 {
1637 KSPROPERTY Property;
1638 LPGUID pGuid;
1639 ULONG NumProperty = 0;
1640 ULONG NumMethods = 0;
1641 ULONG NumEvents = 0;
1642 ULONG Length;
1643 ULONG BytesReturned;
1644 HRESULT hr;
1645
1646 Property.Set = GUID_NULL;
1647 Property.Id = 0;
1648 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1649
1650 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
1651 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
1652 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
1653
1654 Length = NumProperty + NumMethods + NumEvents;
1655
1656 assert(Length);
1657
1658 // allocate guid buffer
1659 pGuid = (LPGUID)CoTaskMemAlloc(Length);
1660 if (!pGuid)
1661 {
1662 // failed
1663 return E_OUTOFMEMORY;
1664 }
1665
1666 NumProperty /= sizeof(GUID);
1667 NumMethods /= sizeof(GUID);
1668 NumEvents /= sizeof(GUID);
1669
1670 #ifdef KSPROXY_TRACE
1671 WCHAR Buffer[200];
1672 swprintf(Buffer, L"CInputPin::GetSupportedSets NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
1673 OutputDebugStringW(Buffer);
1674 #endif
1675
1676 // get all properties
1677 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
1678 if (FAILED(hr))
1679 {
1680 CoTaskMemFree(pGuid);
1681 return E_FAIL;
1682 }
1683 Length -= BytesReturned;
1684
1685 // get all methods
1686 if (Length && NumMethods)
1687 {
1688 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
1689 if (FAILED(hr))
1690 {
1691 CoTaskMemFree(pGuid);
1692 return E_FAIL;
1693 }
1694 Length -= BytesReturned;
1695 }
1696
1697 // get all events
1698 if (Length && NumEvents)
1699 {
1700 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
1701 if (FAILED(hr))
1702 {
1703 CoTaskMemFree(pGuid);
1704 return E_FAIL;
1705 }
1706 Length -= BytesReturned;
1707 }
1708
1709 *pOutGuid = pGuid;
1710 *NumGuids = NumProperty+NumEvents+NumMethods;
1711 return S_OK;
1712 }
1713
1714 HRESULT
1715 STDMETHODCALLTYPE
1716 CInputPin::LoadProxyPlugins(
1717 LPGUID pGuids,
1718 ULONG NumGuids)
1719 {
1720 ULONG Index;
1721 LPOLESTR pStr;
1722 HKEY hKey, hSubKey;
1723 HRESULT hr;
1724 IUnknown * pUnknown;
1725
1726 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1727 {
1728 OutputDebugStringW(L"CInputPin::LoadProxyPlugins failed to open MediaInterfaces key\n");
1729 return E_FAIL;
1730 }
1731
1732 // enumerate all sets
1733 for(Index = 0; Index < NumGuids; Index++)
1734 {
1735 // convert to string
1736 hr = StringFromCLSID(pGuids[Index], &pStr);
1737 if (FAILED(hr))
1738 return E_FAIL;
1739
1740 // now try open class key
1741 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
1742 {
1743 // no plugin for that set exists
1744 CoTaskMemFree(pStr);
1745 continue;
1746 }
1747
1748 // try load plugin
1749 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
1750 if (SUCCEEDED(hr))
1751 {
1752 // store plugin
1753 m_Plugins.push_back(pUnknown);
1754 }
1755 // close key
1756 RegCloseKey(hSubKey);
1757 }
1758
1759 // close media interfaces key
1760 RegCloseKey(hKey);
1761 return S_OK;
1762 }
1763
1764 HRESULT
1765 WINAPI
1766 CInputPin_Constructor(
1767 IBaseFilter * ParentFilter,
1768 LPCWSTR PinName,
1769 HANDLE hFilter,
1770 ULONG PinId,
1771 KSPIN_COMMUNICATION Communication,
1772 REFIID riid,
1773 LPVOID * ppv)
1774 {
1775 CInputPin * handler = new CInputPin(ParentFilter, PinName, PinId, Communication);
1776
1777 if (!handler)
1778 return E_OUTOFMEMORY;
1779
1780 if (FAILED(handler->QueryInterface(riid, ppv)))
1781 {
1782 /* not supported */
1783 delete handler;
1784 return E_NOINTERFACE;
1785 }
1786
1787 return S_OK;
1788 }