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