Author: janderwald Date: Mon Mar 22 06:03:50 2010 New Revision: 46339
URL: http://svn.reactos.org/svn/reactos?rev=46339&view=rev Log: [KSPROXY] - Implement IKsAllocator interface - Implement IMediaSample interface - Implement querying the output pin for IMemInputPin and determine allocator properties. Currently the allocation strategy is limited to 16 Buffers with a size of 2048 * 188 (MPEG2 TS Payload size). Needs more work to determine a reasonable value - Implement overriding allocator if properties are not matching - Implement IPin::BeginFlush, IPin::EndFlush, IPin::EndOfStream, IPin::NewSegment for the OutputPin - Implement a I/O thread which queues the media sample to the kernel pin via IKsInterfaceHandler and then transmitts it to the connected input pin via IMemInputPin interface. - Implement setting pin state via a friend function, in order to synchronize the starting / stopping of the I/O thread - Fix a bug in IAMFilterMiscFlags::GetMiscFlags function - ksproxy (CLSID_Proxy) is now able to connect to MPEG-2 splitter and deliver samples. Needs more investigation why the render filter is not releasing the samples back to allocator, which causes the I/O thread to hang. WIP
Added: trunk/reactos/dll/directx/ksproxy/mediasample.cpp (with props) Modified: trunk/reactos/dll/directx/ksproxy/allocator.cpp trunk/reactos/dll/directx/ksproxy/interface.cpp trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild trunk/reactos/dll/directx/ksproxy/output_pin.cpp trunk/reactos/dll/directx/ksproxy/precomp.h trunk/reactos/dll/directx/ksproxy/proxy.cpp
Modified: trunk/reactos/dll/directx/ksproxy/allocator.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/allocat... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/allocator.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/allocator.cpp [iso-8859-1] Mon Mar 22 06:03:50 2010 @@ -15,6 +15,8 @@ public IMemAllocatorCallbackTemp { public: + typedef std::stack<IMediaSample *>MediaSampleStack; + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef() @@ -58,9 +60,9 @@ HRESULT STDMETHODCALLTYPE GetFreeCount(LONG *plBuffersFree);
- CKsAllocator() : m_Ref(0), m_hAllocator(0), m_Mode(KsAllocatorMode_User), m_Notify(0), m_Allocated(0), m_FreeCount(0), m_cbBuffer(0), m_cBuffers(0), m_cbAlign(0), m_cbPrefix(0){} + CKsAllocator(); virtual ~CKsAllocator(){} - + VOID STDMETHODCALLTYPE FreeMediaSamples(); protected: LONG m_Ref; HANDLE m_hAllocator; @@ -68,11 +70,15 @@ ALLOCATOR_PROPERTIES_EX m_Properties; IMemAllocatorNotifyCallbackTemp *m_Notify; ULONG m_Allocated; - ULONG m_FreeCount; - ULONG m_cbBuffer; - ULONG m_cBuffers; - ULONG m_cbAlign; - ULONG m_cbPrefix; + LONG m_cbBuffer; + LONG m_cBuffers; + LONG m_cbAlign; + LONG m_cbPrefix; + BOOL m_Commited; + CRITICAL_SECTION m_CriticalSection; + MediaSampleStack m_FreeList; + LPVOID m_Buffer; + BOOL m_FreeSamples; };
@@ -93,12 +99,30 @@ if (IsEqualGUID(refiid, IID_IMemAllocator) || IsEqualGUID(refiid, IID_IMemAllocatorCallbackTemp)) { - *Output = (IDistributorNotify*)(this); - reinterpret_cast<IDistributorNotify*>(*Output)->AddRef(); + *Output = (IMemAllocatorCallbackTemp*)(this); + reinterpret_cast<IMemAllocatorCallbackTemp*>(*Output)->AddRef(); return NOERROR; }
return E_NOINTERFACE; +} + +CKsAllocator::CKsAllocator() : m_Ref(0), + m_hAllocator(0), + m_Mode(KsAllocatorMode_User), + m_Notify(0), + m_Allocated(0), + m_cbBuffer(0), + m_cBuffers(0), + m_cbAlign(0), + m_cbPrefix(0), + m_Commited(FALSE), + m_FreeList(), + m_Buffer(0), + m_FreeSamples(FALSE) +{ + InitializeCriticalSection(&m_CriticalSection); + }
//------------------------------------------------------------------- @@ -112,7 +136,8 @@ { SYSTEM_INFO SystemInfo;
- OutputDebugStringW(L"CKsAllocator::SetProperties Stub\n"); + EnterCriticalSection(&m_CriticalSection); + OutputDebugStringW(L"CKsAllocator::SetProperties\n");
if (!pRequest || !pActual) return E_POINTER; @@ -126,18 +151,28 @@ if (!pRequest->cbAlign || (pRequest->cbAlign - 1) & SystemInfo.dwAllocationGranularity) { // bad alignment + LeaveCriticalSection(&m_CriticalSection); return VFW_E_BADALIGN; }
if (m_Mode == KsAllocatorMode_Kernel) { - // u cannt change a kernel allocator + // u can't change a kernel allocator + LeaveCriticalSection(&m_CriticalSection); return VFW_E_ALREADY_COMMITTED; }
- if (m_Allocated != m_FreeCount) + if (m_Commited) + { + // need to decommit first + LeaveCriticalSection(&m_CriticalSection); + return VFW_E_ALREADY_COMMITTED; + } + + if (m_Allocated != m_FreeList.size()) { // outstanding buffers + LeaveCriticalSection(&m_CriticalSection); return VFW_E_BUFFERS_OUTSTANDING; }
@@ -146,6 +181,7 @@ pActual->cbPrefix = m_cbPrefix = pRequest->cbPrefix; pActual->cBuffers = m_cBuffers = pRequest->cBuffers;
+ LeaveCriticalSection(&m_CriticalSection); return NOERROR; }
@@ -169,28 +205,126 @@ STDMETHODCALLTYPE CKsAllocator::Commit() { + LONG Index; + PUCHAR CurrentBuffer; + IMediaSample * Sample; + HRESULT hr; + + //TODO integer overflow checks + EnterCriticalSection(&m_CriticalSection); + + OutputDebugStringW(L"CKsAllocator::Commit\n"); + if (m_Mode == KsAllocatorMode_Kernel) { /* no-op for kernel allocator */ + LeaveCriticalSection(&m_CriticalSection); return NOERROR; }
- OutputDebugStringW(L"CKsAllocator::Commit NotImplemented\n"); - return E_NOTIMPL; + if (m_Commited) + { + // already commited + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + + if (m_cbBuffer < 0 || m_cBuffers < 0 || m_cbPrefix < 0) + { + // invalid parameter + LeaveCriticalSection(&m_CriticalSection); + return E_OUTOFMEMORY; + } + + LONG Size = m_cbBuffer + m_cbPrefix; + + if (m_cbAlign > 1) + { + //check alignment + LONG Mod = Size % m_cbAlign; + if (Mod) + { + // calculate aligned size + Size += m_cbAlign - Mod; + } + } + + LONG TotalSize = Size * m_cBuffers; + + assert(TotalSize); + assert(m_cBuffers); + assert(Size); + + // now allocate buffer + m_Buffer = VirtualAlloc(NULL, TotalSize, MEM_COMMIT, PAGE_READWRITE); + if (!m_Buffer) + { + LeaveCriticalSection(&m_CriticalSection); + return E_OUTOFMEMORY; + } + + ZeroMemory(m_Buffer, TotalSize); + + CurrentBuffer = (PUCHAR)m_Buffer; + + for (Index = 0; Index < m_cBuffers; Index++) + { + // construct media sample + hr = CMediaSample_Constructor((IMemAllocator*)this, CurrentBuffer + m_cbPrefix, m_cbBuffer, IID_IMediaSample, (void**)&Sample); + if (FAILED(hr)) + { + LeaveCriticalSection(&m_CriticalSection); + return E_OUTOFMEMORY; + } + + // add to free list + m_FreeList.push(Sample); + m_Allocated++; + + //next sample buffer + CurrentBuffer += Size; + } + + // we are now commited + m_Commited = true; + + LeaveCriticalSection(&m_CriticalSection); + return S_OK; }
HRESULT STDMETHODCALLTYPE CKsAllocator::Decommit() { + EnterCriticalSection(&m_CriticalSection); + + OutputDebugStringW(L"CKsAllocator::Decommit\n"); + if (m_Mode == KsAllocatorMode_Kernel) { /* no-op for kernel allocator */ - return NOERROR; - } - - OutputDebugStringW(L"CKsAllocator::Decommit NotImplemented\n"); - return E_NOTIMPL; + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + + m_Commited = false; + + if (m_Allocated != m_FreeList.size()) + { + // outstanding buffers + m_FreeSamples = true; + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + else + { + // no outstanding buffers + // free to free them + FreeMediaSamples(); + } + + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; }
@@ -202,8 +336,40 @@ REFERENCE_TIME *pEndTime, DWORD dwFlags) { - OutputDebugStringW(L"CKsAllocator::GetBuffer NotImplemented\n"); - return E_NOTIMPL; + IMediaSample * Sample = NULL; + OutputDebugStringW(L"CKsAllocator::GetBuffer\n"); + + do + { + EnterCriticalSection(&m_CriticalSection); + + if (!m_FreeList.empty()) + { + Sample = m_FreeList.top(); + m_FreeList.pop(); + } + + LeaveCriticalSection(&m_CriticalSection); + + if (dwFlags & AM_GBF_NOWAIT) + { + // never wait untill a buffer becomes available + break; + } + } + while(Sample == NULL); + + if (!Sample) + { + // no sample acquired + return VFW_E_TIMEOUT; + } + + // store result + *ppBuffer = Sample; + + // done + return NOERROR; }
HRESULT @@ -211,8 +377,33 @@ CKsAllocator::ReleaseBuffer( IMediaSample *pBuffer) { - OutputDebugStringW(L"CKsAllocator::ReleaseBuffer NotImplemented\n"); - return E_NOTIMPL; + EnterCriticalSection(&m_CriticalSection); + + OutputDebugStringW(L"CKsAllocator::ReleaseBuffer\n"); + + // media sample always 1 ref count in free list + pBuffer->AddRef(); + + // add the sample to the free list + m_FreeList.push(pBuffer); + + if (m_FreeSamples) + { + // pending de-commit + if (m_FreeList.size () == m_Allocated) + { + FreeMediaSamples(); + } + } + + if (m_Notify) + { + //notify caller of an available buffer + m_Notify->NotifyRelease(); + } + + LeaveCriticalSection(&m_CriticalSection); + return S_OK; }
//------------------------------------------------------------------- @@ -223,6 +414,7 @@ CKsAllocator::SetNotify( IMemAllocatorNotifyCallbackTemp *pNotify) { + EnterCriticalSection(&m_CriticalSection); OutputDebugStringW(L"CKsAllocator::SetNotify\n");
if (pNotify) @@ -232,6 +424,8 @@ m_Notify->Release();
m_Notify = pNotify; + + LeaveCriticalSection(&m_CriticalSection); return NOERROR; }
@@ -240,8 +434,8 @@ CKsAllocator::GetFreeCount( LONG *plBuffersFree) { - OutputDebugStringW(L"CKsAllocator::GetFreeCount NotImplemented\n"); - return E_NOTIMPL; + *plBuffersFree = m_Allocated - m_FreeList.size(); + return S_OK; }
//------------------------------------------------------------------- @@ -349,6 +543,32 @@ return m_hAllocator; }
+//------------------------------------------------------------------- +VOID +STDMETHODCALLTYPE +CKsAllocator::FreeMediaSamples() +{ + ULONG Index; + + for(Index = 0; Index < m_FreeList.size(); Index++) + { + IMediaSample * Sample = m_FreeList.top(); + m_FreeList.pop(); + delete Sample; + } + + m_FreeSamples = false; + m_Allocated = 0; + + if (m_Buffer) + { + // release buffer + VirtualFree(m_Buffer, 0, MEM_RELEASE); + + m_Buffer = NULL; + } +} + HRESULT WINAPI CKsAllocator_Constructor(
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 22 06:03:50 2010 @@ -35,24 +35,25 @@ 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), m_Pin(0){}; + CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0) {m_PinName[0] = L'\0';}; virtual ~CKsInterfaceHandler(){};
protected: LONG m_Ref; HANDLE m_Handle; IKsPinEx * m_Pin; + WCHAR m_PinName[129]; };
typedef struct { KSSTREAM_SEGMENT StreamSegment; + OVERLAPPED Overlapped; IMediaSample * MediaSample[64];
ULONG SampleCount; ULONG ExtendedSize; PKSSTREAM_HEADER StreamHeader; - OVERLAPPED Overlapped; }KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT;
@@ -118,6 +119,38 @@ Pin->Release(); } } +#if 1 + //DBG code + PIN_INFO PinInfo; + IPin * pPin; + if (SUCCEEDED(KsPin->QueryInterface(IID_IPin, (void**)&pPin))) + { + if (SUCCEEDED(pPin->QueryPinInfo(&PinInfo))) + { + if (PinInfo.pFilter) + PinInfo.pFilter->Release(); + + wcscpy(m_PinName, PinInfo.achName); + } + pPin->Release(); + } + + IKsAllocatorEx * Allocator; + + if (SUCCEEDED(KsPin->QueryInterface(IID_IKsAllocatorEx, (void**)&Allocator))) + { + PALLOCATOR_PROPERTIES_EX Properties = Allocator->KsGetProperties(); + + if (Properties) + { + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsInterfaceHandler::KsSetPin PinName %s Properties.cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", m_PinName, Properties->cbAlign, Properties->cbBuffer, Properties->cbPrefix, Properties->cBuffers); + OutputDebugStringW(Buffer); + } + Allocator->Release(); + } + +#endif
// done return hr; @@ -135,8 +168,6 @@ PKSSTREAM_SEGMENT_EXT StreamSegment; ULONG ExtendedSize, Index, BytesReturned; HRESULT hr = S_OK; - - OutputDebugString("CKsInterfaceHandler::KsProcessMediaSamples\n");
// sanity check assert(*SampleCount); @@ -256,6 +287,9 @@ hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop); assert(hr == NOERROR);
+ Properties.cbBuffer = SampleList[Index]->GetSize(); + assert(Properties.cbBuffer); + Properties.dwSampleFlags = 0;
if (SampleList[Index]->IsDiscontinuity() == S_OK) @@ -268,9 +302,9 @@ 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); + WCHAR Buffer[200]; + swprintf(Buffer, L"CKsInterfaceHandler::KsProcessMediaSamples PinName %s BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u\n", m_PinName, Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual); + //OutputDebugStringW(Buffer);
CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize; CurStreamHeader->PresentationTime.Denominator = 1; @@ -336,8 +370,6 @@ AM_SAMPLE2_PROPERTIES Properties; REFERENCE_TIME Start, Stop;
- OutputDebugStringW(L"CKsInterfaceHandler::KsCompleteIo\n"); - // get private stream segment StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment;
@@ -346,6 +378,10 @@ dwError = GetLastError();
CurStreamHeader = StreamSegment->StreamHeader; + + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsInterfaceHandler::KsCompleteIo PinName %s bOverlapped %u hr %lx\n", m_PinName, bOverlapped, dwError); + //OutputDebugStringW(Buffer);
//iterate through all stream headers for(Index = 0; Index < StreamSegment->SampleCount; Index++)
Modified: trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/ksproxy... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild [iso-8859-1] Mon Mar 22 06:03:50 2010 @@ -33,6 +33,7 @@ <file>interface.cpp</file> <file>ksproxy.cpp</file> <file>ksproxy.rc</file> + <file>mediasample.cpp</file> <file>node.cpp</file> <file>output_pin.cpp</file> <file>proxy.cpp</file>
Added: trunk/reactos/dll/directx/ksproxy/mediasample.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/mediasa... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/mediasample.cpp (added) +++ trunk/reactos/dll/directx/ksproxy/mediasample.cpp [iso-8859-1] Mon Mar 22 06:03:50 2010 @@ -1,0 +1,350 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy + * FILE: dll/directx/ksproxy/mediasample.cpp + * PURPOSE: IMediaSample interface + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ +#include "precomp.h" + +class CMediaSample : public IMediaSample +{ +public: + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); + + STDMETHODIMP_(ULONG) AddRef() + { + InterlockedIncrement(&m_Ref); + return m_Ref; + } + STDMETHODIMP_(ULONG) Release() + { + InterlockedDecrement(&m_Ref); + DebugBreak(); + if (!m_Ref) + { + if (m_Allocator) + { + m_Allocator->ReleaseBuffer((IMediaSample*)this); + return 0; + } + delete this; + return 0; + } + return m_Ref; + } + + HRESULT STDMETHODCALLTYPE GetPointer(BYTE **ppBuffer); + long STDMETHODCALLTYPE GetSize(void); + HRESULT STDMETHODCALLTYPE GetTime(REFERENCE_TIME *pTimeStart, REFERENCE_TIME *pTimeEnd); + HRESULT STDMETHODCALLTYPE SetTime(REFERENCE_TIME *pTimeStart, REFERENCE_TIME *pTimeEnd); + HRESULT STDMETHODCALLTYPE IsSyncPoint(); + HRESULT STDMETHODCALLTYPE SetSyncPoint(BOOL bIsSyncPoint); + HRESULT STDMETHODCALLTYPE IsPreroll(); + HRESULT STDMETHODCALLTYPE SetPreroll(BOOL bIsPreroll); + long STDMETHODCALLTYPE GetActualDataLength(); + HRESULT STDMETHODCALLTYPE SetActualDataLength(long Length); + HRESULT STDMETHODCALLTYPE GetMediaType(AM_MEDIA_TYPE **ppMediaType); + HRESULT STDMETHODCALLTYPE SetMediaType(AM_MEDIA_TYPE *pMediaType); + HRESULT STDMETHODCALLTYPE IsDiscontinuity(); + HRESULT STDMETHODCALLTYPE SetDiscontinuity(BOOL bDiscontinuity); + HRESULT STDMETHODCALLTYPE GetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd); + HRESULT STDMETHODCALLTYPE SetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd); + + CMediaSample(IMemAllocator * Allocator, BYTE * Buffer, LONG BufferSize); + virtual ~CMediaSample(){} + +protected: + LONG m_Ref; + IMemAllocator * m_Allocator; + BYTE * m_Buffer; + LONG m_BufferSize; + LONG m_ActualLength; + REFERENCE_TIME m_StartTime; + REFERENCE_TIME m_StopTime; + ULONG m_Flags; + BOOL m_bMediaTimeValid; + LONGLONG m_MediaStart; + LONGLONG m_MediaStop; + +}; + +CMediaSample::CMediaSample( + IMemAllocator * Allocator, + BYTE * Buffer, + LONG BufferSize) : m_Ref(0), + m_Allocator(Allocator), + m_Buffer(Buffer), + m_BufferSize(BufferSize), + m_ActualLength(BufferSize), + m_StartTime(0), + m_StopTime(0), + m_Flags(0), + m_bMediaTimeValid(0), + m_MediaStart(0), + m_MediaStop(0) +{ +} + + +HRESULT +STDMETHODCALLTYPE +CMediaSample::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + if (IsEqualGUID(refiid, IID_IUnknown) || + IsEqualGUID(refiid, IID_IMediaSample)) + { + *Output = PVOID(this); + reinterpret_cast<IMediaSample*>(*Output)->AddRef(); + return NOERROR; + } + if (IsEqualGUID(refiid, IID_IMediaSample2)) + { + + OutputDebugStringW(L"CMediaSample::QueryInterface requested IMediaSample2 interface\n"); +#if 0 + *Output = (IMediaSample2*)(this); + reinterpret_cast<IMediaSample2*>(*Output)->AddRef(); + return NOERROR; +#endif + } + + return E_NOINTERFACE; +} + +//------------------------------------------------------------------- +// IMediaSample interface +// +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetPointer( + BYTE **ppBuffer) +{ + if (!ppBuffer) + return E_POINTER; + + *ppBuffer = m_Buffer; + return S_OK; +} + +long +STDMETHODCALLTYPE +CMediaSample::GetSize() +{ + return m_BufferSize; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetTime( + REFERENCE_TIME *pTimeStart, + REFERENCE_TIME *pTimeEnd) +{ + HRESULT hr; + + if (!pTimeStart || !pTimeEnd) + return E_POINTER; + + if (!(m_Flags & (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID))) + { + // no time is set + return VFW_E_SAMPLE_TIME_NOT_SET; + } + + *pTimeStart = m_StartTime; + + if (m_Flags & AM_SAMPLE_STOPVALID) + { + *pTimeEnd = m_StopTime; + hr = NOERROR; + } + else + { + *pTimeEnd = m_StartTime + 1; + hr = VFW_S_NO_STOP_TIME; + } + return hr; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetTime(REFERENCE_TIME *pTimeStart, REFERENCE_TIME *pTimeEnd) +{ + if (!pTimeStart) + { + m_Flags &= ~(AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID); + return NOERROR; + } + + if (!pTimeEnd) + { + m_Flags &= ~(AM_SAMPLE_STOPVALID); + m_Flags |= AM_SAMPLE_TIMEVALID; + m_StartTime = *pTimeStart; + return NOERROR; + } + + + m_Flags |= (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID); + m_StartTime = *pTimeStart; + m_StopTime = *pTimeEnd; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::IsSyncPoint() +{ + return (m_Flags & AM_SAMPLE_SPLICEPOINT) ? S_OK : S_FALSE; +} +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetSyncPoint(BOOL bIsSyncPoint) +{ + if (bIsSyncPoint) + m_Flags |= AM_SAMPLE_SPLICEPOINT; + else + m_Flags &= ~AM_SAMPLE_SPLICEPOINT; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::IsPreroll() +{ + return (m_Flags & AM_SAMPLE_PREROLL) ? S_OK : S_FALSE; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetPreroll(BOOL bIsPreroll) +{ + if (bIsPreroll) + m_Flags |= AM_SAMPLE_PREROLL; + else + m_Flags &= ~AM_SAMPLE_PREROLL; + + return NOERROR; +} + +long +STDMETHODCALLTYPE +CMediaSample::GetActualDataLength() +{ + return m_ActualLength; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetActualDataLength(long Length) +{ + if (Length > m_BufferSize) + return VFW_E_BUFFER_OVERFLOW; + + m_ActualLength = Length; + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetMediaType(AM_MEDIA_TYPE **ppMediaType) +{ + OutputDebugStringW(L"CMediaSample::GetMediaType NotImplemented\n"); + DebugBreak(); + return E_NOTIMPL; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetMediaType(AM_MEDIA_TYPE *pMediaType) +{ + OutputDebugStringW(L"CMediaSample::SetMediaType NotImplemented\n"); + DebugBreak(); + return E_NOTIMPL; +} + + +HRESULT +STDMETHODCALLTYPE +CMediaSample::IsDiscontinuity() +{ + return (m_Flags & AM_SAMPLE_DATADISCONTINUITY) ? S_OK : S_FALSE; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetDiscontinuity(BOOL bDiscontinuity) +{ + if (bDiscontinuity) + m_Flags |= AM_SAMPLE_DATADISCONTINUITY; + else + m_Flags &= ~AM_SAMPLE_DATADISCONTINUITY; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd) +{ + if (!pTimeStart || !pTimeEnd) + return E_POINTER; + + if (!m_bMediaTimeValid) + return VFW_E_MEDIA_TIME_NOT_SET; + + m_MediaStart = *pTimeStart; + m_MediaStop = *pTimeEnd; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd) +{ + if (!pTimeStart || !pTimeEnd) + { + m_bMediaTimeValid = false; + return NOERROR; + } + + m_MediaStart = *pTimeStart; + m_MediaStop = *pTimeEnd; + + return NOERROR; +} + + + + +HRESULT +WINAPI +CMediaSample_Constructor( + IMemAllocator* Allocator, + BYTE* pBuffer, + ULONG BufferSize, + REFIID riid, + LPVOID * ppv) +{ + OutputDebugStringW(L"CMediaSample_Constructor\n"); + + CMediaSample * handler = new CMediaSample(Allocator, pBuffer, BufferSize); + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return NOERROR; +}
Propchange: trunk/reactos/dll/directx/ksproxy/mediasample.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/directx/ksproxy/output_pin.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/output_... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/output_pin.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/output_pin.cpp [iso-8859-1] Mon Mar 22 06:03:50 2010 @@ -160,6 +160,11 @@ HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); + HRESULT WINAPI IoProcessRoutine(); + HRESULT WINAPI InitializeIOThread(); + + friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter); + friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State);
protected: LONG m_Ref; @@ -178,6 +183,7 @@ PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
IMemAllocator * m_MemAllocator; + IMemInputPin * m_MemInputPin; LONG m_IoCount; KSPIN_COMMUNICATION m_Communication; KSPIN_INTERFACE m_Interface; @@ -187,6 +193,14 @@ IMediaSeeking * m_FilterMediaSeeking; ALLOCATOR_PROPERTIES m_Properties; IKsInterfaceHandler * m_InterfaceHandler; + + HANDLE m_hStartEvent; + HANDLE m_hBufferAvailable; + HANDLE m_hStopEvent; + BOOL m_StopInProgress; + BOOL m_IoThreadStarted; + + KSSTATE m_State; };
COutputPin::~COutputPin() @@ -211,10 +225,17 @@ m_bPinBusCacheInitialized(0), m_FilterName(0), m_MemAllocator(0), + m_MemInputPin(0), m_IoCount(0), m_Communication(Communication), m_FilterMediaSeeking(0), - m_InterfaceHandler(0) + m_InterfaceHandler(0), + m_hStartEvent(0), + m_hBufferAvailable(0), + m_hStopEvent(0), + m_StopInProgress(0), + m_IoThreadStarted(0), + m_State(KSSTATE_STOP) { HRESULT hr;
@@ -452,8 +473,12 @@ STDMETHODCALLTYPE COutputPin::NotifyRelease() { - OutputDebugStringW(L"COutputPin::NotifyRelease NotImplemented\n"); - return E_NOTIMPL; + OutputDebugStringW(L"COutputPin::NotifyRelease\n"); + + // notify thread of new available sample + SetEvent(m_hBufferAvailable); + + return NOERROR; }
//------------------------------------------------------------------- @@ -1220,6 +1245,9 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { HRESULT hr; + ALLOCATOR_PROPERTIES Properties; + IMemAllocatorCallbackTemp *pMemCallback; + WCHAR Buffer[200];
OutputDebugStringW(L"COutputPin::Connect called\n"); if (pmt) @@ -1238,7 +1266,105 @@ pmt = &m_MediaFormat; }
- //FIXME create pin handle + // query for IMemInput interface + hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin); + if (FAILED(hr)) + { + OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n"); + DebugBreak(); + return hr; + } + + // get input pin allocator properties + ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES)); + m_MemInputPin->GetAllocatorRequirements(&Properties); + + //FIXME determine allocator properties + Properties.cBuffers = 16; + Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size + Properties.cbAlign = 4; + + // get input pin allocator + hr = m_MemInputPin->GetAllocator(&m_MemAllocator); + if (SUCCEEDED(hr)) + { + // set allocator properties + hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); + if (FAILED(hr)) + m_MemAllocator->Release(); + } + + if (FAILED(hr)) + { + hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator); + if (FAILED(hr)) + return hr; + + // set allocator properties + hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); + if (FAILED(hr)) + { + swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr); + OutputDebugStringW(Buffer); + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + } + + // commit property changes + hr = m_MemAllocator->Commit(); + if (FAILED(hr)) + { + swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr); + OutputDebugStringW(Buffer); + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + // get callback interface + hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback); + if (FAILED(hr)) + { + swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr); + OutputDebugStringW(Buffer); + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + // set notification routine + hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this); + + // release IMemAllocatorNotifyCallbackTemp interface + pMemCallback->Release(); + + if (FAILED(hr)) + { + swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr); + OutputDebugStringW(Buffer); + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + // now set allocator + hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE); + if (FAILED(hr)) + { + swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr); + OutputDebugStringW(Buffer); + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + if (!m_hPin) + { + //FIXME create pin handle + assert(0); + }
// receive connection; hr = pReceivePin->ReceiveConnection((IPin*)this, pmt); @@ -1249,6 +1375,11 @@ m_Pin = pReceivePin; OutputDebugStringW(L"COutputPin::Connect success\n"); } + else + { + m_MemInputPin->Release(); + m_MemAllocator->Release(); + }
return hr; } @@ -1257,7 +1388,6 @@ STDMETHODCALLTYPE COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) { - OutputDebugStringW(L"COutputPin::ReceiveConnection\n"); return E_UNEXPECTED; } HRESULT @@ -1277,6 +1407,8 @@
m_Pin->Release(); m_Pin = NULL; + m_MemInputPin->Release(); + m_MemAllocator->Release();
OutputDebugStringW(L"COutputPin::Disconnect\n"); return S_OK; @@ -1421,29 +1553,34 @@ STDMETHODCALLTYPE COutputPin::EndOfStream( void) { - OutputDebugStringW(L"COutputPin::EndOfStream called\n"); - return E_NOTIMPL; + /* should be called only on input pins */ + return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::BeginFlush( void) { - OutputDebugStringW(L"COutputPin::BeginFlush called\n"); - return E_NOTIMPL; + /* should be called only on input pins */ + return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::EndFlush( void) { - OutputDebugStringW(L"COutputPin::EndFlush called\n"); - return E_NOTIMPL; + /* should be called only on input pins */ + return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) { - OutputDebugStringW(L"COutputPin::NewSegment called\n"); - return E_NOTIMPL; + if (!m_Pin) + { + // we are not connected + return VFW_E_NOT_CONNECTED; + } + + return m_Pin->NewSegment(tStart, tStop, dRate); }
//------------------------------------------------------------------- @@ -1600,6 +1737,9 @@ PKSDATAFORMAT DataFormat; ULONG Length; HRESULT hr; + //KSALLOCATOR_FRAMING Framing; + //KSPROPERTY Property; + //ULONG BytesReturned;
if (m_hPin != INVALID_HANDLE_VALUE) { @@ -1651,7 +1791,7 @@ assert(hFilter != NULL);
// create pin - hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin); + hr = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
if (SUCCEEDED(hr)) { @@ -1683,6 +1823,28 @@ } CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); } +#if 0 + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; + Property.Flags = KSPROPERTY_TYPE_GET; + + ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING)); + hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); + if (SUCCEEDED(hr)) + { + m_Properties.cbAlign = (Framing.FileAlignment + 1); + m_Properties.cbBuffer = Framing.FrameSize; + m_Properties.cbPrefix = 0; //FIXME + m_Properties.cBuffers = Framing.Frames; + } + hr = S_OK; +#endif + + if (FAILED(InitializeIOThread())) + { + OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n"); + DebugBreak(); + }
//TODO // connect pin pipes @@ -1693,6 +1855,277 @@
return hr; } + +HRESULT +WINAPI +COutputPin::IoProcessRoutine() +{ + IMediaSample *Sample; + LONG SampleCount; + HRESULT hr; + PKSSTREAM_SEGMENT StreamSegment; + HANDLE hEvent; + WCHAR Buffer[100]; + IMediaSample * Samples[1]; + + // first wait for the start event to signal + WaitForSingleObject(m_hStartEvent, INFINITE); + + assert(m_InterfaceHandler); + REFERENCE_TIME Start = 0; + REFERENCE_TIME Stop = 1; + do + { + if (m_StopInProgress) + { + // stop io thread + break; + } + + // get buffer + hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT); + + if (FAILED(hr)) + { + m_Pin->BeginFlush(); + OutputDebugStringW(L"Beginning flushing...\n"); + WaitForSingleObject(m_hBufferAvailable, INFINITE); + m_Pin->EndFlush(); + // now retry again + continue; + } + + // fill buffer + SampleCount = 1; + Samples[0] = Sample; + + + Sample->SetTime(&Start, &Stop); + hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */ + Samples, + &SampleCount, + KsIoOperation_Read, + &StreamSegment); + if (FAILED(hr) || !StreamSegment) + { + swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples PinName %s hr %lx StreamSegment %p\n", m_PinName, hr, StreamSegment); + OutputDebugStringW(Buffer); + break; + } + + // get completion event + hEvent = StreamSegment->CompletionEvent; + + // wait for i/o completion + WaitForSingleObject(hEvent, INFINITE); + + // perform completion + m_InterfaceHandler->KsCompleteIo(StreamSegment); + + // close completion event + CloseHandle(hEvent); + + if (SUCCEEDED(hr)) + { + Sample->GetTime(&Start, &Stop); + Start = Stop; + Stop++; + + // now deliver the sample + hr = m_MemInputPin->Receive(Sample); + + swprintf(Buffer, L"COutputPin::IoProcessRoutine IMemInputPin::Receive hr %lx Start %I64u Stop %I64u\n", hr, Start, Stop); + OutputDebugStringW(Buffer); + } + }while(TRUE); + + // signal end of i/o thread + SetEvent(m_hStopEvent); + + m_IoThreadStarted = false; + + return NOERROR; +} + +DWORD +WINAPI +COutputPin_IoThreadStartup( + LPVOID lpParameter) +{ + COutputPin * Pin = (COutputPin*)lpParameter; + assert(Pin); + + return Pin->IoProcessRoutine(); +} + + +HRESULT +WINAPI +COutputPin::InitializeIOThread() +{ + HANDLE hThread; + + if (m_IoThreadStarted) + return NOERROR; + + if (!m_hStartEvent) + m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + else + ResetEvent(m_hStartEvent); + + if (!m_hStartEvent) + return E_OUTOFMEMORY; + + if (!m_hStopEvent) + m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + else + ResetEvent(m_hStopEvent); + + if (!m_hStopEvent) + return E_OUTOFMEMORY; + + if (!m_hBufferAvailable) + m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL); + else + ResetEvent(m_hBufferAvailable); + + if (!m_hBufferAvailable) + return E_OUTOFMEMORY; + + m_StopInProgress = false; + m_IoThreadStarted = true; + + // now create the startup thread + hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL); + if (!hThread) + return E_OUTOFMEMORY; + + + // close thread handle + CloseHandle(hThread); + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin_SetState( + IPin * Pin, + KSSTATE State) +{ + HRESULT hr = S_OK; + KSPROPERTY Property; + KSSTATE CurState; + WCHAR Buffer[100]; + ULONG BytesReturned; + + COutputPin * pPin = (COutputPin*)Pin; + + + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + + if (pPin->m_State < State) + { + if (pPin->m_State == KSSTATE_STOP) + { + CurState = KSSTATE_ACQUIRE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + + swprintf(Buffer, L"COutputPin_SetState Setting State KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); + if (FAILED(hr)) + return hr; + + pPin->m_State = CurState; + + if (pPin->m_State == State) + return hr; + } + if (pPin->m_State == KSSTATE_ACQUIRE) + { + CurState = KSSTATE_PAUSE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + + swprintf(Buffer, L"COutputPin_SetState Setting State KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); + if (FAILED(hr)) + return hr; + + pPin->m_State = CurState; + + if (pPin->m_State == State) + return hr; + } + + CurState = KSSTATE_RUN; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + + swprintf(Buffer, L"COutputPin_SetState Setting State KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); + if (FAILED(hr)) + return hr; + + // signal start event + SetEvent(pPin->m_hStartEvent); + + + pPin->m_State = CurState; + return hr; + } + else + { + if (pPin->m_State == KSSTATE_RUN) + { + CurState = KSSTATE_PAUSE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + + swprintf(Buffer, L"COutputPin_SetState Setting State KSSTATE_PAUSE PinName %u hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); + if (FAILED(hr)) + return hr; + + pPin->m_State = CurState; + + if (pPin->m_State == State) + return hr; + } + if (pPin->m_State == KSSTATE_PAUSE) + { + CurState = KSSTATE_ACQUIRE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + + swprintf(Buffer, L"COutputPin_SetState Setting State KSSTATE_ACQUIRE PinName %u hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); + if (FAILED(hr)) + return hr; + + pPin->m_State = CurState; + + if (pPin->m_State == State) + return hr; + } + + // setting pending stop flag + pPin->m_StopInProgress = true; + + CurState = KSSTATE_STOP; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + + swprintf(Buffer, L"COutputPin_SetState Setting State KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); + if (FAILED(hr)) + return hr; + + // wait until i/o thread is done + WaitForSingleObject(pPin->m_hStopEvent, INFINITE); + + pPin->m_State = CurState; + return hr; + } +} +
HRESULT WINAPI
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 22 06:03:50 2010 @@ -18,6 +18,7 @@ #include <setupapi.h> #include <stdio.h> #include <vector> +#include <stack> #include <assert.h> #include <ksmedia.h> //#include <debug.h> @@ -138,6 +139,12 @@ REFIID riid, LPVOID * ppv);
+HRESULT +STDMETHODCALLTYPE +COutputPin_SetState( + IPin * Pin, + KSSTATE State); + /* enumpins.cpp */ HRESULT WINAPI @@ -165,11 +172,31 @@ ACCESS_MASK DesiredAccess, REFIID riid, LPVOID * ppv); + +/* allocator.cpp */ +HRESULT +WINAPI +CKsAllocator_Constructor( + IUnknown * pUnkOuter, + REFIID riid, + LPVOID * ppv); + +/* mediasample.cpp */ +HRESULT +WINAPI +CMediaSample_Constructor( + IMemAllocator* Allocator, + BYTE* pBuffer, + ULONG BufferSize, + REFIID riid, + LPVOID * ppv); +
extern const GUID IID_IKsObject; extern const GUID IID_IKsPinEx; extern const GUID IID_IKsAggregateControl; extern const GUID IID_IKsPinPipe; extern const GUID IID_IKsPinFactory; +extern const GUID IID_IKsAllocatorEx; extern KSPIN_INTERFACE StandardPinInterface; extern KSPIN_MEDIUM StandardPinMedium;
Modified: trunk/reactos/dll/directx/ksproxy/proxy.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/proxy.c... ============================================================================== --- trunk/reactos/dll/directx/ksproxy/proxy.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/directx/ksproxy/proxy.cpp [iso-8859-1] Mon Mar 22 06:03:50 2010 @@ -1599,7 +1599,7 @@ if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId &Communication))) { - if (Communication == KSPIN_COMMUNICATION_NONE || Communication == KSPIN_COMMUNICATION_BRIDGE) + if (Communication != KSPIN_COMMUNICATION_NONE && Communication != KSPIN_COMMUNICATION_BRIDGE) { Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE; } @@ -2578,6 +2578,7 @@ IKsObject *pObject; ULONG BytesReturned; KSPROPERTY Property; + PIN_INFO PinInfo;
Property.Set = KSPROPSETID_Connection; Property.Id = KSPROPERTY_CONNECTION_STATE; @@ -2601,6 +2602,22 @@
// release connected pin TempPin->Release(); + + // query for the pin info + hr = Pin->QueryPinInfo(&PinInfo); + + if (SUCCEEDED(hr)) + { + if (PinInfo.pFilter) + PinInfo.pFilter->Release(); + + if (PinInfo.dir == PINDIR_OUTPUT) + { + hr = COutputPin_SetState(Pin, State); + if (SUCCEEDED(hr)) + continue; + } + }
//query IKsObject interface hr = Pin->QueryInterface(IID_IKsObject, (void**)&pObject);