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){};
39 virtual ~CKsInterfaceHandler(){};
49 KSSTREAM_SEGMENT StreamSegment
;
50 IMediaSample
* MediaSample
[64];
54 PKSSTREAM_HEADER StreamHeader
;
55 OVERLAPPED Overlapped
;
56 }KSSTREAM_SEGMENT_EXT
, *PKSSTREAM_SEGMENT_EXT
;
61 CKsInterfaceHandler::QueryInterface(
65 if (IsEqualGUID(refiid
, IID_IUnknown
) ||
66 IsEqualGUID(refiid
, IID_IKsInterfaceHandler
))
68 *Output
= PVOID(this);
69 reinterpret_cast<IUnknown
*>(*Output
)->AddRef();
77 CKsInterfaceHandler::KsSetPin(
84 // get IKsPinEx interface
85 hr
= KsPin
->QueryInterface(IID_IKsPinEx
, (void**)&Pin
);
88 // check if IKsObject is supported
89 hr
= KsPin
->QueryInterface(IID_IKsObject
, (void**)&KsObject
);
94 m_Handle
= KsObject
->KsGetObjectHandle();
96 // release IKsObject interface
101 // expected a file handle
109 // release old interface
117 //release IKsPinEx interface
128 CKsInterfaceHandler::KsProcessMediaSamples(
129 IKsDataTypeHandler
*KsDataTypeHandler
,
130 IMediaSample
** SampleList
,
132 KSIOOPERATION IoOperation
,
133 PKSSTREAM_SEGMENT
*OutStreamSegment
)
135 PKSSTREAM_SEGMENT_EXT StreamSegment
;
136 ULONG ExtendedSize
, Index
, BytesReturned
;
139 OutputDebugString("CKsInterfaceHandler::KsProcessMediaSamples\n");
142 assert(*SampleCount
);
144 if (*SampleCount
== 0 || *SampleCount
< 0)
147 // zero stream segment
148 *OutStreamSegment
= NULL
;
150 // allocate stream segment
151 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT
));
153 return E_OUTOFMEMORY
;
155 // zero stream segment
156 ZeroMemory(StreamSegment
, sizeof(KSSTREAM_SEGMENT_EXT
));
159 StreamSegment
->StreamSegment
.CompletionEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
161 if (!StreamSegment
->StreamSegment
.CompletionEvent
)
163 // failed to create event
164 CoTaskMemFree(StreamSegment
);
165 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
168 // increase our own reference count
171 // setup stream segment
172 StreamSegment
->StreamSegment
.KsDataTypeHandler
= KsDataTypeHandler
;
173 StreamSegment
->StreamSegment
.KsInterfaceHandler
= (IKsInterfaceHandler
*)this;
174 StreamSegment
->StreamSegment
.IoOperation
= IoOperation
;
175 StreamSegment
->Overlapped
.hEvent
= StreamSegment
->StreamSegment
.CompletionEvent
;
180 if (KsDataTypeHandler
)
182 // query extension size
183 KsDataTypeHandler
->KsQueryExtendedSize(&ExtendedSize
);
187 // increment reference count
188 KsDataTypeHandler
->AddRef();
192 // no need for the datatype handler
193 StreamSegment
->StreamSegment
.KsDataTypeHandler
= NULL
;
197 StreamSegment
->ExtendedSize
= ExtendedSize
;
198 StreamSegment
->SampleCount
= (ULONG
)*SampleCount
;
200 // calculate stream header size count
201 ULONG StreamHeaderSize
= StreamSegment
->SampleCount
* (sizeof(KSSTREAM_HEADER
) + ExtendedSize
);
203 // allocate stream header
204 StreamSegment
->StreamHeader
= (PKSSTREAM_HEADER
)CoTaskMemAlloc(StreamHeaderSize
);
205 if (!StreamSegment
->StreamHeader
)
208 CloseHandle(StreamSegment
->StreamSegment
.CompletionEvent
);
210 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
211 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
213 // free stream segment
214 CoTaskMemFree(StreamSegment
);
216 //release our reference count
218 return E_OUTOFMEMORY
;
221 // zero stream headers
222 ZeroMemory(StreamSegment
->StreamHeader
, StreamHeaderSize
);
224 PKSSTREAM_HEADER CurStreamHeader
= StreamSegment
->StreamHeader
;
226 // initialize all stream headers
227 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
231 // initialize extended size
232 hr
= KsDataTypeHandler
->KsPrepareIoOperation(SampleList
[Index
], (CurStreamHeader
+ 1), IoOperation
);
234 assert(hr
== NOERROR
);
237 // query for IMediaSample2 interface
238 IMediaSample2
* MediaSample
;
239 AM_SAMPLE2_PROPERTIES Properties
;
241 hr
= SampleList
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
246 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
248 //release IMediaSample2 interface
249 MediaSample
->Release();
254 hr
= SampleList
[Index
]->GetPointer((BYTE
**)&Properties
.pbBuffer
);
255 assert(hr
== NOERROR
);
256 hr
= SampleList
[Index
]->GetTime(&Properties
.tStart
, &Properties
.tStop
);
257 assert(hr
== NOERROR
);
259 Properties
.dwSampleFlags
= 0;
261 if (SampleList
[Index
]->IsDiscontinuity() == S_OK
)
262 Properties
.dwSampleFlags
|= AM_SAMPLE_DATADISCONTINUITY
;
264 if (SampleList
[Index
]->IsPreroll() == S_OK
)
265 Properties
.dwSampleFlags
|= AM_SAMPLE_PREROLL
;
267 if (SampleList
[Index
]->IsSyncPoint() == S_OK
)
268 Properties
.dwSampleFlags
|= AM_SAMPLE_SPLICEPOINT
;
272 swprintf(Buffer
, L
"BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u\n", Properties
.cbBuffer
, Properties
.pbBuffer
, ExtendedSize
, Properties
.lActual
);
273 OutputDebugStringW(Buffer
);
275 CurStreamHeader
->Size
= sizeof(KSSTREAM_HEADER
) + ExtendedSize
;
276 CurStreamHeader
->PresentationTime
.Denominator
= 1;
277 CurStreamHeader
->PresentationTime
.Numerator
= 1;
278 CurStreamHeader
->FrameExtent
= Properties
.cbBuffer
;
279 CurStreamHeader
->Data
= Properties
.pbBuffer
;
281 if (IoOperation
== KsIoOperation_Write
)
284 CurStreamHeader
->OptionsFlags
= Properties
.dwSampleFlags
;
285 CurStreamHeader
->DataUsed
= Properties
.lActual
;
286 // increment reference count
287 SampleList
[Index
]->AddRef();
290 // store sample in stream segment
291 StreamSegment
->MediaSample
[Index
] = SampleList
[Index
];
293 // move to next header
294 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
298 m_Pin
->KsIncrementPendingIoCount();
300 if (DeviceIoControl(m_Handle
,
301 IoOperation
== KsIoOperation_Write
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
,
303 StreamSegment
->StreamHeader
,
306 &StreamSegment
->Overlapped
))
309 SetEvent(StreamSegment
->StreamSegment
.CompletionEvent
);
311 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
315 if (GetLastError() == ERROR_IO_PENDING
)
317 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
326 CKsInterfaceHandler::KsCompleteIo(
327 PKSSTREAM_SEGMENT InStreamSegment
)
329 PKSSTREAM_SEGMENT_EXT StreamSegment
;
330 PKSSTREAM_HEADER CurStreamHeader
;
331 DWORD dwError
= ERROR_SUCCESS
, BytesReturned
;
335 IMediaSample2
* MediaSample
;
336 AM_SAMPLE2_PROPERTIES Properties
;
337 REFERENCE_TIME Start
, Stop
;
339 OutputDebugStringW(L
"CKsInterfaceHandler::KsCompleteIo\n");
341 // get private stream segment
342 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)InStreamSegment
;
345 bOverlapped
= GetOverlappedResult(m_Handle
, &StreamSegment
->Overlapped
, &BytesReturned
, FALSE
);
346 dwError
= GetLastError();
348 CurStreamHeader
= StreamSegment
->StreamHeader
;
350 //iterate through all stream headers
351 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
356 m_Pin
->KsNotifyError(StreamSegment
->MediaSample
[Index
], MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, dwError
));
359 // query IMediaSample2 interface
360 hr
= StreamSegment
->MediaSample
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
363 // media sample properties
364 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
367 //update media sample properties
368 Properties
.dwTypeSpecificFlags
= CurStreamHeader
->TypeSpecificFlags
;
369 Properties
.dwSampleFlags
|= (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY
);
371 MediaSample
->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
373 // release IMediaSample2 interface
374 MediaSample
->Release();
377 // was an extended header used
378 if (StreamSegment
->ExtendedSize
)
380 // unprepare stream header extension
381 StreamSegment
->StreamSegment
.KsDataTypeHandler
->KsCompleteIoOperation(StreamSegment
->MediaSample
[Index
], (CurStreamHeader
+ 1), StreamSegment
->StreamSegment
.IoOperation
, bOverlapped
== FALSE
);
386 if (bOverlapped
&& StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
388 // update common media sample details
389 StreamSegment
->MediaSample
[Index
]->SetSyncPoint((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT
));
390 StreamSegment
->MediaSample
[Index
]->SetPreroll((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_PREROLL
));
391 StreamSegment
->MediaSample
[Index
]->SetDiscontinuity((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
));
393 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEVALID
)
395 // use valid timestamp
396 Start
= CurStreamHeader
->PresentationTime
.Time
;
398 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DURATIONVALID
)
400 Stop
= CurStreamHeader
->PresentationTime
.Time
+ CurStreamHeader
->Duration
;
406 hr
= StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Stop
);
410 StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Start
);
413 // set valid data length
414 StreamSegment
->MediaSample
[Index
]->SetActualDataLength(CurStreamHeader
->DataUsed
);
416 if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
421 m_Pin
->KsDeliver(StreamSegment
->MediaSample
[Index
], CurStreamHeader
->OptionsFlags
);
424 else if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Write
)
426 // release media sample reference
427 StreamSegment
->MediaSample
[Index
]->Release();
430 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
433 // delete stream headers
434 CoTaskMemFree(StreamSegment
->StreamHeader
);
436 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
439 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
442 // decrement pending i/o count
443 m_Pin
->KsDecrementPendingIoCount();
445 //notify of completion
446 m_Pin
->KsMediaSamplesCompleted(InStreamSegment
);
448 //destroy stream segment
449 CoTaskMemFree(StreamSegment
);
451 //release reference to ourselves
455 // Event handle is closed by caller
461 CKsInterfaceHandler_Constructor(
462 IUnknown
* pUnkOuter
,
466 OutputDebugStringW(L
"CKsInterfaceHandler_Constructor\n");
468 CKsInterfaceHandler
* handler
= new CKsInterfaceHandler();
471 return E_OUTOFMEMORY
;
473 if (FAILED(handler
->QueryInterface(riid
, ppv
)))
477 return E_NOINTERFACE
;