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