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
);
294 CurStreamHeader
->Size
= sizeof(KSSTREAM_HEADER
) + ExtendedSize
;
295 CurStreamHeader
->PresentationTime
.Denominator
= 1;
296 CurStreamHeader
->PresentationTime
.Numerator
= 1;
297 CurStreamHeader
->FrameExtent
= Properties
.cbBuffer
;
298 CurStreamHeader
->Data
= Properties
.pbBuffer
;
300 if (IoOperation
== KsIoOperation_Write
)
303 CurStreamHeader
->OptionsFlags
= Properties
.dwSampleFlags
;
304 CurStreamHeader
->DataUsed
= Properties
.lActual
;
305 // increment reference count
306 SampleList
[Index
]->AddRef();
309 // store sample in stream segment
310 StreamSegment
->MediaSample
[Index
] = SampleList
[Index
];
312 // move to next header
313 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
317 m_Pin
->KsIncrementPendingIoCount();
319 if (DeviceIoControl(m_Handle
,
320 IoOperation
== KsIoOperation_Write
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
,
322 StreamSegment
->StreamHeader
,
325 &StreamSegment
->Overlapped
))
328 SetEvent(StreamSegment
->StreamSegment
.CompletionEvent
);
330 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
334 if (GetLastError() == ERROR_IO_PENDING
)
336 *OutStreamSegment
= (PKSSTREAM_SEGMENT
)StreamSegment
;
345 CKsInterfaceHandler::KsCompleteIo(
346 PKSSTREAM_SEGMENT InStreamSegment
)
348 PKSSTREAM_SEGMENT_EXT StreamSegment
;
349 PKSSTREAM_HEADER CurStreamHeader
;
350 DWORD dwError
= ERROR_SUCCESS
, BytesReturned
;
354 IMediaSample2
* MediaSample
;
355 AM_SAMPLE2_PROPERTIES Properties
;
356 REFERENCE_TIME Start
, Stop
;
358 // get private stream segment
359 StreamSegment
= (PKSSTREAM_SEGMENT_EXT
)InStreamSegment
;
362 bOverlapped
= GetOverlappedResult(m_Handle
, &StreamSegment
->Overlapped
, &BytesReturned
, FALSE
);
363 dwError
= GetLastError();
365 CurStreamHeader
= StreamSegment
->StreamHeader
;
367 //iterate through all stream headers
368 for(Index
= 0; Index
< StreamSegment
->SampleCount
; Index
++)
373 m_Pin
->KsNotifyError(StreamSegment
->MediaSample
[Index
], MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, dwError
));
376 // query IMediaSample2 interface
377 hr
= StreamSegment
->MediaSample
[Index
]->QueryInterface(IID_IMediaSample2
, (void**)&MediaSample
);
380 // media sample properties
381 hr
= MediaSample
->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
384 //update media sample properties
385 Properties
.dwTypeSpecificFlags
= CurStreamHeader
->TypeSpecificFlags
;
386 Properties
.dwSampleFlags
|= (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY
);
388 MediaSample
->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES
), (BYTE
*)&Properties
);
390 // release IMediaSample2 interface
391 MediaSample
->Release();
394 // was an extended header used
395 if (StreamSegment
->ExtendedSize
)
397 // unprepare stream header extension
398 StreamSegment
->StreamSegment
.KsDataTypeHandler
->KsCompleteIoOperation(StreamSegment
->MediaSample
[Index
], (CurStreamHeader
+ 1), StreamSegment
->StreamSegment
.IoOperation
, bOverlapped
== FALSE
);
403 if (bOverlapped
&& StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
405 // update common media sample details
406 StreamSegment
->MediaSample
[Index
]->SetSyncPoint((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT
));
407 StreamSegment
->MediaSample
[Index
]->SetPreroll((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_PREROLL
));
408 StreamSegment
->MediaSample
[Index
]->SetDiscontinuity((CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
));
410 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_TIMEVALID
)
412 // use valid timestamp
413 Start
= CurStreamHeader
->PresentationTime
.Time
;
415 if (CurStreamHeader
->OptionsFlags
& KSSTREAM_HEADER_OPTIONSF_DURATIONVALID
)
417 Stop
= CurStreamHeader
->PresentationTime
.Time
+ CurStreamHeader
->Duration
;
423 hr
= StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Stop
);
427 StreamSegment
->MediaSample
[Index
]->SetTime(&Start
, &Start
);
430 // set valid data length
431 StreamSegment
->MediaSample
[Index
]->SetActualDataLength(CurStreamHeader
->DataUsed
);
433 if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Read
)
438 m_Pin
->KsDeliver(StreamSegment
->MediaSample
[Index
], CurStreamHeader
->OptionsFlags
);
441 else if (StreamSegment
->StreamSegment
.IoOperation
== KsIoOperation_Write
)
443 // release media sample reference
444 StreamSegment
->MediaSample
[Index
]->Release();
447 CurStreamHeader
= (PKSSTREAM_HEADER
)((ULONG_PTR
)CurStreamHeader
+ CurStreamHeader
->Size
);
450 // delete stream headers
451 CoTaskMemFree(StreamSegment
->StreamHeader
);
453 if (StreamSegment
->StreamSegment
.KsDataTypeHandler
)
456 StreamSegment
->StreamSegment
.KsDataTypeHandler
->Release();
459 // decrement pending i/o count
460 m_Pin
->KsDecrementPendingIoCount();
462 //notify of completion
463 m_Pin
->KsMediaSamplesCompleted(InStreamSegment
);
465 //destroy stream segment
466 CoTaskMemFree(StreamSegment
);
468 //release reference to ourselves
472 // Event handle is closed by caller
478 CKsInterfaceHandler_Constructor(
479 IUnknown
* pUnkOuter
,
484 OutputDebugStringW(L
"CKsInterfaceHandler_Constructor\n");
487 CKsInterfaceHandler
* handler
= new CKsInterfaceHandler();
490 return E_OUTOFMEMORY
;
492 if (FAILED(handler
->QueryInterface(riid
, ppv
)))
496 return E_NOINTERFACE
;