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