From: Johannes Anderwald Date: Mon, 15 Mar 2010 13:11:31 +0000 (+0000) Subject: [KSPROXY] X-Git-Tag: backups/header-work@57446~118^2~35 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=59b9f20eeeba2fa1c592deb7cf441c68b00eba9c [KSPROXY] - Implement ISpecifyPropertyPages interface for CInputPin - Implement IKsInterfaceHandler::KsSetPin, IKsInterfaceHandler::KsProcessMediaSamples, IKsInterfaceHandler::KsCompleteIo svn path=/trunk/; revision=46205 --- diff --git a/reactos/dll/directx/ksproxy/input_pin.cpp b/reactos/dll/directx/ksproxy/input_pin.cpp index 857b3cc687e..e922b2e156a 100644 --- a/reactos/dll/directx/ksproxy/input_pin.cpp +++ b/reactos/dll/directx/ksproxy/input_pin.cpp @@ -52,11 +52,11 @@ class CInputPin : public IPin, 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 @@ public: 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 @@ CInputPin::QueryInterface( reinterpret_cast(*Output)->AddRef(); return NOERROR; } - + else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) + { + *Output = (ISpecifyPropertyPages*)(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; @@ -217,6 +225,23 @@ CInputPin::QueryInterface( return E_NOINTERFACE; } +//------------------------------------------------------------------- +// ISpecifyPropertyPages +// + +HRESULT +STDMETHODCALLTYPE +CInputPin::GetPages(CAUUID *pPages) +{ + if (!pPages) + return E_POINTER; + + pPages->cElems = 0; + pPages->pElems = NULL; + + return S_OK; +} + //------------------------------------------------------------------- // IMemInputPin // diff --git a/reactos/dll/directx/ksproxy/interface.cpp b/reactos/dll/directx/ksproxy/interface.cpp index 4289cd1fc11..7b6b0d9961b 100644 --- a/reactos/dll/directx/ksproxy/interface.cpp +++ b/reactos/dll/directx/ksproxy/interface.cpp @@ -35,14 +35,27 @@ public: 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 CKsInterfaceHandler::QueryInterface( @@ -66,22 +79,43 @@ CKsInterfaceHandler::KsSetPin( { HRESULT hr; IKsObject * KsObject; + IKsPinEx * Pin; - // check if IKsObject is supported - hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject); - + // get IKsPinEx interface + hr = KsPin->QueryInterface(IID_IKsPinEx, (void**)&Pin); if (SUCCEEDED(hr)) { - // get pin handle - m_Handle = KsObject->KsGetObjectHandle(); + // 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(); + // release IKsObject interface + KsObject->Release(); - if (!m_Handle) + 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 { - // expected a file handle - return E_UNEXPECTED; + //release IKsPinEx interface + Pin->Release(); } } @@ -96,19 +130,333 @@ CKsInterfaceHandler::KsProcessMediaSamples( IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, - PKSSTREAM_SEGMENT *StreamSegment) + PKSSTREAM_SEGMENT *OutStreamSegment) { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; + 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) + PKSSTREAM_SEGMENT InStreamSegment) { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; + 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 diff --git a/reactos/dll/directx/ksproxy/precomp.h b/reactos/dll/directx/ksproxy/precomp.h index 59e2b23779b..839878ee985 100644 --- a/reactos/dll/directx/ksproxy/precomp.h +++ b/reactos/dll/directx/ksproxy/precomp.h @@ -165,3 +165,4 @@ CKsNode_Constructor( LPVOID * ppv); extern const GUID IID_IKsObject; +extern const GUID IID_IKsPinEx;