[KSPROXY]
[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 HRESULT hr;
1223
1224 OutputDebugStringW(L"COutputPin::Connect called\n");
1225 if (pmt)
1226 {
1227 hr = pReceivePin->QueryAccept(pmt);
1228 if (FAILED(hr))
1229 return hr;
1230 }
1231 else
1232 {
1233 // query accept
1234 hr = pReceivePin->QueryAccept(&m_MediaFormat);
1235 if (FAILED(hr))
1236 return hr;
1237
1238 pmt = &m_MediaFormat;
1239 }
1240
1241 //FIXME create pin handle
1242
1243 // receive connection;
1244 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
1245 if (SUCCEEDED(hr))
1246 {
1247 // increment reference count
1248 pReceivePin->AddRef();
1249 m_Pin = pReceivePin;
1250 OutputDebugStringW(L"COutputPin::Connect success\n");
1251 }
1252
1253 return hr;
1254 }
1255
1256 HRESULT
1257 STDMETHODCALLTYPE
1258 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1259 {
1260 OutputDebugStringW(L"COutputPin::ReceiveConnection\n");
1261 return E_UNEXPECTED;
1262 }
1263 HRESULT
1264 STDMETHODCALLTYPE
1265 COutputPin::Disconnect( void)
1266 {
1267 OutputDebugStringW(L"COutputPin::Disconnect\n");
1268
1269 if (!m_Pin)
1270 {
1271 // pin was not connected
1272 return S_FALSE;
1273 }
1274
1275 //FIXME
1276 //check if filter is active
1277
1278 m_Pin->Release();
1279 m_Pin = NULL;
1280
1281 OutputDebugStringW(L"COutputPin::Disconnect\n");
1282 return S_OK;
1283 }
1284 HRESULT
1285 STDMETHODCALLTYPE
1286 COutputPin::ConnectedTo(IPin **pPin)
1287 {
1288 OutputDebugStringW(L"COutputPin::ConnectedTo\n");
1289
1290 if (!pPin)
1291 return E_POINTER;
1292
1293 if (m_Pin)
1294 {
1295 // increment reference count
1296 m_Pin->AddRef();
1297 *pPin = m_Pin;
1298 return S_OK;
1299 }
1300
1301 *pPin = NULL;
1302 return VFW_E_NOT_CONNECTED;
1303 }
1304 HRESULT
1305 STDMETHODCALLTYPE
1306 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1307 {
1308 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");
1309 return E_NOTIMPL;
1310 }
1311 HRESULT
1312 STDMETHODCALLTYPE
1313 COutputPin::QueryPinInfo(PIN_INFO *pInfo)
1314 {
1315 OutputDebugStringW(L"COutputPin::QueryPinInfo\n");
1316
1317 wcscpy(pInfo->achName, m_PinName);
1318 pInfo->dir = PINDIR_OUTPUT;
1319 pInfo->pFilter = m_ParentFilter;
1320 m_ParentFilter->AddRef();
1321
1322 return S_OK;
1323 }
1324 HRESULT
1325 STDMETHODCALLTYPE
1326 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1327 {
1328 OutputDebugStringW(L"COutputPin::QueryDirection\n");
1329
1330 if (pPinDir)
1331 {
1332 *pPinDir = PINDIR_OUTPUT;
1333 return S_OK;
1334 }
1335
1336 return E_POINTER;
1337 }
1338 HRESULT
1339 STDMETHODCALLTYPE
1340 COutputPin::QueryId(LPWSTR *Id)
1341 {
1342 OutputDebugStringW(L"COutputPin::QueryId\n");
1343
1344 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1345 if (!*Id)
1346 return E_OUTOFMEMORY;
1347
1348 wcscpy(*Id, m_PinName);
1349 return S_OK;
1350 }
1351 HRESULT
1352 STDMETHODCALLTYPE
1353 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
1354 {
1355 OutputDebugStringW(L"COutputPin::QueryAccept called\n");
1356 return E_NOTIMPL;
1357 }
1358 HRESULT
1359 STDMETHODCALLTYPE
1360 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1361 {
1362 HRESULT hr;
1363 ULONG MediaTypeCount = 0, Index;
1364 AM_MEDIA_TYPE * MediaTypes;
1365 HANDLE hFilter;
1366
1367 OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n");
1368
1369 if (!m_KsObjectParent)
1370 {
1371 // no interface
1372 return E_NOINTERFACE;
1373 }
1374
1375 // get parent filter handle
1376 hFilter = m_KsObjectParent->KsGetObjectHandle();
1377
1378 // query media type count
1379 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1380 if (FAILED(hr) || !MediaTypeCount)
1381 {
1382 OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
1383 return hr;
1384 }
1385
1386 // allocate media types
1387 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1388 if (!MediaTypes)
1389 {
1390 // not enough memory
1391 OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n");
1392 return E_OUTOFMEMORY;
1393 }
1394
1395 // zero media types
1396 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1397
1398 for(Index = 0; Index < MediaTypeCount; Index++)
1399 {
1400 // get media type
1401 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1402 if (FAILED(hr))
1403 {
1404 // failed
1405 CoTaskMemFree(MediaTypes);
1406 OutputDebugStringW(L"COutputPin::EnumMediaTypes failed\n");
1407 return hr;
1408 }
1409 }
1410
1411 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1412 }
1413 HRESULT
1414 STDMETHODCALLTYPE
1415 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1416 {
1417 OutputDebugStringW(L"COutputPin::QueryInternalConnections called\n");
1418 return E_NOTIMPL;
1419 }
1420 HRESULT
1421 STDMETHODCALLTYPE
1422 COutputPin::EndOfStream( void)
1423 {
1424 OutputDebugStringW(L"COutputPin::EndOfStream called\n");
1425 return E_NOTIMPL;
1426 }
1427 HRESULT
1428 STDMETHODCALLTYPE
1429 COutputPin::BeginFlush( void)
1430 {
1431 OutputDebugStringW(L"COutputPin::BeginFlush called\n");
1432 return E_NOTIMPL;
1433 }
1434 HRESULT
1435 STDMETHODCALLTYPE
1436 COutputPin::EndFlush( void)
1437 {
1438 OutputDebugStringW(L"COutputPin::EndFlush called\n");
1439 return E_NOTIMPL;
1440 }
1441 HRESULT
1442 STDMETHODCALLTYPE
1443 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1444 {
1445 OutputDebugStringW(L"COutputPin::NewSegment called\n");
1446 return E_NOTIMPL;
1447 }
1448
1449 //-------------------------------------------------------------------
1450 HRESULT
1451 STDMETHODCALLTYPE
1452 COutputPin::CheckFormat(
1453 const AM_MEDIA_TYPE *pmt)
1454 {
1455 PKSMULTIPLE_ITEM MultipleItem;
1456 PKSDATAFORMAT DataFormat;
1457 HRESULT hr;
1458
1459 if (!pmt)
1460 return E_POINTER;
1461
1462 HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
1463 assert(hFilter != NULL);
1464
1465 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1466 if (FAILED(hr))
1467 return S_FALSE;
1468
1469 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1470 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1471 {
1472 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1473 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1474 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1475 {
1476 // format is supported
1477 CoTaskMemFree(MultipleItem);
1478 OutputDebugStringW(L"COutputPin::CheckFormat format OK\n");
1479 return S_OK;
1480 }
1481 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1482 }
1483 //format is not supported
1484 CoTaskMemFree(MultipleItem);
1485 return S_FALSE;
1486 }
1487
1488 HRESULT
1489 STDMETHODCALLTYPE
1490 COutputPin::CreatePin(
1491 const AM_MEDIA_TYPE *pmt)
1492 {
1493 PKSMULTIPLE_ITEM MediumList;
1494 PKSMULTIPLE_ITEM InterfaceList;
1495 PKSPIN_MEDIUM Medium;
1496 PKSPIN_INTERFACE Interface;
1497 IKsInterfaceHandler * InterfaceHandler;
1498 HRESULT hr;
1499
1500 // query for pin medium
1501 hr = KsQueryMediums(&MediumList);
1502 if (FAILED(hr))
1503 return hr;
1504
1505 // query for pin interface
1506 hr = KsQueryInterfaces(&InterfaceList);
1507 if (FAILED(hr))
1508 {
1509 // failed
1510 CoTaskMemFree(MediumList);
1511 return hr;
1512 }
1513
1514 if (MediumList->Count)
1515 {
1516 //use first available medium
1517 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1518 }
1519 else
1520 {
1521 // default to standard medium
1522 Medium = &StandardPinMedium;
1523 }
1524
1525 if (InterfaceList->Count)
1526 {
1527 //use first available interface
1528 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1529 }
1530 else
1531 {
1532 // default to standard interface
1533 Interface = &StandardPinInterface;
1534 }
1535
1536 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1537 {
1538 // now create pin
1539 hr = CreatePinHandle(Medium, Interface, pmt);
1540 if (FAILED(hr))
1541 {
1542 m_InterfaceHandler->Release();
1543 m_InterfaceHandler = InterfaceHandler;
1544 }
1545
1546 if (!m_InterfaceHandler)
1547 {
1548 // now load the IKsInterfaceHandler plugin
1549 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1550 if (FAILED(hr))
1551 {
1552 // failed to load interface handler plugin
1553 OutputDebugStringW(L"COutputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
1554 CoTaskMemFree(MediumList);
1555 CoTaskMemFree(InterfaceList);
1556
1557 return hr;
1558 }
1559
1560 // now set the pin
1561 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
1562 if (FAILED(hr))
1563 {
1564 // failed to load interface handler plugin
1565 OutputDebugStringW(L"COutputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
1566 InterfaceHandler->Release();
1567 CoTaskMemFree(MediumList);
1568 CoTaskMemFree(InterfaceList);
1569 return hr;
1570 }
1571
1572 // store interface handler
1573 m_InterfaceHandler = InterfaceHandler;
1574 }
1575 }
1576 else
1577 {
1578 WCHAR Buffer[100];
1579 swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
1580 OutputDebugStringW(Buffer);
1581 DebugBreak();
1582 hr = E_FAIL;
1583 }
1584
1585 // free medium / interface / dataformat
1586 CoTaskMemFree(MediumList);
1587 CoTaskMemFree(InterfaceList);
1588
1589 return hr;
1590 }
1591
1592 HRESULT
1593 STDMETHODCALLTYPE
1594 COutputPin::CreatePinHandle(
1595 PKSPIN_MEDIUM Medium,
1596 PKSPIN_INTERFACE Interface,
1597 const AM_MEDIA_TYPE *pmt)
1598 {
1599 PKSPIN_CONNECT PinConnect;
1600 PKSDATAFORMAT DataFormat;
1601 ULONG Length;
1602 HRESULT hr;
1603
1604 if (m_hPin != INVALID_HANDLE_VALUE)
1605 {
1606 // pin already exists
1607 //CloseHandle(m_hPin);
1608 //m_hPin = INVALID_HANDLE_VALUE;
1609 return S_OK;
1610 }
1611
1612
1613 // calc format size
1614 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
1615
1616 // allocate pin connect
1617 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
1618 if (!PinConnect)
1619 {
1620 // failed
1621 return E_OUTOFMEMORY;
1622 }
1623
1624 // setup request
1625 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1626 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1627 PinConnect->PinId = m_PinId;
1628 PinConnect->PinToHandle = NULL;
1629 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1630 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1631
1632 // get dataformat offset
1633 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1634
1635 // copy data format
1636 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1637 DataFormat->Flags = 0;
1638 DataFormat->SampleSize = pmt->lSampleSize;
1639 DataFormat->Reserved = 0;
1640 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1641 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
1642 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1643
1644 if (pmt->cbFormat)
1645 {
1646 // copy extended format
1647 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1648 }
1649
1650 HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
1651 assert(hFilter != NULL);
1652
1653 // create pin
1654 hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1655
1656 if (SUCCEEDED(hr))
1657 {
1658 // store current interface / medium
1659 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
1660 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
1661 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
1662
1663 LPOLESTR pMajor, pSub, pFormat;
1664 StringFromIID(m_MediaFormat.majortype, &pMajor);
1665 StringFromIID(m_MediaFormat.subtype , &pSub);
1666 StringFromIID(m_MediaFormat.formattype, &pFormat);
1667 WCHAR Buffer[200];
1668 swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
1669 CoTaskMemFree(pMajor);
1670 CoTaskMemFree(pSub);
1671 CoTaskMemFree(pFormat);
1672 OutputDebugStringW(Buffer);
1673
1674 if (pmt->cbFormat)
1675 {
1676 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
1677 if (!m_MediaFormat.pbFormat)
1678 {
1679 CoTaskMemFree(PinConnect);
1680 m_MediaFormat.pbFormat = NULL;
1681 m_MediaFormat.cbFormat = 0;
1682 return E_OUTOFMEMORY;
1683 }
1684 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
1685 }
1686
1687 //TODO
1688 // connect pin pipes
1689
1690 }
1691 // free pin connect
1692 CoTaskMemFree(PinConnect);
1693
1694 return hr;
1695 }
1696
1697 HRESULT
1698 WINAPI
1699 COutputPin_Constructor(
1700 IBaseFilter * ParentFilter,
1701 LPCWSTR PinName,
1702 ULONG PinId,
1703 KSPIN_COMMUNICATION Communication,
1704 REFIID riid,
1705 LPVOID * ppv)
1706 {
1707 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
1708
1709 if (!handler)
1710 return E_OUTOFMEMORY;
1711
1712 if (FAILED(handler->QueryInterface(riid, ppv)))
1713 {
1714 /* not supported */
1715 delete handler;
1716 return E_NOINTERFACE;
1717 }
1718
1719 return S_OK;
1720 }