52f9cc94f7a3229e806d6cdd8aa1c15ef91964b7
[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 COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId);
158 virtual ~COutputPin();
159
160 protected:
161 LONG m_Ref;
162 IBaseFilter * m_ParentFilter;
163 LPCWSTR m_PinName;
164 HANDLE m_hPin;
165 ULONG m_PinId;
166 IKsObject * m_KsObjectParent;
167 IPin * m_Pin;
168 IKsAllocatorEx * m_KsAllocatorEx;
169 ULONG m_PipeAllocatorFlag;
170 BOOL m_bPinBusCacheInitialized;
171 GUID m_PinBusCache;
172 LPWSTR m_FilterName;
173 FRAMING_PROP m_FramingProp[4];
174 PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
175
176 IMemAllocator * m_MemAllocator;
177 LONG m_IoCount;
178 KSPIN_COMMUNICATION m_Communication;
179 KSPIN_INTERFACE m_Interface;
180 KSPIN_MEDIUM m_Medium;
181 IMediaSeeking * m_FilterMediaSeeking;
182 };
183
184 COutputPin::~COutputPin()
185 {
186 if (m_KsObjectParent)
187 m_KsObjectParent->Release();
188 }
189
190 COutputPin::COutputPin(
191 IBaseFilter * ParentFilter,
192 LPCWSTR PinName,
193 ULONG PinId) : m_Ref(0),
194 m_ParentFilter(ParentFilter),
195 m_PinName(PinName),
196 m_hPin(INVALID_HANDLE_VALUE),
197 m_PinId(PinId),
198 m_KsObjectParent(0),
199 m_Pin(0),
200 m_KsAllocatorEx(0),
201 m_PipeAllocatorFlag(0),
202 m_bPinBusCacheInitialized(0),
203 m_FilterName(0),
204 m_MemAllocator(0),
205 m_IoCount(0),
206 m_Communication(KSPIN_COMMUNICATION_NONE),
207 m_FilterMediaSeeking(0)
208 {
209 HRESULT hr;
210
211 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&m_KsObjectParent);
212 assert(hr == S_OK);
213
214 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&m_FilterMediaSeeking);
215 assert(hr == S_OK);
216
217 ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
218 ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
219 };
220
221 HRESULT
222 STDMETHODCALLTYPE
223 COutputPin::QueryInterface(
224 IN REFIID refiid,
225 OUT PVOID* Output)
226 {
227 *Output = NULL;
228 if (IsEqualGUID(refiid, IID_IUnknown) ||
229 IsEqualGUID(refiid, IID_IPin))
230 {
231 OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n");
232 *Output = PVOID(this);
233 reinterpret_cast<IUnknown*>(*Output)->AddRef();
234 return NOERROR;
235 }
236 else if (IsEqualGUID(refiid, IID_IKsObject))
237 {
238 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
239 *Output = (IKsObject*)(this);
240 reinterpret_cast<IKsObject*>(*Output)->AddRef();
241 return NOERROR;
242 }
243 else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx))
244 {
245 *Output = (IKsPinEx*)(this);
246 reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
247 return NOERROR;
248 }
249 else if (IsEqualGUID(refiid, IID_IKsPinPipe))
250 {
251 *Output = (IKsPinPipe*)(this);
252 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
253 return NOERROR;
254 }
255 else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
256 {
257 *Output = (IKsAggregateControl*)(this);
258 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
259 return NOERROR;
260 }
261 else if (IsEqualGUID(refiid, IID_IQualityControl))
262 {
263 *Output = (IQualityControl*)(this);
264 reinterpret_cast<IQualityControl*>(*Output)->AddRef();
265 return NOERROR;
266 }
267 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
268 {
269 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
270 DebugBreak();
271 *Output = (IKsPropertySet*)(this);
272 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
273 return NOERROR;
274 }
275 else if (IsEqualGUID(refiid, IID_IKsControl))
276 {
277 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");
278 *Output = (IKsControl*)(this);
279 reinterpret_cast<IKsControl*>(*Output)->AddRef();
280 return NOERROR;
281 }
282 #if 0
283 else if (IsEqualGUID(refiid, IID_IStreamBuilder))
284 {
285 *Output = (IStreamBuilder*)(this);
286 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
287 return NOERROR;
288 }
289 #endif
290 else if (IsEqualGUID(refiid, IID_IKsPinFactory))
291 {
292 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");
293 *Output = (IKsPinFactory*)(this);
294 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
295 return NOERROR;
296 }
297 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
298 {
299 OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");
300 *Output = (ISpecifyPropertyPages*)(this);
301 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
302 return NOERROR;
303 }
304 else if (IsEqualGUID(refiid, IID_IMediaSeeking))
305 {
306 *Output = (IMediaSeeking*)(this);
307 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
308 return NOERROR;
309 }
310 else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation))
311 {
312 *Output = (IAMBufferNegotiation*)(this);
313 reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef();
314 return NOERROR;
315 }
316 else if (IsEqualGUID(refiid, IID_IAMStreamConfig))
317 {
318 *Output = (IAMStreamConfig*)(this);
319 reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef();
320 return NOERROR;
321 }
322 else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp))
323 {
324 *Output = (IMemAllocatorNotifyCallbackTemp*)(this);
325 reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef();
326 return NOERROR;
327 }
328
329 WCHAR Buffer[MAX_PATH];
330 LPOLESTR lpstr;
331 StringFromCLSID(refiid, &lpstr);
332 swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s\n", lpstr);
333 OutputDebugStringW(Buffer);
334 CoTaskMemFree(lpstr);
335
336 return E_NOINTERFACE;
337 }
338
339 //-------------------------------------------------------------------
340 // IAMBufferNegotiation interface
341 //
342 HRESULT
343 STDMETHODCALLTYPE
344 COutputPin::SuggestAllocatorProperties(
345 const ALLOCATOR_PROPERTIES *pprop)
346 {
347 OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties NotImplemented\n");
348 return E_NOTIMPL;
349 }
350
351 HRESULT
352 STDMETHODCALLTYPE
353 COutputPin::GetAllocatorProperties(
354 ALLOCATOR_PROPERTIES *pprop)
355 {
356 OutputDebugStringW(L"COutputPin::GetAllocatorProperties NotImplemented\n");
357 return E_NOTIMPL;
358 }
359
360 //-------------------------------------------------------------------
361 // IAMStreamConfig interface
362 //
363 HRESULT
364 STDMETHODCALLTYPE
365 COutputPin::SetFormat(
366 AM_MEDIA_TYPE *pmt)
367 {
368 OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n");
369 return E_NOTIMPL;
370 }
371
372 HRESULT
373 STDMETHODCALLTYPE
374 COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt)
375 {
376 OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n");
377 return E_NOTIMPL;
378 }
379
380 HRESULT
381 STDMETHODCALLTYPE
382 COutputPin::GetNumberOfCapabilities(
383 int *piCount,
384 int *piSize)
385 {
386 OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n");
387 return E_NOTIMPL;
388 }
389
390 HRESULT
391 STDMETHODCALLTYPE
392 COutputPin::GetStreamCaps(
393 int iIndex,
394 AM_MEDIA_TYPE **ppmt,
395 BYTE *pSCC)
396 {
397 OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n");
398 return E_NOTIMPL;
399 }
400
401 //-------------------------------------------------------------------
402 // IMemAllocatorNotifyCallbackTemp interface
403 //
404 HRESULT
405 STDMETHODCALLTYPE
406 COutputPin::NotifyRelease()
407 {
408 OutputDebugStringW(L"COutputPin::NotifyRelease NotImplemented\n");
409 return E_NOTIMPL;
410 }
411
412 //-------------------------------------------------------------------
413 // IMediaSeeking interface
414 //
415 HRESULT
416 STDMETHODCALLTYPE
417 COutputPin::GetCapabilities(
418 DWORD *pCapabilities)
419 {
420 return m_FilterMediaSeeking->GetCapabilities(pCapabilities);
421 }
422
423 HRESULT
424 STDMETHODCALLTYPE
425 COutputPin::CheckCapabilities(
426 DWORD *pCapabilities)
427 {
428 return m_FilterMediaSeeking->CheckCapabilities(pCapabilities);
429 }
430
431 HRESULT
432 STDMETHODCALLTYPE
433 COutputPin::IsFormatSupported(
434 const GUID *pFormat)
435 {
436 return m_FilterMediaSeeking->IsFormatSupported(pFormat);
437 }
438
439 HRESULT
440 STDMETHODCALLTYPE
441 COutputPin::QueryPreferredFormat(
442 GUID *pFormat)
443 {
444 return m_FilterMediaSeeking->QueryPreferredFormat(pFormat);
445 }
446
447 HRESULT
448 STDMETHODCALLTYPE
449 COutputPin::GetTimeFormat(
450 GUID *pFormat)
451 {
452 return m_FilterMediaSeeking->GetTimeFormat(pFormat);
453 }
454
455 HRESULT
456 STDMETHODCALLTYPE
457 COutputPin::IsUsingTimeFormat(
458 const GUID *pFormat)
459 {
460 return m_FilterMediaSeeking->IsUsingTimeFormat(pFormat);
461 }
462
463 HRESULT
464 STDMETHODCALLTYPE
465 COutputPin::SetTimeFormat(
466 const GUID *pFormat)
467 {
468 return m_FilterMediaSeeking->SetTimeFormat(pFormat);
469 }
470
471 HRESULT
472 STDMETHODCALLTYPE
473 COutputPin::GetDuration(
474 LONGLONG *pDuration)
475 {
476 return m_FilterMediaSeeking->GetDuration(pDuration);
477 }
478
479 HRESULT
480 STDMETHODCALLTYPE
481 COutputPin::GetStopPosition(
482 LONGLONG *pStop)
483 {
484 return m_FilterMediaSeeking->GetStopPosition(pStop);
485 }
486
487
488 HRESULT
489 STDMETHODCALLTYPE
490 COutputPin::GetCurrentPosition(
491 LONGLONG *pCurrent)
492 {
493 return m_FilterMediaSeeking->GetCurrentPosition(pCurrent);
494 }
495
496 HRESULT
497 STDMETHODCALLTYPE
498 COutputPin::ConvertTimeFormat(
499 LONGLONG *pTarget,
500 const GUID *pTargetFormat,
501 LONGLONG Source,
502 const GUID *pSourceFormat)
503 {
504 return m_FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
505 }
506
507 HRESULT
508 STDMETHODCALLTYPE
509 COutputPin::SetPositions(
510 LONGLONG *pCurrent,
511 DWORD dwCurrentFlags,
512 LONGLONG *pStop,
513 DWORD dwStopFlags)
514 {
515 return m_FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
516 }
517
518 HRESULT
519 STDMETHODCALLTYPE
520 COutputPin::GetPositions(
521 LONGLONG *pCurrent,
522 LONGLONG *pStop)
523 {
524 return m_FilterMediaSeeking->GetPositions(pCurrent, pStop);
525 }
526
527 HRESULT
528 STDMETHODCALLTYPE
529 COutputPin::GetAvailable(
530 LONGLONG *pEarliest,
531 LONGLONG *pLatest)
532 {
533 return m_FilterMediaSeeking->GetAvailable(pEarliest, pLatest);
534 }
535
536 HRESULT
537 STDMETHODCALLTYPE
538 COutputPin::SetRate(
539 double dRate)
540 {
541 return m_FilterMediaSeeking->SetRate(dRate);
542 }
543
544 HRESULT
545 STDMETHODCALLTYPE
546 COutputPin::GetRate(
547 double *pdRate)
548 {
549 return m_FilterMediaSeeking->GetRate(pdRate);
550 }
551
552 HRESULT
553 STDMETHODCALLTYPE
554 COutputPin::GetPreroll(
555 LONGLONG *pllPreroll)
556 {
557 return m_FilterMediaSeeking->GetPreroll(pllPreroll);
558 }
559
560 //-------------------------------------------------------------------
561 // IQualityControl interface
562 //
563 HRESULT
564 STDMETHODCALLTYPE
565 COutputPin::Notify(
566 IBaseFilter *pSelf,
567 Quality q)
568 {
569 OutputDebugStringW(L"COutputPin::Notify NotImplemented\n");
570 return E_NOTIMPL;
571 }
572
573 HRESULT
574 STDMETHODCALLTYPE
575 COutputPin::SetSink(
576 IQualityControl *piqc)
577 {
578 OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n");
579 return E_NOTIMPL;
580 }
581
582
583 //-------------------------------------------------------------------
584 // IKsAggregateControl interface
585 //
586 HRESULT
587 STDMETHODCALLTYPE
588 COutputPin::KsAddAggregate(
589 IN REFGUID AggregateClass)
590 {
591 OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n");
592 return E_NOTIMPL;
593 }
594
595 HRESULT
596 STDMETHODCALLTYPE
597 COutputPin::KsRemoveAggregate(
598 REFGUID AggregateClass)
599 {
600 OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n");
601 return E_NOTIMPL;
602 }
603
604
605 //-------------------------------------------------------------------
606 // IKsPin
607 //
608
609 HRESULT
610 STDMETHODCALLTYPE
611 COutputPin::KsQueryMediums(
612 PKSMULTIPLE_ITEM* MediumList)
613 {
614 HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
615 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
616 }
617
618 HRESULT
619 STDMETHODCALLTYPE
620 COutputPin::KsQueryInterfaces(
621 PKSMULTIPLE_ITEM* InterfaceList)
622 {
623 HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
624
625 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
626 }
627
628 HRESULT
629 STDMETHODCALLTYPE
630 COutputPin::KsCreateSinkPinHandle(
631 KSPIN_INTERFACE& Interface,
632 KSPIN_MEDIUM& Medium)
633 {
634 OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n");
635 return E_NOTIMPL;
636 }
637
638 HRESULT
639 STDMETHODCALLTYPE
640 COutputPin::KsGetCurrentCommunication(
641 KSPIN_COMMUNICATION *Communication,
642 KSPIN_INTERFACE *Interface,
643 KSPIN_MEDIUM *Medium)
644 {
645 if (Communication)
646 {
647 *Communication = m_Communication;
648 }
649
650 if (Interface)
651 {
652 if (!m_hPin)
653 return VFW_E_NOT_CONNECTED;
654
655 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
656 }
657
658 if (Medium)
659 {
660 if (!m_hPin)
661 return VFW_E_NOT_CONNECTED;
662
663 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
664 }
665 return NOERROR;
666 }
667
668 HRESULT
669 STDMETHODCALLTYPE
670 COutputPin::KsPropagateAcquire()
671 {
672 OutputDebugStringW(L"COutputPin::KsPropagateAcquire NotImplemented\n");
673 return E_NOTIMPL;
674 }
675
676 HRESULT
677 STDMETHODCALLTYPE
678 COutputPin::KsDeliver(
679 IMediaSample* Sample,
680 ULONG Flags)
681 {
682 return E_FAIL;
683 }
684
685 HRESULT
686 STDMETHODCALLTYPE
687 COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
688 {
689 return NOERROR;
690 }
691
692 IMemAllocator *
693 STDMETHODCALLTYPE
694 COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
695 {
696 if (Operation == KsPeekOperation_AddRef)
697 {
698 // add reference on allocator
699 m_MemAllocator->AddRef();
700 }
701
702 return m_MemAllocator;
703 }
704
705 HRESULT
706 STDMETHODCALLTYPE
707 COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
708 {
709 if (MemAllocator)
710 {
711 MemAllocator->AddRef();
712 }
713
714 if (m_MemAllocator)
715 {
716 m_MemAllocator->Release();
717 }
718
719 m_MemAllocator = MemAllocator;
720 return NOERROR;
721 }
722
723 HRESULT
724 STDMETHODCALLTYPE
725 COutputPin::KsRenegotiateAllocator()
726 {
727 return E_FAIL;
728 }
729
730 LONG
731 STDMETHODCALLTYPE
732 COutputPin::KsIncrementPendingIoCount()
733 {
734 return InterlockedIncrement((volatile LONG*)&m_IoCount);
735 }
736
737 LONG
738 STDMETHODCALLTYPE
739 COutputPin::KsDecrementPendingIoCount()
740 {
741 return InterlockedDecrement((volatile LONG*)&m_IoCount);
742 }
743
744 HRESULT
745 STDMETHODCALLTYPE
746 COutputPin::KsQualityNotify(
747 ULONG Proportion,
748 REFERENCE_TIME TimeDelta)
749 {
750 OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n");
751 return E_NOTIMPL;
752 }
753
754 //-------------------------------------------------------------------
755 // IKsPinEx
756 //
757
758 VOID
759 STDMETHODCALLTYPE
760 COutputPin::KsNotifyError(
761 IMediaSample* Sample,
762 HRESULT hr)
763 {
764 OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n");
765 }
766
767
768 //-------------------------------------------------------------------
769 // IKsPinPipe
770 //
771
772 HRESULT
773 STDMETHODCALLTYPE
774 COutputPin::KsGetPinFramingCache(
775 PKSALLOCATOR_FRAMING_EX *FramingEx,
776 PFRAMING_PROP FramingProp,
777 FRAMING_CACHE_OPS Option)
778 {
779 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
780 {
781 // invalid argument
782 return E_INVALIDARG;
783 }
784
785 // get framing properties
786 *FramingProp = m_FramingProp[Option];
787 *FramingEx = m_FramingEx[Option];
788
789 return NOERROR;
790 }
791
792 HRESULT
793 STDMETHODCALLTYPE
794 COutputPin::KsSetPinFramingCache(
795 PKSALLOCATOR_FRAMING_EX FramingEx,
796 PFRAMING_PROP FramingProp,
797 FRAMING_CACHE_OPS Option)
798 {
799 ULONG Index;
800 ULONG RefCount = 0;
801
802 if (m_FramingEx[Option])
803 {
804 for(Index = 1; Index < 4; Index++)
805 {
806 if (m_FramingEx[Index] == m_FramingEx[Option])
807 RefCount++;
808 }
809
810 if (RefCount == 1)
811 {
812 // existing framing is only used once
813 CoTaskMemFree(m_FramingEx[Option]);
814 }
815 }
816
817 // store framing
818 m_FramingEx[Option] = FramingEx;
819 m_FramingProp[Option] = *FramingProp;
820
821 return S_OK;
822 }
823
824 IPin*
825 STDMETHODCALLTYPE
826 COutputPin::KsGetConnectedPin()
827 {
828 return m_Pin;
829 }
830
831 IKsAllocatorEx*
832 STDMETHODCALLTYPE
833 COutputPin::KsGetPipe(
834 KSPEEKOPERATION Operation)
835 {
836 if (Operation == KsPeekOperation_AddRef)
837 {
838 if (m_KsAllocatorEx)
839 m_KsAllocatorEx->AddRef();
840 }
841 return m_KsAllocatorEx;
842 }
843
844 HRESULT
845 STDMETHODCALLTYPE
846 COutputPin::KsSetPipe(
847 IKsAllocatorEx *KsAllocator)
848 {
849 if (KsAllocator)
850 KsAllocator->AddRef();
851
852 if (m_KsAllocatorEx)
853 m_KsAllocatorEx->Release();
854
855 m_KsAllocatorEx = KsAllocator;
856 return NOERROR;
857 }
858
859 ULONG
860 STDMETHODCALLTYPE
861 COutputPin::KsGetPipeAllocatorFlag()
862 {
863 return m_PipeAllocatorFlag;
864 }
865
866
867 HRESULT
868 STDMETHODCALLTYPE
869 COutputPin::KsSetPipeAllocatorFlag(
870 ULONG Flag)
871 {
872 m_PipeAllocatorFlag = Flag;
873 return NOERROR;
874 }
875
876 GUID
877 STDMETHODCALLTYPE
878 COutputPin::KsGetPinBusCache()
879 {
880 if (!m_bPinBusCacheInitialized)
881 {
882 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
883 m_bPinBusCacheInitialized = TRUE;
884 }
885
886 return m_PinBusCache;
887 }
888
889 HRESULT
890 STDMETHODCALLTYPE
891 COutputPin::KsSetPinBusCache(
892 GUID Bus)
893 {
894 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
895 return NOERROR;
896 }
897
898 PWCHAR
899 STDMETHODCALLTYPE
900 COutputPin::KsGetPinName()
901 {
902 return (PWCHAR)m_PinName;
903 }
904
905
906 PWCHAR
907 STDMETHODCALLTYPE
908 COutputPin::KsGetFilterName()
909 {
910 return m_FilterName;
911 }
912
913 //-------------------------------------------------------------------
914 // ISpecifyPropertyPages
915 //
916
917 HRESULT
918 STDMETHODCALLTYPE
919 COutputPin::GetPages(CAUUID *pPages)
920 {
921 OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
922
923 if (!pPages)
924 return E_POINTER;
925
926 pPages->cElems = 0;
927 pPages->pElems = NULL;
928
929 return S_OK;
930 }
931
932 //-------------------------------------------------------------------
933 // IKsPinFactory
934 //
935
936 HRESULT
937 STDMETHODCALLTYPE
938 COutputPin::KsPinFactory(
939 ULONG* PinFactory)
940 {
941 OutputDebugStringW(L"COutputPin::KsPinFactory\n");
942 *PinFactory = m_PinId;
943 return S_OK;
944 }
945
946
947 //-------------------------------------------------------------------
948 // IStreamBuilder
949 //
950
951 HRESULT
952 STDMETHODCALLTYPE
953 COutputPin::Render(
954 IPin *ppinOut,
955 IGraphBuilder *pGraph)
956 {
957 OutputDebugStringW(L"COutputPin::Render\n");
958 return S_OK;
959 }
960
961 HRESULT
962 STDMETHODCALLTYPE
963 COutputPin::Backout(
964 IPin *ppinOut,
965 IGraphBuilder *pGraph)
966 {
967 OutputDebugStringW(L"COutputPin::Backout\n");
968 return S_OK;
969 }
970 //-------------------------------------------------------------------
971 // IKsObject
972 //
973 HANDLE
974 STDMETHODCALLTYPE
975 COutputPin::KsGetObjectHandle()
976 {
977 OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");
978 assert(m_hPin);
979 return m_hPin;
980 }
981
982 //-------------------------------------------------------------------
983 // IKsControl
984 //
985 HRESULT
986 STDMETHODCALLTYPE
987 COutputPin::KsProperty(
988 PKSPROPERTY Property,
989 ULONG PropertyLength,
990 LPVOID PropertyData,
991 ULONG DataLength,
992 ULONG* BytesReturned)
993 {
994 assert(m_hPin != 0);
995 OutputDebugStringW(L"COutputPin::KsProperty\n");
996 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
997 }
998
999 HRESULT
1000 STDMETHODCALLTYPE
1001 COutputPin::KsMethod(
1002 PKSMETHOD Method,
1003 ULONG MethodLength,
1004 LPVOID MethodData,
1005 ULONG DataLength,
1006 ULONG* BytesReturned)
1007 {
1008 assert(m_hPin != 0);
1009 OutputDebugStringW(L"COutputPin::KsMethod\n");
1010 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
1011 }
1012
1013 HRESULT
1014 STDMETHODCALLTYPE
1015 COutputPin::KsEvent(
1016 PKSEVENT Event,
1017 ULONG EventLength,
1018 LPVOID EventData,
1019 ULONG DataLength,
1020 ULONG* BytesReturned)
1021 {
1022 assert(m_hPin != 0);
1023
1024 OutputDebugStringW(L"COutputPin::KsEvent\n");
1025
1026 if (EventLength)
1027 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
1028 else
1029 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
1030 }
1031
1032
1033 //-------------------------------------------------------------------
1034 // IKsPropertySet
1035 //
1036 HRESULT
1037 STDMETHODCALLTYPE
1038 COutputPin::Set(
1039 REFGUID guidPropSet,
1040 DWORD dwPropID,
1041 LPVOID pInstanceData,
1042 DWORD cbInstanceData,
1043 LPVOID pPropData,
1044 DWORD cbPropData)
1045 {
1046 ULONG BytesReturned;
1047
1048 OutputDebugStringW(L"COutputPin::Set\n");
1049
1050 if (cbInstanceData)
1051 {
1052 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1053 if (!Property)
1054 return E_OUTOFMEMORY;
1055
1056 Property->Set = guidPropSet;
1057 Property->Id = dwPropID;
1058 Property->Flags = KSPROPERTY_TYPE_SET;
1059
1060 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1061
1062 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1063 CoTaskMemFree(Property);
1064 return hr;
1065 }
1066 else
1067 {
1068 KSPROPERTY Property;
1069
1070 Property.Set = guidPropSet;
1071 Property.Id = dwPropID;
1072 Property.Flags = KSPROPERTY_TYPE_SET;
1073
1074 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1075 return hr;
1076 }
1077 }
1078
1079 HRESULT
1080 STDMETHODCALLTYPE
1081 COutputPin::Get(
1082 REFGUID guidPropSet,
1083 DWORD dwPropID,
1084 LPVOID pInstanceData,
1085 DWORD cbInstanceData,
1086 LPVOID pPropData,
1087 DWORD cbPropData,
1088 DWORD *pcbReturned)
1089 {
1090 ULONG BytesReturned;
1091
1092 OutputDebugStringW(L"COutputPin::Get\n");
1093
1094 if (cbInstanceData)
1095 {
1096 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1097 if (!Property)
1098 return E_OUTOFMEMORY;
1099
1100 Property->Set = guidPropSet;
1101 Property->Id = dwPropID;
1102 Property->Flags = KSPROPERTY_TYPE_GET;
1103
1104 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1105
1106 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1107 CoTaskMemFree(Property);
1108 return hr;
1109 }
1110 else
1111 {
1112 KSPROPERTY Property;
1113
1114 Property.Set = guidPropSet;
1115 Property.Id = dwPropID;
1116 Property.Flags = KSPROPERTY_TYPE_GET;
1117
1118 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1119 return hr;
1120 }
1121 }
1122
1123 HRESULT
1124 STDMETHODCALLTYPE
1125 COutputPin::QuerySupported(
1126 REFGUID guidPropSet,
1127 DWORD dwPropID,
1128 DWORD *pTypeSupport)
1129 {
1130 KSPROPERTY Property;
1131 ULONG BytesReturned;
1132
1133 OutputDebugStringW(L"COutputPin::QuerySupported\n");
1134
1135 Property.Set = guidPropSet;
1136 Property.Id = dwPropID;
1137 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1138
1139 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1140 }
1141
1142
1143 //-------------------------------------------------------------------
1144 // IPin interface
1145 //
1146 HRESULT
1147 STDMETHODCALLTYPE
1148 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1149 {
1150 AM_MEDIA_TYPE MediaType;
1151 HRESULT hr;
1152 HANDLE hFilter;
1153
1154 OutputDebugStringW(L"COutputPin::Connect called\n");
1155 if (pmt)
1156 {
1157 hr = pReceivePin->QueryAccept(pmt);
1158 if (FAILED(hr))
1159 return hr;
1160 }
1161 else
1162 {
1163 // get parent filter handle
1164 hFilter = m_KsObjectParent->KsGetObjectHandle();
1165
1166 // get media type count
1167 ZeroMemory(&MediaType, sizeof(AM_MEDIA_TYPE));
1168 hr = KsGetMediaType(0, &MediaType, hFilter, m_PinId);
1169 if (FAILED(hr))
1170 return hr;
1171
1172 // query accept
1173 hr = pReceivePin->QueryAccept(&MediaType);
1174 if (FAILED(hr))
1175 return hr;
1176
1177 pmt = &MediaType;
1178 }
1179
1180 //FIXME create pin handle
1181
1182 // receive connection;
1183 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
1184 if (SUCCEEDED(hr))
1185 {
1186 // increment reference count
1187 pReceivePin->AddRef();
1188 m_Pin = pReceivePin;
1189 OutputDebugStringW(L"COutputPin::Connect success\n");
1190 }
1191
1192 return hr;
1193 }
1194
1195 HRESULT
1196 STDMETHODCALLTYPE
1197 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1198 {
1199 OutputDebugStringW(L"COutputPin::ReceiveConnection\n");
1200 return E_UNEXPECTED;
1201 }
1202 HRESULT
1203 STDMETHODCALLTYPE
1204 COutputPin::Disconnect( void)
1205 {
1206 OutputDebugStringW(L"COutputPin::Disconnect\n");
1207
1208 if (!m_Pin)
1209 {
1210 // pin was not connected
1211 return S_FALSE;
1212 }
1213
1214 //FIXME
1215 //check if filter is active
1216
1217 m_Pin->Release();
1218 m_Pin = NULL;
1219
1220 OutputDebugStringW(L"COutputPin::Disconnect\n");
1221 return S_OK;
1222 }
1223 HRESULT
1224 STDMETHODCALLTYPE
1225 COutputPin::ConnectedTo(IPin **pPin)
1226 {
1227 OutputDebugStringW(L"COutputPin::ConnectedTo\n");
1228
1229 if (!pPin)
1230 return E_POINTER;
1231
1232 if (m_Pin)
1233 {
1234 // increment reference count
1235 m_Pin->AddRef();
1236 *pPin = m_Pin;
1237 return S_OK;
1238 }
1239
1240 *pPin = NULL;
1241 return VFW_E_NOT_CONNECTED;
1242 }
1243 HRESULT
1244 STDMETHODCALLTYPE
1245 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1246 {
1247 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");
1248 return E_NOTIMPL;
1249 }
1250 HRESULT
1251 STDMETHODCALLTYPE
1252 COutputPin::QueryPinInfo(PIN_INFO *pInfo)
1253 {
1254 OutputDebugStringW(L"COutputPin::QueryPinInfo\n");
1255
1256 wcscpy(pInfo->achName, m_PinName);
1257 pInfo->dir = PINDIR_OUTPUT;
1258 pInfo->pFilter = m_ParentFilter;
1259 m_ParentFilter->AddRef();
1260
1261 return S_OK;
1262 }
1263 HRESULT
1264 STDMETHODCALLTYPE
1265 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1266 {
1267 OutputDebugStringW(L"COutputPin::QueryDirection\n");
1268
1269 if (pPinDir)
1270 {
1271 *pPinDir = PINDIR_OUTPUT;
1272 return S_OK;
1273 }
1274
1275 return E_POINTER;
1276 }
1277 HRESULT
1278 STDMETHODCALLTYPE
1279 COutputPin::QueryId(LPWSTR *Id)
1280 {
1281 OutputDebugStringW(L"COutputPin::QueryId\n");
1282
1283 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1284 if (!*Id)
1285 return E_OUTOFMEMORY;
1286
1287 wcscpy(*Id, m_PinName);
1288 return S_OK;
1289 }
1290 HRESULT
1291 STDMETHODCALLTYPE
1292 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
1293 {
1294 OutputDebugStringW(L"COutputPin::QueryAccept called\n");
1295 return E_NOTIMPL;
1296 }
1297 HRESULT
1298 STDMETHODCALLTYPE
1299 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1300 {
1301 HRESULT hr;
1302 ULONG MediaTypeCount = 0, Index;
1303 AM_MEDIA_TYPE * MediaTypes;
1304 HANDLE hFilter;
1305
1306 OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n");
1307
1308 if (!m_KsObjectParent)
1309 {
1310 // no interface
1311 return E_NOINTERFACE;
1312 }
1313
1314 // get parent filter handle
1315 hFilter = m_KsObjectParent->KsGetObjectHandle();
1316
1317 // query media type count
1318 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1319 if (FAILED(hr) || !MediaTypeCount)
1320 {
1321 OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
1322 return hr;
1323 }
1324
1325 // allocate media types
1326 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1327 if (!MediaTypes)
1328 {
1329 // not enough memory
1330 OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n");
1331 return E_OUTOFMEMORY;
1332 }
1333
1334 // zero media types
1335 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1336
1337 for(Index = 0; Index < MediaTypeCount; Index++)
1338 {
1339 // get media type
1340 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1341 if (FAILED(hr))
1342 {
1343 // failed
1344 CoTaskMemFree(MediaTypes);
1345 OutputDebugStringW(L"COutputPin::EnumMediaTypes failed\n");
1346 return hr;
1347 }
1348 }
1349
1350 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1351 }
1352 HRESULT
1353 STDMETHODCALLTYPE
1354 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1355 {
1356 OutputDebugStringW(L"COutputPin::QueryInternalConnections called\n");
1357 return E_NOTIMPL;
1358 }
1359 HRESULT
1360 STDMETHODCALLTYPE
1361 COutputPin::EndOfStream( void)
1362 {
1363 OutputDebugStringW(L"COutputPin::EndOfStream called\n");
1364 return E_NOTIMPL;
1365 }
1366 HRESULT
1367 STDMETHODCALLTYPE
1368 COutputPin::BeginFlush( void)
1369 {
1370 OutputDebugStringW(L"COutputPin::BeginFlush called\n");
1371 return E_NOTIMPL;
1372 }
1373 HRESULT
1374 STDMETHODCALLTYPE
1375 COutputPin::EndFlush( void)
1376 {
1377 OutputDebugStringW(L"COutputPin::EndFlush called\n");
1378 return E_NOTIMPL;
1379 }
1380 HRESULT
1381 STDMETHODCALLTYPE
1382 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1383 {
1384 OutputDebugStringW(L"COutputPin::NewSegment called\n");
1385 return E_NOTIMPL;
1386 }
1387
1388 HRESULT
1389 WINAPI
1390 COutputPin_Constructor(
1391 IBaseFilter * ParentFilter,
1392 LPCWSTR PinName,
1393 ULONG PinId,
1394 REFIID riid,
1395 LPVOID * ppv)
1396 {
1397 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId);
1398
1399 if (!handler)
1400 return E_OUTOFMEMORY;
1401
1402 if (FAILED(handler->QueryInterface(riid, ppv)))
1403 {
1404 /* not supported */
1405 delete handler;
1406 return E_NOINTERFACE;
1407 }
1408
1409 return S_OK;
1410 }