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