Author: janderwald Date: Mon Mar 15 14:11:31 2010 New Revision: 46205
URL: http://svn.reactos.org/svn/reactos?rev=46205&view=rev Log: [KSPROXY] - Implement ISpecifyPropertyPages interface for CInputPin - Implement IKsInterfaceHandler::KsSetPin, IKsInterfaceHandler::KsProcessMediaSamples, IKsInterfaceHandler::KsCompleteIo
Modified: trunk/reactos/dll/directx/ksproxy/input_pin.cpp trunk/reactos/dll/directx/ksproxy/interface.cpp trunk/reactos/dll/directx/ksproxy/precomp.h
Modified: trunk/reactos/dll/directx/ksproxy/input_pin.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/input_p... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/input_pin.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/input_pin.cpp [iso-8859-1] Mon Mar 15 14:11:31 2010 @@ -52,11 +52,11 @@ public IKsControl, public IKsObject, public IKsPinEx, - public IMemInputPin + public IMemInputPin, + public ISpecifyPropertyPages /* public IQualityControl, public IKsPinPipe, - public ISpecifyPropertyPages, public IStreamBuilder, public IKsPinFactory, public IKsAggregateControl @@ -98,6 +98,9 @@ HRESULT STDMETHODCALLTYPE EndFlush(); HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+ // ISpecifyPropertyPages + HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages); + //IKsObject methods HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
@@ -205,7 +208,12 @@ reinterpret_cast<IKsPinEx*>(*Output)->AddRef(); return NOERROR; } - + else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) + { + *Output = (ISpecifyPropertyPages*)(this); + reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef(); + return NOERROR; + }
WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; @@ -215,6 +223,23 @@ CoTaskMemFree(lpstr);
return E_NOINTERFACE; +} + +//------------------------------------------------------------------- +// ISpecifyPropertyPages +// + +HRESULT +STDMETHODCALLTYPE +CInputPin::GetPages(CAUUID *pPages) +{ + if (!pPages) + return E_POINTER; + + pPages->cElems = 0; + pPages->pElems = NULL; + + return S_OK; }
//-------------------------------------------------------------------
Modified: trunk/reactos/dll/directx/ksproxy/interface.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/interfa... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/interface.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/interface.cpp [iso-8859-1] Mon Mar 15 14:11:31 2010 @@ -35,13 +35,26 @@ HRESULT STDMETHODCALLTYPE KsProcessMediaSamples(IKsDataTypeHandler *KsDataTypeHandler, IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, PKSSTREAM_SEGMENT *StreamSegment); HRESULT STDMETHODCALLTYPE KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment);
- CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL){}; + CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0){}; virtual ~CKsInterfaceHandler(){};
protected: LONG m_Ref; HANDLE m_Handle; + IKsPinEx * m_Pin; }; + +typedef struct +{ + KSSTREAM_SEGMENT StreamSegment; + IMediaSample * MediaSample[64]; + + ULONG SampleCount; + ULONG ExtendedSize; + PKSSTREAM_HEADER StreamHeader; + OVERLAPPED Overlapped; +}KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT; +
HRESULT STDMETHODCALLTYPE @@ -66,22 +79,43 @@ { HRESULT hr; IKsObject * KsObject; - - // check if IKsObject is supported - hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject); - + IKsPinEx * Pin; + + // get IKsPinEx interface + hr = KsPin->QueryInterface(IID_IKsPinEx, (void**)&Pin); if (SUCCEEDED(hr)) { - // get pin handle - m_Handle = KsObject->KsGetObjectHandle(); - - // release IKsObject interface - KsObject->Release(); - - if (!m_Handle) - { - // expected a file handle - return E_UNEXPECTED; + // check if IKsObject is supported + hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject); + + if (SUCCEEDED(hr)) + { + // get pin handle + m_Handle = KsObject->KsGetObjectHandle(); + + // release IKsObject interface + KsObject->Release(); + + if (!m_Handle) + { + // expected a file handle + hr = E_UNEXPECTED; + Pin->Release(); + } + else + { + if (m_Pin) + { + // release old interface + m_Pin->Release(); + } + m_Pin = Pin; + } + } + else + { + //release IKsPinEx interface + Pin->Release(); } }
@@ -96,19 +130,333 @@ IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, - PKSSTREAM_SEGMENT *StreamSegment) -{ - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; + PKSSTREAM_SEGMENT *OutStreamSegment) +{ + PKSSTREAM_SEGMENT_EXT StreamSegment; + ULONG ExtendedSize, Index, BytesReturned; + HRESULT hr = S_OK; + + OutputDebugString("CKsInterfaceHandler::KsProcessMediaSamples\n"); + + // sanity check + assert(*SampleCount); + + if (*SampleCount == 0 || *SampleCount < 0) + return E_FAIL; + + // zero stream segment + *OutStreamSegment = NULL; + + // allocate stream segment + StreamSegment = (PKSSTREAM_SEGMENT_EXT)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT)); + if (!StreamSegment) + return E_OUTOFMEMORY; + + // zero stream segment + ZeroMemory(StreamSegment, sizeof(KSSTREAM_SEGMENT_EXT)); + + //allocate event + StreamSegment->StreamSegment.CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (!StreamSegment->StreamSegment.CompletionEvent) + { + // failed to create event + CoTaskMemFree(StreamSegment); + return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); + } + + // increase our own reference count + AddRef(); + + // setup stream segment + StreamSegment->StreamSegment.KsDataTypeHandler = KsDataTypeHandler; + StreamSegment->StreamSegment.KsInterfaceHandler = (IKsInterfaceHandler*)this; + StreamSegment->StreamSegment.IoOperation = IoOperation; + StreamSegment->Overlapped.hEvent = StreamSegment->StreamSegment.CompletionEvent; + + + // ge extension size + ExtendedSize = 0; + if (KsDataTypeHandler) + { + // query extension size + KsDataTypeHandler->KsQueryExtendedSize(&ExtendedSize); + + if (ExtendedSize) + { + // increment reference count + KsDataTypeHandler->AddRef(); + } + else + { + // no need for the datatype handler + StreamSegment->StreamSegment.KsDataTypeHandler = NULL; + } + } + + StreamSegment->ExtendedSize = ExtendedSize; + StreamSegment->SampleCount = (ULONG)*SampleCount; + + // calculate stream header size count + ULONG StreamHeaderSize = StreamSegment->SampleCount * (sizeof(KSSTREAM_HEADER) + ExtendedSize); + + // allocate stream header + StreamSegment->StreamHeader = (PKSSTREAM_HEADER)CoTaskMemAlloc(StreamHeaderSize); + if (!StreamSegment->StreamHeader) + { + // not enough memory + CloseHandle(StreamSegment->StreamSegment.CompletionEvent); + + if (StreamSegment->StreamSegment.KsDataTypeHandler) + StreamSegment->StreamSegment.KsDataTypeHandler->Release(); + + // free stream segment + CoTaskMemFree(StreamSegment); + + //release our reference count + Release(); + return E_OUTOFMEMORY; + } + + // zero stream headers + ZeroMemory(StreamSegment->StreamHeader, StreamHeaderSize); + + PKSSTREAM_HEADER CurStreamHeader = StreamSegment->StreamHeader; + + // initialize all stream headers + for(Index = 0; Index < StreamSegment->SampleCount; Index++) + { + if (ExtendedSize) + { + // initialize extended size + hr = KsDataTypeHandler->KsPrepareIoOperation(SampleList[Index], (CurStreamHeader + 1), IoOperation); + // sanity check + assert(hr == NOERROR); + } + + // query for IMediaSample2 interface + IMediaSample2 * MediaSample; + AM_SAMPLE2_PROPERTIES Properties; + + hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample); + if (SUCCEEDED(hr)) + { + //get properties + + hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties); + + //release IMediaSample2 interface + MediaSample->Release(); + if (FAILED(hr)) + OutputDebugStringW(L"CKsInterfaceHandler::KsProcessMediaSamples MediaSample::GetProperties failed\n"); + } + else + { + OutputDebugStringW(L"CKsInterfaceHandler::KsProcessMediaSamples MediaSample:: only IMediaSample supported\n"); + // get properties + hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer); + assert(hr == NOERROR); + hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop); + assert(hr == NOERROR); + + Properties.dwSampleFlags = 0; + + if (SampleList[Index]->IsDiscontinuity() == S_OK) + Properties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY; + + if (SampleList[Index]->IsPreroll() == S_OK) + Properties.dwSampleFlags |= AM_SAMPLE_PREROLL; + + if (SampleList[Index]->IsSyncPoint() == S_OK) + Properties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT; + } + + WCHAR Buffer[100]; + swprintf(Buffer, L"BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u\n", Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual); + OutputDebugStringW(Buffer); + + CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize; + CurStreamHeader->PresentationTime.Denominator = 1; + CurStreamHeader->PresentationTime.Numerator = 1; + CurStreamHeader->FrameExtent = Properties.cbBuffer; + CurStreamHeader->Data = Properties.pbBuffer; + + if (IoOperation == KsIoOperation_Write) + { + // set flags + CurStreamHeader->OptionsFlags = Properties.dwSampleFlags; + CurStreamHeader->DataUsed = Properties.lActual; + // increment reference count + SampleList[Index]->AddRef(); + } + + // store sample in stream segment + StreamSegment->MediaSample[Index] = SampleList[Index]; + + // move to next header + CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size); + } + + // submit to device + m_Pin->KsIncrementPendingIoCount(); + + if (DeviceIoControl(m_Handle, + IoOperation == KsIoOperation_Write ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM, + NULL, 0, + StreamSegment->StreamHeader, + StreamHeaderSize, + &BytesReturned, + &StreamSegment->Overlapped)) + { + // signal completion + SetEvent(StreamSegment->StreamSegment.CompletionEvent); + hr = S_OK; + *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment; + } + else + { + if (GetLastError() == ERROR_IO_PENDING) + { + *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment; + hr = S_OK; + } + } + return hr; }
HRESULT STDMETHODCALLTYPE CKsInterfaceHandler::KsCompleteIo( - PKSSTREAM_SEGMENT StreamSegment) -{ - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; + PKSSTREAM_SEGMENT InStreamSegment) +{ + PKSSTREAM_SEGMENT_EXT StreamSegment; + PKSSTREAM_HEADER CurStreamHeader; + DWORD dwError = ERROR_SUCCESS, BytesReturned; + BOOL bOverlapped; + ULONG Index; + HRESULT hr; + IMediaSample2 * MediaSample; + AM_SAMPLE2_PROPERTIES Properties; + REFERENCE_TIME Start, Stop; + + OutputDebugStringW(L"CKsInterfaceHandler::KsCompleteIo\n"); + + // get private stream segment + StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment; + + // get result + bOverlapped = GetOverlappedResult(m_Handle, &StreamSegment->Overlapped, &BytesReturned, FALSE); + dwError = GetLastError(); + + CurStreamHeader = StreamSegment->StreamHeader; + + //iterate through all stream headers + for(Index = 0; Index < StreamSegment->SampleCount; Index++) + { + if (!bOverlapped) + { + // operation failed + m_Pin->KsNotifyError(StreamSegment->MediaSample[Index], MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwError)); + } + + // query IMediaSample2 interface + hr = StreamSegment->MediaSample[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample); + if (SUCCEEDED(hr)) + { + // media sample properties + hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties); + if (SUCCEEDED(hr)) + { + //update media sample properties + Properties.dwTypeSpecificFlags = CurStreamHeader->TypeSpecificFlags; + Properties.dwSampleFlags |= (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY); + + MediaSample->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties); + } + // release IMediaSample2 interface + MediaSample->Release(); + } + + // was an extended header used + if (StreamSegment->ExtendedSize) + { + // unprepare stream header extension + StreamSegment->StreamSegment.KsDataTypeHandler->KsCompleteIoOperation(StreamSegment->MediaSample[Index], (CurStreamHeader + 1), StreamSegment->StreamSegment.IoOperation, bOverlapped == FALSE); + } + + Start = 0; + Stop = 0; + if (bOverlapped && StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read) + { + // update common media sample details + StreamSegment->MediaSample[Index]->SetSyncPoint((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT)); + StreamSegment->MediaSample[Index]->SetPreroll((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_PREROLL)); + StreamSegment->MediaSample[Index]->SetDiscontinuity((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY)); + + if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID) + { + // use valid timestamp + Start = CurStreamHeader->PresentationTime.Time; + + if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DURATIONVALID) + { + Stop = CurStreamHeader->PresentationTime.Time + CurStreamHeader->Duration; + } + } + } + + // now set time + hr = StreamSegment->MediaSample[Index]->SetTime(&Start, &Stop); + if (FAILED(hr)) + { + // use start time + StreamSegment->MediaSample[Index]->SetTime(&Start, &Start); + } + + // set valid data length + StreamSegment->MediaSample[Index]->SetActualDataLength(CurStreamHeader->DataUsed); + + if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read) + { + if (bOverlapped) + { + // deliver sample + m_Pin->KsDeliver(StreamSegment->MediaSample[Index], CurStreamHeader->OptionsFlags); + } + } + else if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Write) + { + // release media sample reference + StreamSegment->MediaSample[Index]->Release(); + } + + CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size); + } + + // delete stream headers + CoTaskMemFree(StreamSegment->StreamHeader); + + if (StreamSegment->StreamSegment.KsDataTypeHandler) + { + // release reference + StreamSegment->StreamSegment.KsDataTypeHandler->Release(); + } + + // decrement pending i/o count + m_Pin->KsDecrementPendingIoCount(); + + //notify of completion + m_Pin->KsMediaSamplesCompleted(InStreamSegment); + + //destroy stream segment + CoTaskMemFree(StreamSegment); + + //release reference to ourselves + Release(); + + // done + // Event handle is closed by caller + return S_OK; }
HRESULT
Modified: trunk/reactos/dll/directx/ksproxy/precomp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/precomp... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/precomp.h [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/precomp.h [iso-8859-1] Mon Mar 15 14:11:31 2010 @@ -165,3 +165,4 @@ LPVOID * ppv);
extern const GUID IID_IKsObject; +extern const GUID IID_IKsPinEx;