* Bring back rbuild build to be used until bug 6372 is fixed.
[reactos.git] / dll / directx / ksproxy / output_pin.cpp
index c2227ca..2bf85c8 100644 (file)
@@ -246,8 +246,16 @@ COutputPin::COutputPin(
 
     ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
     ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
+    ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE));
 
     hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId);
+
+#ifdef KSPROXY_TRACE
+    WCHAR Buffer[100];
+    swprintf(Buffer, L"COutputPin::COutputPin Format %p pbFormat %lu\n", &m_MediaFormat, m_MediaFormat.cbFormat);
+    OutputDebugStringW(Buffer);
+#endif
+
     assert(hr == S_OK);
 
     InitializeCriticalSection(&m_Lock);
@@ -1518,6 +1526,8 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
     HRESULT hr;
     ALLOCATOR_PROPERTIES Properties;
     IMemAllocatorCallbackTemp *pMemCallback;
+    LPGUID pGuid;
+    ULONG NumGuids = 0;
 
 #ifdef KSPROXY_TRACE
     WCHAR Buffer[200];
@@ -1540,6 +1550,20 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
          pmt = &m_MediaFormat;
     }
 
+    if (m_hPin == INVALID_HANDLE_VALUE)
+    {
+        hr = CreatePin(pmt);
+        if (FAILED(hr))
+        {
+#ifdef KSPROXY_TRACE
+            swprintf(Buffer, L"COutputPin::Connect CreatePin handle failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+#endif
+            return hr;
+        }
+    }
+
+
     // query for IMemInput interface
     hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin);
     if (FAILED(hr))
@@ -1548,7 +1572,6 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
         OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");
 #endif
 
-        DebugBreak();
         return hr;
     }
 
@@ -1649,10 +1672,24 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
         return hr;
     }
 
-    if (!m_hPin)
+
+    assert(m_hPin != INVALID_HANDLE_VALUE);
+
+    // get all supported sets
+    if (m_Plugins.size() == 0)
     {
-        //FIXME create pin handle
-        assert(0);
+        if (GetSupportedSets(&pGuid, &NumGuids))
+        {
+            // load all proxy plugins
+            if (FAILED(LoadProxyPlugins(pGuid, NumGuids)));
+            {
+#ifdef KSPROXY_TRACE
+                OutputDebugStringW(L"COutputPin::Connect LoadProxyPlugins failed\n");
+#endif
+            }
+            // free sets
+            CoTaskMemFree(pGuid);
+        }
     }
 
     // receive connection;
@@ -1946,13 +1983,26 @@ COutputPin::CreatePin(
     // query for pin medium
     hr = KsQueryMediums(&MediumList);
     if (FAILED(hr))
+    {
+#ifdef KSPROXY_TRACE
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr);
+        OutputDebugStringW(Buffer);
+#endif
         return hr;
+    }
 
     // query for pin interface
     hr = KsQueryInterfaces(&InterfaceList);
     if (FAILED(hr))
     {
         // failed
+#ifdef KSPROXY_TRACE
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr);
+        OutputDebugStringW(Buffer);
+#endif
+
         CoTaskMemFree(MediumList);
         return hr;
     }
@@ -1985,8 +2035,12 @@ COutputPin::CreatePin(
         hr = CreatePinHandle(Medium, Interface, pmt);
         if (FAILED(hr))
         {
-            m_InterfaceHandler->Release();
-            m_InterfaceHandler = InterfaceHandler;
+#ifdef KSPROXY_TRACE
+            WCHAR Buffer[100];
+            swprintf(Buffer, L"COutputPin::CreatePinHandle failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+#endif
+            return hr;
         }
 
         if (!m_InterfaceHandler)
@@ -1999,6 +2053,12 @@ COutputPin::CreatePin(
                 CoTaskMemFree(MediumList);
                 CoTaskMemFree(InterfaceList);
 
+#ifdef KSPROXY_TRACE
+                WCHAR Buffer[100];
+                swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr);
+                OutputDebugStringW(Buffer);
+#endif
+
                 return hr;
             }
 
@@ -2006,7 +2066,12 @@ COutputPin::CreatePin(
             hr = InterfaceHandler->KsSetPin((IKsPin*)this);
             if (FAILED(hr))
             {
-                // failed to load interface handler plugin
+                // failed to initialize interface handler plugin
+#ifdef KSPROXY_TRACE
+                WCHAR Buffer[100];
+                swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr);
+                OutputDebugStringW(Buffer);
+#endif
                 InterfaceHandler->Release();
                 CoTaskMemFree(MediumList);
                 CoTaskMemFree(InterfaceList);
@@ -2023,7 +2088,6 @@ COutputPin::CreatePin(
         WCHAR Buffer[100];
         swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
         OutputDebugStringW(Buffer);
-        DebugBreak();
 #endif
 
         hr = E_FAIL;
@@ -2033,6 +2097,12 @@ COutputPin::CreatePin(
     CoTaskMemFree(MediumList);
     CoTaskMemFree(InterfaceList);
 
+#ifdef KSPROXY_TRACE
+    WCHAR Buffer[100];
+    swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr);
+    OutputDebugStringW(Buffer);
+#endif
+
     return hr;
 }
 
@@ -2054,11 +2124,14 @@ COutputPin::CreatePinHandle(
     //KSPROPERTY Property;
     //ULONG BytesReturned;
 
+    OutputDebugStringW(L"COutputPin::CreatePinHandle\n");
+
     if (m_hPin != INVALID_HANDLE_VALUE)
     {
         // pin already exists
         //CloseHandle(m_hPin);
         //m_hPin = INVALID_HANDLE_VALUE;
+        OutputDebugStringW(L"COutputPin::CreatePinHandle pin already exists\n");
         return S_OK;
     }
 
@@ -2071,9 +2144,10 @@ COutputPin::CreatePinHandle(
     if (!PinConnect)
     {
         // failed
+        OutputDebugStringW(L"COutputPin::CreatePinHandle out of memory\n");
         return E_OUTOFMEMORY;
     }
-
+        OutputDebugStringW(L"COutputPin::CreatePinHandle copy pinconnect\n");
     // setup request
     CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
     CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
@@ -2084,7 +2158,7 @@ COutputPin::CreatePinHandle(
 
     // get dataformat offset
     DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
-
+        OutputDebugStringW(L"COutputPin::CreatePinHandle copy format\n");
     // copy data format
     DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
     DataFormat->Flags = 0;
@@ -2097,13 +2171,19 @@ COutputPin::CreatePinHandle(
     if (pmt->cbFormat)
     {
         // copy extended format
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"COutputPin::CreatePinHandle copy format %p pbFormat %lu\n", pmt, pmt->cbFormat);
+        OutputDebugStringW(Buffer);
         CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
     }
 
     // get IKsObject interface
     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
     if (FAILED(hr))
+    {
+        OutputDebugStringW(L"COutputPin::CreatePinHandle no IID_IKsObject interface\n");
         return hr;
+    }
 
     // get parent filter handle
     hFilter = KsObjectParent->KsGetObjectHandle();
@@ -2112,13 +2192,19 @@ COutputPin::CreatePinHandle(
     KsObjectParent->Release();
 
     if (!hFilter)
+    {
+        OutputDebugStringW(L"COutputPin::CreatePinHandle no filter handle\n");
         return E_HANDLE;
+    }
 
+    OutputDebugStringW(L"COutputPin::CreatePinHandle before creating pin\n");
     // create pin
-    hr = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
+    DWORD dwError = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
 
-    if (SUCCEEDED(hr))
+    if (dwError == ERROR_SUCCESS)
     {
+        OutputDebugStringW(L"COutputPin::CreatePinHandle created pin\n");
+
         // store current interface / medium
         CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
         CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
@@ -2169,40 +2255,14 @@ COutputPin::CreatePinHandle(
         if (FAILED(InitializeIOThread()))
         {
             OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
-            DebugBreak();
-        }
-
-        LPGUID pGuid;
-        ULONG NumGuids = 0;
-
-        // get all supported sets
-        hr = GetSupportedSets(&pGuid, &NumGuids);
-        if (FAILED(hr))
-        {
-#ifdef KSPROXY_TRACE
-            OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
-#endif
-            return hr;
-        }
-
-        // load all proxy plugins
-        hr = LoadProxyPlugins(pGuid, NumGuids);
-        if (FAILED(hr))
-        {
-#ifdef KSPROXY_TRACE
-            OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
-#endif
-            return hr;
         }
 
-        // free sets
-        CoTaskMemFree(pGuid);
-
-
         //TODO
         // connect pin pipes
 
     }
+    else
+        OutputDebugStringW(L"COutputPin::CreatePinHandle failed to create pin\n");
     // free pin connect
      CoTaskMemFree(PinConnect);
 
@@ -2234,6 +2294,8 @@ COutputPin::GetSupportedSets(
 
     Length = NumProperty + NumMethods + NumEvents;
 
+    assert(Length);
+
     // allocate guid buffer
     pGuid = (LPGUID)CoTaskMemAlloc(Length);
     if (!pGuid)
@@ -2256,7 +2318,7 @@ COutputPin::GetSupportedSets(
     Length -= BytesReturned;
 
     // get all methods
-    if (Length)
+    if (Length && NumMethods)
     {
         hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
         if (FAILED(hr))
@@ -2268,7 +2330,7 @@ COutputPin::GetSupportedSets(
     }
 
     // get all events
-    if (Length)
+    if (Length && NumEvents)
     {
         hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
         if (FAILED(hr))
@@ -2348,17 +2410,48 @@ COutputPin::IoProcessRoutine()
     IMediaSample *Sample;
     LONG SampleCount;
     HRESULT hr;
-    PKSSTREAM_SEGMENT StreamSegment;
+    PKSSTREAM_SEGMENT StreamSegment;
     HANDLE hEvent;
-    IMediaSample * Samples[1];
+    IMediaSample ** Samples;
+    LONG NumHandles;
+    DWORD dwStatus;
 
 #ifdef KSPROXY_TRACE
     WCHAR Buffer[200];
 #endif
 
+    NumHandles = m_Properties.cBuffers / 2;
+
+    if (!NumHandles)
+        NumHandles = 8;
+
+    assert(NumHandles);
+
+    //allocate stream segment array
+    StreamSegment = (PKSSTREAM_SEGMENT*)CoTaskMemAlloc(sizeof(PKSSTREAM_SEGMENT) * NumHandles);
+    if (!StreamSegment)
+    {
+        OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n");
+        return E_FAIL;
+    }
+
+    // allocate handle array
+    Samples = (IMediaSample**)CoTaskMemAlloc(sizeof(IMediaSample*) * NumHandles);
+    if (!Samples)
+    {
+        OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n");
+        return E_FAIL;
+    }
+
+    // zero handles array
+    ZeroMemory(StreamSegment, sizeof(PKSSTREAM_SEGMENT) * NumHandles);
+    ZeroMemory(Samples, sizeof(IMediaSample*) * NumHandles);
+
     // first wait for the start event to signal
     WaitForSingleObject(m_hStartEvent, INFINITE);
 
+    m_IoCount = 0;
+
     assert(m_InterfaceHandler);
     do
     {
@@ -2383,14 +2476,14 @@ COutputPin::IoProcessRoutine()
 
         // fill buffer
         SampleCount = 1;
-        Samples[0] = Sample;
+        Samples[m_IoCount] = Sample;
 
         Sample->SetTime(NULL, NULL);
         hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */
-                                                       Samples,
+                                                       &Samples[m_IoCount],
                                                        &SampleCount,
                                                        KsIoOperation_Read,
-                                                       &StreamSegment);
+                                                       &StreamSegment[m_IoCount]);
         if (FAILED(hr) || !StreamSegment)
         {
 #ifdef KSPROXY_TRACE
@@ -2400,14 +2493,26 @@ COutputPin::IoProcessRoutine()
             break;
         }
 
-        // get completion event
-        hEvent = StreamSegment->CompletionEvent;
+        // interface handle should increment pending i/o count
+        assert(m_IoCount >= 1);
+
+        swprintf(Buffer, L"COutputPin::IoProcessRoutine m_IoCount %lu NumHandles %lu\n", m_IoCount, NumHandles);
+        OutputDebugStringW(Buffer);
+
+        if (m_IoCount != NumHandles)
+            continue;
+
+        // get completion handle
+        hEvent = StreamSegment[0]->CompletionEvent;
 
         // wait for i/o completion
-        WaitForSingleObject(hEvent, INFINITE);
+        dwStatus = WaitForSingleObject(hEvent, INFINITE);
+
+        swprintf(Buffer, L"COutputPin::IoProcessRoutine dwStatus %lx Error %lx NumHandles %lu\n", dwStatus, GetLastError(), NumHandles);
+        OutputDebugStringW(Buffer);
 
         // perform completion
-        m_InterfaceHandler->KsCompleteIo(StreamSegment);
+        m_InterfaceHandler->KsCompleteIo(StreamSegment[0]);
 
         // close completion event
         CloseHandle(hEvent);
@@ -2417,7 +2522,7 @@ COutputPin::IoProcessRoutine()
             assert(m_MemInputPin);
 
             // now deliver the sample
-            hr = m_MemInputPin->Receive(Sample);
+            hr = m_MemInputPin->Receive(Samples[0]);
 
 #ifdef KSPROXY_TRACE
             swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator);
@@ -2429,6 +2534,11 @@ COutputPin::IoProcessRoutine()
 
             Sample = NULL;
         }
+
+        //circular stream segment array
+        RtlMoveMemory(StreamSegment, &StreamSegment[1], sizeof(PKSSTREAM_SEGMENT) * (NumHandles - 1));
+        RtlMoveMemory(Samples, &Samples[1], sizeof(IMediaSample*) * (NumHandles - 1));
+
     }while(TRUE);
 
     // signal end of i/o thread