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