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