mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 00:45:49 +00:00
[KSPROXY]
- HACK: Return the oldest used sample when the allocator runs out of samples. Fixes playback as the render does not seem to release the media samples - Start implementing IKsClockForwarder interface - Fix a few bugs in KsOpenDefaultDevice - Implement IMediaSample::GetMediaType - Always use the CKsAllocator interface for allocating samples svn path=/trunk/; revision=46346
This commit is contained in:
parent
f93825c2b2
commit
89cff88aa2
8 changed files with 261 additions and 77 deletions
|
@ -16,6 +16,7 @@ class CKsAllocator : public IKsAllocatorEx,
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::stack<IMediaSample *>MediaSampleStack;
|
typedef std::stack<IMediaSample *>MediaSampleStack;
|
||||||
|
typedef std::list<IMediaSample *>MediaSampleList;
|
||||||
|
|
||||||
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
|
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ protected:
|
||||||
BOOL m_Commited;
|
BOOL m_Commited;
|
||||||
CRITICAL_SECTION m_CriticalSection;
|
CRITICAL_SECTION m_CriticalSection;
|
||||||
MediaSampleStack m_FreeList;
|
MediaSampleStack m_FreeList;
|
||||||
|
MediaSampleList m_UsedList;
|
||||||
LPVOID m_Buffer;
|
LPVOID m_Buffer;
|
||||||
BOOL m_FreeSamples;
|
BOOL m_FreeSamples;
|
||||||
};
|
};
|
||||||
|
@ -118,6 +120,7 @@ CKsAllocator::CKsAllocator() : m_Ref(0),
|
||||||
m_cbPrefix(0),
|
m_cbPrefix(0),
|
||||||
m_Commited(FALSE),
|
m_Commited(FALSE),
|
||||||
m_FreeList(),
|
m_FreeList(),
|
||||||
|
m_UsedList(),
|
||||||
m_Buffer(0),
|
m_Buffer(0),
|
||||||
m_FreeSamples(FALSE)
|
m_FreeSamples(FALSE)
|
||||||
{
|
{
|
||||||
|
@ -362,12 +365,20 @@ CKsAllocator::GetBuffer(
|
||||||
if (!Sample)
|
if (!Sample)
|
||||||
{
|
{
|
||||||
// no sample acquired
|
// no sample acquired
|
||||||
return VFW_E_TIMEOUT;
|
//HACKKKKKKK
|
||||||
|
Sample = m_UsedList.back();
|
||||||
|
m_UsedList.pop_back();
|
||||||
|
|
||||||
|
if (!Sample)
|
||||||
|
return VFW_E_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store result
|
// store result
|
||||||
*ppBuffer = Sample;
|
*ppBuffer = Sample;
|
||||||
|
|
||||||
|
// store sample in used list
|
||||||
|
m_UsedList.push_front(Sample);
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return NOERROR;
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
@ -387,6 +398,7 @@ CKsAllocator::ReleaseBuffer(
|
||||||
// add the sample to the free list
|
// add the sample to the free list
|
||||||
m_FreeList.push(pBuffer);
|
m_FreeList.push(pBuffer);
|
||||||
|
|
||||||
|
|
||||||
if (m_FreeSamples)
|
if (m_FreeSamples)
|
||||||
{
|
{
|
||||||
// pending de-commit
|
// pending de-commit
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
const GUID KSCATEGORY_CLOCK = {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
const GUID KSCATEGORY_CLOCK = {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter);
|
||||||
|
|
||||||
class CKsClockForwarder : public IDistributorNotify,
|
class CKsClockForwarder : public IDistributorNotify,
|
||||||
public IKsObject
|
public IKsObject
|
||||||
{
|
{
|
||||||
|
@ -45,14 +47,38 @@ public:
|
||||||
// IKsObject interface
|
// IKsObject interface
|
||||||
HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
|
HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
|
||||||
|
|
||||||
CKsClockForwarder(HANDLE handle) : m_Ref(0), m_Handle(handle){}
|
CKsClockForwarder(HANDLE handle);
|
||||||
virtual ~CKsClockForwarder(){ if (m_Handle) CloseHandle(m_Handle);}
|
virtual ~CKsClockForwarder(){};
|
||||||
|
HRESULT STDMETHODCALLTYPE SetClockState(KSSTATE State);
|
||||||
protected:
|
protected:
|
||||||
LONG m_Ref;
|
LONG m_Ref;
|
||||||
HANDLE m_Handle;
|
HANDLE m_Handle;
|
||||||
|
IReferenceClock * m_Clock;
|
||||||
|
HANDLE m_hEvent;
|
||||||
|
HANDLE m_hThread;
|
||||||
|
BOOL m_ThreadStarted;
|
||||||
|
BOOL m_PendingStop;
|
||||||
|
BOOL m_ForceStart;
|
||||||
|
KSSTATE m_State;
|
||||||
|
REFERENCE_TIME m_Time;
|
||||||
|
|
||||||
|
friend DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CKsClockForwarder::CKsClockForwarder(
|
||||||
|
HANDLE handle) : m_Ref(0),
|
||||||
|
m_Handle(handle),
|
||||||
|
m_Clock(0),
|
||||||
|
m_hEvent(NULL),
|
||||||
|
m_hThread(NULL),
|
||||||
|
m_ThreadStarted(FALSE),
|
||||||
|
m_PendingStop(FALSE),
|
||||||
|
m_ForceStart(FALSE),
|
||||||
|
m_State(KSSTATE_STOP),
|
||||||
|
m_Time(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
CKsClockForwarder::QueryInterface(
|
CKsClockForwarder::QueryInterface(
|
||||||
|
@ -100,16 +126,79 @@ HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
CKsClockForwarder::Stop()
|
CKsClockForwarder::Stop()
|
||||||
{
|
{
|
||||||
OutputDebugString("UNIMPLEMENTED\n");
|
OutputDebugString("CKsClockForwarder::Stop\n");
|
||||||
return E_NOTIMPL;
|
|
||||||
|
if (m_ThreadStarted)
|
||||||
|
{
|
||||||
|
// signal pending stop
|
||||||
|
m_PendingStop = true;
|
||||||
|
|
||||||
|
assert(m_hThread);
|
||||||
|
assert(m_hEvent);
|
||||||
|
|
||||||
|
// set stop event
|
||||||
|
SetEvent(m_hEvent);
|
||||||
|
|
||||||
|
// wait untill the thread has finished
|
||||||
|
WaitForSingleObject(m_hThread, INFINITE);
|
||||||
|
|
||||||
|
// close thread handle
|
||||||
|
CloseHandle(m_hThread);
|
||||||
|
|
||||||
|
// zero handle
|
||||||
|
m_hThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hEvent)
|
||||||
|
{
|
||||||
|
// close stop event
|
||||||
|
CloseHandle(m_hEvent);
|
||||||
|
m_hEvent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_PendingStop = false;
|
||||||
|
|
||||||
|
SetClockState(KSSTATE_STOP);
|
||||||
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
CKsClockForwarder::Pause()
|
CKsClockForwarder::Pause()
|
||||||
{
|
{
|
||||||
OutputDebugString("UNIMPLEMENTED\n");
|
OutputDebugString("CKsClockForwarder::Pause\n");
|
||||||
return E_NOTIMPL;
|
|
||||||
|
if (!m_hEvent)
|
||||||
|
{
|
||||||
|
m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (!m_hEvent)
|
||||||
|
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_State <= KSSTATE_PAUSE)
|
||||||
|
{
|
||||||
|
if (m_State == KSSTATE_STOP)
|
||||||
|
SetClockState(KSSTATE_ACQUIRE);
|
||||||
|
|
||||||
|
if (m_State == KSSTATE_ACQUIRE)
|
||||||
|
SetClockState(KSSTATE_PAUSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!m_ForceStart)
|
||||||
|
{
|
||||||
|
SetClockState(KSSTATE_PAUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_hThread)
|
||||||
|
{
|
||||||
|
m_hThread = CreateThread(NULL, 0, CKsClockForwarder_ThreadStartup, (LPVOID)this, 0, NULL);
|
||||||
|
if (!m_hThread)
|
||||||
|
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
@ -117,8 +206,26 @@ STDMETHODCALLTYPE
|
||||||
CKsClockForwarder::Run(
|
CKsClockForwarder::Run(
|
||||||
REFERENCE_TIME tStart)
|
REFERENCE_TIME tStart)
|
||||||
{
|
{
|
||||||
OutputDebugString("UNIMPLEMENTED\n");
|
OutputDebugString("CKsClockForwarder::Run\n");
|
||||||
return E_NOTIMPL;
|
|
||||||
|
m_Time = tStart;
|
||||||
|
|
||||||
|
if (!m_hEvent || !m_hThread)
|
||||||
|
{
|
||||||
|
m_ForceStart = TRUE;
|
||||||
|
HRESULT hr = Pause();
|
||||||
|
m_ForceStart = FALSE;
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(m_hThread);
|
||||||
|
|
||||||
|
SetClockState(KSSTATE_RUN);
|
||||||
|
SetEvent(m_hEvent);
|
||||||
|
|
||||||
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
@ -126,15 +233,25 @@ STDMETHODCALLTYPE
|
||||||
CKsClockForwarder::SetSyncSource(
|
CKsClockForwarder::SetSyncSource(
|
||||||
IReferenceClock *pClock)
|
IReferenceClock *pClock)
|
||||||
{
|
{
|
||||||
OutputDebugString("UNIMPLEMENTED\n");
|
OutputDebugString("CKsClockForwarder::SetSyncSource\n");
|
||||||
return E_NOTIMPL;
|
|
||||||
|
if (pClock)
|
||||||
|
pClock->AddRef();
|
||||||
|
|
||||||
|
if (m_Clock)
|
||||||
|
m_Clock->Release();
|
||||||
|
|
||||||
|
|
||||||
|
m_Clock = pClock;
|
||||||
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
CKsClockForwarder::NotifyGraphChange()
|
CKsClockForwarder::NotifyGraphChange()
|
||||||
{
|
{
|
||||||
OutputDebugString("UNIMPLEMENTED\n");
|
OutputDebugString("CKsClockForwarder::NotifyGraphChange\n");
|
||||||
|
DebugBreak();
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +266,60 @@ CKsClockForwarder::KsGetObjectHandle()
|
||||||
return m_Handle;
|
return m_Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
HRESULT
|
||||||
|
STDMETHODCALLTYPE
|
||||||
|
CKsClockForwarder::SetClockState(KSSTATE State)
|
||||||
|
{
|
||||||
|
KSPROPERTY Property;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
|
||||||
|
Property.Set = KSPROPSETID_Clock;
|
||||||
|
Property.Id = KSPROPERTY_CLOCK_STATE;
|
||||||
|
Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
|
||||||
|
HRESULT hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &BytesReturned);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
m_State = State;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WINAPI
|
||||||
|
CKsClockForwarder_ThreadStartup(LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
REFERENCE_TIME Time;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
|
||||||
|
CKsClockForwarder * Fwd = (CKsClockForwarder*)lpParameter;
|
||||||
|
|
||||||
|
Fwd->m_ThreadStarted = TRUE;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (Fwd->m_PendingStop)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (Fwd->m_State != KSSTATE_RUN)
|
||||||
|
WaitForSingleObject(Fwd->m_hEvent, INFINITE);
|
||||||
|
|
||||||
|
KSPROPERTY Property;
|
||||||
|
Property.Set = KSPROPSETID_Clock;
|
||||||
|
Property.Id = KSPROPERTY_CLOCK_TIME;
|
||||||
|
Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
|
||||||
|
Fwd->m_Clock->GetTime(&Time);
|
||||||
|
Time -= Fwd->m_Time;
|
||||||
|
|
||||||
|
KsSynchronousDeviceControl(Fwd->m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &Time, sizeof(REFERENCE_TIME), &BytesReturned);
|
||||||
|
}
|
||||||
|
while(TRUE);
|
||||||
|
|
||||||
|
Fwd->m_ThreadStarted = FALSE;
|
||||||
|
return NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
WINAPI
|
WINAPI
|
||||||
CKsClockForwarder_Constructor(
|
CKsClockForwarder_Constructor(
|
||||||
|
|
|
@ -657,6 +657,7 @@ STDMETHODCALLTYPE
|
||||||
CInputPin::Receive(IMediaSample *pSample)
|
CInputPin::Receive(IMediaSample *pSample)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
|
OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
|
||||||
|
DebugBreak();
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,6 +666,7 @@ STDMETHODCALLTYPE
|
||||||
CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
|
CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
|
OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
|
||||||
|
DebugBreak();
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,6 +675,7 @@ STDMETHODCALLTYPE
|
||||||
CInputPin::ReceiveCanBlock( void)
|
CInputPin::ReceiveCanBlock( void)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
|
OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
|
||||||
|
DebugBreak();
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,8 +747,6 @@ CInputPin::KsPropagateAcquire()
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
OutputDebugStringW(L"CInputPin::KsPropagateAcquire\n");
|
|
||||||
|
|
||||||
assert(m_hPin != INVALID_HANDLE_VALUE);
|
assert(m_hPin != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
Property.Set = KSPROPSETID_Connection;
|
Property.Set = KSPROPSETID_Connection;
|
||||||
|
@ -838,6 +839,7 @@ CInputPin::KsQualityNotify(
|
||||||
REFERENCE_TIME TimeDelta)
|
REFERENCE_TIME TimeDelta)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
|
OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
|
||||||
|
DebugBreak();
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,6 +1027,7 @@ STDMETHODCALLTYPE
|
||||||
CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
|
CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
|
OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
|
||||||
|
DebugBreak();
|
||||||
return NOERROR;
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,6 +1107,7 @@ CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
|
||||||
return VFW_E_NOT_CONNECTED;
|
return VFW_E_NOT_CONNECTED;
|
||||||
|
|
||||||
OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
|
OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
|
||||||
|
DebugBreak();
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
@ -134,22 +134,6 @@ CKsInterfaceHandler::KsSetPin(
|
||||||
}
|
}
|
||||||
pPin->Release();
|
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
|
#endif
|
||||||
|
|
||||||
// done
|
// done
|
||||||
|
@ -268,6 +252,7 @@ CKsInterfaceHandler::KsProcessMediaSamples(
|
||||||
// query for IMediaSample2 interface
|
// query for IMediaSample2 interface
|
||||||
IMediaSample2 * MediaSample;
|
IMediaSample2 * MediaSample;
|
||||||
AM_SAMPLE2_PROPERTIES Properties;
|
AM_SAMPLE2_PROPERTIES Properties;
|
||||||
|
ZeroMemory(&Properties, sizeof(AM_SAMPLE2_PROPERTIES));
|
||||||
|
|
||||||
hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
|
hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
@ -285,7 +270,6 @@ CKsInterfaceHandler::KsProcessMediaSamples(
|
||||||
hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer);
|
hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer);
|
||||||
assert(hr == NOERROR);
|
assert(hr == NOERROR);
|
||||||
hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop);
|
hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop);
|
||||||
assert(hr == NOERROR);
|
|
||||||
|
|
||||||
Properties.cbBuffer = SampleList[Index]->GetSize();
|
Properties.cbBuffer = SampleList[Index]->GetSize();
|
||||||
assert(Properties.cbBuffer);
|
assert(Properties.cbBuffer);
|
||||||
|
@ -303,7 +287,7 @@ CKsInterfaceHandler::KsProcessMediaSamples(
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR Buffer[200];
|
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);
|
swprintf(Buffer, L"CKsInterfaceHandler::KsProcessMediaSamples PinName %s BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u dwSampleFlags %lx\n", m_PinName, Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual, Properties.dwSampleFlags);
|
||||||
//OutputDebugStringW(Buffer);
|
//OutputDebugStringW(Buffer);
|
||||||
|
|
||||||
CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize;
|
CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize;
|
||||||
|
@ -379,10 +363,6 @@ CKsInterfaceHandler::KsCompleteIo(
|
||||||
|
|
||||||
CurStreamHeader = StreamSegment->StreamHeader;
|
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
|
//iterate through all stream headers
|
||||||
for(Index = 0; Index < StreamSegment->SampleCount; Index++)
|
for(Index = 0; Index < StreamSegment->SampleCount; Index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -117,7 +117,7 @@ KsOpenDefaultDevice(
|
||||||
WCHAR Path[MAX_PATH+sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)];
|
WCHAR Path[MAX_PATH+sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)];
|
||||||
|
|
||||||
/* open device list */
|
/* open device list */
|
||||||
hList = SetupDiGetClassDevsW(&Category, NULL, NULL, DIGCF_DEVICEINTERFACE /* | DIGCF_PRESENT*/);
|
hList = SetupDiGetClassDevsW(&Category, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
|
||||||
|
|
||||||
if (hList == INVALID_HANDLE_VALUE)
|
if (hList == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
@ -129,7 +129,7 @@ KsOpenDefaultDevice(
|
||||||
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||||
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||||
|
|
||||||
if (SetupDiEnumDeviceInterfaces(hList, &DeviceInfoData, &Category, 0, &DeviceInterfaceData))
|
if (SetupDiEnumDeviceInterfaces(hList, NULL, &Category, 0, &DeviceInterfaceData))
|
||||||
{
|
{
|
||||||
/* setup interface data struct */
|
/* setup interface data struct */
|
||||||
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)Path;
|
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)Path;
|
||||||
|
|
|
@ -56,34 +56,47 @@ public:
|
||||||
virtual ~CMediaSample(){}
|
virtual ~CMediaSample(){}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LONG m_Ref;
|
ULONG m_Flags;
|
||||||
IMemAllocator * m_Allocator;
|
ULONG m_TypeFlags;
|
||||||
BYTE * m_Buffer;
|
BYTE * m_Buffer;
|
||||||
LONG m_BufferSize;
|
|
||||||
LONG m_ActualLength;
|
LONG m_ActualLength;
|
||||||
|
LONG m_BufferSize;
|
||||||
|
IMemAllocator * m_Allocator;
|
||||||
|
CMediaSample * m_Next;
|
||||||
REFERENCE_TIME m_StartTime;
|
REFERENCE_TIME m_StartTime;
|
||||||
REFERENCE_TIME m_StopTime;
|
REFERENCE_TIME m_StopTime;
|
||||||
ULONG m_Flags;
|
|
||||||
BOOL m_bMediaTimeValid;
|
|
||||||
LONGLONG m_MediaStart;
|
LONGLONG m_MediaStart;
|
||||||
LONGLONG m_MediaStop;
|
LONGLONG m_MediaStop;
|
||||||
|
AM_MEDIA_TYPE * m_MediaType;
|
||||||
|
ULONG m_StreamId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LONG m_Ref;
|
||||||
|
|
||||||
|
BOOL m_bMediaTimeValid;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CMediaSample::CMediaSample(
|
CMediaSample::CMediaSample(
|
||||||
IMemAllocator * Allocator,
|
IMemAllocator * Allocator,
|
||||||
BYTE * Buffer,
|
BYTE * Buffer,
|
||||||
LONG BufferSize) : m_Ref(0),
|
LONG BufferSize) :
|
||||||
m_Allocator(Allocator),
|
m_Flags(0),
|
||||||
|
m_TypeFlags(0),
|
||||||
m_Buffer(Buffer),
|
m_Buffer(Buffer),
|
||||||
m_BufferSize(BufferSize),
|
|
||||||
m_ActualLength(BufferSize),
|
m_ActualLength(BufferSize),
|
||||||
|
m_BufferSize(BufferSize),
|
||||||
|
m_Allocator(Allocator),
|
||||||
|
m_Next(0),
|
||||||
m_StartTime(0),
|
m_StartTime(0),
|
||||||
m_StopTime(0),
|
m_StopTime(0),
|
||||||
m_Flags(0),
|
|
||||||
m_bMediaTimeValid(0),
|
|
||||||
m_MediaStart(0),
|
m_MediaStart(0),
|
||||||
m_MediaStop(0)
|
m_MediaStop(0),
|
||||||
|
m_MediaType(0),
|
||||||
|
m_StreamId(0),
|
||||||
|
m_Ref(0),
|
||||||
|
m_bMediaTimeValid(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +267,15 @@ HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
CMediaSample::GetMediaType(AM_MEDIA_TYPE **ppMediaType)
|
CMediaSample::GetMediaType(AM_MEDIA_TYPE **ppMediaType)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"CMediaSample::GetMediaType NotImplemented\n");
|
OutputDebugStringW(L"CMediaSample::GetMediaType\n");
|
||||||
DebugBreak();
|
|
||||||
|
if (!m_MediaType)
|
||||||
|
{
|
||||||
|
*ppMediaType = NULL;
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0);
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1280,11 +1280,12 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
|
||||||
m_MemInputPin->GetAllocatorRequirements(&Properties);
|
m_MemInputPin->GetAllocatorRequirements(&Properties);
|
||||||
|
|
||||||
//FIXME determine allocator properties
|
//FIXME determine allocator properties
|
||||||
Properties.cBuffers = 16;
|
Properties.cBuffers = 32;
|
||||||
Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size
|
Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size
|
||||||
Properties.cbAlign = 4;
|
Properties.cbAlign = 4;
|
||||||
|
|
||||||
// get input pin allocator
|
// get input pin allocator
|
||||||
|
#if 0
|
||||||
hr = m_MemInputPin->GetAllocator(&m_MemAllocator);
|
hr = m_MemInputPin->GetAllocator(&m_MemAllocator);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -1293,8 +1294,9 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
m_MemAllocator->Release();
|
m_MemAllocator->Release();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (1)
|
||||||
{
|
{
|
||||||
hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator);
|
hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
@ -1444,8 +1446,6 @@ HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
COutputPin::QueryPinInfo(PIN_INFO *pInfo)
|
COutputPin::QueryPinInfo(PIN_INFO *pInfo)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"COutputPin::QueryPinInfo\n");
|
|
||||||
|
|
||||||
wcscpy(pInfo->achName, m_PinName);
|
wcscpy(pInfo->achName, m_PinName);
|
||||||
pInfo->dir = PINDIR_OUTPUT;
|
pInfo->dir = PINDIR_OUTPUT;
|
||||||
pInfo->pFilter = m_ParentFilter;
|
pInfo->pFilter = m_ParentFilter;
|
||||||
|
@ -1457,8 +1457,6 @@ HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
|
COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"COutputPin::QueryDirection\n");
|
|
||||||
|
|
||||||
if (pPinDir)
|
if (pPinDir)
|
||||||
{
|
{
|
||||||
*pPinDir = PINDIR_OUTPUT;
|
*pPinDir = PINDIR_OUTPUT;
|
||||||
|
@ -1471,8 +1469,6 @@ HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
COutputPin::QueryId(LPWSTR *Id)
|
COutputPin::QueryId(LPWSTR *Id)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"COutputPin::QueryId\n");
|
|
||||||
|
|
||||||
*Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
|
*Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
|
||||||
if (!*Id)
|
if (!*Id)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
@ -1496,8 +1492,6 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
|
||||||
AM_MEDIA_TYPE * MediaTypes;
|
AM_MEDIA_TYPE * MediaTypes;
|
||||||
HANDLE hFilter;
|
HANDLE hFilter;
|
||||||
|
|
||||||
OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n");
|
|
||||||
|
|
||||||
if (!m_KsObjectParent)
|
if (!m_KsObjectParent)
|
||||||
{
|
{
|
||||||
// no interface
|
// no interface
|
||||||
|
@ -1511,7 +1505,6 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
|
||||||
hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
|
hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
|
||||||
if (FAILED(hr) || !MediaTypeCount)
|
if (FAILED(hr) || !MediaTypeCount)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1520,7 +1513,6 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
|
||||||
if (!MediaTypes)
|
if (!MediaTypes)
|
||||||
{
|
{
|
||||||
// not enough memory
|
// not enough memory
|
||||||
OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n");
|
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1535,7 +1527,6 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
|
||||||
{
|
{
|
||||||
// failed
|
// failed
|
||||||
CoTaskMemFree(MediaTypes);
|
CoTaskMemFree(MediaTypes);
|
||||||
OutputDebugStringW(L"COutputPin::EnumMediaTypes failed\n");
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1546,7 +1537,6 @@ HRESULT
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
|
COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(L"COutputPin::QueryInternalConnections called\n");
|
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
HRESULT
|
HRESULT
|
||||||
|
@ -1612,7 +1602,6 @@ COutputPin::CheckFormat(
|
||||||
{
|
{
|
||||||
// format is supported
|
// format is supported
|
||||||
CoTaskMemFree(MultipleItem);
|
CoTaskMemFree(MultipleItem);
|
||||||
OutputDebugStringW(L"COutputPin::CheckFormat format OK\n");
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
|
DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
|
||||||
|
@ -1687,7 +1676,6 @@ COutputPin::CreatePin(
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
// failed to load interface handler plugin
|
// failed to load interface handler plugin
|
||||||
OutputDebugStringW(L"COutputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
|
|
||||||
CoTaskMemFree(MediumList);
|
CoTaskMemFree(MediumList);
|
||||||
CoTaskMemFree(InterfaceList);
|
CoTaskMemFree(InterfaceList);
|
||||||
|
|
||||||
|
@ -1699,7 +1687,6 @@ COutputPin::CreatePin(
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
// failed to load interface handler plugin
|
// failed to load interface handler plugin
|
||||||
OutputDebugStringW(L"COutputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
|
|
||||||
InterfaceHandler->Release();
|
InterfaceHandler->Release();
|
||||||
CoTaskMemFree(MediumList);
|
CoTaskMemFree(MediumList);
|
||||||
CoTaskMemFree(InterfaceList);
|
CoTaskMemFree(InterfaceList);
|
||||||
|
@ -1887,10 +1874,11 @@ COutputPin::IoProcessRoutine()
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
OutputDebugStringW(L"OutOfSamples\n");
|
||||||
m_Pin->BeginFlush();
|
m_Pin->BeginFlush();
|
||||||
OutputDebugStringW(L"Beginning flushing...\n");
|
|
||||||
WaitForSingleObject(m_hBufferAvailable, INFINITE);
|
WaitForSingleObject(m_hBufferAvailable, INFINITE);
|
||||||
m_Pin->EndFlush();
|
m_Pin->EndFlush();
|
||||||
|
OutputDebugStringW(L"After Wait OutOfSamples\n");
|
||||||
// now retry again
|
// now retry again
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1899,8 +1887,7 @@ COutputPin::IoProcessRoutine()
|
||||||
SampleCount = 1;
|
SampleCount = 1;
|
||||||
Samples[0] = Sample;
|
Samples[0] = Sample;
|
||||||
|
|
||||||
|
Sample->SetTime(NULL, NULL);
|
||||||
Sample->SetTime(&Start, &Stop);
|
|
||||||
hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
|
hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
|
||||||
Samples,
|
Samples,
|
||||||
&SampleCount,
|
&SampleCount,
|
||||||
|
@ -1908,9 +1895,11 @@ COutputPin::IoProcessRoutine()
|
||||||
&StreamSegment);
|
&StreamSegment);
|
||||||
if (FAILED(hr) || !StreamSegment)
|
if (FAILED(hr) || !StreamSegment)
|
||||||
{
|
{
|
||||||
swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples PinName %s hr %lx StreamSegment %p\n", m_PinName, hr, StreamSegment);
|
swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr);
|
||||||
OutputDebugStringW(Buffer);
|
OutputDebugStringW(Buffer);
|
||||||
break;
|
SetEvent(m_hStopEvent);
|
||||||
|
m_IoThreadStarted = false;
|
||||||
|
ExitThread(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get completion event
|
// get completion event
|
||||||
|
@ -1927,15 +1916,19 @@ COutputPin::IoProcessRoutine()
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
Sample->GetTime(&Start, &Stop);
|
LONG Length = Sample->GetActualDataLength();
|
||||||
|
Stop += Length;
|
||||||
|
// Sample->SetMediaTime(&Start, &Stop);
|
||||||
Start = Stop;
|
Start = Stop;
|
||||||
Stop++;
|
|
||||||
|
|
||||||
// now deliver the sample
|
// now deliver the sample
|
||||||
hr = m_MemInputPin->Receive(Sample);
|
hr = m_MemInputPin->Receive(Sample);
|
||||||
|
|
||||||
swprintf(Buffer, L"COutputPin::IoProcessRoutine IMemInputPin::Receive hr %lx Start %I64u Stop %I64u\n", hr, Start, Stop);
|
swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator);
|
||||||
OutputDebugStringW(Buffer);
|
OutputDebugStringW(Buffer);
|
||||||
|
if (FAILED(hr))
|
||||||
|
DebugBreak();
|
||||||
|
Sample = NULL;
|
||||||
}
|
}
|
||||||
}while(TRUE);
|
}while(TRUE);
|
||||||
|
|
||||||
|
@ -2118,6 +2111,9 @@ COutputPin_SetState(
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
// release any waiting threads
|
||||||
|
SetEvent(pPin->m_hBufferAvailable);
|
||||||
|
|
||||||
// wait until i/o thread is done
|
// wait until i/o thread is done
|
||||||
WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
|
WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <list>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ksmedia.h>
|
#include <ksmedia.h>
|
||||||
//#include <debug.h>
|
//#include <debug.h>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue