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