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
);
138 IKsAllocatorEx
* Allocator
;
140 if (SUCCEEDED(KsPin
->QueryInterface(IID_IKsAllocatorEx
, (void**)&Allocator
)))
142 PALLOCATOR_PROPERTIES_EX Properties
= Allocator
->KsGetProperties();
147 swprintf(Buffer
, L
"CKsInterfaceHandler::KsSetPin PinName %s Properties.cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", m_PinName
, Properties
->cbAlign
, Properties
->cbBuffer
, Properties
->cbPrefix
, Properties
->cBuffers
);
148 OutputDebugStringW(Buffer
);
150 Allocator
->Release();
161 CKsInterfaceHandler::KsProcessMediaSamples(
162 IKsDataTypeHandler
*KsDataTypeHandler
,
163 IMediaSample
** SampleList
,
165 KSIOOPERATION IoOperation
,
166 PKSSTREAM_SEGMENT
*OutStreamSegment
)
168 PKSSTREAM_SEGMENT_EXT StreamSegment
;
169 ULONG ExtendedSize
, Index
, BytesReturned
;
173 assert(*SampleCount
);
175 if (*SampleCount
== 0 || *SampleCount
< 0)
178 // zero stream segment
179 *OutStreamSegment
= NULL
;
181 // allocate stream segment
182 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT
));
184 return E_OUTOFMEMORY
;
186 // zero stream segment
187 ZeroMemory(StreamSegment
, sizeof(KSSTREAM_SEGMENT_EXT
));
190 StreamSegment
->StreamSegment
.CompletionEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
192 if (!StreamSegment
->StreamSegment
.CompletionEvent
)
194 // failed to create event
195 CoTaskMemFree(StreamSegment
);
196 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
199 // increase our own reference count
202 // setup stream segment
203 StreamSegment
->StreamSegment
.KsDataTypeHandler
= KsDataTypeHandler
;
204 StreamSegment
->StreamSegment
.KsInterfaceHandler
= (IKsInterfaceHandler
*)this;
205 StreamSegment
->StreamSegment
.IoOperation
= IoOperation
;
206 StreamSegment
->Overlapped
.hEvent
= StreamSegment
->StreamSegment
.CompletionEvent
;
211 if (KsDataTypeHandler
)
213 // query extension size
214 KsDataTypeHandler
->KsQueryExtendedSize(&ExtendedSize
);
218 // increment reference count
219 KsDataTypeHandler
->AddRef();
223 // no need for the datatype handler
224 StreamSegment
->StreamSegment
.KsDataTypeHandler
= NULL
;
228 StreamSegment
->ExtendedSize
= ExtendedSize
;
229 StreamSegment
->SampleCount
= (ULONG
)*SampleCount
;
231 // calculate stream header size count
232 ULONG StreamHeaderSize
= StreamSegment
->SampleCount
* (sizeof(KSSTREAM_HEADER
) + ExtendedSize
);
234 // allocate stream header
235 StreamSegment
->StreamHeader
= (PKSSTREAM_HEADER
)CoTaskMemAlloc(StreamHeaderSize
);
236 if (!StreamSegment
->StreamHeader
)
239 CloseHandle(StreamSegment
->StreamSegment
.CompletionEvent
);
241 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
242 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
244 // free stream segment
245 CoTaskMemFree(StreamSegment
);
247 //release our reference count
249 return E_OUTOFMEMORY
;
252 // zero stream headers
253 ZeroMemory(StreamSegment
->StreamHeader
, StreamHeaderSize
);
255 PKSSTREAM_HEADER CurStreamHeader
= StreamSegment
->StreamHeader
;
257 // initialize all stream headers
258 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
262 // initialize extended size
263 hr
= KsDataTypeHandler
->KsPrepareIoOperation(SampleList
[Index
], (CurStreamHeader
+ 1), IoOperation
);
265 assert(hr
== NOERROR
);
268 // query for IMediaSample2 interface
269 IMediaSample2
* MediaSample
;
270 AM_SAMPLE2_PROPERTIES Properties
;
272 hr
= SampleList
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
277 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
279 //release IMediaSample2 interface
280 MediaSample
->Release();
285 hr
= SampleList
[Index
]->GetPointer((BYTE
**)&Properties
.pbBuffer
);
286 assert(hr
== NOERROR
);
287 hr
= SampleList
[Index
]->GetTime(&Properties
.tStart
, &Properties
.tStop
);
288 assert(hr
== NOERROR
);
290 Properties
.cbBuffer
= SampleList
[Index
]->GetSize();
291 assert(Properties
.cbBuffer
);
293 Properties
.dwSampleFlags
= 0;
295 if (SampleList
[Index
]->IsDiscontinuity() == S_OK
)
296 Properties
.dwSampleFlags
|= AM_SAMPLE_DATADISCONTINUITY
;
298 if (SampleList
[Index
]->IsPreroll() == S_OK
)
299 Properties
.dwSampleFlags
|= AM_SAMPLE_PREROLL
;
301 if (SampleList
[Index
]->IsSyncPoint() == S_OK
)
302 Properties
.dwSampleFlags
|= AM_SAMPLE_SPLICEPOINT
;
306 swprintf(Buffer
, L
"CKsInterfaceHandler::KsProcessMediaSamples PinName %s BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u\n", m_PinName
, Properties
.cbBuffer
, Properties
.pbBuffer
, ExtendedSize
, Properties
.lActual
);
307 //OutputDebugStringW(Buffer);
309 CurStreamHeader
->Size
= sizeof(KSSTREAM_HEADER
) + ExtendedSize
;
310 CurStreamHeader
->PresentationTime
.Denominator
= 1;
311 CurStreamHeader
->PresentationTime
.Numerator
= 1;
312 CurStreamHeader
->FrameExtent
= Properties
.cbBuffer
;
313 CurStreamHeader
->Data
= Properties
.pbBuffer
;
315 if (IoOperation
== KsIoOperation_Write
)
318 CurStreamHeader
->OptionsFlags
= Properties
.dwSampleFlags
;
319 CurStreamHeader
->DataUsed
= Properties
.lActual
;
320 // increment reference count
321 SampleList
[Index
]->AddRef();
324 // store sample in stream segment
325 StreamSegment
->MediaSample
[Index
] = SampleList
[Index
];
327 // move to next header
328 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
332 m_Pin
->KsIncrementPendingIoCount();
334 if (DeviceIoControl(m_Handle
,
335 IoOperation
== KsIoOperation_Write
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
,
337 StreamSegment
->StreamHeader
,
340 &StreamSegment
->Overlapped
))
343 SetEvent(StreamSegment
->StreamSegment
.CompletionEvent
);
345 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
349 if (GetLastError() == ERROR_IO_PENDING
)
351 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
360 CKsInterfaceHandler::KsCompleteIo(
361 PKSSTREAM_SEGMENT InStreamSegment
)
363 PKSSTREAM_SEGMENT_EXT StreamSegment
;
364 PKSSTREAM_HEADER CurStreamHeader
;
365 DWORD dwError
= ERROR_SUCCESS
, BytesReturned
;
369 IMediaSample2
* MediaSample
;
370 AM_SAMPLE2_PROPERTIES Properties
;
371 REFERENCE_TIME Start
, Stop
;
373 // get private stream segment
374 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)InStreamSegment
;
377 bOverlapped
= GetOverlappedResult(m_Handle
, &StreamSegment
->Overlapped
, &BytesReturned
, FALSE
);
378 dwError
= GetLastError();
380 CurStreamHeader
= StreamSegment
->StreamHeader
;
383 swprintf(Buffer
, L
"CKsInterfaceHandler::KsCompleteIo PinName %s bOverlapped %u hr %lx\n", m_PinName
, bOverlapped
, dwError
);
384 //OutputDebugStringW(Buffer);
386 //iterate through all stream headers
387 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
392 m_Pin
->KsNotifyError(StreamSegment
->MediaSample
[Index
], MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, dwError
));
395 // query IMediaSample2 interface
396 hr
= StreamSegment
->MediaSample
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
399 // media sample properties
400 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
403 //update media sample properties
404 Properties
.dwTypeSpecificFlags
= CurStreamHeader
->TypeSpecificFlags
;
405 Properties
.dwSampleFlags
|= (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY
);
407 MediaSample
->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
409 // release IMediaSample2 interface
410 MediaSample
->Release();
413 // was an extended header used
414 if (StreamSegment
->ExtendedSize
)
416 // unprepare stream header extension
417 StreamSegment
->StreamSegment
.KsDataTypeHandler
->KsCompleteIoOperation(StreamSegment
->MediaSample
[Index
], (CurStreamHeader
+ 1), StreamSegment
->StreamSegment
.IoOperation
, bOverlapped
== FALSE
);
422 if (bOverlapped
&& StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
424 // update common media sample details
425 StreamSegment
->MediaSample
[Index
]->SetSyncPoint((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT
));
426 StreamSegment
->MediaSample
[Index
]->SetPreroll((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_PREROLL
));
427 StreamSegment
->MediaSample
[Index
]->SetDiscontinuity((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
));
429 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEVALID
)
431 // use valid timestamp
432 Start
= CurStreamHeader
->PresentationTime
.Time
;
434 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DURATIONVALID
)
436 Stop
= CurStreamHeader
->PresentationTime
.Time
+ CurStreamHeader
->Duration
;
442 hr
= StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Stop
);
446 StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Start
);
449 // set valid data length
450 StreamSegment
->MediaSample
[Index
]->SetActualDataLength(CurStreamHeader
->DataUsed
);
452 if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
457 m_Pin
->KsDeliver(StreamSegment
->MediaSample
[Index
], CurStreamHeader
->OptionsFlags
);
460 else if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Write
)
462 // release media sample reference
463 StreamSegment
->MediaSample
[Index
]->Release();
466 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
469 // delete stream headers
470 CoTaskMemFree(StreamSegment
->StreamHeader
);
472 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
475 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
478 // decrement pending i/o count
479 m_Pin
->KsDecrementPendingIoCount();
481 //notify of completion
482 m_Pin
->KsMediaSamplesCompleted(InStreamSegment
);
484 //destroy stream segment
485 CoTaskMemFree(StreamSegment
);
487 //release reference to ourselves
491 // Event handle is closed by caller
497 CKsInterfaceHandler_Constructor(
498 IUnknown
* pUnkOuter
,
502 OutputDebugStringW(L
"CKsInterfaceHandler_Constructor\n");
504 CKsInterfaceHandler
* handler
= new CKsInterfaceHandler();
507 return E_OUTOFMEMORY
;
509 if (FAILED(handler
->QueryInterface(riid
, ppv
)))
513 return E_NOINTERFACE
;