[RICHED20_WINETEST]
[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 return E_NOTIMPL;
661 }
662
663 HRESULT
664 STDMETHODCALLTYPE
665 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
666 {
667 OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
668 return E_NOTIMPL;
669 }
670
671 HRESULT
672 STDMETHODCALLTYPE
673 CInputPin::ReceiveCanBlock( void)
674 {
675 OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
676 return S_FALSE;
677 }
678
679 //-------------------------------------------------------------------
680 // IKsPin
681 //
682
683 HRESULT
684 STDMETHODCALLTYPE
685 CInputPin::KsQueryMediums(
686 PKSMULTIPLE_ITEM* MediumList)
687 {
688 return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
689 }
690
691 HRESULT
692 STDMETHODCALLTYPE
693 CInputPin::KsQueryInterfaces(
694 PKSMULTIPLE_ITEM* InterfaceList)
695 {
696 return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
697 }
698
699 HRESULT
700 STDMETHODCALLTYPE
701 CInputPin::KsCreateSinkPinHandle(
702 KSPIN_INTERFACE& Interface,
703 KSPIN_MEDIUM& Medium)
704 {
705 return CreatePin(&m_MediaFormat);
706 }
707
708 HRESULT
709 STDMETHODCALLTYPE
710 CInputPin::KsGetCurrentCommunication(
711 KSPIN_COMMUNICATION *Communication,
712 KSPIN_INTERFACE *Interface,
713 KSPIN_MEDIUM *Medium)
714 {
715 if (Communication)
716 {
717 *Communication = m_Communication;
718 }
719
720 if (Interface)
721 {
722 if (!m_hPin)
723 return VFW_E_NOT_CONNECTED;
724
725 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
726 }
727
728 if (Medium)
729 {
730 if (!m_hPin)
731 return VFW_E_NOT_CONNECTED;
732
733 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
734 }
735 return NOERROR;
736 }
737
738 HRESULT
739 STDMETHODCALLTYPE
740 CInputPin::KsPropagateAcquire()
741 {
742 KSPROPERTY Property;
743 KSSTATE State;
744 ULONG BytesReturned;
745 HRESULT hr;
746
747 OutputDebugStringW(L"CInputPin::KsPropagateAcquire\n");
748
749 assert(m_hPin != INVALID_HANDLE_VALUE);
750
751 Property.Set = KSPROPSETID_Connection;
752 Property.Id = KSPROPERTY_CONNECTION_STATE;
753 Property.Flags = KSPROPERTY_TYPE_SET;
754
755 State = KSSTATE_ACQUIRE;
756
757 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
758
759 //TODO
760 //propagate to connected pin on the pipe
761
762 return hr;
763 }
764
765 HRESULT
766 STDMETHODCALLTYPE
767 CInputPin::KsDeliver(
768 IMediaSample* Sample,
769 ULONG Flags)
770 {
771 return E_FAIL;
772 }
773
774 HRESULT
775 STDMETHODCALLTYPE
776 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
777 {
778 return NOERROR;
779 }
780
781 IMemAllocator *
782 STDMETHODCALLTYPE
783 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
784 {
785 if (Operation == KsPeekOperation_AddRef)
786 {
787 // add reference on allocator
788 m_MemAllocator->AddRef();
789 }
790
791 return m_MemAllocator;
792 }
793
794 HRESULT
795 STDMETHODCALLTYPE
796 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
797 {
798
799 if (MemAllocator)
800 {
801 MemAllocator->AddRef();
802 }
803
804 if (m_MemAllocator)
805 {
806 m_MemAllocator->Release();
807 }
808
809 m_MemAllocator = MemAllocator;
810 return NOERROR;
811 }
812
813 HRESULT
814 STDMETHODCALLTYPE
815 CInputPin::KsRenegotiateAllocator()
816 {
817 return E_FAIL;
818 }
819
820 LONG
821 STDMETHODCALLTYPE
822 CInputPin::KsIncrementPendingIoCount()
823 {
824 return InterlockedIncrement((volatile LONG*)&m_IoCount);
825 }
826
827 LONG
828 STDMETHODCALLTYPE
829 CInputPin::KsDecrementPendingIoCount()
830 {
831 return InterlockedDecrement((volatile LONG*)&m_IoCount);
832 }
833
834 HRESULT
835 STDMETHODCALLTYPE
836 CInputPin::KsQualityNotify(
837 ULONG Proportion,
838 REFERENCE_TIME TimeDelta)
839 {
840 OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
841 return E_NOTIMPL;
842 }
843
844 //-------------------------------------------------------------------
845 // IKsPinEx
846 //
847
848 VOID
849 STDMETHODCALLTYPE
850 CInputPin::KsNotifyError(
851 IMediaSample* Sample,
852 HRESULT hr)
853 {
854 OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n");
855 }
856
857
858 //-------------------------------------------------------------------
859 // IKsControl
860 //
861 HRESULT
862 STDMETHODCALLTYPE
863 CInputPin::KsProperty(
864 PKSPROPERTY Property,
865 ULONG PropertyLength,
866 LPVOID PropertyData,
867 ULONG DataLength,
868 ULONG* BytesReturned)
869 {
870 assert(m_hPin != INVALID_HANDLE_VALUE);
871 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
872 }
873
874 HRESULT
875 STDMETHODCALLTYPE
876 CInputPin::KsMethod(
877 PKSMETHOD Method,
878 ULONG MethodLength,
879 LPVOID MethodData,
880 ULONG DataLength,
881 ULONG* BytesReturned)
882 {
883 assert(m_hPin != INVALID_HANDLE_VALUE);
884 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
885 }
886
887 HRESULT
888 STDMETHODCALLTYPE
889 CInputPin::KsEvent(
890 PKSEVENT Event,
891 ULONG EventLength,
892 LPVOID EventData,
893 ULONG DataLength,
894 ULONG* BytesReturned)
895 {
896 assert(m_hPin != INVALID_HANDLE_VALUE);
897
898 if (EventLength)
899 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
900 else
901 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
902 }
903
904
905 //-------------------------------------------------------------------
906 // IKsPropertySet
907 //
908 HRESULT
909 STDMETHODCALLTYPE
910 CInputPin::Set(
911 REFGUID guidPropSet,
912 DWORD dwPropID,
913 LPVOID pInstanceData,
914 DWORD cbInstanceData,
915 LPVOID pPropData,
916 DWORD cbPropData)
917 {
918 ULONG BytesReturned;
919
920 if (cbInstanceData)
921 {
922 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
923 if (!Property)
924 return E_OUTOFMEMORY;
925
926 Property->Set = guidPropSet;
927 Property->Id = dwPropID;
928 Property->Flags = KSPROPERTY_TYPE_SET;
929
930 CopyMemory((Property+1), pInstanceData, cbInstanceData);
931
932 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
933 CoTaskMemFree(Property);
934 return hr;
935 }
936 else
937 {
938 KSPROPERTY Property;
939
940 Property.Set = guidPropSet;
941 Property.Id = dwPropID;
942 Property.Flags = KSPROPERTY_TYPE_SET;
943
944 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
945 return hr;
946 }
947 }
948
949 HRESULT
950 STDMETHODCALLTYPE
951 CInputPin::Get(
952 REFGUID guidPropSet,
953 DWORD dwPropID,
954 LPVOID pInstanceData,
955 DWORD cbInstanceData,
956 LPVOID pPropData,
957 DWORD cbPropData,
958 DWORD *pcbReturned)
959 {
960 ULONG BytesReturned;
961
962 if (cbInstanceData)
963 {
964 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
965 if (!Property)
966 return E_OUTOFMEMORY;
967
968 Property->Set = guidPropSet;
969 Property->Id = dwPropID;
970 Property->Flags = KSPROPERTY_TYPE_GET;
971
972 CopyMemory((Property+1), pInstanceData, cbInstanceData);
973
974 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
975 CoTaskMemFree(Property);
976 return hr;
977 }
978 else
979 {
980 KSPROPERTY Property;
981
982 Property.Set = guidPropSet;
983 Property.Id = dwPropID;
984 Property.Flags = KSPROPERTY_TYPE_GET;
985
986 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
987 return hr;
988 }
989 }
990
991 HRESULT
992 STDMETHODCALLTYPE
993 CInputPin::QuerySupported(
994 REFGUID guidPropSet,
995 DWORD dwPropID,
996 DWORD *pTypeSupport)
997 {
998 KSPROPERTY Property;
999 ULONG BytesReturned;
1000
1001 Property.Set = guidPropSet;
1002 Property.Id = dwPropID;
1003 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1004
1005 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1006 }
1007
1008
1009 //-------------------------------------------------------------------
1010 // IKsObject
1011 //
1012 HANDLE
1013 STDMETHODCALLTYPE
1014 CInputPin::KsGetObjectHandle()
1015 {
1016 assert(m_hPin);
1017 return m_hPin;
1018 }
1019
1020 //-------------------------------------------------------------------
1021 // IPin interface
1022 //
1023 HRESULT
1024 STDMETHODCALLTYPE
1025 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1026 {
1027 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
1028 return NOERROR;
1029 }
1030
1031 HRESULT
1032 STDMETHODCALLTYPE
1033 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1034 {
1035 HRESULT hr;
1036
1037 if (m_Pin)
1038 {
1039 // already connected
1040 return VFW_E_ALREADY_CONNECTED;
1041 }
1042
1043 // first check format
1044 hr = CheckFormat(pmt);
1045 if (FAILED(hr))
1046 {
1047 // format is not supported
1048 return hr;
1049 }
1050
1051 hr = CreatePin(pmt);
1052 if (FAILED(hr))
1053 {
1054 return hr;
1055 }
1056
1057 m_Pin = pConnector;
1058 m_Pin->AddRef();
1059
1060 return S_OK;
1061 }
1062 HRESULT
1063 STDMETHODCALLTYPE
1064 CInputPin::Disconnect( void)
1065 {
1066 if (!m_Pin)
1067 {
1068 // pin was not connected
1069 return S_FALSE;
1070 }
1071
1072 //FIXME
1073 //check if filter is active
1074
1075 m_Pin->Release();
1076 m_Pin = NULL;
1077
1078 OutputDebugStringW(L"CInputPin::Disconnect\n");
1079 return S_OK;
1080 }
1081 HRESULT
1082 STDMETHODCALLTYPE
1083 CInputPin::ConnectedTo(IPin **pPin)
1084 {
1085 if (!pPin)
1086 return E_POINTER;
1087
1088 if (m_Pin)
1089 {
1090 // increment reference count
1091 m_Pin->AddRef();
1092 *pPin = m_Pin;
1093 return S_OK;
1094 }
1095
1096 *pPin = NULL;
1097 return VFW_E_NOT_CONNECTED;
1098 }
1099 HRESULT
1100 STDMETHODCALLTYPE
1101 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1102 {
1103 if (!m_Pin)
1104 return VFW_E_NOT_CONNECTED;
1105
1106 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
1107 return E_NOTIMPL;
1108 }
1109 HRESULT
1110 STDMETHODCALLTYPE
1111 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
1112 {
1113 wcscpy(pInfo->achName, m_PinName);
1114 pInfo->dir = PINDIR_INPUT;
1115 pInfo->pFilter = m_ParentFilter;
1116 m_ParentFilter->AddRef();
1117
1118 return S_OK;
1119 }
1120 HRESULT
1121 STDMETHODCALLTYPE
1122 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1123 {
1124 if (pPinDir)
1125 {
1126 *pPinDir = PINDIR_INPUT;
1127 return S_OK;
1128 }
1129
1130 return E_POINTER;
1131 }
1132 HRESULT
1133 STDMETHODCALLTYPE
1134 CInputPin::QueryId(LPWSTR *Id)
1135 {
1136 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1137 if (!*Id)
1138 return E_OUTOFMEMORY;
1139
1140 wcscpy(*Id, m_PinName);
1141 return S_OK;
1142 }
1143
1144 HRESULT
1145 STDMETHODCALLTYPE
1146 CInputPin::QueryAccept(
1147 const AM_MEDIA_TYPE *pmt)
1148 {
1149 return CheckFormat(pmt);
1150 }
1151 HRESULT
1152 STDMETHODCALLTYPE
1153 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1154 {
1155 HRESULT hr;
1156 ULONG MediaTypeCount = 0, Index;
1157 AM_MEDIA_TYPE * MediaTypes;
1158
1159 // query media type count
1160 hr = KsGetMediaTypeCount(m_hFilter, m_PinId, &MediaTypeCount);
1161 if (FAILED(hr) || !MediaTypeCount)
1162 return hr;
1163
1164 // allocate media types
1165 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1166 if (!MediaTypes)
1167 {
1168 // not enough memory
1169 return E_OUTOFMEMORY;
1170 }
1171
1172 // zero media types
1173 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1174
1175 for(Index = 0; Index < MediaTypeCount; Index++)
1176 {
1177 // get media type
1178 hr = KsGetMediaType(Index, &MediaTypes[Index], m_hFilter, m_PinId);
1179 if (FAILED(hr))
1180 {
1181 // failed
1182 CoTaskMemFree(MediaTypes);
1183 return hr;
1184 }
1185 }
1186
1187 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1188 }
1189
1190 HRESULT
1191 STDMETHODCALLTYPE
1192 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1193 {
1194 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
1195 return E_NOTIMPL;
1196 }
1197 HRESULT
1198 STDMETHODCALLTYPE
1199 CInputPin::EndOfStream( void)
1200 {
1201 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
1202 return E_NOTIMPL;
1203 }
1204 HRESULT
1205 STDMETHODCALLTYPE
1206 CInputPin::BeginFlush( void)
1207 {
1208 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
1209 return E_NOTIMPL;
1210 }
1211 HRESULT
1212 STDMETHODCALLTYPE
1213 CInputPin::EndFlush( void)
1214 {
1215 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
1216 return E_NOTIMPL;
1217 }
1218 HRESULT
1219 STDMETHODCALLTYPE
1220 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1221 {
1222 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
1223 return E_NOTIMPL;
1224 }
1225
1226
1227 //-------------------------------------------------------------------
1228 HRESULT
1229 STDMETHODCALLTYPE
1230 CInputPin::CheckFormat(
1231 const AM_MEDIA_TYPE *pmt)
1232 {
1233 PKSMULTIPLE_ITEM MultipleItem;
1234 PKSDATAFORMAT DataFormat;
1235 HRESULT hr;
1236
1237 if (!pmt)
1238 return E_POINTER;
1239
1240 hr = KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1241 if (FAILED(hr))
1242 return S_FALSE;
1243
1244 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1245 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1246 {
1247 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1248 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1249 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1250 {
1251 // format is supported
1252 CoTaskMemFree(MultipleItem);
1253 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
1254 return S_OK;
1255 }
1256 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1257 }
1258 //format is not supported
1259 CoTaskMemFree(MultipleItem);
1260 return S_FALSE;
1261 }
1262
1263 HRESULT
1264 STDMETHODCALLTYPE
1265 CInputPin::CreatePin(
1266 const AM_MEDIA_TYPE *pmt)
1267 {
1268 PKSMULTIPLE_ITEM MediumList;
1269 PKSMULTIPLE_ITEM InterfaceList;
1270 PKSPIN_MEDIUM Medium;
1271 PKSPIN_INTERFACE Interface;
1272 IKsInterfaceHandler * InterfaceHandler;
1273 HRESULT hr;
1274
1275 // query for pin medium
1276 hr = KsQueryMediums(&MediumList);
1277 if (FAILED(hr))
1278 return hr;
1279
1280 // query for pin interface
1281 hr = KsQueryInterfaces(&InterfaceList);
1282 if (FAILED(hr))
1283 {
1284 // failed
1285 CoTaskMemFree(MediumList);
1286 return hr;
1287 }
1288
1289 if (MediumList->Count)
1290 {
1291 //use first available medium
1292 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1293 }
1294 else
1295 {
1296 // default to standard medium
1297 Medium = &StandardPinMedium;
1298 }
1299
1300 if (InterfaceList->Count)
1301 {
1302 //use first available interface
1303 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1304 }
1305 else
1306 {
1307 // default to standard interface
1308 Interface = &StandardPinInterface;
1309 }
1310
1311 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1312 {
1313 if (!m_InterfaceHandler)
1314 {
1315 // now load the IKsInterfaceHandler plugin
1316 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1317 if (FAILED(hr))
1318 {
1319 // failed to load interface handler plugin
1320 OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
1321 CoTaskMemFree(MediumList);
1322 CoTaskMemFree(InterfaceList);
1323
1324 return hr;
1325 }
1326
1327 // now set the pin
1328 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
1329 if (FAILED(hr))
1330 {
1331 // failed to load interface handler plugin
1332 OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
1333 InterfaceHandler->Release();
1334 CoTaskMemFree(MediumList);
1335 CoTaskMemFree(InterfaceList);
1336 return hr;
1337 }
1338
1339 // store interface handler
1340 m_InterfaceHandler = InterfaceHandler;
1341 }
1342
1343 // now create pin
1344 hr = CreatePinHandle(Medium, Interface, pmt);
1345 if (FAILED(hr))
1346 {
1347 m_InterfaceHandler->Release();
1348 m_InterfaceHandler = InterfaceHandler;
1349 }
1350 }
1351 else
1352 {
1353 WCHAR Buffer[100];
1354 swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
1355 OutputDebugStringW(Buffer);
1356 DebugBreak();
1357 hr = E_FAIL;
1358 }
1359
1360 // free medium / interface / dataformat
1361 CoTaskMemFree(MediumList);
1362 CoTaskMemFree(InterfaceList);
1363
1364 return hr;
1365 }
1366
1367 HRESULT
1368 STDMETHODCALLTYPE
1369 CInputPin::CreatePinHandle(
1370 PKSPIN_MEDIUM Medium,
1371 PKSPIN_INTERFACE Interface,
1372 const AM_MEDIA_TYPE *pmt)
1373 {
1374 PKSPIN_CONNECT PinConnect;
1375 PKSDATAFORMAT DataFormat;
1376 ULONG Length;
1377 HRESULT hr;
1378
1379 if (m_hPin != INVALID_HANDLE_VALUE)
1380 {
1381 // pin already exists
1382 //CloseHandle(m_hPin);
1383 //m_hPin = INVALID_HANDLE_VALUE;
1384 return S_OK;
1385 }
1386
1387
1388 // calc format size
1389 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
1390
1391 // allocate pin connect
1392 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
1393 if (!PinConnect)
1394 {
1395 // failed
1396 return E_OUTOFMEMORY;
1397 }
1398
1399 // setup request
1400 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1401 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1402 PinConnect->PinId = m_PinId;
1403 PinConnect->PinToHandle = NULL;
1404 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1405 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1406
1407 // get dataformat offset
1408 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1409
1410 // copy data format
1411 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1412 DataFormat->Flags = 0;
1413 DataFormat->SampleSize = pmt->lSampleSize;
1414 DataFormat->Reserved = 0;
1415 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1416 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
1417 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1418
1419 if (pmt->cbFormat)
1420 {
1421 // copy extended format
1422 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1423 }
1424
1425 // create pin
1426 hr = KsCreatePin(m_hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1427
1428 if (SUCCEEDED(hr))
1429 {
1430 // store current interface / medium
1431 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
1432 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
1433 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
1434
1435 LPOLESTR pMajor, pSub, pFormat;
1436 StringFromIID(m_MediaFormat.majortype, &pMajor);
1437 StringFromIID(m_MediaFormat.subtype , &pSub);
1438 StringFromIID(m_MediaFormat.formattype, &pFormat);
1439 WCHAR Buffer[200];
1440 swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
1441 CoTaskMemFree(pMajor);
1442 CoTaskMemFree(pSub);
1443 CoTaskMemFree(pFormat);
1444 OutputDebugStringW(Buffer);
1445
1446 if (pmt->cbFormat)
1447 {
1448 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
1449 if (!m_MediaFormat.pbFormat)
1450 {
1451 CoTaskMemFree(PinConnect);
1452 m_MediaFormat.pbFormat = NULL;
1453 m_MediaFormat.cbFormat = 0;
1454 return E_OUTOFMEMORY;
1455 }
1456 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
1457 }
1458
1459 //TODO
1460 // connect pin pipes
1461
1462 }
1463
1464 // free pin connect
1465 CoTaskMemFree(PinConnect);
1466
1467 return hr;
1468 }
1469
1470 HRESULT
1471 WINAPI
1472 CInputPin_Constructor(
1473 IBaseFilter * ParentFilter,
1474 LPCWSTR PinName,
1475 HANDLE hFilter,
1476 ULONG PinId,
1477 KSPIN_COMMUNICATION Communication,
1478 REFIID riid,
1479 LPVOID * ppv)
1480 {
1481 CInputPin * handler = new CInputPin(ParentFilter, PinName, hFilter, PinId, Communication);
1482
1483 if (!handler)
1484 return E_OUTOFMEMORY;
1485
1486 if (FAILED(handler->QueryInterface(riid, ppv)))
1487 {
1488 /* not supported */
1489 delete handler;
1490 return E_NOINTERFACE;
1491 }
1492
1493 return S_OK;
1494 }