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