- merge audio headers
[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 #endif
704
705 return E_NOTIMPL;
706 }
707
708 HRESULT
709 STDMETHODCALLTYPE
710 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
711 {
712 #ifdef KSPROXY_TRACE
713 OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
714 #endif
715
716 return E_NOTIMPL;
717 }
718
719 HRESULT
720 STDMETHODCALLTYPE
721 CInputPin::ReceiveCanBlock( void)
722 {
723 #ifdef KSPROXY_TRACE
724 OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
725 #endif
726
727 return S_FALSE;
728 }
729
730 //-------------------------------------------------------------------
731 // IKsPin
732 //
733
734 HRESULT
735 STDMETHODCALLTYPE
736 CInputPin::KsQueryMediums(
737 PKSMULTIPLE_ITEM* MediumList)
738 {
739 HRESULT hr;
740 IKsObject * KsObjectParent;
741 HANDLE hFilter;
742
743 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
744 if (FAILED(hr))
745 return hr;
746
747 hFilter = KsObjectParent->KsGetObjectHandle();
748
749 KsObjectParent->Release();
750
751 if (!hFilter)
752 return E_HANDLE;
753
754 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
755 }
756
757 HRESULT
758 STDMETHODCALLTYPE
759 CInputPin::KsQueryInterfaces(
760 PKSMULTIPLE_ITEM* InterfaceList)
761 {
762 HRESULT hr;
763 IKsObject * KsObjectParent;
764 HANDLE hFilter;
765
766 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
767 if (FAILED(hr))
768 return hr;
769
770 hFilter = KsObjectParent->KsGetObjectHandle();
771
772 KsObjectParent->Release();
773
774 if (!hFilter)
775 return E_HANDLE;
776
777 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
778 }
779
780 HRESULT
781 STDMETHODCALLTYPE
782 CInputPin::KsCreateSinkPinHandle(
783 KSPIN_INTERFACE& Interface,
784 KSPIN_MEDIUM& Medium)
785 {
786 return CreatePin(&m_MediaFormat);
787 }
788
789 HRESULT
790 STDMETHODCALLTYPE
791 CInputPin::KsGetCurrentCommunication(
792 KSPIN_COMMUNICATION *Communication,
793 KSPIN_INTERFACE *Interface,
794 KSPIN_MEDIUM *Medium)
795 {
796 if (Communication)
797 {
798 *Communication = m_Communication;
799 }
800
801 if (Interface)
802 {
803 if (!m_hPin)
804 return VFW_E_NOT_CONNECTED;
805
806 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
807 }
808
809 if (Medium)
810 {
811 if (!m_hPin)
812 return VFW_E_NOT_CONNECTED;
813
814 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
815 }
816 return NOERROR;
817 }
818
819 HRESULT
820 STDMETHODCALLTYPE
821 CInputPin::KsPropagateAcquire()
822 {
823 KSPROPERTY Property;
824 KSSTATE State;
825 ULONG BytesReturned;
826 HRESULT hr;
827
828 assert(m_hPin != INVALID_HANDLE_VALUE);
829
830 Property.Set = KSPROPSETID_Connection;
831 Property.Id = KSPROPERTY_CONNECTION_STATE;
832 Property.Flags = KSPROPERTY_TYPE_SET;
833
834 State = KSSTATE_ACQUIRE;
835
836 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
837
838 //TODO
839 //propagate to connected pin on the pipe
840
841 return hr;
842 }
843
844 HRESULT
845 STDMETHODCALLTYPE
846 CInputPin::KsDeliver(
847 IMediaSample* Sample,
848 ULONG Flags)
849 {
850 return E_FAIL;
851 }
852
853 HRESULT
854 STDMETHODCALLTYPE
855 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
856 {
857 return NOERROR;
858 }
859
860 IMemAllocator *
861 STDMETHODCALLTYPE
862 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
863 {
864 if (Operation == KsPeekOperation_AddRef)
865 {
866 // add reference on allocator
867 m_MemAllocator->AddRef();
868 }
869
870 return m_MemAllocator;
871 }
872
873 HRESULT
874 STDMETHODCALLTYPE
875 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
876 {
877
878 if (MemAllocator)
879 {
880 MemAllocator->AddRef();
881 }
882
883 if (m_MemAllocator)
884 {
885 m_MemAllocator->Release();
886 }
887
888 m_MemAllocator = MemAllocator;
889 return NOERROR;
890 }
891
892 HRESULT
893 STDMETHODCALLTYPE
894 CInputPin::KsRenegotiateAllocator()
895 {
896 return E_FAIL;
897 }
898
899 LONG
900 STDMETHODCALLTYPE
901 CInputPin::KsIncrementPendingIoCount()
902 {
903 return InterlockedIncrement((volatile LONG*)&m_IoCount);
904 }
905
906 LONG
907 STDMETHODCALLTYPE
908 CInputPin::KsDecrementPendingIoCount()
909 {
910 return InterlockedDecrement((volatile LONG*)&m_IoCount);
911 }
912
913 HRESULT
914 STDMETHODCALLTYPE
915 CInputPin::KsQualityNotify(
916 ULONG Proportion,
917 REFERENCE_TIME TimeDelta)
918 {
919 #ifdef KSPROXY_TRACE
920 OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
921 #endif
922
923 return E_NOTIMPL;
924 }
925
926 //-------------------------------------------------------------------
927 // IKsPinEx
928 //
929
930 VOID
931 STDMETHODCALLTYPE
932 CInputPin::KsNotifyError(
933 IMediaSample* Sample,
934 HRESULT hr)
935 {
936 #ifdef KSPROXY_TRACE
937 OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n");
938 #endif
939 }
940
941
942 //-------------------------------------------------------------------
943 // IKsControl
944 //
945 HRESULT
946 STDMETHODCALLTYPE
947 CInputPin::KsProperty(
948 PKSPROPERTY Property,
949 ULONG PropertyLength,
950 LPVOID PropertyData,
951 ULONG DataLength,
952 ULONG* BytesReturned)
953 {
954 assert(m_hPin != INVALID_HANDLE_VALUE);
955 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
956 }
957
958 HRESULT
959 STDMETHODCALLTYPE
960 CInputPin::KsMethod(
961 PKSMETHOD Method,
962 ULONG MethodLength,
963 LPVOID MethodData,
964 ULONG DataLength,
965 ULONG* BytesReturned)
966 {
967 assert(m_hPin != INVALID_HANDLE_VALUE);
968 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
969 }
970
971 HRESULT
972 STDMETHODCALLTYPE
973 CInputPin::KsEvent(
974 PKSEVENT Event,
975 ULONG EventLength,
976 LPVOID EventData,
977 ULONG DataLength,
978 ULONG* BytesReturned)
979 {
980 assert(m_hPin != INVALID_HANDLE_VALUE);
981
982 if (EventLength)
983 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
984 else
985 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
986 }
987
988
989 //-------------------------------------------------------------------
990 // IKsPropertySet
991 //
992 HRESULT
993 STDMETHODCALLTYPE
994 CInputPin::Set(
995 REFGUID guidPropSet,
996 DWORD dwPropID,
997 LPVOID pInstanceData,
998 DWORD cbInstanceData,
999 LPVOID pPropData,
1000 DWORD cbPropData)
1001 {
1002 ULONG BytesReturned;
1003
1004 if (cbInstanceData)
1005 {
1006 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1007 if (!Property)
1008 return E_OUTOFMEMORY;
1009
1010 Property->Set = guidPropSet;
1011 Property->Id = dwPropID;
1012 Property->Flags = KSPROPERTY_TYPE_SET;
1013
1014 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1015
1016 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1017 CoTaskMemFree(Property);
1018 return hr;
1019 }
1020 else
1021 {
1022 KSPROPERTY Property;
1023
1024 Property.Set = guidPropSet;
1025 Property.Id = dwPropID;
1026 Property.Flags = KSPROPERTY_TYPE_SET;
1027
1028 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1029 return hr;
1030 }
1031 }
1032
1033 HRESULT
1034 STDMETHODCALLTYPE
1035 CInputPin::Get(
1036 REFGUID guidPropSet,
1037 DWORD dwPropID,
1038 LPVOID pInstanceData,
1039 DWORD cbInstanceData,
1040 LPVOID pPropData,
1041 DWORD cbPropData,
1042 DWORD *pcbReturned)
1043 {
1044 ULONG BytesReturned;
1045
1046 if (cbInstanceData)
1047 {
1048 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1049 if (!Property)
1050 return E_OUTOFMEMORY;
1051
1052 Property->Set = guidPropSet;
1053 Property->Id = dwPropID;
1054 Property->Flags = KSPROPERTY_TYPE_GET;
1055
1056 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1057
1058 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1059 CoTaskMemFree(Property);
1060 return hr;
1061 }
1062 else
1063 {
1064 KSPROPERTY Property;
1065
1066 Property.Set = guidPropSet;
1067 Property.Id = dwPropID;
1068 Property.Flags = KSPROPERTY_TYPE_GET;
1069
1070 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1071 return hr;
1072 }
1073 }
1074
1075 HRESULT
1076 STDMETHODCALLTYPE
1077 CInputPin::QuerySupported(
1078 REFGUID guidPropSet,
1079 DWORD dwPropID,
1080 DWORD *pTypeSupport)
1081 {
1082 KSPROPERTY Property;
1083 ULONG BytesReturned;
1084
1085 Property.Set = guidPropSet;
1086 Property.Id = dwPropID;
1087 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1088
1089 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1090 }
1091
1092
1093 //-------------------------------------------------------------------
1094 // IKsObject
1095 //
1096 HANDLE
1097 STDMETHODCALLTYPE
1098 CInputPin::KsGetObjectHandle()
1099 {
1100 assert(m_hPin);
1101 return m_hPin;
1102 }
1103
1104 //-------------------------------------------------------------------
1105 // IPin interface
1106 //
1107 HRESULT
1108 STDMETHODCALLTYPE
1109 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1110 {
1111 #ifdef KSPROXY_TRACE
1112 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
1113 #endif
1114 return NOERROR;
1115 }
1116
1117 HRESULT
1118 STDMETHODCALLTYPE
1119 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1120 {
1121 HRESULT hr;
1122
1123 if (m_Pin)
1124 {
1125 // already connected
1126 return VFW_E_ALREADY_CONNECTED;
1127 }
1128
1129 // first check format
1130 hr = CheckFormat(pmt);
1131 if (FAILED(hr))
1132 {
1133 // format is not supported
1134 return hr;
1135 }
1136
1137 hr = CreatePin(pmt);
1138 if (FAILED(hr))
1139 {
1140 return hr;
1141 }
1142
1143 m_Pin = pConnector;
1144 m_Pin->AddRef();
1145
1146 return S_OK;
1147 }
1148 HRESULT
1149 STDMETHODCALLTYPE
1150 CInputPin::Disconnect( void)
1151 {
1152 if (!m_Pin)
1153 {
1154 // pin was not connected
1155 return S_FALSE;
1156 }
1157
1158 //FIXME
1159 //check if filter is active
1160
1161 m_Pin->Release();
1162 m_Pin = NULL;
1163
1164 #ifdef KSPROXY_TRACE
1165 OutputDebugStringW(L"CInputPin::Disconnect\n");
1166 #endif
1167
1168 return S_OK;
1169 }
1170 HRESULT
1171 STDMETHODCALLTYPE
1172 CInputPin::ConnectedTo(IPin **pPin)
1173 {
1174 if (!pPin)
1175 return E_POINTER;
1176
1177 if (m_Pin)
1178 {
1179 // increment reference count
1180 m_Pin->AddRef();
1181 *pPin = m_Pin;
1182 return S_OK;
1183 }
1184
1185 *pPin = NULL;
1186 return VFW_E_NOT_CONNECTED;
1187 }
1188 HRESULT
1189 STDMETHODCALLTYPE
1190 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1191 {
1192 if (!m_Pin)
1193 return VFW_E_NOT_CONNECTED;
1194
1195 #ifdef KSPROXY_TRACE
1196 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
1197 #endif
1198
1199 return E_NOTIMPL;
1200 }
1201 HRESULT
1202 STDMETHODCALLTYPE
1203 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
1204 {
1205 wcscpy(pInfo->achName, m_PinName);
1206 pInfo->dir = PINDIR_INPUT;
1207 pInfo->pFilter = m_ParentFilter;
1208 m_ParentFilter->AddRef();
1209
1210 return S_OK;
1211 }
1212 HRESULT
1213 STDMETHODCALLTYPE
1214 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1215 {
1216 if (pPinDir)
1217 {
1218 *pPinDir = PINDIR_INPUT;
1219 return S_OK;
1220 }
1221
1222 return E_POINTER;
1223 }
1224 HRESULT
1225 STDMETHODCALLTYPE
1226 CInputPin::QueryId(LPWSTR *Id)
1227 {
1228 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1229 if (!*Id)
1230 return E_OUTOFMEMORY;
1231
1232 wcscpy(*Id, m_PinName);
1233 return S_OK;
1234 }
1235
1236 HRESULT
1237 STDMETHODCALLTYPE
1238 CInputPin::QueryAccept(
1239 const AM_MEDIA_TYPE *pmt)
1240 {
1241 return CheckFormat(pmt);
1242 }
1243 HRESULT
1244 STDMETHODCALLTYPE
1245 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1246 {
1247 HRESULT hr;
1248 ULONG MediaTypeCount = 0, Index;
1249 AM_MEDIA_TYPE * MediaTypes;
1250 IKsObject * KsObjectParent;
1251 HANDLE hFilter;
1252
1253 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1254 if (FAILED(hr))
1255 return hr;
1256
1257 hFilter = KsObjectParent->KsGetObjectHandle();
1258
1259 KsObjectParent->Release();
1260
1261 if (!hFilter)
1262 return E_HANDLE;
1263
1264
1265 // query media type count
1266 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1267 if (FAILED(hr) || !MediaTypeCount)
1268 return hr;
1269
1270 // allocate media types
1271 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1272 if (!MediaTypes)
1273 {
1274 // not enough memory
1275 return E_OUTOFMEMORY;
1276 }
1277
1278 // zero media types
1279 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1280
1281 for(Index = 0; Index < MediaTypeCount; Index++)
1282 {
1283 // get media type
1284 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1285 if (FAILED(hr))
1286 {
1287 // failed
1288 CoTaskMemFree(MediaTypes);
1289 return hr;
1290 }
1291 }
1292
1293 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1294 }
1295
1296 HRESULT
1297 STDMETHODCALLTYPE
1298 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1299 {
1300 #ifdef KSPROXY_TRACE
1301 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
1302 #endif
1303 return E_NOTIMPL;
1304 }
1305 HRESULT
1306 STDMETHODCALLTYPE
1307 CInputPin::EndOfStream( void)
1308 {
1309 #ifdef KSPROXY_TRACE
1310 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
1311 #endif
1312 return E_NOTIMPL;
1313 }
1314 HRESULT
1315 STDMETHODCALLTYPE
1316 CInputPin::BeginFlush( void)
1317 {
1318 #ifdef KSPROXY_TRACE
1319 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
1320 #endif
1321 return E_NOTIMPL;
1322 }
1323 HRESULT
1324 STDMETHODCALLTYPE
1325 CInputPin::EndFlush( void)
1326 {
1327 #ifdef KSPROXY_TRACE
1328 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
1329 #endif
1330 return E_NOTIMPL;
1331 }
1332 HRESULT
1333 STDMETHODCALLTYPE
1334 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1335 {
1336 #ifdef KSPROXY_TRACE
1337 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
1338 #endif
1339 return E_NOTIMPL;
1340 }
1341
1342
1343 //-------------------------------------------------------------------
1344 HRESULT
1345 STDMETHODCALLTYPE
1346 CInputPin::CheckFormat(
1347 const AM_MEDIA_TYPE *pmt)
1348 {
1349 PKSMULTIPLE_ITEM MultipleItem;
1350 PKSDATAFORMAT DataFormat;
1351 HRESULT hr;
1352 IKsObject * KsObjectParent;
1353 HANDLE hFilter;
1354
1355 if (!pmt)
1356 return E_POINTER;
1357
1358 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1359 if (FAILED(hr))
1360 return hr;
1361
1362 hFilter = KsObjectParent->KsGetObjectHandle();
1363
1364 KsObjectParent->Release();
1365
1366 if (!hFilter)
1367 return E_HANDLE;
1368
1369
1370 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1371 if (FAILED(hr))
1372 return S_FALSE;
1373
1374 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1375 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1376 {
1377 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1378 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1379 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1380 {
1381 // format is supported
1382 CoTaskMemFree(MultipleItem);
1383 #ifdef KSPROXY_TRACE
1384 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
1385 #endif
1386 return S_OK;
1387 }
1388 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1389 }
1390 //format is not supported
1391 CoTaskMemFree(MultipleItem);
1392 return S_FALSE;
1393 }
1394
1395 HRESULT
1396 STDMETHODCALLTYPE
1397 CInputPin::CreatePin(
1398 const AM_MEDIA_TYPE *pmt)
1399 {
1400 PKSMULTIPLE_ITEM MediumList;
1401 PKSMULTIPLE_ITEM InterfaceList;
1402 PKSPIN_MEDIUM Medium;
1403 PKSPIN_INTERFACE Interface;
1404 IKsInterfaceHandler * InterfaceHandler;
1405 HRESULT hr;
1406
1407 // query for pin medium
1408 hr = KsQueryMediums(&MediumList);
1409 if (FAILED(hr))
1410 return hr;
1411
1412 // query for pin interface
1413 hr = KsQueryInterfaces(&InterfaceList);
1414 if (FAILED(hr))
1415 {
1416 // failed
1417 CoTaskMemFree(MediumList);
1418 return hr;
1419 }
1420
1421 if (MediumList->Count)
1422 {
1423 //use first available medium
1424 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1425 }
1426 else
1427 {
1428 // default to standard medium
1429 Medium = &StandardPinMedium;
1430 }
1431
1432 if (InterfaceList->Count)
1433 {
1434 //use first available interface
1435 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1436 }
1437 else
1438 {
1439 // default to standard interface
1440 Interface = &StandardPinInterface;
1441 }
1442
1443 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1444 {
1445 if (!m_InterfaceHandler)
1446 {
1447 // now load the IKsInterfaceHandler plugin
1448 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1449 if (FAILED(hr))
1450 {
1451 // failed to load interface handler plugin
1452 #ifdef KSPROXY_TRACE
1453 OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
1454 #endif
1455 CoTaskMemFree(MediumList);
1456 CoTaskMemFree(InterfaceList);
1457
1458 return hr;
1459 }
1460
1461 // now set the pin
1462 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
1463 if (FAILED(hr))
1464 {
1465 // failed to load interface handler plugin
1466 #ifdef KSPROXY_TRACE
1467 OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
1468 #endif
1469 InterfaceHandler->Release();
1470 CoTaskMemFree(MediumList);
1471 CoTaskMemFree(InterfaceList);
1472 return hr;
1473 }
1474
1475 // store interface handler
1476 m_InterfaceHandler = InterfaceHandler;
1477 }
1478
1479 // now create pin
1480 hr = CreatePinHandle(Medium, Interface, pmt);
1481 if (FAILED(hr))
1482 {
1483 m_InterfaceHandler->Release();
1484 m_InterfaceHandler = InterfaceHandler;
1485 }
1486 }
1487 else
1488 {
1489 #ifdef KSPROXY_TRACE
1490 WCHAR Buffer[100];
1491 swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
1492 OutputDebugStringW(Buffer);
1493 #endif
1494 hr = E_FAIL;
1495 }
1496
1497 // free medium / interface / dataformat
1498 CoTaskMemFree(MediumList);
1499 CoTaskMemFree(InterfaceList);
1500
1501 return hr;
1502 }
1503
1504 HRESULT
1505 STDMETHODCALLTYPE
1506 CInputPin::CreatePinHandle(
1507 PKSPIN_MEDIUM Medium,
1508 PKSPIN_INTERFACE Interface,
1509 const AM_MEDIA_TYPE *pmt)
1510 {
1511 PKSPIN_CONNECT PinConnect;
1512 PKSDATAFORMAT DataFormat;
1513 ULONG Length;
1514 HRESULT hr;
1515 IKsObject * KsObjectParent;
1516 HANDLE hFilter;
1517
1518 if (!pmt)
1519 return E_POINTER;
1520
1521 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1522 if (FAILED(hr))
1523 return hr;
1524
1525 hFilter = KsObjectParent->KsGetObjectHandle();
1526
1527 KsObjectParent->Release();
1528
1529 if (!hFilter)
1530 return E_HANDLE;
1531
1532
1533 if (m_hPin != INVALID_HANDLE_VALUE)
1534 {
1535 // pin already exists
1536 //CloseHandle(m_hPin);
1537 //m_hPin = INVALID_HANDLE_VALUE;
1538 return S_OK;
1539 }
1540
1541
1542 // calc format size
1543 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
1544
1545 // allocate pin connect
1546 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
1547 if (!PinConnect)
1548 {
1549 // failed
1550 return E_OUTOFMEMORY;
1551 }
1552
1553 // setup request
1554 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1555 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1556 PinConnect->PinId = m_PinId;
1557 PinConnect->PinToHandle = NULL;
1558 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1559 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1560
1561 // get dataformat offset
1562 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1563
1564 // copy data format
1565 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1566 DataFormat->Flags = 0;
1567 DataFormat->SampleSize = pmt->lSampleSize;
1568 DataFormat->Reserved = 0;
1569 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1570 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
1571 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1572
1573 if (pmt->cbFormat)
1574 {
1575 // copy extended format
1576 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1577 }
1578
1579 // create pin
1580 hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1581
1582 if (SUCCEEDED(hr))
1583 {
1584 // store current interface / medium
1585 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
1586 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
1587 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
1588
1589 #ifdef KSPROXY_TRACE
1590 LPOLESTR pMajor, pSub, pFormat;
1591 StringFromIID(m_MediaFormat.majortype, &pMajor);
1592 StringFromIID(m_MediaFormat.subtype , &pSub);
1593 StringFromIID(m_MediaFormat.formattype, &pFormat);
1594
1595 WCHAR Buffer[200];
1596 swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
1597 CoTaskMemFree(pMajor);
1598 CoTaskMemFree(pSub);
1599 CoTaskMemFree(pFormat);
1600 OutputDebugStringW(Buffer);
1601 #endif
1602
1603 if (pmt->cbFormat)
1604 {
1605 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
1606 if (!m_MediaFormat.pbFormat)
1607 {
1608 CoTaskMemFree(PinConnect);
1609 m_MediaFormat.pbFormat = NULL;
1610 m_MediaFormat.cbFormat = 0;
1611 return E_OUTOFMEMORY;
1612 }
1613 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
1614 }
1615
1616 LPGUID pGuid;
1617 ULONG NumGuids = 0;
1618
1619 // get all supported sets
1620 hr = GetSupportedSets(&pGuid, &NumGuids);
1621 if (FAILED(hr))
1622 {
1623 #ifdef KSPROXY_TRACE
1624 OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
1625 #endif
1626 return hr;
1627 }
1628
1629 // load all proxy plugins
1630 hr = LoadProxyPlugins(pGuid, NumGuids);
1631 if (FAILED(hr))
1632 {
1633 #ifdef KSPROXY_TRACE
1634 OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
1635 #endif
1636 return hr;
1637 }
1638
1639 // free sets
1640 CoTaskMemFree(pGuid);
1641
1642
1643 //TODO
1644 // connect pin pipes
1645
1646 }
1647
1648 // free pin connect
1649 CoTaskMemFree(PinConnect);
1650
1651 return hr;
1652 }
1653
1654 HRESULT
1655 STDMETHODCALLTYPE
1656 CInputPin::GetSupportedSets(
1657 LPGUID * pOutGuid,
1658 PULONG NumGuids)
1659 {
1660 KSPROPERTY Property;
1661 LPGUID pGuid;
1662 ULONG NumProperty = 0;
1663 ULONG NumMethods = 0;
1664 ULONG NumEvents = 0;
1665 ULONG Length;
1666 ULONG BytesReturned;
1667 HRESULT hr;
1668
1669 Property.Set = GUID_NULL;
1670 Property.Id = 0;
1671 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1672
1673 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
1674 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
1675 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
1676
1677 Length = NumProperty + NumMethods + NumEvents;
1678
1679 assert(Length);
1680
1681 // allocate guid buffer
1682 pGuid = (LPGUID)CoTaskMemAlloc(Length);
1683 if (!pGuid)
1684 {
1685 // failed
1686 return E_OUTOFMEMORY;
1687 }
1688
1689 NumProperty /= sizeof(GUID);
1690 NumMethods /= sizeof(GUID);
1691 NumEvents /= sizeof(GUID);
1692
1693 #ifdef KSPROXY_TRACE
1694 WCHAR Buffer[200];
1695 swprintf(Buffer, L"CInputPin::GetSupportedSets NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
1696 OutputDebugStringW(Buffer);
1697 #endif
1698
1699 // get all properties
1700 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
1701 if (FAILED(hr))
1702 {
1703 CoTaskMemFree(pGuid);
1704 return E_FAIL;
1705 }
1706 Length -= BytesReturned;
1707
1708 // get all methods
1709 if (Length && NumMethods)
1710 {
1711 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
1712 if (FAILED(hr))
1713 {
1714 CoTaskMemFree(pGuid);
1715 return E_FAIL;
1716 }
1717 Length -= BytesReturned;
1718 }
1719
1720 // get all events
1721 if (Length && NumEvents)
1722 {
1723 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
1724 if (FAILED(hr))
1725 {
1726 CoTaskMemFree(pGuid);
1727 return E_FAIL;
1728 }
1729 Length -= BytesReturned;
1730 }
1731
1732 *pOutGuid = pGuid;
1733 *NumGuids = NumProperty+NumEvents+NumMethods;
1734 return S_OK;
1735 }
1736
1737 HRESULT
1738 STDMETHODCALLTYPE
1739 CInputPin::LoadProxyPlugins(
1740 LPGUID pGuids,
1741 ULONG NumGuids)
1742 {
1743 ULONG Index;
1744 LPOLESTR pStr;
1745 HKEY hKey, hSubKey;
1746 HRESULT hr;
1747 IUnknown * pUnknown;
1748
1749 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1750 {
1751 OutputDebugStringW(L"CInputPin::LoadProxyPlugins failed to open MediaInterfaces key\n");
1752 return E_FAIL;
1753 }
1754
1755 // enumerate all sets
1756 for(Index = 0; Index < NumGuids; Index++)
1757 {
1758 // convert to string
1759 hr = StringFromCLSID(pGuids[Index], &pStr);
1760 if (FAILED(hr))
1761 return E_FAIL;
1762
1763 // now try open class key
1764 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
1765 {
1766 // no plugin for that set exists
1767 CoTaskMemFree(pStr);
1768 continue;
1769 }
1770
1771 // try load plugin
1772 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
1773 if (SUCCEEDED(hr))
1774 {
1775 // store plugin
1776 m_Plugins.push_back(pUnknown);
1777 }
1778 // close key
1779 RegCloseKey(hSubKey);
1780 }
1781
1782 // close media interfaces key
1783 RegCloseKey(hKey);
1784 return S_OK;
1785 }
1786
1787 HRESULT
1788 WINAPI
1789 CInputPin_Constructor(
1790 IBaseFilter * ParentFilter,
1791 LPCWSTR PinName,
1792 HANDLE hFilter,
1793 ULONG PinId,
1794 KSPIN_COMMUNICATION Communication,
1795 REFIID riid,
1796 LPVOID * ppv)
1797 {
1798 CInputPin * handler = new CInputPin(ParentFilter, PinName, PinId, Communication);
1799
1800 if (!handler)
1801 return E_OUTOFMEMORY;
1802
1803 if (FAILED(handler->QueryInterface(riid, ppv)))
1804 {
1805 /* not supported */
1806 delete handler;
1807 return E_NOINTERFACE;
1808 }
1809
1810 return S_OK;
1811 }