[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 HRESULT WINAPI IoProcessRoutine();
164 HRESULT WINAPI InitializeIOThread();
165
166 friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter);
167 friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State);
168
169 protected:
170 LONG m_Ref;
171 IBaseFilter * m_ParentFilter;
172 LPCWSTR m_PinName;
173 HANDLE m_hPin;
174 ULONG m_PinId;
175 IPin * m_Pin;
176 IKsAllocatorEx * m_KsAllocatorEx;
177 ULONG m_PipeAllocatorFlag;
178 BOOL m_bPinBusCacheInitialized;
179 GUID m_PinBusCache;
180 LPWSTR m_FilterName;
181 FRAMING_PROP m_FramingProp[4];
182 PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
183
184 IMemAllocator * m_MemAllocator;
185 IMemInputPin * m_MemInputPin;
186 LONG m_IoCount;
187 KSPIN_COMMUNICATION m_Communication;
188 KSPIN_INTERFACE m_Interface;
189 KSPIN_MEDIUM m_Medium;
190 AM_MEDIA_TYPE m_MediaFormat;
191 ALLOCATOR_PROPERTIES m_Properties;
192 IKsInterfaceHandler * m_InterfaceHandler;
193
194 HANDLE m_hStartEvent;
195 HANDLE m_hBufferAvailable;
196 HANDLE m_hStopEvent;
197 BOOL m_StopInProgress;
198 BOOL m_IoThreadStarted;
199
200 KSSTATE m_State;
201 CRITICAL_SECTION m_Lock;
202 };
203
204 COutputPin::~COutputPin()
205 {
206 }
207
208 COutputPin::COutputPin(
209 IBaseFilter * ParentFilter,
210 LPCWSTR PinName,
211 ULONG PinId,
212 KSPIN_COMMUNICATION Communication) : m_Ref(0),
213 m_ParentFilter(ParentFilter),
214 m_PinName(PinName),
215 m_hPin(INVALID_HANDLE_VALUE),
216 m_PinId(PinId),
217 m_Pin(0),
218 m_KsAllocatorEx(0),
219 m_PipeAllocatorFlag(0),
220 m_bPinBusCacheInitialized(0),
221 m_FilterName(0),
222 m_MemAllocator(0),
223 m_MemInputPin(0),
224 m_IoCount(0),
225 m_Communication(Communication),
226 m_InterfaceHandler(0),
227 m_hStartEvent(0),
228 m_hBufferAvailable(0),
229 m_hStopEvent(0),
230 m_StopInProgress(0),
231 m_IoThreadStarted(0),
232 m_State(KSSTATE_STOP)
233 {
234 HRESULT hr;
235 IKsObject * KsObjectParent;
236
237 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
238 assert(hr == S_OK);
239
240 ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
241 ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
242
243 hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId);
244 assert(hr == S_OK);
245
246 InitializeCriticalSection(&m_Lock);
247
248 KsObjectParent->Release();
249 };
250
251 HRESULT
252 STDMETHODCALLTYPE
253 COutputPin::QueryInterface(
254 IN REFIID refiid,
255 OUT PVOID* Output)
256 {
257 *Output = NULL;
258 if (IsEqualGUID(refiid, IID_IUnknown) ||
259 IsEqualGUID(refiid, IID_IPin))
260 {
261 #ifdef KSPROXY_TRACE
262 OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n");
263 #endif
264 *Output = PVOID(this);
265 reinterpret_cast<IUnknown*>(*Output)->AddRef();
266 return NOERROR;
267 }
268 else if (IsEqualGUID(refiid, IID_IKsObject))
269 {
270 if (m_hPin == INVALID_HANDLE_VALUE)
271 {
272 HRESULT hr = CreatePin(&m_MediaFormat);
273 if (FAILED(hr))
274 return hr;
275 }
276 #ifdef KSPROXY_TRACE
277 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
278 #endif
279 *Output = (IKsObject*)(this);
280 reinterpret_cast<IKsObject*>(*Output)->AddRef();
281 return NOERROR;
282 }
283 else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx))
284 {
285 *Output = (IKsPinEx*)(this);
286 reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
287 return NOERROR;
288 }
289 else if (IsEqualGUID(refiid, IID_IKsPinPipe))
290 {
291 *Output = (IKsPinPipe*)(this);
292 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
293 return NOERROR;
294 }
295 else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
296 {
297 *Output = (IKsAggregateControl*)(this);
298 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
299 return NOERROR;
300 }
301 else if (IsEqualGUID(refiid, IID_IQualityControl))
302 {
303 *Output = (IQualityControl*)(this);
304 reinterpret_cast<IQualityControl*>(*Output)->AddRef();
305 return NOERROR;
306 }
307 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
308 {
309 if (m_hPin == INVALID_HANDLE_VALUE)
310 {
311 HRESULT hr = CreatePin(&m_MediaFormat);
312 if (FAILED(hr))
313 return hr;
314 }
315 #ifdef KSPROXY_TRACE
316 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
317 #endif
318 *Output = (IKsPropertySet*)(this);
319 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
320 return NOERROR;
321 }
322 else if (IsEqualGUID(refiid, IID_IKsControl))
323 {
324 #ifdef KSPROXY_TRACE
325 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");
326 #endif
327 *Output = (IKsControl*)(this);
328 reinterpret_cast<IKsControl*>(*Output)->AddRef();
329 return NOERROR;
330 }
331 #if 0
332 else if (IsEqualGUID(refiid, IID_IStreamBuilder))
333 {
334 *Output = (IStreamBuilder*)(this);
335 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
336 return NOERROR;
337 }
338 #endif
339 else if (IsEqualGUID(refiid, IID_IKsPinFactory))
340 {
341 #ifdef KSPROXY_TRACE
342 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");
343 #endif
344 *Output = (IKsPinFactory*)(this);
345 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
346 return NOERROR;
347 }
348 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
349 {
350 #ifdef KSPROXY_TRACE
351 OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");
352 #endif
353 *Output = (ISpecifyPropertyPages*)(this);
354 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
355 return NOERROR;
356 }
357 else if (IsEqualGUID(refiid, IID_IMediaSeeking))
358 {
359 *Output = (IMediaSeeking*)(this);
360 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
361 return NOERROR;
362 }
363 else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation))
364 {
365 *Output = (IAMBufferNegotiation*)(this);
366 reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef();
367 return NOERROR;
368 }
369 else if (IsEqualGUID(refiid, IID_IAMStreamConfig))
370 {
371 *Output = (IAMStreamConfig*)(this);
372 reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef();
373 return NOERROR;
374 }
375 else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp))
376 {
377 *Output = (IMemAllocatorNotifyCallbackTemp*)(this);
378 reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef();
379 return NOERROR;
380 }
381
382 #ifdef KSPROXY_TRACE
383 WCHAR Buffer[MAX_PATH];
384 LPOLESTR lpstr;
385 StringFromCLSID(refiid, &lpstr);
386 swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName);
387 OutputDebugStringW(Buffer);
388 CoTaskMemFree(lpstr);
389 #endif
390
391 return E_NOINTERFACE;
392 }
393
394 //-------------------------------------------------------------------
395 // IAMBufferNegotiation interface
396 //
397 HRESULT
398 STDMETHODCALLTYPE
399 COutputPin::SuggestAllocatorProperties(
400 const ALLOCATOR_PROPERTIES *pprop)
401 {
402 #ifdef KSPROXY_TRACE
403 OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n");
404 #endif
405
406 if (m_Pin)
407 {
408 // pin is already connected
409 return VFW_E_ALREADY_CONNECTED;
410 }
411
412 CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES));
413 return NOERROR;
414 }
415
416 HRESULT
417 STDMETHODCALLTYPE
418 COutputPin::GetAllocatorProperties(
419 ALLOCATOR_PROPERTIES *pprop)
420 {
421 #ifdef KSPROXY_TRACE
422 OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n");
423 #endif
424
425 if (!m_Pin)
426 {
427 // you should call this method AFTER you connected
428 return E_UNEXPECTED;
429 }
430
431 if (!m_KsAllocatorEx)
432 {
433 // something went wrong while creating the allocator
434 return E_FAIL;
435 }
436
437 CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES));
438 return NOERROR;
439 }
440
441 //-------------------------------------------------------------------
442 // IAMStreamConfig interface
443 //
444 HRESULT
445 STDMETHODCALLTYPE
446 COutputPin::SetFormat(
447 AM_MEDIA_TYPE *pmt)
448 {
449 #ifdef KSPROXY_TRACE
450 OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n");
451 #endif
452 return E_NOTIMPL;
453 }
454
455 HRESULT
456 STDMETHODCALLTYPE
457 COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt)
458 {
459 #ifdef KSPROXY_TRACE
460 OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n");
461 #endif
462 return E_NOTIMPL;
463 }
464
465 HRESULT
466 STDMETHODCALLTYPE
467 COutputPin::GetNumberOfCapabilities(
468 int *piCount,
469 int *piSize)
470 {
471 #ifdef KSPROXY_TRACE
472 OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n");
473 #endif
474 return E_NOTIMPL;
475 }
476
477 HRESULT
478 STDMETHODCALLTYPE
479 COutputPin::GetStreamCaps(
480 int iIndex,
481 AM_MEDIA_TYPE **ppmt,
482 BYTE *pSCC)
483 {
484 #ifdef KSPROXY_TRACE
485 OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n");
486 #endif
487 return E_NOTIMPL;
488 }
489
490 //-------------------------------------------------------------------
491 // IMemAllocatorNotifyCallbackTemp interface
492 //
493 HRESULT
494 STDMETHODCALLTYPE
495 COutputPin::NotifyRelease()
496 {
497 #ifdef KSPROXY_TRACE
498 OutputDebugStringW(L"COutputPin::NotifyRelease\n");
499 #endif
500
501 // notify thread of new available sample
502 SetEvent(m_hBufferAvailable);
503
504 return NOERROR;
505 }
506
507 //-------------------------------------------------------------------
508 // IMediaSeeking interface
509 //
510 HRESULT
511 STDMETHODCALLTYPE
512 COutputPin::GetCapabilities(
513 DWORD *pCapabilities)
514 {
515 IMediaSeeking * FilterMediaSeeking;
516 HRESULT hr;
517
518 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
519 if (FAILED(hr))
520 return hr;
521
522 hr = FilterMediaSeeking->GetCapabilities(pCapabilities);
523
524 FilterMediaSeeking->Release();
525 return hr;
526 }
527
528 HRESULT
529 STDMETHODCALLTYPE
530 COutputPin::CheckCapabilities(
531 DWORD *pCapabilities)
532 {
533 IMediaSeeking * FilterMediaSeeking;
534 HRESULT hr;
535
536 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
537 if (FAILED(hr))
538 return hr;
539
540 hr = FilterMediaSeeking->CheckCapabilities(pCapabilities);
541
542 FilterMediaSeeking->Release();
543 return hr;
544 }
545
546 HRESULT
547 STDMETHODCALLTYPE
548 COutputPin::IsFormatSupported(
549 const GUID *pFormat)
550 {
551 IMediaSeeking * FilterMediaSeeking;
552 HRESULT hr;
553
554 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
555 if (FAILED(hr))
556 return hr;
557
558 hr = FilterMediaSeeking->IsFormatSupported(pFormat);
559
560 FilterMediaSeeking->Release();
561 return hr;
562 }
563
564 HRESULT
565 STDMETHODCALLTYPE
566 COutputPin::QueryPreferredFormat(
567 GUID *pFormat)
568 {
569 IMediaSeeking * FilterMediaSeeking;
570 HRESULT hr;
571
572 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
573 if (FAILED(hr))
574 return hr;
575
576 hr = FilterMediaSeeking->QueryPreferredFormat(pFormat);
577
578 FilterMediaSeeking->Release();
579 return hr;
580 }
581
582 HRESULT
583 STDMETHODCALLTYPE
584 COutputPin::GetTimeFormat(
585 GUID *pFormat)
586 {
587 IMediaSeeking * FilterMediaSeeking;
588 HRESULT hr;
589
590 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
591 if (FAILED(hr))
592 return hr;
593
594 hr = FilterMediaSeeking->GetTimeFormat(pFormat);
595
596 FilterMediaSeeking->Release();
597 return hr;
598 }
599
600 HRESULT
601 STDMETHODCALLTYPE
602 COutputPin::IsUsingTimeFormat(
603 const GUID *pFormat)
604 {
605 IMediaSeeking * FilterMediaSeeking;
606 HRESULT hr;
607
608 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
609 if (FAILED(hr))
610 return hr;
611
612 hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat);
613
614 FilterMediaSeeking->Release();
615 return hr;
616 }
617
618 HRESULT
619 STDMETHODCALLTYPE
620 COutputPin::SetTimeFormat(
621 const GUID *pFormat)
622 {
623 IMediaSeeking * FilterMediaSeeking;
624 HRESULT hr;
625
626 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
627 if (FAILED(hr))
628 return hr;
629
630 hr = FilterMediaSeeking->SetTimeFormat(pFormat);
631
632 FilterMediaSeeking->Release();
633 return hr;
634 }
635
636 HRESULT
637 STDMETHODCALLTYPE
638 COutputPin::GetDuration(
639 LONGLONG *pDuration)
640 {
641 IMediaSeeking * FilterMediaSeeking;
642 HRESULT hr;
643
644 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
645 if (FAILED(hr))
646 return hr;
647
648 hr = FilterMediaSeeking->GetDuration(pDuration);
649
650 FilterMediaSeeking->Release();
651 return hr;
652 }
653
654 HRESULT
655 STDMETHODCALLTYPE
656 COutputPin::GetStopPosition(
657 LONGLONG *pStop)
658 {
659 IMediaSeeking * FilterMediaSeeking;
660 HRESULT hr;
661
662 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
663 if (FAILED(hr))
664 return hr;
665
666 hr = FilterMediaSeeking->GetStopPosition(pStop);
667
668 FilterMediaSeeking->Release();
669 return hr;
670 }
671
672
673 HRESULT
674 STDMETHODCALLTYPE
675 COutputPin::GetCurrentPosition(
676 LONGLONG *pCurrent)
677 {
678 IMediaSeeking * FilterMediaSeeking;
679 HRESULT hr;
680
681 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
682 if (FAILED(hr))
683 return hr;
684
685 hr = FilterMediaSeeking->GetCurrentPosition(pCurrent);
686
687 FilterMediaSeeking->Release();
688 return hr;
689 }
690
691 HRESULT
692 STDMETHODCALLTYPE
693 COutputPin::ConvertTimeFormat(
694 LONGLONG *pTarget,
695 const GUID *pTargetFormat,
696 LONGLONG Source,
697 const GUID *pSourceFormat)
698 {
699 IMediaSeeking * FilterMediaSeeking;
700 HRESULT hr;
701
702 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
703 if (FAILED(hr))
704 return hr;
705
706 hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
707
708 FilterMediaSeeking->Release();
709 return hr;
710 }
711
712 HRESULT
713 STDMETHODCALLTYPE
714 COutputPin::SetPositions(
715 LONGLONG *pCurrent,
716 DWORD dwCurrentFlags,
717 LONGLONG *pStop,
718 DWORD dwStopFlags)
719 {
720 IMediaSeeking * FilterMediaSeeking;
721 HRESULT hr;
722
723 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
724 if (FAILED(hr))
725 return hr;
726
727 hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
728
729 FilterMediaSeeking->Release();
730 return hr;
731 }
732
733 HRESULT
734 STDMETHODCALLTYPE
735 COutputPin::GetPositions(
736 LONGLONG *pCurrent,
737 LONGLONG *pStop)
738 {
739 IMediaSeeking * FilterMediaSeeking;
740 HRESULT hr;
741
742 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
743 if (FAILED(hr))
744 return hr;
745
746 hr = FilterMediaSeeking->GetPositions(pCurrent, pStop);
747
748 FilterMediaSeeking->Release();
749 return hr;
750 }
751
752 HRESULT
753 STDMETHODCALLTYPE
754 COutputPin::GetAvailable(
755 LONGLONG *pEarliest,
756 LONGLONG *pLatest)
757 {
758 IMediaSeeking * FilterMediaSeeking;
759 HRESULT hr;
760
761 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
762 if (FAILED(hr))
763 return hr;
764
765 hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest);
766
767 FilterMediaSeeking->Release();
768 return hr;
769 }
770
771 HRESULT
772 STDMETHODCALLTYPE
773 COutputPin::SetRate(
774 double dRate)
775 {
776 IMediaSeeking * FilterMediaSeeking;
777 HRESULT hr;
778
779 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
780 if (FAILED(hr))
781 return hr;
782
783 hr = FilterMediaSeeking->SetRate(dRate);
784
785 FilterMediaSeeking->Release();
786 return hr;
787 }
788
789 HRESULT
790 STDMETHODCALLTYPE
791 COutputPin::GetRate(
792 double *pdRate)
793 {
794 IMediaSeeking * FilterMediaSeeking;
795 HRESULT hr;
796
797 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
798 if (FAILED(hr))
799 return hr;
800
801 hr = FilterMediaSeeking->GetRate(pdRate);
802
803 FilterMediaSeeking->Release();
804 return hr;
805 }
806
807 HRESULT
808 STDMETHODCALLTYPE
809 COutputPin::GetPreroll(
810 LONGLONG *pllPreroll)
811 {
812 IMediaSeeking * FilterMediaSeeking;
813 HRESULT hr;
814
815 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking);
816 if (FAILED(hr))
817 return hr;
818
819 hr = FilterMediaSeeking->GetPreroll(pllPreroll);
820
821 FilterMediaSeeking->Release();
822 return hr;
823 }
824
825 //-------------------------------------------------------------------
826 // IQualityControl interface
827 //
828 HRESULT
829 STDMETHODCALLTYPE
830 COutputPin::Notify(
831 IBaseFilter *pSelf,
832 Quality q)
833 {
834 #ifdef KSPROXY_TRACE
835 OutputDebugStringW(L"COutputPin::Notify NotImplemented\n");
836 #endif
837 return E_NOTIMPL;
838 }
839
840 HRESULT
841 STDMETHODCALLTYPE
842 COutputPin::SetSink(
843 IQualityControl *piqc)
844 {
845 #ifdef KSPROXY_TRACE
846 OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n");
847 #endif
848 return E_NOTIMPL;
849 }
850
851
852 //-------------------------------------------------------------------
853 // IKsAggregateControl interface
854 //
855 HRESULT
856 STDMETHODCALLTYPE
857 COutputPin::KsAddAggregate(
858 IN REFGUID AggregateClass)
859 {
860 #ifdef KSPROXY_TRACE
861 OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n");
862 #endif
863 return E_NOTIMPL;
864 }
865
866 HRESULT
867 STDMETHODCALLTYPE
868 COutputPin::KsRemoveAggregate(
869 REFGUID AggregateClass)
870 {
871 #ifdef KSPROXY_TRACE
872 OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n");
873 #endif
874 return E_NOTIMPL;
875 }
876
877
878 //-------------------------------------------------------------------
879 // IKsPin
880 //
881
882 HRESULT
883 STDMETHODCALLTYPE
884 COutputPin::KsQueryMediums(
885 PKSMULTIPLE_ITEM* MediumList)
886 {
887 HRESULT hr;
888 HANDLE hFilter;
889 IKsObject * KsObjectParent;
890
891 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
892 if (FAILED(hr))
893 return E_NOINTERFACE;
894
895 hFilter = KsObjectParent->KsGetObjectHandle();
896
897 if (hFilter)
898 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
899 else
900 hr = E_HANDLE;
901
902 KsObjectParent->Release();
903
904 return hr;
905 }
906
907 HRESULT
908 STDMETHODCALLTYPE
909 COutputPin::KsQueryInterfaces(
910 PKSMULTIPLE_ITEM* InterfaceList)
911 {
912 HRESULT hr;
913 HANDLE hFilter;
914 IKsObject * KsObjectParent;
915
916 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
917 if (FAILED(hr))
918 return hr;
919
920 hFilter = KsObjectParent->KsGetObjectHandle();
921
922 if (hFilter)
923 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
924 else
925 hr = E_HANDLE;
926
927 KsObjectParent->Release();
928
929 return hr;
930 }
931
932 HRESULT
933 STDMETHODCALLTYPE
934 COutputPin::KsCreateSinkPinHandle(
935 KSPIN_INTERFACE& Interface,
936 KSPIN_MEDIUM& Medium)
937 {
938 #ifdef KSPROXY_TRACE
939 OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n");
940 #endif
941 return E_NOTIMPL;
942 }
943
944 HRESULT
945 STDMETHODCALLTYPE
946 COutputPin::KsGetCurrentCommunication(
947 KSPIN_COMMUNICATION *Communication,
948 KSPIN_INTERFACE *Interface,
949 KSPIN_MEDIUM *Medium)
950 {
951 if (Communication)
952 {
953 *Communication = m_Communication;
954 }
955
956 if (Interface)
957 {
958 if (!m_hPin)
959 return VFW_E_NOT_CONNECTED;
960
961 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
962 }
963
964 if (Medium)
965 {
966 if (!m_hPin)
967 return VFW_E_NOT_CONNECTED;
968
969 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
970 }
971 return NOERROR;
972 }
973
974 HRESULT
975 STDMETHODCALLTYPE
976 COutputPin::KsPropagateAcquire()
977 {
978 KSPROPERTY Property;
979 KSSTATE State;
980 ULONG BytesReturned;
981 HRESULT hr;
982
983 #ifdef KSPROXY_TRACE
984 OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n");
985 #endif
986
987 assert(m_hPin != INVALID_HANDLE_VALUE);
988
989 Property.Set = KSPROPSETID_Connection;
990 Property.Id = KSPROPERTY_CONNECTION_STATE;
991 Property.Flags = KSPROPERTY_TYPE_SET;
992
993 State = KSSTATE_ACQUIRE;
994
995 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
996 if (SUCCEEDED(hr))
997 {
998 m_State = State;
999 }
1000
1001 //TODO
1002 //propagate to connected pin on the pipe
1003
1004 return hr;
1005 }
1006
1007 HRESULT
1008 STDMETHODCALLTYPE
1009 COutputPin::KsDeliver(
1010 IMediaSample* Sample,
1011 ULONG Flags)
1012 {
1013 return E_FAIL;
1014 }
1015
1016 HRESULT
1017 STDMETHODCALLTYPE
1018 COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
1019 {
1020 return NOERROR;
1021 }
1022
1023 IMemAllocator *
1024 STDMETHODCALLTYPE
1025 COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
1026 {
1027 if (Operation == KsPeekOperation_AddRef)
1028 {
1029 // add reference on allocator
1030 m_MemAllocator->AddRef();
1031 }
1032
1033 return m_MemAllocator;
1034 }
1035
1036 HRESULT
1037 STDMETHODCALLTYPE
1038 COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
1039 {
1040 if (MemAllocator)
1041 {
1042 MemAllocator->AddRef();
1043 }
1044
1045 if (m_MemAllocator)
1046 {
1047 m_MemAllocator->Release();
1048 }
1049
1050 m_MemAllocator = MemAllocator;
1051 return NOERROR;
1052 }
1053
1054 HRESULT
1055 STDMETHODCALLTYPE
1056 COutputPin::KsRenegotiateAllocator()
1057 {
1058 return E_FAIL;
1059 }
1060
1061 LONG
1062 STDMETHODCALLTYPE
1063 COutputPin::KsIncrementPendingIoCount()
1064 {
1065 return InterlockedIncrement((volatile LONG*)&m_IoCount);
1066 }
1067
1068 LONG
1069 STDMETHODCALLTYPE
1070 COutputPin::KsDecrementPendingIoCount()
1071 {
1072 return InterlockedDecrement((volatile LONG*)&m_IoCount);
1073 }
1074
1075 HRESULT
1076 STDMETHODCALLTYPE
1077 COutputPin::KsQualityNotify(
1078 ULONG Proportion,
1079 REFERENCE_TIME TimeDelta)
1080 {
1081 #ifdef KSPROXY_TRACE
1082 OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n");
1083 #endif
1084 return E_NOTIMPL;
1085 }
1086
1087 //-------------------------------------------------------------------
1088 // IKsPinEx
1089 //
1090
1091 VOID
1092 STDMETHODCALLTYPE
1093 COutputPin::KsNotifyError(
1094 IMediaSample* Sample,
1095 HRESULT hr)
1096 {
1097 #ifdef KSPROXY_TRACE
1098 OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n");
1099 #endif
1100 }
1101
1102
1103 //-------------------------------------------------------------------
1104 // IKsPinPipe
1105 //
1106
1107 HRESULT
1108 STDMETHODCALLTYPE
1109 COutputPin::KsGetPinFramingCache(
1110 PKSALLOCATOR_FRAMING_EX *FramingEx,
1111 PFRAMING_PROP FramingProp,
1112 FRAMING_CACHE_OPS Option)
1113 {
1114 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
1115 {
1116 // invalid argument
1117 return E_INVALIDARG;
1118 }
1119
1120 // get framing properties
1121 *FramingProp = m_FramingProp[Option];
1122 *FramingEx = m_FramingEx[Option];
1123
1124 return NOERROR;
1125 }
1126
1127 HRESULT
1128 STDMETHODCALLTYPE
1129 COutputPin::KsSetPinFramingCache(
1130 PKSALLOCATOR_FRAMING_EX FramingEx,
1131 PFRAMING_PROP FramingProp,
1132 FRAMING_CACHE_OPS Option)
1133 {
1134 ULONG Index;
1135 ULONG RefCount = 0;
1136
1137 if (m_FramingEx[Option])
1138 {
1139 for(Index = 1; Index < 4; Index++)
1140 {
1141 if (m_FramingEx[Index] == m_FramingEx[Option])
1142 RefCount++;
1143 }
1144
1145 if (RefCount == 1)
1146 {
1147 // existing framing is only used once
1148 CoTaskMemFree(m_FramingEx[Option]);
1149 }
1150 }
1151
1152 // store framing
1153 m_FramingEx[Option] = FramingEx;
1154 m_FramingProp[Option] = *FramingProp;
1155
1156 return S_OK;
1157 }
1158
1159 IPin*
1160 STDMETHODCALLTYPE
1161 COutputPin::KsGetConnectedPin()
1162 {
1163 return m_Pin;
1164 }
1165
1166 IKsAllocatorEx*
1167 STDMETHODCALLTYPE
1168 COutputPin::KsGetPipe(
1169 KSPEEKOPERATION Operation)
1170 {
1171 if (Operation == KsPeekOperation_AddRef)
1172 {
1173 if (m_KsAllocatorEx)
1174 m_KsAllocatorEx->AddRef();
1175 }
1176 return m_KsAllocatorEx;
1177 }
1178
1179 HRESULT
1180 STDMETHODCALLTYPE
1181 COutputPin::KsSetPipe(
1182 IKsAllocatorEx *KsAllocator)
1183 {
1184 if (KsAllocator)
1185 KsAllocator->AddRef();
1186
1187 if (m_KsAllocatorEx)
1188 m_KsAllocatorEx->Release();
1189
1190 m_KsAllocatorEx = KsAllocator;
1191 return NOERROR;
1192 }
1193
1194 ULONG
1195 STDMETHODCALLTYPE
1196 COutputPin::KsGetPipeAllocatorFlag()
1197 {
1198 return m_PipeAllocatorFlag;
1199 }
1200
1201
1202 HRESULT
1203 STDMETHODCALLTYPE
1204 COutputPin::KsSetPipeAllocatorFlag(
1205 ULONG Flag)
1206 {
1207 m_PipeAllocatorFlag = Flag;
1208 return NOERROR;
1209 }
1210
1211 GUID
1212 STDMETHODCALLTYPE
1213 COutputPin::KsGetPinBusCache()
1214 {
1215 if (!m_bPinBusCacheInitialized)
1216 {
1217 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
1218 m_bPinBusCacheInitialized = TRUE;
1219 }
1220
1221 return m_PinBusCache;
1222 }
1223
1224 HRESULT
1225 STDMETHODCALLTYPE
1226 COutputPin::KsSetPinBusCache(
1227 GUID Bus)
1228 {
1229 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
1230 return NOERROR;
1231 }
1232
1233 PWCHAR
1234 STDMETHODCALLTYPE
1235 COutputPin::KsGetPinName()
1236 {
1237 return (PWCHAR)m_PinName;
1238 }
1239
1240
1241 PWCHAR
1242 STDMETHODCALLTYPE
1243 COutputPin::KsGetFilterName()
1244 {
1245 return m_FilterName;
1246 }
1247
1248 //-------------------------------------------------------------------
1249 // ISpecifyPropertyPages
1250 //
1251
1252 HRESULT
1253 STDMETHODCALLTYPE
1254 COutputPin::GetPages(CAUUID *pPages)
1255 {
1256 #ifdef KSPROXY_TRACE
1257 OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
1258 #endif
1259
1260 if (!pPages)
1261 return E_POINTER;
1262
1263 pPages->cElems = 0;
1264 pPages->pElems = NULL;
1265
1266 return S_OK;
1267 }
1268
1269 //-------------------------------------------------------------------
1270 // IKsPinFactory
1271 //
1272
1273 HRESULT
1274 STDMETHODCALLTYPE
1275 COutputPin::KsPinFactory(
1276 ULONG* PinFactory)
1277 {
1278 #ifdef KSPROXY_TRACE
1279 OutputDebugStringW(L"COutputPin::KsPinFactory\n");
1280 #endif
1281
1282 *PinFactory = m_PinId;
1283 return S_OK;
1284 }
1285
1286
1287 //-------------------------------------------------------------------
1288 // IStreamBuilder
1289 //
1290
1291 HRESULT
1292 STDMETHODCALLTYPE
1293 COutputPin::Render(
1294 IPin *ppinOut,
1295 IGraphBuilder *pGraph)
1296 {
1297 #ifdef KSPROXY_TRACE
1298 OutputDebugStringW(L"COutputPin::Render\n");
1299 #endif
1300 return S_OK;
1301 }
1302
1303 HRESULT
1304 STDMETHODCALLTYPE
1305 COutputPin::Backout(
1306 IPin *ppinOut,
1307 IGraphBuilder *pGraph)
1308 {
1309 #ifdef KSPROXY_TRACE
1310 OutputDebugStringW(L"COutputPin::Backout\n");
1311 #endif
1312
1313 return S_OK;
1314 }
1315 //-------------------------------------------------------------------
1316 // IKsObject
1317 //
1318 HANDLE
1319 STDMETHODCALLTYPE
1320 COutputPin::KsGetObjectHandle()
1321 {
1322 #ifdef KSPROXY_TRACE
1323 OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");
1324 #endif
1325
1326 assert(m_hPin != INVALID_HANDLE_VALUE);
1327 return m_hPin;
1328 }
1329
1330 //-------------------------------------------------------------------
1331 // IKsControl
1332 //
1333 HRESULT
1334 STDMETHODCALLTYPE
1335 COutputPin::KsProperty(
1336 PKSPROPERTY Property,
1337 ULONG PropertyLength,
1338 LPVOID PropertyData,
1339 ULONG DataLength,
1340 ULONG* BytesReturned)
1341 {
1342 HRESULT hr;
1343
1344 assert(m_hPin != INVALID_HANDLE_VALUE);
1345
1346 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
1347 #ifdef KSPROXY_TRACE
1348 WCHAR Buffer[100];
1349 LPOLESTR pstr;
1350 StringFromCLSID(Property->Set, &pstr);
1351 swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr);
1352 OutputDebugStringW(Buffer);
1353 #endif
1354
1355 return hr;
1356 }
1357
1358 HRESULT
1359 STDMETHODCALLTYPE
1360 COutputPin::KsMethod(
1361 PKSMETHOD Method,
1362 ULONG MethodLength,
1363 LPVOID MethodData,
1364 ULONG DataLength,
1365 ULONG* BytesReturned)
1366 {
1367 assert(m_hPin != INVALID_HANDLE_VALUE);
1368 #ifdef KSPROXY_TRACE
1369 OutputDebugStringW(L"COutputPin::KsMethod\n");
1370 #endif
1371 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
1372 }
1373
1374 HRESULT
1375 STDMETHODCALLTYPE
1376 COutputPin::KsEvent(
1377 PKSEVENT Event,
1378 ULONG EventLength,
1379 LPVOID EventData,
1380 ULONG DataLength,
1381 ULONG* BytesReturned)
1382 {
1383 assert(m_hPin != INVALID_HANDLE_VALUE);
1384
1385 #ifdef KSPROXY_TRACE
1386 OutputDebugStringW(L"COutputPin::KsEvent\n");
1387 #endif
1388
1389 if (EventLength)
1390 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
1391 else
1392 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
1393 }
1394
1395
1396 //-------------------------------------------------------------------
1397 // IKsPropertySet
1398 //
1399 HRESULT
1400 STDMETHODCALLTYPE
1401 COutputPin::Set(
1402 REFGUID guidPropSet,
1403 DWORD dwPropID,
1404 LPVOID pInstanceData,
1405 DWORD cbInstanceData,
1406 LPVOID pPropData,
1407 DWORD cbPropData)
1408 {
1409 ULONG BytesReturned;
1410
1411 if (cbInstanceData)
1412 {
1413 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1414 if (!Property)
1415 return E_OUTOFMEMORY;
1416
1417 Property->Set = guidPropSet;
1418 Property->Id = dwPropID;
1419 Property->Flags = KSPROPERTY_TYPE_SET;
1420
1421 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1422
1423 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1424 CoTaskMemFree(Property);
1425 return hr;
1426 }
1427 else
1428 {
1429 KSPROPERTY Property;
1430
1431 Property.Set = guidPropSet;
1432 Property.Id = dwPropID;
1433 Property.Flags = KSPROPERTY_TYPE_SET;
1434
1435 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1436 return hr;
1437 }
1438 }
1439
1440 HRESULT
1441 STDMETHODCALLTYPE
1442 COutputPin::Get(
1443 REFGUID guidPropSet,
1444 DWORD dwPropID,
1445 LPVOID pInstanceData,
1446 DWORD cbInstanceData,
1447 LPVOID pPropData,
1448 DWORD cbPropData,
1449 DWORD *pcbReturned)
1450 {
1451 ULONG BytesReturned;
1452
1453 if (cbInstanceData)
1454 {
1455 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1456 if (!Property)
1457 return E_OUTOFMEMORY;
1458
1459 Property->Set = guidPropSet;
1460 Property->Id = dwPropID;
1461 Property->Flags = KSPROPERTY_TYPE_GET;
1462
1463 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1464
1465 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1466 CoTaskMemFree(Property);
1467 return hr;
1468 }
1469 else
1470 {
1471 KSPROPERTY Property;
1472
1473 Property.Set = guidPropSet;
1474 Property.Id = dwPropID;
1475 Property.Flags = KSPROPERTY_TYPE_GET;
1476
1477 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1478 return hr;
1479 }
1480 }
1481
1482 HRESULT
1483 STDMETHODCALLTYPE
1484 COutputPin::QuerySupported(
1485 REFGUID guidPropSet,
1486 DWORD dwPropID,
1487 DWORD *pTypeSupport)
1488 {
1489 KSPROPERTY Property;
1490 ULONG BytesReturned;
1491
1492 #ifdef KSPROXY_TRACE
1493 OutputDebugStringW(L"COutputPin::QuerySupported\n");
1494 #endif
1495
1496 Property.Set = guidPropSet;
1497 Property.Id = dwPropID;
1498 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1499
1500 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1501 }
1502
1503
1504 //-------------------------------------------------------------------
1505 // IPin interface
1506 //
1507 HRESULT
1508 STDMETHODCALLTYPE
1509 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1510 {
1511 HRESULT hr;
1512 ALLOCATOR_PROPERTIES Properties;
1513 IMemAllocatorCallbackTemp *pMemCallback;
1514
1515 #ifdef KSPROXY_TRACE
1516 WCHAR Buffer[200];
1517 OutputDebugStringW(L"COutputPin::Connect called\n");
1518 #endif
1519
1520 if (pmt)
1521 {
1522 hr = pReceivePin->QueryAccept(pmt);
1523 if (FAILED(hr))
1524 return hr;
1525 }
1526 else
1527 {
1528 // query accept
1529 hr = pReceivePin->QueryAccept(&m_MediaFormat);
1530 if (FAILED(hr))
1531 return hr;
1532
1533 pmt = &m_MediaFormat;
1534 }
1535
1536 // query for IMemInput interface
1537 hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin);
1538 if (FAILED(hr))
1539 {
1540 #ifdef KSPROXY_TRACE
1541 OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");
1542 #endif
1543
1544 DebugBreak();
1545 return hr;
1546 }
1547
1548 // get input pin allocator properties
1549 ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES));
1550 m_MemInputPin->GetAllocatorRequirements(&Properties);
1551
1552 //FIXME determine allocator properties
1553 Properties.cBuffers = 32;
1554 Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size
1555 Properties.cbAlign = 4;
1556
1557 // get input pin allocator
1558 #if 0
1559 hr = m_MemInputPin->GetAllocator(&m_MemAllocator);
1560 if (SUCCEEDED(hr))
1561 {
1562 // set allocator properties
1563 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties);
1564 if (FAILED(hr))
1565 m_MemAllocator->Release();
1566 }
1567 #endif
1568
1569 if (1)
1570 {
1571 hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator);
1572 if (FAILED(hr))
1573 return hr;
1574
1575 // set allocator properties
1576 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties);
1577 if (FAILED(hr))
1578 {
1579 #ifdef KSPROXY_TRACE
1580 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr);
1581 OutputDebugStringW(Buffer);
1582 #endif
1583 m_MemAllocator->Release();
1584 m_MemInputPin->Release();
1585 return hr;
1586 }
1587 }
1588
1589 // commit property changes
1590 hr = m_MemAllocator->Commit();
1591 if (FAILED(hr))
1592 {
1593 #ifdef KSPROXY_TRACE
1594 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr);
1595 OutputDebugStringW(Buffer);
1596 #endif
1597 m_MemAllocator->Release();
1598 m_MemInputPin->Release();
1599 return hr;
1600 }
1601
1602 // get callback interface
1603 hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback);
1604 if (FAILED(hr))
1605 {
1606 #ifdef KSPROXY_TRACE
1607 swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr);
1608 OutputDebugStringW(Buffer);
1609 #endif
1610 m_MemAllocator->Release();
1611 m_MemInputPin->Release();
1612 return hr;
1613 }
1614
1615 // set notification routine
1616 hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this);
1617
1618 // release IMemAllocatorNotifyCallbackTemp interface
1619 pMemCallback->Release();
1620
1621 if (FAILED(hr))
1622 {
1623 #ifdef KSPROXY_TRACE
1624 swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr);
1625 OutputDebugStringW(Buffer);
1626 #endif
1627 m_MemAllocator->Release();
1628 m_MemInputPin->Release();
1629 return hr;
1630 }
1631
1632 // now set allocator
1633 hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE);
1634 if (FAILED(hr))
1635 {
1636 #ifdef KSPROXY_TRACE
1637 swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr);
1638 OutputDebugStringW(Buffer);
1639 #endif
1640 m_MemAllocator->Release();
1641 m_MemInputPin->Release();
1642 return hr;
1643 }
1644
1645 if (!m_hPin)
1646 {
1647 //FIXME create pin handle
1648 assert(0);
1649 }
1650
1651 // receive connection;
1652 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
1653 if (SUCCEEDED(hr))
1654 {
1655 // increment reference count
1656 pReceivePin->AddRef();
1657 m_Pin = pReceivePin;
1658 #ifdef KSPROXY_TRACE
1659 OutputDebugStringW(L"COutputPin::Connect success\n");
1660 #endif
1661 }
1662 else
1663 {
1664 m_MemInputPin->Release();
1665 m_MemAllocator->Release();
1666 }
1667
1668 return hr;
1669 }
1670
1671 HRESULT
1672 STDMETHODCALLTYPE
1673 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1674 {
1675 return E_UNEXPECTED;
1676 }
1677 HRESULT
1678 STDMETHODCALLTYPE
1679 COutputPin::Disconnect( void)
1680 {
1681 #ifdef KSPROXY_TRACE
1682 OutputDebugStringW(L"COutputPin::Disconnect\n");
1683 #endif
1684
1685 if (!m_Pin)
1686 {
1687 // pin was not connected
1688 return S_FALSE;
1689 }
1690
1691 //FIXME
1692 //check if filter is active
1693
1694 m_Pin->Release();
1695 m_Pin = NULL;
1696 m_MemInputPin->Release();
1697 m_MemAllocator->Release();
1698
1699 CloseHandle(m_hPin);
1700 m_hPin = INVALID_HANDLE_VALUE;
1701
1702 #ifdef KSPROXY_TRACE
1703 OutputDebugStringW(L"COutputPin::Disconnect\n");
1704 #endif
1705 return S_OK;
1706 }
1707 HRESULT
1708 STDMETHODCALLTYPE
1709 COutputPin::ConnectedTo(IPin **pPin)
1710 {
1711 #ifdef KSPROXY_TRACE
1712 OutputDebugStringW(L"COutputPin::ConnectedTo\n");
1713 #endif
1714
1715 if (!pPin)
1716 return E_POINTER;
1717
1718 if (m_Pin)
1719 {
1720 // increment reference count
1721 m_Pin->AddRef();
1722 *pPin = m_Pin;
1723 return S_OK;
1724 }
1725
1726 *pPin = NULL;
1727 return VFW_E_NOT_CONNECTED;
1728 }
1729 HRESULT
1730 STDMETHODCALLTYPE
1731 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1732 {
1733 #ifdef KSPROXY_TRACE
1734 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");
1735 #endif
1736
1737 return E_NOTIMPL;
1738 }
1739 HRESULT
1740 STDMETHODCALLTYPE
1741 COutputPin::QueryPinInfo(PIN_INFO *pInfo)
1742 {
1743 wcscpy(pInfo->achName, m_PinName);
1744 pInfo->dir = PINDIR_OUTPUT;
1745 pInfo->pFilter = m_ParentFilter;
1746 m_ParentFilter->AddRef();
1747
1748 return S_OK;
1749 }
1750 HRESULT
1751 STDMETHODCALLTYPE
1752 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1753 {
1754 if (pPinDir)
1755 {
1756 *pPinDir = PINDIR_OUTPUT;
1757 return S_OK;
1758 }
1759
1760 return E_POINTER;
1761 }
1762 HRESULT
1763 STDMETHODCALLTYPE
1764 COutputPin::QueryId(LPWSTR *Id)
1765 {
1766 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1767 if (!*Id)
1768 return E_OUTOFMEMORY;
1769
1770 wcscpy(*Id, m_PinName);
1771 return S_OK;
1772 }
1773 HRESULT
1774 STDMETHODCALLTYPE
1775 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
1776 {
1777 #ifdef KSPROXY_TRACE
1778 OutputDebugStringW(L"COutputPin::QueryAccept called\n");
1779 #endif
1780
1781 return E_NOTIMPL;
1782 }
1783 HRESULT
1784 STDMETHODCALLTYPE
1785 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1786 {
1787 HRESULT hr;
1788 ULONG MediaTypeCount = 0, Index;
1789 AM_MEDIA_TYPE * MediaTypes;
1790 HANDLE hFilter;
1791 IKsObject * KsObjectParent;
1792
1793 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1794 if (FAILED(hr))
1795 return hr;
1796
1797 // get parent filter handle
1798 hFilter = KsObjectParent->KsGetObjectHandle();
1799
1800 // release IKsObject
1801 KsObjectParent->Release();
1802
1803 // query media type count
1804 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1805 if (FAILED(hr) || !MediaTypeCount)
1806 {
1807 return hr;
1808 }
1809
1810 // allocate media types
1811 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1812 if (!MediaTypes)
1813 {
1814 // not enough memory
1815 return E_OUTOFMEMORY;
1816 }
1817
1818 // zero media types
1819 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1820
1821 for(Index = 0; Index < MediaTypeCount; Index++)
1822 {
1823 // get media type
1824 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1825 if (FAILED(hr))
1826 {
1827 // failed
1828 CoTaskMemFree(MediaTypes);
1829 return hr;
1830 }
1831 }
1832
1833 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1834 }
1835 HRESULT
1836 STDMETHODCALLTYPE
1837 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1838 {
1839 return E_NOTIMPL;
1840 }
1841 HRESULT
1842 STDMETHODCALLTYPE
1843 COutputPin::EndOfStream( void)
1844 {
1845 /* should be called only on input pins */
1846 return E_UNEXPECTED;
1847 }
1848 HRESULT
1849 STDMETHODCALLTYPE
1850 COutputPin::BeginFlush( void)
1851 {
1852 /* should be called only on input pins */
1853 return E_UNEXPECTED;
1854 }
1855 HRESULT
1856 STDMETHODCALLTYPE
1857 COutputPin::EndFlush( void)
1858 {
1859 /* should be called only on input pins */
1860 return E_UNEXPECTED;
1861 }
1862 HRESULT
1863 STDMETHODCALLTYPE
1864 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1865 {
1866 if (!m_Pin)
1867 {
1868 // we are not connected
1869 return VFW_E_NOT_CONNECTED;
1870 }
1871
1872 return m_Pin->NewSegment(tStart, tStop, dRate);
1873 }
1874
1875 //-------------------------------------------------------------------
1876 HRESULT
1877 STDMETHODCALLTYPE
1878 COutputPin::CheckFormat(
1879 const AM_MEDIA_TYPE *pmt)
1880 {
1881 PKSMULTIPLE_ITEM MultipleItem;
1882 PKSDATAFORMAT DataFormat;
1883 HRESULT hr;
1884 IKsObject * KsObjectParent;
1885 HANDLE hFilter;
1886
1887 if (!pmt)
1888 return E_POINTER;
1889
1890 // get IKsObject interface
1891 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1892 if (FAILED(hr))
1893 return hr;
1894
1895 // get parent filter handle
1896 hFilter = KsObjectParent->KsGetObjectHandle();
1897
1898 // release IKsObject
1899 KsObjectParent->Release();
1900
1901 if (!hFilter)
1902 return E_HANDLE;
1903
1904
1905 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1906 if (FAILED(hr))
1907 return S_FALSE;
1908
1909 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1910 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1911 {
1912 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1913 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1914 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1915 {
1916 // format is supported
1917 CoTaskMemFree(MultipleItem);
1918 return S_OK;
1919 }
1920 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1921 }
1922 //format is not supported
1923 CoTaskMemFree(MultipleItem);
1924 return S_FALSE;
1925 }
1926
1927 HRESULT
1928 STDMETHODCALLTYPE
1929 COutputPin::CreatePin(
1930 const AM_MEDIA_TYPE *pmt)
1931 {
1932 PKSMULTIPLE_ITEM MediumList;
1933 PKSMULTIPLE_ITEM InterfaceList;
1934 PKSPIN_MEDIUM Medium;
1935 PKSPIN_INTERFACE Interface;
1936 IKsInterfaceHandler * InterfaceHandler;
1937 HRESULT hr;
1938
1939 // query for pin medium
1940 hr = KsQueryMediums(&MediumList);
1941 if (FAILED(hr))
1942 return hr;
1943
1944 // query for pin interface
1945 hr = KsQueryInterfaces(&InterfaceList);
1946 if (FAILED(hr))
1947 {
1948 // failed
1949 CoTaskMemFree(MediumList);
1950 return hr;
1951 }
1952
1953 if (MediumList->Count)
1954 {
1955 //use first available medium
1956 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1957 }
1958 else
1959 {
1960 // default to standard medium
1961 Medium = &StandardPinMedium;
1962 }
1963
1964 if (InterfaceList->Count)
1965 {
1966 //use first available interface
1967 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1968 }
1969 else
1970 {
1971 // default to standard interface
1972 Interface = &StandardPinInterface;
1973 }
1974
1975 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1976 {
1977 // now create pin
1978 hr = CreatePinHandle(Medium, Interface, pmt);
1979 if (FAILED(hr))
1980 {
1981 m_InterfaceHandler->Release();
1982 m_InterfaceHandler = InterfaceHandler;
1983 }
1984
1985 if (!m_InterfaceHandler)
1986 {
1987 // now load the IKsInterfaceHandler plugin
1988 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1989 if (FAILED(hr))
1990 {
1991 // failed to load interface handler plugin
1992 CoTaskMemFree(MediumList);
1993 CoTaskMemFree(InterfaceList);
1994
1995 return hr;
1996 }
1997
1998 // now set the pin
1999 hr = InterfaceHandler->KsSetPin((IKsPin*)this);
2000 if (FAILED(hr))
2001 {
2002 // failed to load interface handler plugin
2003 InterfaceHandler->Release();
2004 CoTaskMemFree(MediumList);
2005 CoTaskMemFree(InterfaceList);
2006 return hr;
2007 }
2008
2009 // store interface handler
2010 m_InterfaceHandler = InterfaceHandler;
2011 }
2012 }
2013 else
2014 {
2015 #ifdef KSPROXY_TRACE
2016 WCHAR Buffer[100];
2017 swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
2018 OutputDebugStringW(Buffer);
2019 DebugBreak();
2020 #endif
2021
2022 hr = E_FAIL;
2023 }
2024
2025 // free medium / interface / dataformat
2026 CoTaskMemFree(MediumList);
2027 CoTaskMemFree(InterfaceList);
2028
2029 return hr;
2030 }
2031
2032 HRESULT
2033 STDMETHODCALLTYPE
2034 COutputPin::CreatePinHandle(
2035 PKSPIN_MEDIUM Medium,
2036 PKSPIN_INTERFACE Interface,
2037 const AM_MEDIA_TYPE *pmt)
2038 {
2039 PKSPIN_CONNECT PinConnect;
2040 PKSDATAFORMAT DataFormat;
2041 ULONG Length;
2042 HRESULT hr;
2043 HANDLE hFilter;
2044 IKsObject * KsObjectParent;
2045
2046 //KSALLOCATOR_FRAMING Framing;
2047 //KSPROPERTY Property;
2048 //ULONG BytesReturned;
2049
2050 if (m_hPin != INVALID_HANDLE_VALUE)
2051 {
2052 // pin already exists
2053 //CloseHandle(m_hPin);
2054 //m_hPin = INVALID_HANDLE_VALUE;
2055 return S_OK;
2056 }
2057
2058
2059 // calc format size
2060 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
2061
2062 // allocate pin connect
2063 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
2064 if (!PinConnect)
2065 {
2066 // failed
2067 return E_OUTOFMEMORY;
2068 }
2069
2070 // setup request
2071 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
2072 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
2073 PinConnect->PinId = m_PinId;
2074 PinConnect->PinToHandle = NULL;
2075 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
2076 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
2077
2078 // get dataformat offset
2079 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
2080
2081 // copy data format
2082 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
2083 DataFormat->Flags = 0;
2084 DataFormat->SampleSize = pmt->lSampleSize;
2085 DataFormat->Reserved = 0;
2086 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
2087 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
2088 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
2089
2090 if (pmt->cbFormat)
2091 {
2092 // copy extended format
2093 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
2094 }
2095
2096 // get IKsObject interface
2097 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
2098 if (FAILED(hr))
2099 return hr;
2100
2101 // get parent filter handle
2102 hFilter = KsObjectParent->KsGetObjectHandle();
2103
2104 // release IKsObject
2105 KsObjectParent->Release();
2106
2107 if (!hFilter)
2108 return E_HANDLE;
2109
2110 // create pin
2111 hr = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
2112
2113 if (SUCCEEDED(hr))
2114 {
2115 // store current interface / medium
2116 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
2117 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
2118 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
2119
2120 #ifdef KSPROXY_TRACE
2121 LPOLESTR pMajor, pSub, pFormat;
2122 StringFromIID(m_MediaFormat.majortype, &pMajor);
2123 StringFromIID(m_MediaFormat.subtype , &pSub);
2124 StringFromIID(m_MediaFormat.formattype, &pFormat);
2125 WCHAR Buffer[200];
2126 swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
2127 CoTaskMemFree(pMajor);
2128 CoTaskMemFree(pSub);
2129 CoTaskMemFree(pFormat);
2130 OutputDebugStringW(Buffer);
2131 #endif
2132
2133 if (pmt->cbFormat)
2134 {
2135 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
2136 if (!m_MediaFormat.pbFormat)
2137 {
2138 CoTaskMemFree(PinConnect);
2139 m_MediaFormat.pbFormat = NULL;
2140 m_MediaFormat.cbFormat = 0;
2141 return E_OUTOFMEMORY;
2142 }
2143 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
2144 }
2145 #if 0
2146 Property.Set = KSPROPSETID_Connection;
2147 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
2148 Property.Flags = KSPROPERTY_TYPE_GET;
2149
2150 ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING));
2151 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
2152 if (SUCCEEDED(hr))
2153 {
2154 m_Properties.cbAlign = (Framing.FileAlignment + 1);
2155 m_Properties.cbBuffer = Framing.FrameSize;
2156 m_Properties.cbPrefix = 0; //FIXME
2157 m_Properties.cBuffers = Framing.Frames;
2158 }
2159 hr = S_OK;
2160 #endif
2161
2162 if (FAILED(InitializeIOThread()))
2163 {
2164 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
2165 DebugBreak();
2166 }
2167
2168 //TODO
2169 // connect pin pipes
2170
2171 }
2172 // free pin connect
2173 CoTaskMemFree(PinConnect);
2174
2175 return hr;
2176 }
2177
2178 HRESULT
2179 WINAPI
2180 COutputPin::IoProcessRoutine()
2181 {
2182 IMediaSample *Sample;
2183 LONG SampleCount;
2184 HRESULT hr;
2185 PKSSTREAM_SEGMENT StreamSegment;
2186 HANDLE hEvent;
2187 IMediaSample * Samples[1];
2188
2189 #ifdef KSPROXY_TRACE
2190 WCHAR Buffer[200];
2191 #endif
2192
2193 // first wait for the start event to signal
2194 WaitForSingleObject(m_hStartEvent, INFINITE);
2195
2196 assert(m_InterfaceHandler);
2197 do
2198 {
2199 if (m_StopInProgress)
2200 {
2201 // stop io thread
2202 break;
2203 }
2204
2205 assert(m_State == KSSTATE_RUN);
2206 assert(m_MemAllocator);
2207
2208 // get buffer
2209 hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT);
2210
2211 if (FAILED(hr))
2212 {
2213 WaitForSingleObject(m_hBufferAvailable, INFINITE);
2214 // now retry again
2215 continue;
2216 }
2217
2218 // fill buffer
2219 SampleCount = 1;
2220 Samples[0] = Sample;
2221
2222 Sample->SetTime(NULL, NULL);
2223 hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
2224 Samples,
2225 &SampleCount,
2226 KsIoOperation_Read,
2227 &StreamSegment);
2228 if (FAILED(hr) || !StreamSegment)
2229 {
2230 #ifdef KSPROXY_TRACE
2231 swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr);
2232 OutputDebugStringW(Buffer);
2233 #endif
2234 break;
2235 }
2236
2237 // get completion event
2238 hEvent = StreamSegment->CompletionEvent;
2239
2240 // wait for i/o completion
2241 WaitForSingleObject(hEvent, INFINITE);
2242
2243 // perform completion
2244 m_InterfaceHandler->KsCompleteIo(StreamSegment);
2245
2246 // close completion event
2247 CloseHandle(hEvent);
2248
2249 if (SUCCEEDED(hr))
2250 {
2251 assert(m_MemInputPin);
2252
2253 // now deliver the sample
2254 hr = m_MemInputPin->Receive(Sample);
2255
2256 #ifdef KSPROXY_TRACE
2257 swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator);
2258 OutputDebugStringW(Buffer);
2259 #endif
2260
2261 if (FAILED(hr))
2262 break;
2263
2264 Sample = NULL;
2265 }
2266 }while(TRUE);
2267
2268 // signal end of i/o thread
2269 SetEvent(m_hStopEvent);
2270
2271 m_IoThreadStarted = false;
2272
2273 return NOERROR;
2274 }
2275
2276 DWORD
2277 WINAPI
2278 COutputPin_IoThreadStartup(
2279 LPVOID lpParameter)
2280 {
2281 COutputPin * Pin = (COutputPin*)lpParameter;
2282 assert(Pin);
2283
2284 return Pin->IoProcessRoutine();
2285 }
2286
2287
2288 HRESULT
2289 WINAPI
2290 COutputPin::InitializeIOThread()
2291 {
2292 HANDLE hThread;
2293
2294 if (m_IoThreadStarted)
2295 return NOERROR;
2296
2297 if (!m_hStartEvent)
2298 m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2299
2300 if (!m_hStartEvent)
2301 return E_OUTOFMEMORY;
2302
2303 if (!m_hStopEvent)
2304 m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2305
2306 if (!m_hStopEvent)
2307 return E_OUTOFMEMORY;
2308
2309 if (!m_hBufferAvailable)
2310 m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL);
2311
2312 if (!m_hBufferAvailable)
2313 return E_OUTOFMEMORY;
2314
2315 m_StopInProgress = false;
2316 m_IoThreadStarted = true;
2317
2318 // now create the startup thread
2319 hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL);
2320 if (!hThread)
2321 return E_OUTOFMEMORY;
2322
2323
2324 // close thread handle
2325 CloseHandle(hThread);
2326 return NOERROR;
2327 }
2328
2329 HRESULT
2330 STDMETHODCALLTYPE
2331 COutputPin_SetState(
2332 IPin * Pin,
2333 KSSTATE State)
2334 {
2335 HRESULT hr = S_OK;
2336 KSPROPERTY Property;
2337 KSSTATE CurState;
2338 ULONG BytesReturned;
2339 COutputPin * pPin = (COutputPin*)Pin;
2340
2341 #ifdef KSPROXY_TRACE
2342 WCHAR Buffer[200];
2343 #endif
2344
2345 Property.Set = KSPROPSETID_Connection;
2346 Property.Id = KSPROPERTY_CONNECTION_STATE;
2347 Property.Flags = KSPROPERTY_TYPE_SET;
2348
2349 EnterCriticalSection(&pPin->m_Lock);
2350
2351 if (pPin->m_State <= State)
2352 {
2353 if (pPin->m_State == KSSTATE_STOP)
2354 {
2355 hr = pPin->InitializeIOThread();
2356 if (FAILED(hr))
2357 {
2358 // failed to initialize I/O thread
2359 #ifdef KSPROXY_TRACE
2360 OutputDebugStringW(L"Failed to initialize I/O Thread\n");
2361 #endif
2362 LeaveCriticalSection(&pPin->m_Lock);
2363 return hr;
2364 }
2365 CurState = KSSTATE_ACQUIRE;
2366 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2367
2368 #ifdef KSPROXY_TRACE
2369 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
2370 OutputDebugStringW(Buffer);
2371 #endif
2372
2373 if (FAILED(hr))
2374 {
2375 LeaveCriticalSection(&pPin->m_Lock);
2376 return hr;
2377 }
2378
2379 pPin->m_State = CurState;
2380
2381 if (pPin->m_State == State)
2382 {
2383 LeaveCriticalSection(&pPin->m_Lock);
2384 return hr;
2385 }
2386 }
2387 if (pPin->m_State == KSSTATE_ACQUIRE)
2388 {
2389 CurState = KSSTATE_PAUSE;
2390 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2391
2392 #ifdef KSPROXY_TRACE
2393 swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
2394 OutputDebugStringW(Buffer);
2395 #endif
2396
2397 if (FAILED(hr))
2398 {
2399 LeaveCriticalSection(&pPin->m_Lock);
2400 return hr;
2401 }
2402
2403 pPin->m_State = CurState;
2404
2405 if (pPin->m_State == State)
2406 {
2407 LeaveCriticalSection(&pPin->m_Lock);
2408 return hr;
2409 }
2410 }
2411 if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE)
2412 {
2413 CurState = KSSTATE_RUN;
2414 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2415
2416 #ifdef KSPROXY_TRACE
2417 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr);
2418 OutputDebugStringW(Buffer);
2419 #endif
2420
2421 if (SUCCEEDED(hr))
2422 {
2423 pPin->m_State = CurState;
2424 // signal start event
2425 SetEvent(pPin->m_hStartEvent);
2426 }
2427 }
2428
2429 LeaveCriticalSection(&pPin->m_Lock);
2430 return hr;
2431 }
2432 else
2433 {
2434 if (pPin->m_State == KSSTATE_RUN)
2435 {
2436 // setting pending stop flag
2437 pPin->m_StopInProgress = true;
2438
2439 // release any waiting threads
2440 SetEvent(pPin->m_hBufferAvailable);
2441
2442 // wait until i/o thread is done
2443 WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
2444
2445 CurState = KSSTATE_PAUSE;
2446 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2447
2448 #ifdef KSPROXY_TRACE
2449 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr);
2450 OutputDebugStringW(Buffer);
2451 #endif
2452
2453 if (FAILED(hr))
2454 {
2455 LeaveCriticalSection(&pPin->m_Lock);
2456 return hr;
2457 }
2458
2459 pPin->m_State = CurState;
2460
2461 if (FAILED(hr))
2462 {
2463 LeaveCriticalSection(&pPin->m_Lock);
2464 return hr;
2465 }
2466 }
2467 if (pPin->m_State == KSSTATE_PAUSE)
2468 {
2469 CurState = KSSTATE_ACQUIRE;
2470 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2471
2472 #ifdef KSPROXY_TRACE
2473 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr);
2474 OutputDebugStringW(Buffer);
2475 #endif
2476
2477 if (FAILED(hr))
2478 {
2479 LeaveCriticalSection(&pPin->m_Lock);
2480 return hr;
2481 }
2482
2483 pPin->m_State = CurState;
2484
2485 if (pPin->m_State == State)
2486 {
2487 LeaveCriticalSection(&pPin->m_Lock);
2488 return hr;
2489 }
2490 }
2491
2492 CloseHandle(pPin->m_hStopEvent);
2493 CloseHandle(pPin->m_hStartEvent);
2494 CloseHandle(pPin->m_hBufferAvailable);
2495
2496 /* close event handles */
2497 pPin->m_hStopEvent = NULL;
2498 pPin->m_hStartEvent = NULL;
2499 pPin->m_hBufferAvailable = NULL;
2500
2501 CurState = KSSTATE_STOP;
2502 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
2503
2504 #ifdef KSPROXY_TRACE
2505 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr);
2506 OutputDebugStringW(Buffer);
2507 #endif
2508
2509 if (SUCCEEDED(hr))
2510 {
2511 // store state
2512 pPin->m_State = CurState;
2513 }
2514
2515 // unset pending stop flag
2516 pPin->m_StopInProgress = false;
2517
2518 LeaveCriticalSection(&pPin->m_Lock);
2519 return hr;
2520 }
2521 }
2522
2523 HRESULT
2524 WINAPI
2525 COutputPin_Constructor(
2526 IBaseFilter * ParentFilter,
2527 LPCWSTR PinName,
2528 ULONG PinId,
2529 KSPIN_COMMUNICATION Communication,
2530 REFIID riid,
2531 LPVOID * ppv)
2532 {
2533 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
2534
2535 if (!handler)
2536 return E_OUTOFMEMORY;
2537
2538 if (FAILED(handler->QueryInterface(riid, ppv)))
2539 {
2540 /* not supported */
2541 delete handler;
2542 return E_NOINTERFACE;
2543 }
2544
2545 return S_OK;
2546 }