2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/interface.cpp
5 * PURPOSE: IKsInterfaceHandler interface
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
11 const GUID IID_IKsObject
= {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
13 class CKsInterfaceHandler
: public IKsInterfaceHandler
16 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
18 STDMETHODIMP_(ULONG
) AddRef()
20 InterlockedIncrement(&m_Ref
);
23 STDMETHODIMP_(ULONG
) Release()
25 InterlockedDecrement(&m_Ref
);
34 HRESULT STDMETHODCALLTYPE
KsSetPin(IKsPin
*KsPin
);
35 HRESULT STDMETHODCALLTYPE
KsProcessMediaSamples(IKsDataTypeHandler
*KsDataTypeHandler
, IMediaSample
** SampleList
, PLONG SampleCount
, KSIOOPERATION IoOperation
, PKSSTREAM_SEGMENT
*StreamSegment
);
36 HRESULT STDMETHODCALLTYPE
KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment
);
38 CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL
), m_Pin(0) {m_PinName
[0] = L
'\0';};
39 virtual ~CKsInterfaceHandler(){};
50 KSSTREAM_SEGMENT StreamSegment
;
51 OVERLAPPED Overlapped
;
52 IMediaSample
* MediaSample
[64];
56 PKSSTREAM_HEADER StreamHeader
;
57 }KSSTREAM_SEGMENT_EXT
, *PKSSTREAM_SEGMENT_EXT
;
62 CKsInterfaceHandler::QueryInterface(
66 if (IsEqualGUID(refiid
, IID_IUnknown
) ||
67 IsEqualGUID(refiid
, IID_IKsInterfaceHandler
))
69 *Output
= PVOID(this);
70 reinterpret_cast<IUnknown
*>(*Output
)->AddRef();
78 CKsInterfaceHandler::KsSetPin(
85 // get IKsPinEx interface
86 hr
= KsPin
->QueryInterface(IID_IKsPinEx
, (void**)&Pin
);
89 // check if IKsObject is supported
90 hr
= KsPin
->QueryInterface(IID_IKsObject
, (void**)&KsObject
);
95 m_Handle
= KsObject
->KsGetObjectHandle();
97 // release IKsObject interface
102 // expected a file handle
110 // release old interface
118 //release IKsPinEx interface
126 if (SUCCEEDED(KsPin
->QueryInterface(IID_IPin
, (void**)&pPin
)))
128 if (SUCCEEDED(pPin
->QueryPinInfo(&PinInfo
)))
131 PinInfo
.pFilter
->Release();
133 wcscpy(m_PinName
, PinInfo
.achName
);
145 CKsInterfaceHandler::KsProcessMediaSamples(
146 IKsDataTypeHandler
*KsDataTypeHandler
,
147 IMediaSample
** SampleList
,
149 KSIOOPERATION IoOperation
,
150 PKSSTREAM_SEGMENT
*OutStreamSegment
)
152 PKSSTREAM_SEGMENT_EXT StreamSegment
;
153 ULONG ExtendedSize
, Index
, BytesReturned
;
157 assert(*SampleCount
);
159 if (*SampleCount
== 0 || *SampleCount
< 0)
162 // zero stream segment
163 *OutStreamSegment
= NULL
;
165 // allocate stream segment
166 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT
));
168 return E_OUTOFMEMORY
;
170 // zero stream segment
171 ZeroMemory(StreamSegment
, sizeof(KSSTREAM_SEGMENT_EXT
));
174 StreamSegment
->StreamSegment
.CompletionEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
176 if (!StreamSegment
->StreamSegment
.CompletionEvent
)
178 // failed to create event
179 CoTaskMemFree(StreamSegment
);
180 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
183 // increase our own reference count
186 // setup stream segment
187 StreamSegment
->StreamSegment
.KsDataTypeHandler
= KsDataTypeHandler
;
188 StreamSegment
->StreamSegment
.KsInterfaceHandler
= (IKsInterfaceHandler
*)this;
189 StreamSegment
->StreamSegment
.IoOperation
= IoOperation
;
190 StreamSegment
->Overlapped
.hEvent
= StreamSegment
->StreamSegment
.CompletionEvent
;
195 if (KsDataTypeHandler
)
197 // query extension size
198 KsDataTypeHandler
->KsQueryExtendedSize(&ExtendedSize
);
202 // increment reference count
203 KsDataTypeHandler
->AddRef();
207 // no need for the datatype handler
208 StreamSegment
->StreamSegment
.KsDataTypeHandler
= NULL
;
212 StreamSegment
->ExtendedSize
= ExtendedSize
;
213 StreamSegment
->SampleCount
= (ULONG
)*SampleCount
;
215 // calculate stream header size count
216 ULONG StreamHeaderSize
= StreamSegment
->SampleCount
* (sizeof(KSSTREAM_HEADER
) + ExtendedSize
);
218 // allocate stream header
219 StreamSegment
->StreamHeader
= (PKSSTREAM_HEADER
)CoTaskMemAlloc(StreamHeaderSize
);
220 if (!StreamSegment
->StreamHeader
)
223 CloseHandle(StreamSegment
->StreamSegment
.CompletionEvent
);
225 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
226 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
228 // free stream segment
229 CoTaskMemFree(StreamSegment
);
231 //release our reference count
233 return E_OUTOFMEMORY
;
236 // zero stream headers
237 ZeroMemory(StreamSegment
->StreamHeader
, StreamHeaderSize
);
239 PKSSTREAM_HEADER CurStreamHeader
= StreamSegment
->StreamHeader
;
241 // initialize all stream headers
242 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
246 // initialize extended size
247 hr
= KsDataTypeHandler
->KsPrepareIoOperation(SampleList
[Index
], (CurStreamHeader
+ 1), IoOperation
);
249 assert(hr
== NOERROR
);
252 // query for IMediaSample2 interface
253 IMediaSample2
* MediaSample
;
254 AM_SAMPLE2_PROPERTIES Properties
;
255 ZeroMemory(&Properties
, sizeof(AM_SAMPLE2_PROPERTIES
));
257 hr
= SampleList
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
262 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
264 //release IMediaSample2 interface
265 MediaSample
->Release();
270 hr
= SampleList
[Index
]->GetPointer((BYTE
**)&Properties
.pbBuffer
);
271 assert(hr
== NOERROR
);
272 hr
= SampleList
[Index
]->GetTime(&Properties
.tStart
, &Properties
.tStop
);
274 Properties
.cbBuffer
= SampleList
[Index
]->GetSize();
275 assert(Properties
.cbBuffer
);
277 Properties
.dwSampleFlags
= 0;
279 if (SampleList
[Index
]->IsDiscontinuity() == S_OK
)
280 Properties
.dwSampleFlags
|= AM_SAMPLE_DATADISCONTINUITY
;
282 if (SampleList
[Index
]->IsPreroll() == S_OK
)
283 Properties
.dwSampleFlags
|= AM_SAMPLE_PREROLL
;
285 if (SampleList
[Index
]->IsSyncPoint() == S_OK
)
286 Properties
.dwSampleFlags
|= AM_SAMPLE_SPLICEPOINT
;
290 swprintf(Buffer
, L
"CKsInterfaceHandler::KsProcessMediaSamples PinName %s BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u dwSampleFlags %lx\n", m_PinName
, Properties
.cbBuffer
, Properties
.pbBuffer
, ExtendedSize
, Properties
.lActual
, Properties
.dwSampleFlags
);
291 //OutputDebugStringW(Buffer);
293 CurStreamHeader
->Size
= sizeof(KSSTREAM_HEADER
) + ExtendedSize
;
294 CurStreamHeader
->PresentationTime
.Denominator
= 1;
295 CurStreamHeader
->PresentationTime
.Numerator
= 1;
296 CurStreamHeader
->FrameExtent
= Properties
.cbBuffer
;
297 CurStreamHeader
->Data
= Properties
.pbBuffer
;
299 if (IoOperation
== KsIoOperation_Write
)
302 CurStreamHeader
->OptionsFlags
= Properties
.dwSampleFlags
;
303 CurStreamHeader
->DataUsed
= Properties
.lActual
;
304 // increment reference count
305 SampleList
[Index
]->AddRef();
308 // store sample in stream segment
309 StreamSegment
->MediaSample
[Index
] = SampleList
[Index
];
311 // move to next header
312 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
316 m_Pin
->KsIncrementPendingIoCount();
318 if (DeviceIoControl(m_Handle
,
319 IoOperation
== KsIoOperation_Write
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
,
321 StreamSegment
->StreamHeader
,
324 &StreamSegment
->Overlapped
))
327 SetEvent(StreamSegment
->StreamSegment
.CompletionEvent
);
329 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
333 if (GetLastError() == ERROR_IO_PENDING
)
335 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
344 CKsInterfaceHandler::KsCompleteIo(
345 PKSSTREAM_SEGMENT InStreamSegment
)
347 PKSSTREAM_SEGMENT_EXT StreamSegment
;
348 PKSSTREAM_HEADER CurStreamHeader
;
349 DWORD dwError
= ERROR_SUCCESS
, BytesReturned
;
353 IMediaSample2
* MediaSample
;
354 AM_SAMPLE2_PROPERTIES Properties
;
355 REFERENCE_TIME Start
, Stop
;
357 // get private stream segment
358 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)InStreamSegment
;
361 bOverlapped
= GetOverlappedResult(m_Handle
, &StreamSegment
->Overlapped
, &BytesReturned
, FALSE
);
362 dwError
= GetLastError();
364 CurStreamHeader
= StreamSegment
->StreamHeader
;
366 //iterate through all stream headers
367 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
372 m_Pin
->KsNotifyError(StreamSegment
->MediaSample
[Index
], MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, dwError
));
375 // query IMediaSample2 interface
376 hr
= StreamSegment
->MediaSample
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
379 // media sample properties
380 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
383 //update media sample properties
384 Properties
.dwTypeSpecificFlags
= CurStreamHeader
->TypeSpecificFlags
;
385 Properties
.dwSampleFlags
|= (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY
);
387 MediaSample
->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
389 // release IMediaSample2 interface
390 MediaSample
->Release();
393 // was an extended header used
394 if (StreamSegment
->ExtendedSize
)
396 // unprepare stream header extension
397 StreamSegment
->StreamSegment
.KsDataTypeHandler
->KsCompleteIoOperation(StreamSegment
->MediaSample
[Index
], (CurStreamHeader
+ 1), StreamSegment
->StreamSegment
.IoOperation
, bOverlapped
== FALSE
);
402 if (bOverlapped
&& StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
404 // update common media sample details
405 StreamSegment
->MediaSample
[Index
]->SetSyncPoint((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT
));
406 StreamSegment
->MediaSample
[Index
]->SetPreroll((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_PREROLL
));
407 StreamSegment
->MediaSample
[Index
]->SetDiscontinuity((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
));
409 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEVALID
)
411 // use valid timestamp
412 Start
= CurStreamHeader
->PresentationTime
.Time
;
414 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DURATIONVALID
)
416 Stop
= CurStreamHeader
->PresentationTime
.Time
+ CurStreamHeader
->Duration
;
422 hr
= StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Stop
);
426 StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Start
);
429 // set valid data length
430 StreamSegment
->MediaSample
[Index
]->SetActualDataLength(CurStreamHeader
->DataUsed
);
432 if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
437 m_Pin
->KsDeliver(StreamSegment
->MediaSample
[Index
], CurStreamHeader
->OptionsFlags
);
440 else if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Write
)
442 // release media sample reference
443 StreamSegment
->MediaSample
[Index
]->Release();
446 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
449 // delete stream headers
450 CoTaskMemFree(StreamSegment
->StreamHeader
);
452 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
455 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
458 // decrement pending i/o count
459 m_Pin
->KsDecrementPendingIoCount();
461 //notify of completion
462 m_Pin
->KsMediaSamplesCompleted(InStreamSegment
);
464 //destroy stream segment
465 CoTaskMemFree(StreamSegment
);
467 //release reference to ourselves
471 // Event handle is closed by caller
477 CKsInterfaceHandler_Constructor(
478 IUnknown
* pUnkOuter
,
482 OutputDebugStringW(L
"CKsInterfaceHandler_Constructor\n");
484 CKsInterfaceHandler
* handler
= new CKsInterfaceHandler();
487 return E_OUTOFMEMORY
;
489 if (FAILED(handler
->QueryInterface(riid
, ppv
)))
493 return E_NOINTERFACE
;