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/alloca…
==============================================================================
--- 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/interf…
==============================================================================
--- 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/ksprox…
==============================================================================
--- 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/medias…
==============================================================================
--- 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(a)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/precom…
==============================================================================
--- 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.…
==============================================================================
--- 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);