Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninterface.cpp
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy 00004 * FILE: dll/directx/ksproxy/interface.cpp 00005 * PURPOSE: IKsInterfaceHandler interface 00006 * 00007 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) 00008 */ 00009 #include "precomp.h" 00010 00011 const GUID IID_IKsObject = {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}}; 00012 00013 class CKsInterfaceHandler : public IKsInterfaceHandler 00014 { 00015 public: 00016 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 00017 00018 STDMETHODIMP_(ULONG) AddRef() 00019 { 00020 InterlockedIncrement(&m_Ref); 00021 return m_Ref; 00022 } 00023 STDMETHODIMP_(ULONG) Release() 00024 { 00025 InterlockedDecrement(&m_Ref); 00026 00027 if (!m_Ref) 00028 { 00029 delete this; 00030 return 0; 00031 } 00032 return m_Ref; 00033 } 00034 HRESULT STDMETHODCALLTYPE KsSetPin(IKsPin *KsPin); 00035 HRESULT STDMETHODCALLTYPE KsProcessMediaSamples(IKsDataTypeHandler *KsDataTypeHandler, IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, PKSSTREAM_SEGMENT *StreamSegment); 00036 HRESULT STDMETHODCALLTYPE KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment); 00037 00038 CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0) {m_PinName[0] = L'\0';}; 00039 virtual ~CKsInterfaceHandler(){}; 00040 00041 protected: 00042 LONG m_Ref; 00043 HANDLE m_Handle; 00044 IKsPinEx * m_Pin; 00045 WCHAR m_PinName[129]; 00046 }; 00047 00048 typedef struct 00049 { 00050 KSSTREAM_SEGMENT StreamSegment; 00051 OVERLAPPED Overlapped; 00052 IMediaSample * MediaSample[64]; 00053 00054 ULONG SampleCount; 00055 ULONG ExtendedSize; 00056 PKSSTREAM_HEADER StreamHeader; 00057 }KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT; 00058 00059 00060 HRESULT 00061 STDMETHODCALLTYPE 00062 CKsInterfaceHandler::QueryInterface( 00063 IN REFIID refiid, 00064 OUT PVOID* Output) 00065 { 00066 if (IsEqualGUID(refiid, IID_IUnknown) || 00067 IsEqualGUID(refiid, IID_IKsInterfaceHandler)) 00068 { 00069 *Output = PVOID(this); 00070 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 00071 return NOERROR; 00072 } 00073 return E_NOINTERFACE; 00074 } 00075 00076 HRESULT 00077 STDMETHODCALLTYPE 00078 CKsInterfaceHandler::KsSetPin( 00079 IKsPin *KsPin) 00080 { 00081 HRESULT hr; 00082 IKsObject * KsObject; 00083 IKsPinEx * Pin; 00084 00085 // get IKsPinEx interface 00086 hr = KsPin->QueryInterface(IID_IKsPinEx, (void**)&Pin); 00087 if (SUCCEEDED(hr)) 00088 { 00089 // check if IKsObject is supported 00090 hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject); 00091 00092 if (SUCCEEDED(hr)) 00093 { 00094 // get pin handle 00095 m_Handle = KsObject->KsGetObjectHandle(); 00096 00097 // release IKsObject interface 00098 KsObject->Release(); 00099 00100 if (!m_Handle) 00101 { 00102 // expected a file handle 00103 hr = E_UNEXPECTED; 00104 Pin->Release(); 00105 } 00106 else 00107 { 00108 if (m_Pin) 00109 { 00110 // release old interface 00111 m_Pin->Release(); 00112 } 00113 m_Pin = Pin; 00114 } 00115 } 00116 else 00117 { 00118 //release IKsPinEx interface 00119 Pin->Release(); 00120 } 00121 } 00122 #if 1 00123 //DBG code 00124 PIN_INFO PinInfo; 00125 IPin * pPin; 00126 if (SUCCEEDED(KsPin->QueryInterface(IID_IPin, (void**)&pPin))) 00127 { 00128 if (SUCCEEDED(pPin->QueryPinInfo(&PinInfo))) 00129 { 00130 if (PinInfo.pFilter) 00131 PinInfo.pFilter->Release(); 00132 00133 wcscpy(m_PinName, PinInfo.achName); 00134 } 00135 pPin->Release(); 00136 } 00137 #endif 00138 00139 // done 00140 return hr; 00141 } 00142 00143 HRESULT 00144 STDMETHODCALLTYPE 00145 CKsInterfaceHandler::KsProcessMediaSamples( 00146 IKsDataTypeHandler *KsDataTypeHandler, 00147 IMediaSample** SampleList, 00148 PLONG SampleCount, 00149 KSIOOPERATION IoOperation, 00150 PKSSTREAM_SEGMENT *OutStreamSegment) 00151 { 00152 PKSSTREAM_SEGMENT_EXT StreamSegment; 00153 ULONG ExtendedSize, Index, BytesReturned; 00154 HRESULT hr = S_OK; 00155 00156 // sanity check 00157 assert(*SampleCount); 00158 00159 if (*SampleCount == 0 || *SampleCount < 0) 00160 return E_FAIL; 00161 00162 // zero stream segment 00163 *OutStreamSegment = NULL; 00164 00165 // allocate stream segment 00166 StreamSegment = (PKSSTREAM_SEGMENT_EXT)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT)); 00167 if (!StreamSegment) 00168 return E_OUTOFMEMORY; 00169 00170 // zero stream segment 00171 ZeroMemory(StreamSegment, sizeof(KSSTREAM_SEGMENT_EXT)); 00172 00173 //allocate event 00174 StreamSegment->StreamSegment.CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 00175 00176 if (!StreamSegment->StreamSegment.CompletionEvent) 00177 { 00178 // failed to create event 00179 CoTaskMemFree(StreamSegment); 00180 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 00181 } 00182 00183 // increase our own reference count 00184 AddRef(); 00185 00186 // setup stream segment 00187 StreamSegment->StreamSegment.KsDataTypeHandler = KsDataTypeHandler; 00188 StreamSegment->StreamSegment.KsInterfaceHandler = (IKsInterfaceHandler*)this; 00189 StreamSegment->StreamSegment.IoOperation = IoOperation; 00190 StreamSegment->Overlapped.hEvent = StreamSegment->StreamSegment.CompletionEvent; 00191 00192 00193 // ge extension size 00194 ExtendedSize = 0; 00195 if (KsDataTypeHandler) 00196 { 00197 // query extension size 00198 KsDataTypeHandler->KsQueryExtendedSize(&ExtendedSize); 00199 00200 if (ExtendedSize) 00201 { 00202 // increment reference count 00203 KsDataTypeHandler->AddRef(); 00204 } 00205 else 00206 { 00207 // no need for the datatype handler 00208 StreamSegment->StreamSegment.KsDataTypeHandler = NULL; 00209 } 00210 } 00211 00212 StreamSegment->ExtendedSize = ExtendedSize; 00213 StreamSegment->SampleCount = (ULONG)*SampleCount; 00214 00215 // calculate stream header size count 00216 ULONG StreamHeaderSize = StreamSegment->SampleCount * (sizeof(KSSTREAM_HEADER) + ExtendedSize); 00217 00218 // allocate stream header 00219 StreamSegment->StreamHeader = (PKSSTREAM_HEADER)CoTaskMemAlloc(StreamHeaderSize); 00220 if (!StreamSegment->StreamHeader) 00221 { 00222 // not enough memory 00223 CloseHandle(StreamSegment->StreamSegment.CompletionEvent); 00224 00225 if (StreamSegment->StreamSegment.KsDataTypeHandler) 00226 StreamSegment->StreamSegment.KsDataTypeHandler->Release(); 00227 00228 // free stream segment 00229 CoTaskMemFree(StreamSegment); 00230 00231 //release our reference count 00232 Release(); 00233 return E_OUTOFMEMORY; 00234 } 00235 00236 // zero stream headers 00237 ZeroMemory(StreamSegment->StreamHeader, StreamHeaderSize); 00238 00239 PKSSTREAM_HEADER CurStreamHeader = StreamSegment->StreamHeader; 00240 00241 // initialize all stream headers 00242 for(Index = 0; Index < StreamSegment->SampleCount; Index++) 00243 { 00244 if (ExtendedSize) 00245 { 00246 // initialize extended size 00247 hr = KsDataTypeHandler->KsPrepareIoOperation(SampleList[Index], (CurStreamHeader + 1), IoOperation); 00248 // sanity check 00249 assert(hr == NOERROR); 00250 } 00251 00252 // query for IMediaSample2 interface 00253 IMediaSample2 * MediaSample; 00254 AM_SAMPLE2_PROPERTIES Properties; 00255 ZeroMemory(&Properties, sizeof(AM_SAMPLE2_PROPERTIES)); 00256 00257 hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample); 00258 if (SUCCEEDED(hr)) 00259 { 00260 //get properties 00261 00262 hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties); 00263 00264 //release IMediaSample2 interface 00265 MediaSample->Release(); 00266 } 00267 else 00268 { 00269 // get properties 00270 hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer); 00271 assert(hr == NOERROR); 00272 hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop); 00273 00274 Properties.cbBuffer = SampleList[Index]->GetSize(); 00275 assert(Properties.cbBuffer); 00276 00277 Properties.dwSampleFlags = 0; 00278 00279 if (SampleList[Index]->IsDiscontinuity() == S_OK) 00280 Properties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY; 00281 00282 if (SampleList[Index]->IsPreroll() == S_OK) 00283 Properties.dwSampleFlags |= AM_SAMPLE_PREROLL; 00284 00285 if (SampleList[Index]->IsSyncPoint() == S_OK) 00286 Properties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT; 00287 } 00288 #ifdef KSPROXY_TRACE 00289 WCHAR Buffer[200]; 00290 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); 00291 OutputDebugStringW(Buffer); 00292 #endif 00293 00294 CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize; 00295 CurStreamHeader->PresentationTime.Denominator = 1; 00296 CurStreamHeader->PresentationTime.Numerator = 1; 00297 CurStreamHeader->FrameExtent = Properties.cbBuffer; 00298 CurStreamHeader->Data = Properties.pbBuffer; 00299 00300 if (IoOperation == KsIoOperation_Write) 00301 { 00302 // set flags 00303 CurStreamHeader->OptionsFlags = Properties.dwSampleFlags; 00304 CurStreamHeader->DataUsed = Properties.lActual; 00305 // increment reference count 00306 SampleList[Index]->AddRef(); 00307 } 00308 00309 // store sample in stream segment 00310 StreamSegment->MediaSample[Index] = SampleList[Index]; 00311 00312 // move to next header 00313 CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size); 00314 } 00315 00316 // submit to device 00317 m_Pin->KsIncrementPendingIoCount(); 00318 00319 if (DeviceIoControl(m_Handle, 00320 IoOperation == KsIoOperation_Write ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM, 00321 NULL, 0, 00322 StreamSegment->StreamHeader, 00323 StreamHeaderSize, 00324 &BytesReturned, 00325 &StreamSegment->Overlapped)) 00326 { 00327 // signal completion 00328 SetEvent(StreamSegment->StreamSegment.CompletionEvent); 00329 hr = S_OK; 00330 *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment; 00331 } 00332 else 00333 { 00334 if (GetLastError() == ERROR_IO_PENDING) 00335 { 00336 *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment; 00337 hr = S_OK; 00338 } 00339 } 00340 return hr; 00341 } 00342 00343 HRESULT 00344 STDMETHODCALLTYPE 00345 CKsInterfaceHandler::KsCompleteIo( 00346 PKSSTREAM_SEGMENT InStreamSegment) 00347 { 00348 PKSSTREAM_SEGMENT_EXT StreamSegment; 00349 PKSSTREAM_HEADER CurStreamHeader; 00350 DWORD dwError = ERROR_SUCCESS, BytesReturned; 00351 BOOL bOverlapped; 00352 ULONG Index; 00353 HRESULT hr; 00354 IMediaSample2 * MediaSample; 00355 AM_SAMPLE2_PROPERTIES Properties; 00356 REFERENCE_TIME Start, Stop; 00357 00358 // get private stream segment 00359 StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment; 00360 00361 // get result 00362 bOverlapped = GetOverlappedResult(m_Handle, &StreamSegment->Overlapped, &BytesReturned, FALSE); 00363 dwError = GetLastError(); 00364 00365 CurStreamHeader = StreamSegment->StreamHeader; 00366 00367 //iterate through all stream headers 00368 for(Index = 0; Index < StreamSegment->SampleCount; Index++) 00369 { 00370 if (!bOverlapped) 00371 { 00372 // operation failed 00373 m_Pin->KsNotifyError(StreamSegment->MediaSample[Index], MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwError)); 00374 } 00375 00376 // query IMediaSample2 interface 00377 hr = StreamSegment->MediaSample[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample); 00378 if (SUCCEEDED(hr)) 00379 { 00380 // media sample properties 00381 hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties); 00382 if (SUCCEEDED(hr)) 00383 { 00384 //update media sample properties 00385 Properties.dwTypeSpecificFlags = CurStreamHeader->TypeSpecificFlags; 00386 Properties.dwSampleFlags |= (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY); 00387 00388 MediaSample->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties); 00389 } 00390 // release IMediaSample2 interface 00391 MediaSample->Release(); 00392 } 00393 00394 // was an extended header used 00395 if (StreamSegment->ExtendedSize) 00396 { 00397 // unprepare stream header extension 00398 StreamSegment->StreamSegment.KsDataTypeHandler->KsCompleteIoOperation(StreamSegment->MediaSample[Index], (CurStreamHeader + 1), StreamSegment->StreamSegment.IoOperation, bOverlapped == FALSE); 00399 } 00400 00401 Start = 0; 00402 Stop = 0; 00403 if (bOverlapped && StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read) 00404 { 00405 // update common media sample details 00406 StreamSegment->MediaSample[Index]->SetSyncPoint((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT)); 00407 StreamSegment->MediaSample[Index]->SetPreroll((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_PREROLL)); 00408 StreamSegment->MediaSample[Index]->SetDiscontinuity((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY)); 00409 00410 if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID) 00411 { 00412 // use valid timestamp 00413 Start = CurStreamHeader->PresentationTime.Time; 00414 00415 if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DURATIONVALID) 00416 { 00417 Stop = CurStreamHeader->PresentationTime.Time + CurStreamHeader->Duration; 00418 } 00419 } 00420 } 00421 00422 // now set time 00423 hr = StreamSegment->MediaSample[Index]->SetTime(&Start, &Stop); 00424 if (FAILED(hr)) 00425 { 00426 // use start time 00427 StreamSegment->MediaSample[Index]->SetTime(&Start, &Start); 00428 } 00429 00430 // set valid data length 00431 StreamSegment->MediaSample[Index]->SetActualDataLength(CurStreamHeader->DataUsed); 00432 00433 if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read) 00434 { 00435 if (bOverlapped) 00436 { 00437 // deliver sample 00438 m_Pin->KsDeliver(StreamSegment->MediaSample[Index], CurStreamHeader->OptionsFlags); 00439 } 00440 } 00441 else if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Write) 00442 { 00443 // release media sample reference 00444 StreamSegment->MediaSample[Index]->Release(); 00445 } 00446 00447 CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size); 00448 } 00449 00450 // delete stream headers 00451 CoTaskMemFree(StreamSegment->StreamHeader); 00452 00453 if (StreamSegment->StreamSegment.KsDataTypeHandler) 00454 { 00455 // release reference 00456 StreamSegment->StreamSegment.KsDataTypeHandler->Release(); 00457 } 00458 00459 // decrement pending i/o count 00460 m_Pin->KsDecrementPendingIoCount(); 00461 00462 //notify of completion 00463 m_Pin->KsMediaSamplesCompleted(InStreamSegment); 00464 00465 //destroy stream segment 00466 CoTaskMemFree(StreamSegment); 00467 00468 //release reference to ourselves 00469 Release(); 00470 00471 // done 00472 // Event handle is closed by caller 00473 return S_OK; 00474 } 00475 00476 HRESULT 00477 WINAPI 00478 CKsInterfaceHandler_Constructor( 00479 IUnknown * pUnkOuter, 00480 REFIID riid, 00481 LPVOID * ppv) 00482 { 00483 #ifdef KSPROXY_TRACE 00484 OutputDebugStringW(L"CKsInterfaceHandler_Constructor\n"); 00485 #endif 00486 00487 CKsInterfaceHandler * handler = new CKsInterfaceHandler(); 00488 00489 if (!handler) 00490 return E_OUTOFMEMORY; 00491 00492 if (FAILED(handler->QueryInterface(riid, ppv))) 00493 { 00494 /* not supported */ 00495 delete handler; 00496 return E_NOINTERFACE; 00497 } 00498 00499 return NOERROR; 00500 } Generated on Sun May 27 2012 04:21:51 for ReactOS by
1.7.6.1
|