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