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 extern const GUID IID_IKsInterfaceHandler
;
15 class CKsInterfaceHandler
: public IKsInterfaceHandler
18 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
20 STDMETHODIMP_(ULONG
) AddRef()
22 InterlockedIncrement(&m_Ref
);
25 STDMETHODIMP_(ULONG
) Release()
27 InterlockedDecrement(&m_Ref
);
36 HRESULT STDMETHODCALLTYPE
KsSetPin(IKsPin
*KsPin
);
37 HRESULT STDMETHODCALLTYPE
KsProcessMediaSamples(IKsDataTypeHandler
*KsDataTypeHandler
, IMediaSample
** SampleList
, PLONG SampleCount
, KSIOOPERATION IoOperation
, PKSSTREAM_SEGMENT
*StreamSegment
);
38 HRESULT STDMETHODCALLTYPE
KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment
);
40 CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL
), m_Pin(0) {m_PinName
[0] = L
'\0';};
41 virtual ~CKsInterfaceHandler(){};
52 KSSTREAM_SEGMENT StreamSegment
;
53 OVERLAPPED Overlapped
;
54 IMediaSample
* MediaSample
[64];
58 PKSSTREAM_HEADER StreamHeader
;
59 }KSSTREAM_SEGMENT_EXT
, *PKSSTREAM_SEGMENT_EXT
;
64 CKsInterfaceHandler::QueryInterface(
68 if (IsEqualGUID(refiid
, IID_IUnknown
) ||
69 IsEqualGUID(refiid
, IID_IKsInterfaceHandler
))
71 *Output
= PVOID(this);
72 reinterpret_cast<IUnknown
*>(*Output
)->AddRef();
80 CKsInterfaceHandler::KsSetPin(
87 // get IKsPinEx interface
88 hr
= KsPin
->QueryInterface(IID_IKsPinEx
, (void**)&Pin
);
91 // check if IKsObject is supported
92 hr
= KsPin
->QueryInterface(IID_IKsObject
, (void**)&KsObject
);
97 m_Handle
= KsObject
->KsGetObjectHandle();
99 // release IKsObject interface
104 // expected a file handle
112 // release old interface
120 //release IKsPinEx interface
128 if (SUCCEEDED(KsPin
->QueryInterface(IID_IPin
, (void**)&pPin
)))
130 if (SUCCEEDED(pPin
->QueryPinInfo(&PinInfo
)))
133 PinInfo
.pFilter
->Release();
135 wcscpy(m_PinName
, PinInfo
.achName
);
147 CKsInterfaceHandler::KsProcessMediaSamples(
148 IKsDataTypeHandler
*KsDataTypeHandler
,
149 IMediaSample
** SampleList
,
151 KSIOOPERATION IoOperation
,
152 PKSSTREAM_SEGMENT
*OutStreamSegment
)
154 PKSSTREAM_SEGMENT_EXT StreamSegment
;
155 ULONG ExtendedSize
, Index
, BytesReturned
;
159 assert(*SampleCount
);
161 if (*SampleCount
== 0 || *SampleCount
< 0)
164 // zero stream segment
165 *OutStreamSegment
= NULL
;
167 // allocate stream segment
168 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT
));
170 return E_OUTOFMEMORY
;
172 // zero stream segment
173 ZeroMemory(StreamSegment
, sizeof(KSSTREAM_SEGMENT_EXT
));
176 StreamSegment
->StreamSegment
.CompletionEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
178 if (!StreamSegment
->StreamSegment
.CompletionEvent
)
180 // failed to create event
181 CoTaskMemFree(StreamSegment
);
182 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
185 // increase our own reference count
188 // setup stream segment
189 StreamSegment
->StreamSegment
.KsDataTypeHandler
= KsDataTypeHandler
;
190 StreamSegment
->StreamSegment
.KsInterfaceHandler
= (IKsInterfaceHandler
*)this;
191 StreamSegment
->StreamSegment
.IoOperation
= IoOperation
;
192 StreamSegment
->Overlapped
.hEvent
= StreamSegment
->StreamSegment
.CompletionEvent
;
197 if (KsDataTypeHandler
)
199 // query extension size
200 KsDataTypeHandler
->KsQueryExtendedSize(&ExtendedSize
);
204 // increment reference count
205 KsDataTypeHandler
->AddRef();
209 // no need for the datatype handler
210 StreamSegment
->StreamSegment
.KsDataTypeHandler
= NULL
;
214 StreamSegment
->ExtendedSize
= ExtendedSize
;
215 StreamSegment
->SampleCount
= (ULONG
)*SampleCount
;
217 // calculate stream header size count
218 ULONG StreamHeaderSize
= StreamSegment
->SampleCount
* (sizeof(KSSTREAM_HEADER
) + ExtendedSize
);
220 // allocate stream header
221 StreamSegment
->StreamHeader
= (PKSSTREAM_HEADER
)CoTaskMemAlloc(StreamHeaderSize
);
222 if (!StreamSegment
->StreamHeader
)
225 CloseHandle(StreamSegment
->StreamSegment
.CompletionEvent
);
227 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
228 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
230 // free stream segment
231 CoTaskMemFree(StreamSegment
);
233 //release our reference count
235 return E_OUTOFMEMORY
;
238 // zero stream headers
239 ZeroMemory(StreamSegment
->StreamHeader
, StreamHeaderSize
);
241 PKSSTREAM_HEADER CurStreamHeader
= StreamSegment
->StreamHeader
;
243 // initialize all stream headers
244 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
248 // initialize extended size
249 hr
= KsDataTypeHandler
->KsPrepareIoOperation(SampleList
[Index
], (CurStreamHeader
+ 1), IoOperation
);
251 assert(hr
== NOERROR
);
254 // query for IMediaSample2 interface
255 IMediaSample2
* MediaSample
;
256 AM_SAMPLE2_PROPERTIES Properties
;
257 ZeroMemory(&Properties
, sizeof(AM_SAMPLE2_PROPERTIES
));
259 hr
= SampleList
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
264 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
266 //release IMediaSample2 interface
267 MediaSample
->Release();
272 hr
= SampleList
[Index
]->GetPointer((BYTE
**)&Properties
.pbBuffer
);
273 assert(hr
== NOERROR
);
274 hr
= SampleList
[Index
]->GetTime(&Properties
.tStart
, &Properties
.tStop
);
276 Properties
.cbBuffer
= SampleList
[Index
]->GetSize();
277 assert(Properties
.cbBuffer
);
279 Properties
.dwSampleFlags
= 0;
281 if (SampleList
[Index
]->IsDiscontinuity() == S_OK
)
282 Properties
.dwSampleFlags
|= AM_SAMPLE_DATADISCONTINUITY
;
284 if (SampleList
[Index
]->IsPreroll() == S_OK
)
285 Properties
.dwSampleFlags
|= AM_SAMPLE_PREROLL
;
287 if (SampleList
[Index
]->IsSyncPoint() == S_OK
)
288 Properties
.dwSampleFlags
|= AM_SAMPLE_SPLICEPOINT
;
292 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
);
293 OutputDebugStringW(Buffer
);
296 CurStreamHeader
->Size
= sizeof(KSSTREAM_HEADER
) + ExtendedSize
;
297 CurStreamHeader
->PresentationTime
.Denominator
= 1;
298 CurStreamHeader
->PresentationTime
.Numerator
= 1;
299 CurStreamHeader
->FrameExtent
= Properties
.cbBuffer
;
300 CurStreamHeader
->Data
= Properties
.pbBuffer
;
302 if (IoOperation
== KsIoOperation_Write
)
305 CurStreamHeader
->OptionsFlags
= Properties
.dwSampleFlags
;
306 CurStreamHeader
->DataUsed
= Properties
.lActual
;
307 // increment reference count
308 SampleList
[Index
]->AddRef();
311 // store sample in stream segment
312 StreamSegment
->MediaSample
[Index
] = SampleList
[Index
];
314 // move to next header
315 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
319 m_Pin
->KsIncrementPendingIoCount();
321 if (DeviceIoControl(m_Handle
,
322 IoOperation
== KsIoOperation_Write
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
,
324 StreamSegment
->StreamHeader
,
327 &StreamSegment
->Overlapped
))
330 SetEvent(StreamSegment
->StreamSegment
.CompletionEvent
);
332 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
336 if (GetLastError() == ERROR_IO_PENDING
)
338 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
347 CKsInterfaceHandler::KsCompleteIo(
348 PKSSTREAM_SEGMENT InStreamSegment
)
350 PKSSTREAM_SEGMENT_EXT StreamSegment
;
351 PKSSTREAM_HEADER CurStreamHeader
;
352 DWORD dwError
= ERROR_SUCCESS
, BytesReturned
;
356 IMediaSample2
* MediaSample
;
357 AM_SAMPLE2_PROPERTIES Properties
;
358 REFERENCE_TIME Start
, Stop
;
360 // get private stream segment
361 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)InStreamSegment
;
364 bOverlapped
= GetOverlappedResult(m_Handle
, &StreamSegment
->Overlapped
, &BytesReturned
, FALSE
);
365 dwError
= GetLastError();
367 CurStreamHeader
= StreamSegment
->StreamHeader
;
369 //iterate through all stream headers
370 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
375 m_Pin
->KsNotifyError(StreamSegment
->MediaSample
[Index
], MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, dwError
));
378 // query IMediaSample2 interface
379 hr
= StreamSegment
->MediaSample
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
382 // media sample properties
383 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
386 //update media sample properties
387 Properties
.dwTypeSpecificFlags
= CurStreamHeader
->TypeSpecificFlags
;
388 Properties
.dwSampleFlags
|= (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY
);
390 MediaSample
->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
392 // release IMediaSample2 interface
393 MediaSample
->Release();
396 // was an extended header used
397 if (StreamSegment
->ExtendedSize
)
399 // unprepare stream header extension
400 StreamSegment
->StreamSegment
.KsDataTypeHandler
->KsCompleteIoOperation(StreamSegment
->MediaSample
[Index
], (CurStreamHeader
+ 1), StreamSegment
->StreamSegment
.IoOperation
, bOverlapped
== FALSE
);
405 if (bOverlapped
&& StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
407 // update common media sample details
408 StreamSegment
->MediaSample
[Index
]->SetSyncPoint((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT
));
409 StreamSegment
->MediaSample
[Index
]->SetPreroll((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_PREROLL
));
410 StreamSegment
->MediaSample
[Index
]->SetDiscontinuity((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
));
412 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEVALID
)
414 // use valid timestamp
415 Start
= CurStreamHeader
->PresentationTime
.Time
;
417 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DURATIONVALID
)
419 Stop
= CurStreamHeader
->PresentationTime
.Time
+ CurStreamHeader
->Duration
;
425 hr
= StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Stop
);
429 StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Start
);
432 // set valid data length
433 StreamSegment
->MediaSample
[Index
]->SetActualDataLength(CurStreamHeader
->DataUsed
);
435 if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
440 m_Pin
->KsDeliver(StreamSegment
->MediaSample
[Index
], CurStreamHeader
->OptionsFlags
);
443 else if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Write
)
445 // release media sample reference
446 StreamSegment
->MediaSample
[Index
]->Release();
449 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
452 // delete stream headers
453 CoTaskMemFree(StreamSegment
->StreamHeader
);
455 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
458 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
461 // decrement pending i/o count
462 m_Pin
->KsDecrementPendingIoCount();
464 //notify of completion
465 m_Pin
->KsMediaSamplesCompleted(InStreamSegment
);
467 //destroy stream segment
468 CoTaskMemFree(StreamSegment
);
470 //release reference to ourselves
474 // Event handle is closed by caller
480 CKsInterfaceHandler_Constructor(
481 IUnknown
* pUnkOuter
,
486 OutputDebugStringW(L
"CKsInterfaceHandler_Constructor\n");
489 CKsInterfaceHandler
* handler
= new CKsInterfaceHandler();
492 return E_OUTOFMEMORY
;
494 if (FAILED(handler
->QueryInterface(riid
, ppv
)))
498 return E_NOINTERFACE
;