[KSPROXY]
[reactos.git] / reactos / dll / directx / ksproxy / input_pin.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/input_cpp.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_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
12
13 #ifndef _MSC_VER
14 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 #endif
16
17 #ifndef _MSC_VER
18 KSPIN_INTERFACE StandardPinInterface =
19 {
20 {STATIC_KSINTERFACESETID_Standard},
21 KSINTERFACE_STANDARD_STREAMING,
22 0
23 };
24
25 KSPIN_MEDIUM StandardPinMedium =
26 {
27 {STATIC_KSMEDIUMSETID_Standard},
28 KSMEDIUM_TYPE_ANYINSTANCE,
29 0
30 };
31
32 #else
33
34 KSPIN_INTERFACE StandardPinInterface =
35 {
36 STATIC_KSINTERFACESETID_Standard,
37 KSINTERFACE_STANDARD_STREAMING,
38 0
39 };
40
41 KSPIN_MEDIUM StandardPinMedium =
42 {
43 STATIC_KSMEDIUMSETID_Standard,
44 KSMEDIUM_TYPE_ANYINSTANCE,
45 0
46 };
47
48 #endif
49
50 class CInputPin : public IPin,
51 public IKsPropertySet,
52 public IKsControl,
53 public IKsObject,
54 public IKsPinEx,
55 public IMemInputPin,
56 public ISpecifyPropertyPages
57 /*
58 public IQualityControl,
59 public IKsPinPipe,
60 public IStreamBuilder,
61 public IKsPinFactory,
62 public IKsAggregateControl
63 */
64 {
65 public:
66 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
67
68 STDMETHODIMP_(ULONG) AddRef()
69 {
70 InterlockedIncrement(&m_Ref);
71 return m_Ref;
72 }
73 STDMETHODIMP_(ULONG) Release()
74 {
75 InterlockedDecrement(&m_Ref);
76 if (!m_Ref)
77 {
78 delete this;
79 return 0;
80 }
81 return m_Ref;
82 }
83
84 //IPin methods
85 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
86 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
87 HRESULT STDMETHODCALLTYPE Disconnect();
88 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
89 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
90 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
91 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
92 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
93 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
94 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
95 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
96 HRESULT STDMETHODCALLTYPE EndOfStream();
97 HRESULT STDMETHODCALLTYPE BeginFlush();
98 HRESULT STDMETHODCALLTYPE EndFlush();
99 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
100
101 // ISpecifyPropertyPages
102 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
103
104 //IKsObject methods
105 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
106
107 //IKsPropertySet
108 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
109 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
110 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
111
112 //IKsControl
113 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
114 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
115 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
116
117 //IKsPin
118 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
119 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
120 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
121 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
122 HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
123 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
124 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
125 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
126 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
127 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
128 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
129 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
130 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
131 // IKsPinEx
132 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
133
134 //IMemInputPin
135 HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
136 HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
137 HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
138 HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
139 HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
140 HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void);
141
142 //---------------------------------------------------------------
143 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
144 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
145 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
146 CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0), m_ReadOnly(0), m_InterfaceHandler(0){};
147 virtual ~CInputPin(){};
148
149 protected:
150 LONG m_Ref;
151 IBaseFilter * m_ParentFilter;
152 LPCWSTR m_PinName;
153 HANDLE m_hFilter;
154 HANDLE m_hPin;
155 ULONG m_PinId;
156 IMemAllocator * m_MemAllocator;
157 LONG m_IoCount;
158 KSPIN_COMMUNICATION m_Communication;
159 KSPIN_INTERFACE m_Interface;
160 KSPIN_MEDIUM m_Medium;
161 IPin * m_Pin;
162 IKsInterfaceHandler * m_InterfaceHandler;
163 BOOL m_ReadOnly;
164 };
165
166 HRESULT
167 STDMETHODCALLTYPE
168 CInputPin::QueryInterface(
169 IN REFIID refiid,
170 OUT PVOID* Output)
171 {
172 *Output = NULL;
173
174 if (IsEqualGUID(refiid, IID_IUnknown) ||
175 IsEqualGUID(refiid, IID_IPin))
176 {
177 *Output = PVOID(this);
178 reinterpret_cast<IUnknown*>(*Output)->AddRef();
179 return NOERROR;
180 }
181 else if (IsEqualGUID(refiid, IID_IMemInputPin))
182 {
183 *Output = (IMemInputPin*)(this);
184 reinterpret_cast<IMemInputPin*>(*Output)->AddRef();
185 return NOERROR;
186 }
187 else if (IsEqualGUID(refiid, IID_IKsObject))
188 {
189 *Output = (IKsObject*)(this);
190 reinterpret_cast<IKsObject*>(*Output)->AddRef();
191 return NOERROR;
192 }
193 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
194 {
195 *Output = (IKsPropertySet*)(this);
196 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
197 return NOERROR;
198 }
199 else if (IsEqualGUID(refiid, IID_IKsControl))
200 {
201 *Output = (IKsControl*)(this);
202 reinterpret_cast<IKsControl*>(*Output)->AddRef();
203 return NOERROR;
204 }
205 else if (IsEqualGUID(refiid, IID_IKsPin) ||
206 IsEqualGUID(refiid, IID_IKsPinEx))
207 {
208 *Output = (IKsPinEx*)(this);
209 reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
210 return NOERROR;
211 }
212 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
213 {
214 *Output = (ISpecifyPropertyPages*)(this);
215 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
216 return NOERROR;
217 }
218
219 WCHAR Buffer[MAX_PATH];
220 LPOLESTR lpstr;
221 StringFromCLSID(refiid, &lpstr);
222 swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr);
223 OutputDebugStringW(Buffer);
224 CoTaskMemFree(lpstr);
225
226 return E_NOINTERFACE;
227 }
228
229 //-------------------------------------------------------------------
230 // ISpecifyPropertyPages
231 //
232
233 HRESULT
234 STDMETHODCALLTYPE
235 CInputPin::GetPages(CAUUID *pPages)
236 {
237 if (!pPages)
238 return E_POINTER;
239
240 pPages->cElems = 0;
241 pPages->pElems = NULL;
242
243 return S_OK;
244 }
245
246 //-------------------------------------------------------------------
247 // IMemInputPin
248 //
249
250
251 HRESULT
252 STDMETHODCALLTYPE
253 CInputPin::GetAllocator(IMemAllocator **ppAllocator)
254 {
255 OutputDebugStringW(L"CInputPin::GetAllocator\n");
256 return VFW_E_NO_ALLOCATOR;
257 }
258
259 HRESULT
260 STDMETHODCALLTYPE
261 CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
262 {
263 if (pAllocator)
264 {
265 pAllocator->AddRef();
266 }
267
268 if (m_MemAllocator)
269 {
270 m_MemAllocator->Release();
271 }
272
273 m_MemAllocator = pAllocator;
274 m_ReadOnly = bReadOnly;
275 return NOERROR;
276 }
277
278 HRESULT
279 STDMETHODCALLTYPE
280 CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
281 {
282 KSALLOCATOR_FRAMING Framing;
283 KSPROPERTY Property;
284 HRESULT hr;
285 ULONG BytesReturned;
286
287 Property.Set = KSPROPSETID_Connection;
288 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
289 Property.Flags = KSPROPERTY_TYPE_SET;
290
291 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
292 if (SUCCEEDED(hr))
293 {
294 pProps->cBuffers = Framing.Frames;
295 pProps->cbBuffer = Framing.FrameSize;
296 pProps->cbAlign = Framing.FileAlignment;
297 pProps->cbPrefix = 0;
298 return hr;
299 }
300 else
301 return E_NOTIMPL;
302 }
303
304 HRESULT
305 STDMETHODCALLTYPE
306 CInputPin::Receive(IMediaSample *pSample)
307 {
308 OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
309 return E_NOTIMPL;
310 }
311
312 HRESULT
313 STDMETHODCALLTYPE
314 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
315 {
316 OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
317 return E_NOTIMPL;
318 }
319
320 HRESULT
321 STDMETHODCALLTYPE
322 CInputPin::ReceiveCanBlock( void)
323 {
324 OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
325 return S_FALSE;
326 }
327
328
329 //-------------------------------------------------------------------
330 // IKsPin
331 //
332
333 HRESULT
334 STDMETHODCALLTYPE
335 CInputPin::KsQueryMediums(
336 PKSMULTIPLE_ITEM* MediumList)
337 {
338 return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
339 }
340
341 HRESULT
342 STDMETHODCALLTYPE
343 CInputPin::KsQueryInterfaces(
344 PKSMULTIPLE_ITEM* InterfaceList)
345 {
346 return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
347 }
348
349 HRESULT
350 STDMETHODCALLTYPE
351 CInputPin::KsCreateSinkPinHandle(
352 KSPIN_INTERFACE& Interface,
353 KSPIN_MEDIUM& Medium)
354 {
355 OutputDebugStringW(L"CInputPin::KsCreateSinkPinHandle NotImplemented\n");
356 return E_NOTIMPL;
357 }
358
359 HRESULT
360 STDMETHODCALLTYPE
361 CInputPin::KsGetCurrentCommunication(
362 KSPIN_COMMUNICATION *Communication,
363 KSPIN_INTERFACE *Interface,
364 KSPIN_MEDIUM *Medium)
365 {
366 if (Communication)
367 {
368 *Communication = m_Communication;
369 }
370
371 if (Interface)
372 {
373 if (!m_hPin)
374 return VFW_E_NOT_CONNECTED;
375
376 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
377 }
378
379 if (Medium)
380 {
381 if (!m_hPin)
382 return VFW_E_NOT_CONNECTED;
383
384 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
385 }
386 return NOERROR;
387 }
388
389 HRESULT
390 STDMETHODCALLTYPE
391 CInputPin::KsPropagateAcquire()
392 {
393 OutputDebugStringW(L"CInputPin::KsPropagateAcquire NotImplemented\n");
394 return E_NOTIMPL;
395 }
396
397 HRESULT
398 STDMETHODCALLTYPE
399 CInputPin::KsDeliver(
400 IMediaSample* Sample,
401 ULONG Flags)
402 {
403 return E_FAIL;
404 }
405
406 HRESULT
407 STDMETHODCALLTYPE
408 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
409 {
410 return NOERROR;
411 }
412
413 IMemAllocator *
414 STDMETHODCALLTYPE
415 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
416 {
417 if (Operation == KsPeekOperation_AddRef)
418 {
419 // add reference on allocator
420 m_MemAllocator->AddRef();
421 }
422
423 return m_MemAllocator;
424 }
425
426 HRESULT
427 STDMETHODCALLTYPE
428 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
429 {
430 if (MemAllocator)
431 {
432 MemAllocator->AddRef();
433 }
434
435 if (m_MemAllocator)
436 {
437 m_MemAllocator->Release();
438 }
439
440 m_MemAllocator = MemAllocator;
441 return NOERROR;
442 }
443
444 HRESULT
445 STDMETHODCALLTYPE
446 CInputPin::KsRenegotiateAllocator()
447 {
448 return E_FAIL;
449 }
450
451 LONG
452 STDMETHODCALLTYPE
453 CInputPin::KsIncrementPendingIoCount()
454 {
455 return InterlockedIncrement((volatile LONG*)&m_IoCount);
456 }
457
458 LONG
459 STDMETHODCALLTYPE
460 CInputPin::KsDecrementPendingIoCount()
461 {
462 return InterlockedDecrement((volatile LONG*)&m_IoCount);
463 }
464
465 HRESULT
466 STDMETHODCALLTYPE
467 CInputPin::KsQualityNotify(
468 ULONG Proportion,
469 REFERENCE_TIME TimeDelta)
470 {
471 OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
472 return E_NOTIMPL;
473 }
474
475 //-------------------------------------------------------------------
476 // IKsPinEx
477 //
478
479 VOID
480 STDMETHODCALLTYPE
481 CInputPin::KsNotifyError(
482 IMediaSample* Sample,
483 HRESULT hr)
484 {
485 OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n");
486 }
487
488
489 //-------------------------------------------------------------------
490 // IKsControl
491 //
492 HRESULT
493 STDMETHODCALLTYPE
494 CInputPin::KsProperty(
495 PKSPROPERTY Property,
496 ULONG PropertyLength,
497 LPVOID PropertyData,
498 ULONG DataLength,
499 ULONG* BytesReturned)
500 {
501 assert(m_hPin != 0);
502 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
503 }
504
505 HRESULT
506 STDMETHODCALLTYPE
507 CInputPin::KsMethod(
508 PKSMETHOD Method,
509 ULONG MethodLength,
510 LPVOID MethodData,
511 ULONG DataLength,
512 ULONG* BytesReturned)
513 {
514 assert(m_hPin != 0);
515 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
516 }
517
518 HRESULT
519 STDMETHODCALLTYPE
520 CInputPin::KsEvent(
521 PKSEVENT Event,
522 ULONG EventLength,
523 LPVOID EventData,
524 ULONG DataLength,
525 ULONG* BytesReturned)
526 {
527 assert(m_hPin != 0);
528
529 if (EventLength)
530 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
531 else
532 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
533 }
534
535
536 //-------------------------------------------------------------------
537 // IKsPropertySet
538 //
539 HRESULT
540 STDMETHODCALLTYPE
541 CInputPin::Set(
542 REFGUID guidPropSet,
543 DWORD dwPropID,
544 LPVOID pInstanceData,
545 DWORD cbInstanceData,
546 LPVOID pPropData,
547 DWORD cbPropData)
548 {
549 ULONG BytesReturned;
550
551 if (cbInstanceData)
552 {
553 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
554 if (!Property)
555 return E_OUTOFMEMORY;
556
557 Property->Set = guidPropSet;
558 Property->Id = dwPropID;
559 Property->Flags = KSPROPERTY_TYPE_SET;
560
561 CopyMemory((Property+1), pInstanceData, cbInstanceData);
562
563 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
564 CoTaskMemFree(Property);
565 return hr;
566 }
567 else
568 {
569 KSPROPERTY Property;
570
571 Property.Set = guidPropSet;
572 Property.Id = dwPropID;
573 Property.Flags = KSPROPERTY_TYPE_SET;
574
575 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
576 return hr;
577 }
578 }
579
580 HRESULT
581 STDMETHODCALLTYPE
582 CInputPin::Get(
583 REFGUID guidPropSet,
584 DWORD dwPropID,
585 LPVOID pInstanceData,
586 DWORD cbInstanceData,
587 LPVOID pPropData,
588 DWORD cbPropData,
589 DWORD *pcbReturned)
590 {
591 ULONG BytesReturned;
592
593 if (cbInstanceData)
594 {
595 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
596 if (!Property)
597 return E_OUTOFMEMORY;
598
599 Property->Set = guidPropSet;
600 Property->Id = dwPropID;
601 Property->Flags = KSPROPERTY_TYPE_GET;
602
603 CopyMemory((Property+1), pInstanceData, cbInstanceData);
604
605 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
606 CoTaskMemFree(Property);
607 return hr;
608 }
609 else
610 {
611 KSPROPERTY Property;
612
613 Property.Set = guidPropSet;
614 Property.Id = dwPropID;
615 Property.Flags = KSPROPERTY_TYPE_GET;
616
617 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
618 return hr;
619 }
620 }
621
622 HRESULT
623 STDMETHODCALLTYPE
624 CInputPin::QuerySupported(
625 REFGUID guidPropSet,
626 DWORD dwPropID,
627 DWORD *pTypeSupport)
628 {
629 KSPROPERTY Property;
630 ULONG BytesReturned;
631
632 Property.Set = guidPropSet;
633 Property.Id = dwPropID;
634 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
635
636 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
637 }
638
639
640 //-------------------------------------------------------------------
641 // IKsObject
642 //
643 HANDLE
644 STDMETHODCALLTYPE
645 CInputPin::KsGetObjectHandle()
646 {
647 assert(m_hPin);
648 return m_hPin;
649 }
650
651 //-------------------------------------------------------------------
652 // IPin interface
653 //
654 HRESULT
655 STDMETHODCALLTYPE
656 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
657 {
658 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
659 return NOERROR;
660 }
661
662 HRESULT
663 STDMETHODCALLTYPE
664 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
665 {
666 HRESULT hr;
667
668 if (m_Pin)
669 {
670 // already connected
671 return VFW_E_ALREADY_CONNECTED;
672 }
673
674 // first check format
675 hr = CheckFormat(pmt);
676 if (FAILED(hr))
677 {
678 // format is not supported
679 return hr;
680 }
681
682 hr = CreatePin(pmt);
683 if (FAILED(hr))
684 {
685 return hr;
686 }
687
688 m_Pin = pConnector;
689 m_Pin->AddRef();
690
691 return S_OK;
692 }
693 HRESULT
694 STDMETHODCALLTYPE
695 CInputPin::Disconnect( void)
696 {
697 if (!m_Pin)
698 {
699 // pin was not connected
700 return S_FALSE;
701 }
702
703 //FIXME
704 //check if filter is active
705
706 m_Pin->Release();
707 m_Pin = NULL;
708
709 OutputDebugStringW(L"CInputPin::Disconnect\n");
710 return S_OK;
711 }
712 HRESULT
713 STDMETHODCALLTYPE
714 CInputPin::ConnectedTo(IPin **pPin)
715 {
716 if (!pPin)
717 return E_POINTER;
718
719 if (m_Pin)
720 {
721 // increment reference count
722 m_Pin->AddRef();
723 *pPin = m_Pin;
724 return S_OK;
725 }
726
727 *pPin = NULL;
728 return VFW_E_NOT_CONNECTED;
729 }
730 HRESULT
731 STDMETHODCALLTYPE
732 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
733 {
734 if (!m_Pin)
735 return VFW_E_NOT_CONNECTED;
736
737 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
738 return E_NOTIMPL;
739 }
740 HRESULT
741 STDMETHODCALLTYPE
742 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
743 {
744 wcscpy(pInfo->achName, m_PinName);
745 pInfo->dir = PINDIR_INPUT;
746 pInfo->pFilter = m_ParentFilter;
747 m_ParentFilter->AddRef();
748
749 return S_OK;
750 }
751 HRESULT
752 STDMETHODCALLTYPE
753 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
754 {
755 if (pPinDir)
756 {
757 *pPinDir = PINDIR_INPUT;
758 return S_OK;
759 }
760
761 return E_POINTER;
762 }
763 HRESULT
764 STDMETHODCALLTYPE
765 CInputPin::QueryId(LPWSTR *Id)
766 {
767 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
768 if (!*Id)
769 return E_OUTOFMEMORY;
770
771 wcscpy(*Id, m_PinName);
772 return S_OK;
773 }
774
775 HRESULT
776 STDMETHODCALLTYPE
777 CInputPin::QueryAccept(
778 const AM_MEDIA_TYPE *pmt)
779 {
780 return CheckFormat(pmt);
781 }
782 HRESULT
783 STDMETHODCALLTYPE
784 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
785 {
786 HRESULT hr;
787 ULONG MediaTypeCount = 0, Index;
788 AM_MEDIA_TYPE * MediaTypes;
789
790 // query media type count
791 hr = KsGetMediaTypeCount(m_hFilter, m_PinId, &MediaTypeCount);
792 if (FAILED(hr) || !MediaTypeCount)
793 return hr;
794
795 // allocate media types
796 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
797 if (!MediaTypes)
798 {
799 // not enough memory
800 return E_OUTOFMEMORY;
801 }
802
803 // zero media types
804 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
805
806 for(Index = 0; Index < MediaTypeCount; Index++)
807 {
808 // get media type
809 hr = KsGetMediaType(Index, &MediaTypes[Index], m_hFilter, m_PinId);
810 if (FAILED(hr))
811 {
812 // failed
813 CoTaskMemFree(MediaTypes);
814 return hr;
815 }
816 }
817
818 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
819 }
820
821 HRESULT
822 STDMETHODCALLTYPE
823 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
824 {
825 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
826 return E_NOTIMPL;
827 }
828 HRESULT
829 STDMETHODCALLTYPE
830 CInputPin::EndOfStream( void)
831 {
832 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
833 return E_NOTIMPL;
834 }
835 HRESULT
836 STDMETHODCALLTYPE
837 CInputPin::BeginFlush( void)
838 {
839 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
840 return E_NOTIMPL;
841 }
842 HRESULT
843 STDMETHODCALLTYPE
844 CInputPin::EndFlush( void)
845 {
846 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
847 return E_NOTIMPL;
848 }
849 HRESULT
850 STDMETHODCALLTYPE
851 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
852 {
853 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
854 return E_NOTIMPL;
855 }
856
857 //-------------------------------------------------------------------
858 HRESULT
859 STDMETHODCALLTYPE
860 CInputPin::CheckFormat(
861 const AM_MEDIA_TYPE *pmt)
862 {
863 KSP_PIN Property;
864 PKSMULTIPLE_ITEM MultipleItem;
865 PKSDATAFORMAT DataFormat;
866 ULONG BytesReturned;
867 HRESULT hr;
868
869 // prepare request
870 Property.Property.Set = KSPROPSETID_Pin;
871 Property.Property.Id = KSPROPERTY_PIN_DATARANGES;
872 Property.Property.Flags = KSPROPERTY_TYPE_GET;
873 Property.PinId = m_PinId;
874 Property.Reserved = 0;
875
876 if (!pmt)
877 return E_POINTER;
878
879 // query for size of dataranges
880 hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
881
882 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
883 {
884 // allocate dataranges buffer
885 MultipleItem = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
886
887 if (!MultipleItem)
888 return E_OUTOFMEMORY;
889
890 // query dataranges
891 hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
892
893 if (FAILED(hr))
894 {
895 // failed to query data ranges
896 CoTaskMemFree(MultipleItem);
897 return hr;
898 }
899
900 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
901 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
902 {
903 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
904 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
905 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
906 {
907 // format is supported
908 CoTaskMemFree(MultipleItem);
909 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
910 return S_OK;
911 }
912 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
913 }
914 //format is not supported
915 CoTaskMemFree(MultipleItem);
916 }
917 return S_FALSE;
918 }
919
920 HRESULT
921 STDMETHODCALLTYPE
922 CInputPin::CreatePin(
923 const AM_MEDIA_TYPE *pmt)
924 {
925 PKSMULTIPLE_ITEM MediumList;
926 PKSMULTIPLE_ITEM InterfaceList;
927 PKSPIN_MEDIUM Medium;
928 PKSPIN_INTERFACE Interface;
929 IKsInterfaceHandler * InterfaceHandler;
930 HRESULT hr;
931
932 // query for pin medium
933 hr = KsQueryMediums(&MediumList);
934 if (FAILED(hr))
935 return hr;
936
937 // query for pin interface
938 hr = KsQueryInterfaces(&InterfaceList);
939 if (FAILED(hr))
940 {
941 // failed
942 CoTaskMemFree(MediumList);
943 return hr;
944 }
945
946 if (MediumList->Count)
947 {
948 //use first available medium
949 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
950 }
951 else
952 {
953 // default to standard medium
954 Medium = &StandardPinMedium;
955 }
956
957 if (InterfaceList->Count)
958 {
959 //use first available interface
960 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
961 }
962 else
963 {
964 // default to standard interface
965 Interface = &StandardPinInterface;
966 }
967
968 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
969 {
970 // now load the IKsInterfaceHandler plugin
971 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
972 if (FAILED(hr))
973 {
974 // failed to load interface handler plugin
975 OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
976 CoTaskMemFree(MediumList);
977 CoTaskMemFree(InterfaceList);
978
979 return hr;
980 }
981
982 // now set the pin
983 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
984 if (FAILED(hr))
985 {
986 // failed to load interface handler plugin
987 OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
988 InterfaceHandler->Release();
989 CoTaskMemFree(MediumList);
990 CoTaskMemFree(InterfaceList);
991 return hr;
992 }
993
994 // store interface handler
995 m_InterfaceHandler = InterfaceHandler;
996
997 // now create pin
998 hr = CreatePinHandle(Medium, Interface, pmt);
999 if (FAILED(hr))
1000 {
1001 m_InterfaceHandler->Release();
1002 m_InterfaceHandler = InterfaceHandler;
1003 }
1004 }
1005
1006 // free medium / interface / dataformat
1007 CoTaskMemFree(MediumList);
1008 CoTaskMemFree(InterfaceList);
1009
1010 return hr;
1011 }
1012
1013 HRESULT
1014 STDMETHODCALLTYPE
1015 CInputPin::CreatePinHandle(
1016 PKSPIN_MEDIUM Medium,
1017 PKSPIN_INTERFACE Interface,
1018 const AM_MEDIA_TYPE *pmt)
1019 {
1020 PKSPIN_CONNECT PinConnect;
1021 PKSDATAFORMAT DataFormat;
1022 ULONG Length;
1023 HRESULT hr;
1024
1025 // calc format size
1026 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
1027
1028 // allocate pin connect
1029 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
1030 if (!PinConnect)
1031 {
1032 // failed
1033 return E_OUTOFMEMORY;
1034 }
1035
1036 // setup request
1037 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1038 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1039 PinConnect->PinId = m_PinId;
1040 PinConnect->PinToHandle = NULL;
1041 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1042 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1043
1044 // get dataformat offset
1045 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1046
1047 // copy data format
1048 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1049 DataFormat->Flags = 0;
1050 DataFormat->SampleSize = pmt->lSampleSize;
1051 DataFormat->Reserved = 0;
1052 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1053 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
1054 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1055
1056 if (pmt->cbFormat)
1057 {
1058 // copy extended format
1059 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1060 }
1061
1062 // create pin
1063 hr = KsCreatePin(m_hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1064
1065 // free pin connect
1066 CoTaskMemFree(PinConnect);
1067
1068 return hr;
1069 }
1070
1071 HRESULT
1072 WINAPI
1073 CInputPin_Constructor(
1074 IBaseFilter * ParentFilter,
1075 LPCWSTR PinName,
1076 HANDLE hFilter,
1077 ULONG PinId,
1078 KSPIN_COMMUNICATION Communication,
1079 REFIID riid,
1080 LPVOID * ppv)
1081 {
1082 CInputPin * handler = new CInputPin(ParentFilter, PinName, hFilter, PinId, Communication);
1083
1084 if (!handler)
1085 return E_OUTOFMEMORY;
1086
1087 if (FAILED(handler->QueryInterface(riid, ppv)))
1088 {
1089 /* not supported */
1090 delete handler;
1091 return E_NOINTERFACE;
1092 }
1093
1094 return S_OK;
1095 }