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