[KSPROXY]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 19 Mar 2010 15:39:08 +0000 (15:39 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 19 Mar 2010 15:39:08 +0000 (15:39 +0000)
- Start implementing IKsAllocator interface
- Retrieve the default format for the input and output pin
- Instantiate the kernel pin when an interface request for IMemInputPin / IKsPropertySet / IKsObject request arrives
- Implement IKsPin::KsCreateSinkPinHandle for the input pin
- Partly implement IKsPin::KsPropagateAcquire for input / output pin
- Fix asserts in IKsControl::KsProperty, IKsControl::KsMethod, IKsControl::KsEvent
- Simplify CInputPin::CheckFormat
- Store the currently used pin medium / interface and connection format
- Implement IAMBufferNegotiation::SuggestAllocatorProperties, IAMBufferNegotiation::GetAllocatorProperties for the output pin
- Pass pin's communication to output pin
- Implement IMediaFilter::Pause, IMediaFilter::Run for CKsProxy
- CKsProxy is now able to deliver signal statistics for BDA devices (app: SageDvbRecorder, OS: WinXP SP3)

svn path=/trunk/; revision=46274

reactos/dll/directx/ksproxy/allocator.cpp [new file with mode: 0644]
reactos/dll/directx/ksproxy/input_pin.cpp
reactos/dll/directx/ksproxy/ksproxy.rbuild
reactos/dll/directx/ksproxy/output_pin.cpp
reactos/dll/directx/ksproxy/precomp.h
reactos/dll/directx/ksproxy/proxy.cpp

diff --git a/reactos/dll/directx/ksproxy/allocator.cpp b/reactos/dll/directx/ksproxy/allocator.cpp
new file mode 100644 (file)
index 0000000..2b5cd1a
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
+ * FILE:            dll/directx/ksproxy/allocator.cpp
+ * PURPOSE:         IKsAllocator interface
+ *
+ * PROGRAMMERS:     Johannes Anderwald (janderwald@reactos.org)
+ */
+#include "precomp.h"
+
+const GUID IID_IKsAllocatorEx = {0x091bb63a, 0x603f, 0x11d1, {0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}};
+const GUID IID_IKsAllocator   = {0x8da64899, 0xc0d9, 0x11d0, {0x84, 0x13, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a}};
+
+class CKsAllocator : public IKsAllocatorEx,
+                     public IMemAllocatorCallbackTemp
+{
+public:
+    STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+
+    STDMETHODIMP_(ULONG) AddRef()
+    {
+        InterlockedIncrement(&m_Ref);
+        return m_Ref;
+    }
+    STDMETHODIMP_(ULONG) Release()
+    {
+        InterlockedDecrement(&m_Ref);
+
+        if (!m_Ref)
+        {
+            delete this;
+            return 0;
+        }
+        return m_Ref;
+    }
+    //IKsAllocator
+    HANDLE STDMETHODCALLTYPE KsGetAllocatorHandle();
+    KSALLOCATORMODE STDMETHODCALLTYPE KsGetAllocatorMode();
+    HRESULT STDMETHODCALLTYPE KsGetAllocatorStatus(PKSSTREAMALLOCATOR_STATUS AllocatorStatus);
+    VOID STDMETHODCALLTYPE KsSetAllocatorMode(KSALLOCATORMODE Mode);
+
+    //IKsAllocatorEx
+    PALLOCATOR_PROPERTIES_EX STDMETHODCALLTYPE KsGetProperties();
+    VOID STDMETHODCALLTYPE KsSetProperties(PALLOCATOR_PROPERTIES_EX Properties);
+    VOID STDMETHODCALLTYPE KsSetAllocatorHandle(HANDLE AllocatorHandle);
+    HANDLE STDMETHODCALLTYPE KsCreateAllocatorAndGetHandle(IKsPin* KsPin);
+
+    //IMemAllocator
+    HRESULT STDMETHODCALLTYPE SetProperties(ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual);
+    HRESULT STDMETHODCALLTYPE GetProperties(ALLOCATOR_PROPERTIES *pProps);
+    HRESULT STDMETHODCALLTYPE Commit();
+    HRESULT STDMETHODCALLTYPE Decommit();
+    HRESULT STDMETHODCALLTYPE GetBuffer(IMediaSample **ppBuffer, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags);
+    HRESULT STDMETHODCALLTYPE ReleaseBuffer(IMediaSample *pBuffer);
+
+    //IMemAllocatorCallbackTemp
+    HRESULT STDMETHODCALLTYPE SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
+    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){}
+    virtual ~CKsAllocator(){}
+
+protected:
+    LONG m_Ref;
+    HANDLE m_hAllocator;
+    KSALLOCATORMODE m_Mode;
+    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;
+};
+
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    if (IsEqualGUID(refiid, IID_IUnknown) ||
+        IsEqualGUID(refiid, IID_IKsAllocator) ||
+        IsEqualGUID(refiid, IID_IKsAllocatorEx))
+    {
+        *Output = PVOID(this);
+        reinterpret_cast<IUnknown*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    if (IsEqualGUID(refiid, IID_IMemAllocator) ||
+        IsEqualGUID(refiid, IID_IMemAllocatorCallbackTemp))
+    {
+        *Output = (IDistributorNotify*)(this);
+        reinterpret_cast<IDistributorNotify*>(*Output)->AddRef();
+        return NOERROR;
+    }
+
+    return E_NOINTERFACE;
+}
+
+//-------------------------------------------------------------------
+// IMemAllocator
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::SetProperties(
+    ALLOCATOR_PROPERTIES *pRequest,
+    ALLOCATOR_PROPERTIES *pActual)
+{
+    SYSTEM_INFO SystemInfo;
+
+    OutputDebugStringW(L"CKsAllocator::SetProperties Stub\n");
+
+    if (!pRequest || !pActual)
+        return E_POINTER;
+
+    // zero output properties
+    ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
+
+    // get system info
+    GetSystemInfo(&SystemInfo);
+
+    if (!pRequest->cbAlign || (pRequest->cbAlign - 1) & SystemInfo.dwAllocationGranularity)
+    {
+        // bad alignment
+        return VFW_E_BADALIGN;
+    }
+
+    if (m_Mode == KsAllocatorMode_Kernel)
+    {
+        // u cannt change a kernel allocator
+        return VFW_E_ALREADY_COMMITTED;
+    }
+
+    if (m_Allocated != m_FreeCount)
+    {
+        // outstanding buffers
+        return VFW_E_BUFFERS_OUTSTANDING;
+    }
+
+    pActual->cbAlign = m_cbAlign = pRequest->cbAlign;
+    pActual->cbBuffer = m_cbBuffer = pRequest->cbBuffer;
+    pActual->cbPrefix = m_cbPrefix = pRequest->cbPrefix;
+    pActual->cBuffers = m_cBuffers = pRequest->cBuffers;
+
+    return NOERROR;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::GetProperties(
+    ALLOCATOR_PROPERTIES *pProps)
+{
+    if (!pProps)
+        return E_POINTER;
+
+    pProps->cbBuffer = m_cbBuffer;
+    pProps->cBuffers = m_cBuffers;
+    pProps->cbAlign = m_cbAlign;
+    pProps->cbPrefix = m_cbPrefix;
+
+    return NOERROR;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::Commit()
+{
+    if (m_Mode == KsAllocatorMode_Kernel)
+    {
+        /* no-op for kernel allocator */
+       return NOERROR;
+    }
+
+    OutputDebugStringW(L"CKsAllocator::Commit NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::Decommit()
+{
+    if (m_Mode == KsAllocatorMode_Kernel)
+    {
+        /* no-op for kernel allocator */
+       return NOERROR;
+    }
+
+    OutputDebugStringW(L"CKsAllocator::Decommit NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::GetBuffer(
+    IMediaSample **ppBuffer,
+    REFERENCE_TIME *pStartTime,
+    REFERENCE_TIME *pEndTime,
+    DWORD dwFlags)
+{
+    OutputDebugStringW(L"CKsAllocator::GetBuffer NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::ReleaseBuffer(
+    IMediaSample *pBuffer)
+{
+    OutputDebugStringW(L"CKsAllocator::ReleaseBuffer NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IMemAllocatorCallbackTemp
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::SetNotify(
+    IMemAllocatorNotifyCallbackTemp *pNotify)
+{
+    OutputDebugStringW(L"CKsAllocator::SetNotify\n");
+
+    if (pNotify)
+        pNotify->AddRef();
+
+    if (m_Notify)
+        m_Notify->Release();
+
+    m_Notify = pNotify;
+    return NOERROR;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::GetFreeCount(
+    LONG *plBuffersFree)
+{
+    OutputDebugStringW(L"CKsAllocator::GetFreeCount NotImplemented\n");
+    return E_NOTIMPL;
+}
+
+//-------------------------------------------------------------------
+// IKsAllocator
+//
+HANDLE
+STDMETHODCALLTYPE
+CKsAllocator::KsGetAllocatorHandle()
+{
+    return m_hAllocator;
+}
+
+KSALLOCATORMODE
+STDMETHODCALLTYPE
+CKsAllocator::KsGetAllocatorMode()
+{
+    return m_Mode;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsAllocator::KsGetAllocatorStatus(
+    PKSSTREAMALLOCATOR_STATUS AllocatorStatus)
+{
+    return NOERROR;
+}
+VOID
+STDMETHODCALLTYPE
+CKsAllocator::KsSetAllocatorMode(
+    KSALLOCATORMODE Mode)
+{
+    m_Mode = Mode;
+}
+
+//-------------------------------------------------------------------
+// IKsAllocatorEx
+//
+PALLOCATOR_PROPERTIES_EX
+STDMETHODCALLTYPE
+CKsAllocator::KsGetProperties()
+{
+    return &m_Properties;
+}
+
+VOID
+STDMETHODCALLTYPE
+CKsAllocator::KsSetProperties(
+    PALLOCATOR_PROPERTIES_EX Properties)
+{
+    CopyMemory(&m_Properties, Properties, sizeof(ALLOCATOR_PROPERTIES_EX));
+}
+
+VOID
+STDMETHODCALLTYPE
+CKsAllocator::KsSetAllocatorHandle(
+    HANDLE AllocatorHandle)
+{
+    m_hAllocator = AllocatorHandle;
+}
+
+
+HANDLE
+STDMETHODCALLTYPE
+CKsAllocator::KsCreateAllocatorAndGetHandle(
+    IKsPin* KsPin)
+{
+    HRESULT hr;
+    IKsObject * pObject;
+    KSALLOCATOR_FRAMING AllocatorFraming;
+    HANDLE hPin;
+
+    OutputDebugStringW(L"CKsAllocator::KsCreateAllocatorAndGetHandle\n");
+
+    if (m_hAllocator)
+    {
+        CloseHandle(m_hAllocator);
+        m_hAllocator = NULL;
+    }
+
+    // get pin IKsObject interface
+    hr = KsPin->QueryInterface(IID_IKsObject, (void**)&pObject);
+    if (FAILED(hr))
+        return NULL;
+
+    // get pin handle
+    hPin = pObject->KsGetObjectHandle();
+
+    //release IKsObject interface
+    pObject->Release();
+
+    if (!hPin || hPin == INVALID_HANDLE_VALUE)
+        return NULL;
+
+    //setup allocator framing
+    AllocatorFraming.Frames = m_Properties.cBuffers;
+    AllocatorFraming.FrameSize = m_Properties.cbBuffer;
+    AllocatorFraming.FileAlignment = (m_Properties.cbAlign -1);
+    AllocatorFraming.OptionsFlags = KSALLOCATOR_OPTIONF_SYSTEM_MEMORY;
+    AllocatorFraming.PoolType = (m_Properties.LogicalMemoryType == KS_MemoryTypeKernelPaged);
+
+    DWORD dwError = KsCreateAllocator(hPin, &AllocatorFraming, &m_hAllocator);
+    if (dwError)
+        return NULL;
+
+    return m_hAllocator;
+}
+
+HRESULT
+WINAPI
+CKsAllocator_Constructor(
+    IUnknown * pUnkOuter,
+    REFIID riid,
+    LPVOID * ppv)
+{
+    OutputDebugStringW(L"CKsAllocator_Constructor\n");
+
+    CKsAllocator * handler = new CKsAllocator();
+
+    if (!handler)
+        return E_OUTOFMEMORY;
+
+    if (FAILED(handler->QueryInterface(riid, ppv)))
+    {
+        /* not supported */
+        delete handler;
+        return E_NOINTERFACE;
+    }
+
+    return NOERROR;
+}
index e95894f..ef1cb54 100644 (file)
@@ -185,6 +185,7 @@ protected:
     KSPIN_COMMUNICATION m_Communication;
     KSPIN_INTERFACE m_Interface;
     KSPIN_MEDIUM m_Medium;
+    AM_MEDIA_TYPE m_MediaFormat;
     IPin * m_Pin;
     BOOL m_ReadOnly;
     IKsInterfaceHandler * m_InterfaceHandler;
@@ -221,6 +222,10 @@ CInputPin::CInputPin(
 {
     ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
     ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
+
+    ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE));
+    HRESULT hr = KsGetMediaType(0, &m_MediaFormat, m_hFilter, m_PinId);
+    assert(hr == S_OK);
 }
 
 HRESULT
@@ -229,6 +234,8 @@ CInputPin::QueryInterface(
     IN  REFIID refiid,
     OUT PVOID* Output)
 {
+    WCHAR Buffer[100];
+
     *Output = NULL;
 
     if (IsEqualGUID(refiid, IID_IUnknown) ||
@@ -240,6 +247,13 @@ CInputPin::QueryInterface(
     }
     else if (IsEqualGUID(refiid, IID_IMemInputPin))
     {
+        if (m_hPin == INVALID_HANDLE_VALUE)
+        {
+            HRESULT hr = CreatePin(&m_MediaFormat);
+            if (FAILED(hr))
+                return hr;
+        }
+
         *Output = (IMemInputPin*)(this);
         reinterpret_cast<IMemInputPin*>(*Output)->AddRef();
         return NOERROR;
@@ -252,6 +266,13 @@ CInputPin::QueryInterface(
     }
     else if (IsEqualGUID(refiid, IID_IKsPropertySet))
     {
+        if (m_hPin == INVALID_HANDLE_VALUE)
+        {
+            HRESULT hr = CreatePin(&m_MediaFormat);
+            if (FAILED(hr))
+                return hr;
+        }
+
         *Output = (IKsPropertySet*)(this);
         reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
         return NOERROR;
@@ -308,7 +329,6 @@ CInputPin::QueryInterface(
         return NOERROR;
     }
 
-    WCHAR Buffer[MAX_PATH];
     LPOLESTR lpstr;
     StringFromCLSID(refiid, &lpstr);
     swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr);
@@ -578,6 +598,14 @@ HRESULT
 STDMETHODCALLTYPE
 CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
 {
+    WCHAR Buffer[100];
+    HRESULT hr;
+    ALLOCATOR_PROPERTIES Properties;
+
+    hr = pAllocator->GetProperties(&Properties);
+    swprintf(Buffer, L"CInputPin::NotifyAllocator hr %lx bReadOnly, %u cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", hr, bReadOnly, Properties.cbAlign, Properties.cbBuffer, Properties.cbPrefix, Properties.cBuffers);
+    OutputDebugStringW(Buffer);
+
     if (pAllocator)
     {
         pAllocator->AddRef();
@@ -613,10 +641,15 @@ CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
         pProps->cbBuffer = Framing.FrameSize;
         pProps->cbAlign = Framing.FileAlignment;
         pProps->cbPrefix = 0;
-        return hr;
     }
     else
-        return E_NOTIMPL;
+        hr = E_NOTIMPL;
+
+    WCHAR Buffer[100];
+    swprintf(Buffer, L"CInputPin::GetAllocatorRequirements hr %lx m_hPin %p cBuffers %u cbBuffer %u cbAlign %u cbPrefix %u\n", hr, m_hPin, pProps->cBuffers, pProps->cbBuffer, pProps->cbAlign, pProps->cbPrefix);
+    OutputDebugStringW(Buffer);
+
+    return hr;
 }
 
 HRESULT
@@ -669,8 +702,7 @@ CInputPin::KsCreateSinkPinHandle(
     KSPIN_INTERFACE& Interface,
     KSPIN_MEDIUM& Medium)
 {
-    OutputDebugStringW(L"CInputPin::KsCreateSinkPinHandle NotImplemented\n");
-    return E_NOTIMPL;
+    return CreatePin(&m_MediaFormat);
 }
 
 HRESULT
@@ -707,8 +739,27 @@ HRESULT
 STDMETHODCALLTYPE
 CInputPin::KsPropagateAcquire()
 {
-    OutputDebugStringW(L"CInputPin::KsPropagateAcquire NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    KSSTATE State;
+    ULONG BytesReturned;
+    HRESULT hr;
+
+    OutputDebugStringW(L"CInputPin::KsPropagateAcquire\n");
+
+    assert(m_hPin != INVALID_HANDLE_VALUE);
+
+    Property.Set = KSPROPSETID_Connection;
+    Property.Id = KSPROPERTY_CONNECTION_STATE;
+    Property.Flags = KSPROPERTY_TYPE_SET;
+
+    State = KSSTATE_ACQUIRE;
+
+    hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
+
+    //TODO
+    //propagate to connected pin on the pipe
+
+    return hr;
 }
 
 HRESULT
@@ -744,6 +795,7 @@ HRESULT
 STDMETHODCALLTYPE
 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
 {
+
     if (MemAllocator)
     {
         MemAllocator->AddRef();
@@ -815,7 +867,7 @@ CInputPin::KsProperty(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
-    assert(m_hPin != 0);
+    assert(m_hPin != INVALID_HANDLE_VALUE);
     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
 }
 
@@ -828,7 +880,7 @@ CInputPin::KsMethod(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
-    assert(m_hPin != 0);
+    assert(m_hPin != INVALID_HANDLE_VALUE);
     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
 }
 
@@ -841,7 +893,7 @@ CInputPin::KsEvent(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
-    assert(m_hPin != 0);
+    assert(m_hPin != INVALID_HANDLE_VALUE);
 
     if (EventLength)
         return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
@@ -1178,60 +1230,33 @@ STDMETHODCALLTYPE
 CInputPin::CheckFormat(
     const AM_MEDIA_TYPE *pmt)
 {
-    KSP_PIN Property;
     PKSMULTIPLE_ITEM MultipleItem;
     PKSDATAFORMAT DataFormat;
-    ULONG BytesReturned;
     HRESULT hr;
 
-    // prepare request
-    Property.Property.Set = KSPROPSETID_Pin;
-    Property.Property.Id = KSPROPERTY_PIN_DATARANGES;
-    Property.Property.Flags = KSPROPERTY_TYPE_GET;
-    Property.PinId = m_PinId;
-    Property.Reserved = 0;
-
     if (!pmt)
         return E_POINTER;
 
-    // query for size of dataranges
-    hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
+    hr = KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
+    if (FAILED(hr))
+        return S_FALSE;
 
-    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
+    DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
+    for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
     {
-        // allocate dataranges buffer
-        MultipleItem = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
-
-        if (!MultipleItem)
-            return E_OUTOFMEMORY;
-
-        // query dataranges
-        hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
-
-        if (FAILED(hr))
+        if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
+            IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
+            IsEqualGUID(pmt->formattype, DataFormat->Specifier))
         {
-            // failed to query data ranges
+            // format is supported
             CoTaskMemFree(MultipleItem);
-            return hr;
-        }
-
-        DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
-        for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
-        {
-            if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
-                IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
-                IsEqualGUID(pmt->formattype, DataFormat->Specifier))
-            {
-                // format is supported
-                CoTaskMemFree(MultipleItem);
-                OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
-                return S_OK;
-            }
-            DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
+            OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
+            return S_OK;
         }
-        //format is not supported
-        CoTaskMemFree(MultipleItem);
+        DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
     }
+    //format is not supported
+    CoTaskMemFree(MultipleItem);
     return S_FALSE;
 }
 
@@ -1285,32 +1310,35 @@ CInputPin::CreatePin(
 
     if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
     {
-        // now load the IKsInterfaceHandler plugin
-        hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
-        if (FAILED(hr))
+        if (!m_InterfaceHandler)
         {
-            // failed to load interface handler plugin
-            OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
-            CoTaskMemFree(MediumList);
-            CoTaskMemFree(InterfaceList);
+            // now load the IKsInterfaceHandler plugin
+            hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
+            if (FAILED(hr))
+            {
+                // failed to load interface handler plugin
+                OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
+                CoTaskMemFree(MediumList);
+                CoTaskMemFree(InterfaceList);
 
-            return hr;
-        }
+                return hr;
+            }
 
-        // now set the pin
-        hr = InterfaceHandler->KsSetPin((IKsPin*)this);
-        if (FAILED(hr))
-        {
-            // failed to load interface handler plugin
-            OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
-            InterfaceHandler->Release();
-            CoTaskMemFree(MediumList);
-            CoTaskMemFree(InterfaceList);
-            return hr;
-        }
+            // now set the pin
+            hr = InterfaceHandler->KsSetPin((IKsPin*)this);
+            if (FAILED(hr))
+            {
+                // failed to load interface handler plugin
+                OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
+                InterfaceHandler->Release();
+                CoTaskMemFree(MediumList);
+                CoTaskMemFree(InterfaceList);
+                return hr;
+            }
 
-        // store interface handler
-        m_InterfaceHandler = InterfaceHandler;
+            // store interface handler
+            m_InterfaceHandler = InterfaceHandler;
+        }
 
         // now create pin
         hr = CreatePinHandle(Medium, Interface, pmt);
@@ -1320,6 +1348,14 @@ CInputPin::CreatePin(
             m_InterfaceHandler = InterfaceHandler;
         }
     }
+    else
+    {
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
+        OutputDebugStringW(Buffer);
+        DebugBreak();
+        hr = E_FAIL;
+    }
 
     // free medium / interface / dataformat
     CoTaskMemFree(MediumList);
@@ -1340,6 +1376,15 @@ CInputPin::CreatePinHandle(
     ULONG Length;
     HRESULT hr;
 
+    if (m_hPin != INVALID_HANDLE_VALUE)
+    {
+        // pin already exists
+        //CloseHandle(m_hPin);
+        //m_hPin = INVALID_HANDLE_VALUE;
+        return S_OK;
+    }
+
+
     // calc format size
     Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
 
@@ -1380,6 +1425,42 @@ CInputPin::CreatePinHandle(
     // create pin
     hr = KsCreatePin(m_hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
 
+    if (SUCCEEDED(hr))
+    {
+        // store current interface / medium
+        CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
+        CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
+        CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
+
+        LPOLESTR pMajor, pSub, pFormat;
+        StringFromIID(m_MediaFormat.majortype, &pMajor);
+        StringFromIID(m_MediaFormat.subtype , &pSub);
+        StringFromIID(m_MediaFormat.formattype, &pFormat);
+        WCHAR Buffer[200];
+        swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
+        CoTaskMemFree(pMajor);
+        CoTaskMemFree(pSub);
+        CoTaskMemFree(pFormat);
+        OutputDebugStringW(Buffer);
+
+        if (pmt->cbFormat)
+        {
+            m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
+            if (!m_MediaFormat.pbFormat)
+            {
+                CoTaskMemFree(PinConnect);
+                m_MediaFormat.pbFormat = NULL;
+                m_MediaFormat.cbFormat = 0;
+                return E_OUTOFMEMORY;
+            }
+            CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
+        }
+
+        //TODO
+        // connect pin pipes
+
+    }
+
     // free pin connect
      CoTaskMemFree(PinConnect);
 
index e5bc87e..269d986 100644 (file)
@@ -20,7 +20,7 @@
        <group compilerset="msc">
                <compilerflag compiler="cxx">/GR-</compilerflag>
        </group>
-
+       <file>allocator.cpp</file>
        <file>basicaudio.cpp</file>
        <file>classfactory.cpp</file>
        <file>clockforward.cpp</file>
index 52f9cc9..7f8a421 100644 (file)
@@ -154,8 +154,12 @@ public:
     //IMemAllocatorNotifyCallbackTemp
     HRESULT STDMETHODCALLTYPE NotifyRelease();
 
-    COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId);
+    //---------------------------------------------------------------
+    COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication);
     virtual ~COutputPin();
+    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);
 
 protected:
     LONG m_Ref;
@@ -178,7 +182,11 @@ protected:
     KSPIN_COMMUNICATION m_Communication;
     KSPIN_INTERFACE m_Interface;
     KSPIN_MEDIUM m_Medium;
+    AM_MEDIA_TYPE m_MediaFormat;
+
     IMediaSeeking * m_FilterMediaSeeking;
+    ALLOCATOR_PROPERTIES m_Properties;
+    IKsInterfaceHandler * m_InterfaceHandler;
 };
 
 COutputPin::~COutputPin()
@@ -190,21 +198,23 @@ COutputPin::~COutputPin()
 COutputPin::COutputPin(
     IBaseFilter * ParentFilter,
     LPCWSTR PinName,
-    ULONG PinId) : m_Ref(0),
-                   m_ParentFilter(ParentFilter),
-                   m_PinName(PinName),
-                   m_hPin(INVALID_HANDLE_VALUE),
-                   m_PinId(PinId),
-                   m_KsObjectParent(0),
-                   m_Pin(0),
-                   m_KsAllocatorEx(0),
-                   m_PipeAllocatorFlag(0),
-                   m_bPinBusCacheInitialized(0),
-                   m_FilterName(0),
-                   m_MemAllocator(0),
-                   m_IoCount(0),
-                   m_Communication(KSPIN_COMMUNICATION_NONE),
-                   m_FilterMediaSeeking(0)
+    ULONG PinId,
+    KSPIN_COMMUNICATION Communication) : m_Ref(0),
+                                         m_ParentFilter(ParentFilter),
+                                         m_PinName(PinName),
+                                         m_hPin(INVALID_HANDLE_VALUE),
+                                         m_PinId(PinId),
+                                         m_KsObjectParent(0),
+                                         m_Pin(0),
+                                         m_KsAllocatorEx(0),
+                                         m_PipeAllocatorFlag(0),
+                                         m_bPinBusCacheInitialized(0),
+                                         m_FilterName(0),
+                                         m_MemAllocator(0),
+                                         m_IoCount(0),
+                                         m_Communication(Communication),
+                                         m_FilterMediaSeeking(0),
+                                         m_InterfaceHandler(0)
 {
     HRESULT hr;
 
@@ -216,6 +226,9 @@ COutputPin::COutputPin(
 
     ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
     ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
+
+    hr = KsGetMediaType(0, &m_MediaFormat, m_KsObjectParent->KsGetObjectHandle(), m_PinId);
+    assert(hr == S_OK);
 };
 
 HRESULT
@@ -235,6 +248,13 @@ COutputPin::QueryInterface(
     }
     else if (IsEqualGUID(refiid, IID_IKsObject))
     {
+        if (m_hPin == INVALID_HANDLE_VALUE)
+        {
+            HRESULT hr = CreatePin(&m_MediaFormat);
+            if (FAILED(hr))
+                return hr;
+        }
+
         OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
         *Output = (IKsObject*)(this);
         reinterpret_cast<IKsObject*>(*Output)->AddRef();
@@ -266,8 +286,13 @@ COutputPin::QueryInterface(
     }
     else if (IsEqualGUID(refiid, IID_IKsPropertySet))
     {
+        if (m_hPin == INVALID_HANDLE_VALUE)
+        {
+            HRESULT hr = CreatePin(&m_MediaFormat);
+            if (FAILED(hr))
+                return hr;
+        }
         OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
-        DebugBreak();
         *Output = (IKsPropertySet*)(this);
         reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
         return NOERROR;
@@ -329,7 +354,7 @@ COutputPin::QueryInterface(
     WCHAR Buffer[MAX_PATH];
     LPOLESTR lpstr;
     StringFromCLSID(refiid, &lpstr);
-    swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s\n", lpstr);
+    swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName);
     OutputDebugStringW(Buffer);
     CoTaskMemFree(lpstr);
 
@@ -344,8 +369,16 @@ STDMETHODCALLTYPE
 COutputPin::SuggestAllocatorProperties(
     const ALLOCATOR_PROPERTIES *pprop)
 {
-    OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n");
+
+    if (m_Pin)
+    {
+        // pin is already connected
+        return VFW_E_ALREADY_CONNECTED;
+    }
+
+    CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES));
+    return NOERROR;
 }
 
 HRESULT
@@ -353,8 +386,22 @@ STDMETHODCALLTYPE
 COutputPin::GetAllocatorProperties(
     ALLOCATOR_PROPERTIES *pprop)
 {
-    OutputDebugStringW(L"COutputPin::GetAllocatorProperties NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n");
+
+    if (!m_Pin)
+    {
+        // you should call this method AFTER you connected
+        return E_UNEXPECTED;
+    }
+
+    if (!m_KsAllocatorEx)
+    {
+        // something went wrong while creating the allocator
+        return E_FAIL;
+    }
+
+    CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES));
+    return NOERROR;
 }
 
 //-------------------------------------------------------------------
@@ -669,8 +716,27 @@ HRESULT
 STDMETHODCALLTYPE
 COutputPin::KsPropagateAcquire()
 {
-    OutputDebugStringW(L"COutputPin::KsPropagateAcquire NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    KSSTATE State;
+    ULONG BytesReturned;
+    HRESULT hr;
+
+    OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n");
+
+    assert(m_hPin != INVALID_HANDLE_VALUE);
+
+    Property.Set = KSPROPSETID_Connection;
+    Property.Id = KSPROPERTY_CONNECTION_STATE;
+    Property.Flags = KSPROPERTY_TYPE_SET;
+
+    State = KSSTATE_ACQUIRE;
+
+    hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
+
+    //TODO
+    //propagate to connected pin on the pipe
+
+    return hr;
 }
 
 HRESULT
@@ -975,7 +1041,7 @@ STDMETHODCALLTYPE
 COutputPin::KsGetObjectHandle()
 {
     OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");
-    assert(m_hPin);
+    assert(m_hPin != INVALID_HANDLE_VALUE);
     return m_hPin;
 }
 
@@ -991,9 +1057,19 @@ COutputPin::KsProperty(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
-    assert(m_hPin != 0);
-    OutputDebugStringW(L"COutputPin::KsProperty\n");
-    return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
+    HRESULT hr;
+    WCHAR Buffer[100];
+    LPOLESTR pstr;
+
+    assert(m_hPin != INVALID_HANDLE_VALUE);
+
+    hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
+
+    StringFromCLSID(Property->Set, &pstr);
+    swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr);
+    OutputDebugStringW(Buffer);
+
+    return hr;
 }
 
 HRESULT
@@ -1005,7 +1081,7 @@ COutputPin::KsMethod(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
-    assert(m_hPin != 0);
+    assert(m_hPin != INVALID_HANDLE_VALUE);
     OutputDebugStringW(L"COutputPin::KsMethod\n");
     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
 }
@@ -1019,7 +1095,7 @@ COutputPin::KsEvent(
     ULONG DataLength,
     ULONG* BytesReturned)
 {
-    assert(m_hPin != 0);
+    assert(m_hPin != INVALID_HANDLE_VALUE);
 
     OutputDebugStringW(L"COutputPin::KsEvent\n");
 
@@ -1045,8 +1121,6 @@ COutputPin::Set(
 {
     ULONG BytesReturned;
 
-    OutputDebugStringW(L"COutputPin::Set\n");
-
     if (cbInstanceData)
     {
         PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
@@ -1089,8 +1163,6 @@ COutputPin::Get(
 {
     ULONG BytesReturned;
 
-    OutputDebugStringW(L"COutputPin::Get\n");
-
     if (cbInstanceData)
     {
         PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
@@ -1160,21 +1232,12 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
     }
     else
     {
-        // get parent filter handle
-        hFilter = m_KsObjectParent->KsGetObjectHandle();
-
-        // get media type count
-        ZeroMemory(&MediaType, sizeof(AM_MEDIA_TYPE));
-        hr = KsGetMediaType(0, &MediaType, hFilter, m_PinId);
-        if (FAILED(hr))
-            return hr;
-
         // query accept
-        hr = pReceivePin->QueryAccept(&MediaType);
+        hr = pReceivePin->QueryAccept(&m_MediaFormat);
         if (FAILED(hr))
             return hr;
 
-         pmt = &MediaType;
+         pmt = &m_MediaFormat;
     }
 
     //FIXME create pin handle
@@ -1385,16 +1448,265 @@ COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate
     return E_NOTIMPL;
 }
 
+//-------------------------------------------------------------------
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::CheckFormat(
+    const AM_MEDIA_TYPE *pmt)
+{
+    PKSMULTIPLE_ITEM MultipleItem;
+    PKSDATAFORMAT DataFormat;
+    HRESULT hr;
+
+    if (!pmt)
+        return E_POINTER;
+
+    HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
+    assert(hFilter != NULL);
+
+    hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
+    if (FAILED(hr))
+        return S_FALSE;
+
+    DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
+    for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
+    {
+        if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
+            IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
+            IsEqualGUID(pmt->formattype, DataFormat->Specifier))
+        {
+            // format is supported
+            CoTaskMemFree(MultipleItem);
+            OutputDebugStringW(L"COutputPin::CheckFormat format OK\n");
+            return S_OK;
+        }
+        DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
+    }
+    //format is not supported
+    CoTaskMemFree(MultipleItem);
+    return S_FALSE;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::CreatePin(
+    const AM_MEDIA_TYPE *pmt)
+{
+    PKSMULTIPLE_ITEM MediumList;
+    PKSMULTIPLE_ITEM InterfaceList;
+    PKSPIN_MEDIUM Medium;
+    PKSPIN_INTERFACE Interface;
+    IKsInterfaceHandler * InterfaceHandler;
+    HRESULT hr;
+
+    // query for pin medium
+    hr = KsQueryMediums(&MediumList);
+    if (FAILED(hr))
+        return hr;
+
+    // query for pin interface
+    hr = KsQueryInterfaces(&InterfaceList);
+    if (FAILED(hr))
+    {
+        // failed
+        CoTaskMemFree(MediumList);
+        return hr;
+    }
+
+    if (MediumList->Count)
+    {
+        //use first available medium
+        Medium = (PKSPIN_MEDIUM)(MediumList + 1);
+    }
+    else
+    {
+        // default to standard medium
+        Medium = &StandardPinMedium;
+    }
+
+    if (InterfaceList->Count)
+    {
+        //use first available interface
+        Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
+    }
+    else
+    {
+        // default to standard interface
+        Interface = &StandardPinInterface;
+    }
+
+    if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
+    {
+        // now create pin
+        hr = CreatePinHandle(Medium, Interface, pmt);
+        if (FAILED(hr))
+        {
+            m_InterfaceHandler->Release();
+            m_InterfaceHandler = InterfaceHandler;
+        }
+
+        if (!m_InterfaceHandler)
+        {
+            // now load the IKsInterfaceHandler plugin
+            hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
+            if (FAILED(hr))
+            {
+                // failed to load interface handler plugin
+                OutputDebugStringW(L"COutputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
+                CoTaskMemFree(MediumList);
+                CoTaskMemFree(InterfaceList);
+
+                return hr;
+            }
+
+            // now set the pin
+            hr = InterfaceHandler->KsSetPin((IKsPin*)this);
+            if (FAILED(hr))
+            {
+                // failed to load interface handler plugin
+                OutputDebugStringW(L"COutputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
+                InterfaceHandler->Release();
+                CoTaskMemFree(MediumList);
+                CoTaskMemFree(InterfaceList);
+                return hr;
+            }
+
+            // store interface handler
+            m_InterfaceHandler = InterfaceHandler;
+        }
+    }
+    else
+    {
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
+        OutputDebugStringW(Buffer);
+        DebugBreak();
+        hr = E_FAIL;
+    }
+
+    // free medium / interface / dataformat
+    CoTaskMemFree(MediumList);
+    CoTaskMemFree(InterfaceList);
+
+    return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::CreatePinHandle(
+    PKSPIN_MEDIUM Medium,
+    PKSPIN_INTERFACE Interface,
+    const AM_MEDIA_TYPE *pmt)
+{
+    PKSPIN_CONNECT PinConnect;
+    PKSDATAFORMAT DataFormat;
+    ULONG Length;
+    HRESULT hr;
+
+    if (m_hPin != INVALID_HANDLE_VALUE)
+    {
+        // pin already exists
+        //CloseHandle(m_hPin);
+        //m_hPin = INVALID_HANDLE_VALUE;
+        return S_OK;
+    }
+
+
+    // calc format size
+    Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
+
+    // allocate pin connect
+    PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
+    if (!PinConnect)
+    {
+        // failed
+        return E_OUTOFMEMORY;
+    }
+
+    // setup request
+    CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
+    CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
+    PinConnect->PinId = m_PinId;
+    PinConnect->PinToHandle = NULL;
+    PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
+    PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
+
+    // get dataformat offset
+    DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
+
+    // copy data format
+    DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
+    DataFormat->Flags = 0;
+    DataFormat->SampleSize = pmt->lSampleSize;
+    DataFormat->Reserved = 0;
+    CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
+    CopyMemory(&DataFormat->SubFormat,  &pmt->subtype, sizeof(GUID));
+    CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
+
+    if (pmt->cbFormat)
+    {
+        // copy extended format
+        CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
+    }
+
+    HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
+    assert(hFilter != NULL);
+
+    // create pin
+    hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
+
+    if (SUCCEEDED(hr))
+    {
+        // store current interface / medium
+        CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
+        CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
+        CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
+
+        LPOLESTR pMajor, pSub, pFormat;
+        StringFromIID(m_MediaFormat.majortype, &pMajor);
+        StringFromIID(m_MediaFormat.subtype , &pSub);
+        StringFromIID(m_MediaFormat.formattype, &pFormat);
+        WCHAR Buffer[200];
+        swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
+        CoTaskMemFree(pMajor);
+        CoTaskMemFree(pSub);
+        CoTaskMemFree(pFormat);
+        OutputDebugStringW(Buffer);
+
+        if (pmt->cbFormat)
+        {
+            m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
+            if (!m_MediaFormat.pbFormat)
+            {
+                CoTaskMemFree(PinConnect);
+                m_MediaFormat.pbFormat = NULL;
+                m_MediaFormat.cbFormat = 0;
+                return E_OUTOFMEMORY;
+            }
+            CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
+        }
+
+        //TODO
+        // connect pin pipes
+
+    }
+    // free pin connect
+     CoTaskMemFree(PinConnect);
+
+    return hr;
+}
+
 HRESULT
 WINAPI
 COutputPin_Constructor(
     IBaseFilter * ParentFilter,
     LPCWSTR PinName,
     ULONG PinId,
+    KSPIN_COMMUNICATION Communication,
     REFIID riid,
     LPVOID * ppv)
 {
-    COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId);
+    COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
 
     if (!handler)
         return E_OUTOFMEMORY;
index 2ea89aa..6df3ddf 100644 (file)
@@ -134,6 +134,7 @@ COutputPin_Constructor(
     IBaseFilter * ParentFilter,
     LPCWSTR PinName,
     ULONG PinId,
+    KSPIN_COMMUNICATION Communication,
     REFIID riid,
     LPVOID * ppv);
 
@@ -170,3 +171,5 @@ extern const GUID IID_IKsPinEx;
 extern const GUID IID_IKsAggregateControl;
 extern const GUID IID_IKsPinPipe;
 extern const GUID IID_IKsPinFactory;
+extern KSPIN_INTERFACE StandardPinInterface;
+extern KSPIN_MEDIUM StandardPinMedium;
index 371176f..39d6386 100644 (file)
@@ -171,7 +171,7 @@ public:
     HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
 
 
-    CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0), m_hClock(0) {};
+    CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock((IReferenceClock*)this), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0), m_hClock(0) {};
     ~CKsProxy()
     {
         if (m_hDevice)
@@ -189,6 +189,9 @@ public:
     HRESULT STDMETHODCALLTYPE GetMediaSeekingFormats(PKSMULTIPLE_ITEM *FormatList);
     HRESULT STDMETHODCALLTYPE CreateClockInstance();
     HRESULT STDMETHODCALLTYPE PerformClockProperty(ULONG PropertyId, ULONG PropertyFlags, PVOID OutputBuffer, ULONG OutputBufferSize);
+    HRESULT STDMETHODCALLTYPE SetPinState(KSSTATE State);
+
+
 protected:
     LONG m_Ref;
     IFilterGraph *m_pGraph;
@@ -1581,6 +1584,7 @@ CKsProxy::GetMiscFlags()
     HRESULT hr;
     PIN_DIRECTION PinDirection;
     KSPIN_COMMUNICATION Communication;
+    WCHAR Buffer[100];
 
     for(Index = 0; Index < m_Pins.size(); Index++)
     {
@@ -1604,7 +1608,8 @@ CKsProxy::GetMiscFlags()
         }
     }
 
-    OutputDebugStringW(L"CKsProxy::GetMiscFlags stub\n");
+    swprintf(Buffer, L"CKsProxy::GetMiscFlags stub Flags %x\n", Flags);
+    OutputDebugStringW(Buffer);
     return Flags;
 }
 
@@ -2373,7 +2378,7 @@ CKsProxy::CreatePins()
         }
         else
         {
-            hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, IID_IPin, (void**)&pPin);
+            hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, Communication, IID_IPin, (void**)&pPin);
             if (FAILED(hr))
             {
                 CoTaskMemFree(PinName);
@@ -2519,8 +2524,21 @@ HRESULT
 STDMETHODCALLTYPE
 CKsProxy::Pause()
 {
-    OutputDebugStringW(L"CKsProxy::Pause : NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr = S_OK;
+
+    OutputDebugStringW(L"CKsProxy::Pause\n");
+
+    if (m_FilterState == State_Stopped)
+    {
+        hr = SetPinState(KSSTATE_PAUSE);
+        if (FAILED(hr))
+            return hr;
+
+    }
+
+    m_FilterState = State_Paused;
+    return hr;
+
 }
 
 HRESULT
@@ -2528,8 +2546,82 @@ STDMETHODCALLTYPE
 CKsProxy::Run(
     REFERENCE_TIME tStart)
 {
-    OutputDebugStringW(L"CKsProxy::Run : NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+
+    OutputDebugStringW(L"CKsProxy::Run\n");
+
+    if (m_FilterState == State_Stopped)
+    {
+        // setting filter state to pause
+        hr = Pause();
+        if (FAILED(hr))
+            return hr;
+
+        assert(m_FilterState == State_Paused);
+    }
+
+    hr = SetPinState(KSSTATE_RUN);
+    if (FAILED(hr))
+        return hr;
+
+    m_FilterState = State_Running;
+    return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::SetPinState(
+    KSSTATE State)
+{
+    HRESULT hr = S_OK;
+    ULONG Index;
+    IKsObject *pObject;
+    ULONG BytesReturned;
+    KSPROPERTY Property;
+
+    Property.Set = KSPROPSETID_Connection;
+    Property.Id = KSPROPERTY_CONNECTION_STATE;
+    Property.Flags = KSPROPERTY_TYPE_SET;
+
+    // set all pins to running state
+    for(Index = 0; Index < m_Pins.size(); Index++)
+    {
+        IPin * Pin = m_Pins[Index];
+        if (!Pin)
+            continue;
+
+        //check if the pin is connected
+        IPin * TempPin;
+        hr = Pin->ConnectedTo(&TempPin);
+        if (FAILED(hr))
+        {
+            // skip unconnected pins
+            continue;
+        }
+
+        // release connected pin
+        TempPin->Release();
+
+        //query IKsObject interface
+        hr = Pin->QueryInterface(IID_IKsObject, (void**)&pObject);
+
+        // get pin handle
+        HANDLE hPin = pObject->KsGetObjectHandle();
+
+        // sanity check
+        assert(hPin && hPin != INVALID_HANDLE_VALUE);
+
+        // now set state
+        hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
+
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"CKsProxy::SetPinState Index %u State %u hr %lx\n", Index, State, hr);
+        OutputDebugStringW(Buffer);
+
+        if (FAILED(hr))
+            return hr;
+    }
+    return hr;
 }
 
 HRESULT
@@ -2563,21 +2655,29 @@ CKsProxy::SetSyncSource(
     // FIXME
     // need locks
 
-    if (!pClock)
-        return E_POINTER;
+    if (pClock)
+    {
+        hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
+        if (FAILED(hr))
+        {
+            hr = m_ReferenceClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
+            if (FAILED(hr))
+                return hr;
+        }
 
-    hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
-    if (FAILED(hr))
-        return hr;
+        // get clock handle
+        hClock = pKsClock->KsGetClockHandle();
 
-    // get clock handle
-    hClock = pKsClock->KsGetClockHandle();
-    if (!hClock || hClock == INVALID_HANDLE_VALUE)
-    {
-        // failed
+        // release IKsClock interface
         pKsClock->Release();
-        return E_FAIL;
+        m_hClock = hClock;
     }
+    else
+    {
+        // no clock handle
+        m_hClock = NULL;
+    }
+
 
     // distribute clock to all pins
     for(Index = 0; Index < m_Pins.size(); Index++)
@@ -2601,7 +2701,7 @@ CKsProxy::SetSyncSource(
                 Property.Flags = KSPROPERTY_TYPE_SET;
 
                 // set master clock
-                hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)hClock, sizeof(HANDLE), &BytesReturned);
+                hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&m_hClock, sizeof(HANDLE), &BytesReturned);
 
                 if (FAILED(hr))
                 {
@@ -2609,8 +2709,10 @@ CKsProxy::SetSyncSource(
                         hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
                     {
                         // failed to set master clock
-                        pKsClock->Release();
                         pObject->Release();
+                        WCHAR Buffer[100];
+                        swprintf(Buffer, L"CKsProxy::SetSyncSource KSPROPERTY_STREAM_MASTERCLOCK failed with %lx\n", hr);
+                        OutputDebugStringW(Buffer);
                         return hr;
                     }
                 }
@@ -2642,6 +2744,7 @@ CKsProxy::SetSyncSource(
     }
 
     m_ReferenceClock = pClock;
+    OutputDebugStringW(L"CKsProxy::SetSyncSource done\n");
     return S_OK;
 }