Quartz: Fix For IAsyncReader Output Pin (resend)

Robert Shearman rob at codeweavers.com
Wed Aug 18 19:46:27 CDT 2004


This time without the conflicts with current CVS.

Changelog:
- Remove duplicated code in file reader.
- Use new CreateSpecific function for file reader that doesn't query for 
IMemInputPin.
- Get rid of inefficient use of IMemInputPin in general pin code.

-------------- next part --------------
Index: wine/dlls/quartz/filesource.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/filesource.c,v
retrieving revision 1.6
diff -u -p -r1.6 filesource.c
--- wine/dlls/quartz/filesource.c	13 Aug 2004 19:49:16 -0000	1.6
+++ wine/dlls/quartz/filesource.c	19 Aug 2004 00:43:07 -0000
@@ -766,82 +766,13 @@ static HRESULT WINAPI FileAsyncReaderPin
     return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
 }
 
-static HRESULT WINAPI FileAsyncReaderPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
-{
-    HRESULT hr = S_OK;
-    ICOM_THIS(OutputPin, iface);
-
-    TRACE("(%p, %p)\n", pReceivePin, pmt);
-    dump_AM_MEDIA_TYPE(pmt);
-
-    /* If we try to connect to ourself, we will definitely deadlock.
-     * There are other cases where we could deadlock too, but this
-     * catches the obvious case */
-    assert(pReceivePin != iface);
-
-    EnterCriticalSection(This->pin.pCritSec);
-    {
-        /* if we have been a specific type to connect with, then we can either connect
-         * with that or fail. We cannot choose different AM_MEDIA_TYPE */
-        if (pmt && !IsEqualGUID(&pmt->majortype, &GUID_NULL) && !IsEqualGUID(&pmt->subtype, &GUID_NULL))
-            hr = This->pConnectSpecific(iface, pReceivePin, pmt);
-        else
-        {
-            /* negotiate media type */
-
-            IEnumMediaTypes * pEnumCandidates;
-            AM_MEDIA_TYPE * pmtCandidate; /* Candidate media type */
-
-            if (SUCCEEDED(IPin_EnumMediaTypes(iface, &pEnumCandidates)))
-            {
-                hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */
-
-                /* try this filter's media types first */
-                while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL))
-                {
-                    if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && 
-                        (This->pConnectSpecific(iface, pReceivePin, pmtCandidate) == S_OK))
-                    {
-                        hr = S_OK;
-                        CoTaskMemFree(pmtCandidate);
-                        break;
-                    }
-                    CoTaskMemFree(pmtCandidate);
-                }
-                IEnumMediaTypes_Release(pEnumCandidates);
-            }
-
-            /* then try receiver filter's media types */
-            if (hr != S_OK && SUCCEEDED(IPin_EnumMediaTypes(pReceivePin, &pEnumCandidates))) /* if we haven't already connected successfully */
-            {
-                while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL))
-                {
-                    if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && 
-                        (This->pConnectSpecific(iface, pReceivePin, pmtCandidate) == S_OK))
-                    {
-                        hr = S_OK;
-                        CoTaskMemFree(pmtCandidate);
-                        break;
-                    }
-                    CoTaskMemFree(pmtCandidate);
-                } /* while */
-                IEnumMediaTypes_Release(pEnumCandidates);
-            } /* if not found */
-        } /* if negotiate media type */
-    } /* if succeeded */
-    LeaveCriticalSection(This->pin.pCritSec);
-
-    TRACE("-- %lx\n", hr);
-    return hr;
-}
-
 static const IPinVtbl FileAsyncReaderPin_Vtbl = 
 {
     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
     FileAsyncReaderPin_QueryInterface,
     IPinImpl_AddRef,
     FileAsyncReaderPin_Release,
-    FileAsyncReaderPin_Connect,
+    OutputPin_Connect,
     OutputPin_ReceiveConnection,
     IPinImpl_Disconnect,
     IPinImpl_ConnectedTo,
@@ -858,6 +789,37 @@ static const IPinVtbl FileAsyncReaderPin
     OutputPin_NewSegment
 };
 
+/* Function called as a helper to IPin_Connect */
+/* specific AM_MEDIA_TYPE - it cannot be NULL */
+/* this differs from standard OutputPin_ConnectSpecific only in that it
+ * doesn't need the IMemInputPin interface on the receiving pin */
+static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
+{
+    ICOM_THIS(OutputPin, iface);
+    HRESULT hr;
+
+    TRACE("(%p, %p)\n", pReceivePin, pmt);
+    dump_AM_MEDIA_TYPE(pmt);
+
+    /* FIXME: call queryacceptproc */
+
+    This->pin.pConnectedTo = pReceivePin;
+    IPin_AddRef(pReceivePin);
+    CopyMediaType(&This->pin.mtCurrent, pmt);
+
+    hr = IPin_ReceiveConnection(pReceivePin, iface, pmt);
+
+    if (FAILED(hr))
+    {
+        IPin_Release(This->pin.pConnectedTo);
+        This->pin.pConnectedTo = NULL;
+        DeleteMediaType(&This->pin.mtCurrent);
+    }
+
+    TRACE(" -- %lx\n", hr);
+    return hr;
+}
+
 static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
 {
     FileAsyncReader * pPinImpl;
@@ -882,6 +844,7 @@ static HRESULT FileAsyncReader_Construct
         pPinImpl->hEvent = CreateEventW(NULL, 0, 0, NULL);
         pPinImpl->bFlushing = FALSE;
         pPinImpl->pHead = NULL;
+        pPinImpl->pin.pConnectSpecific = FileAsyncReaderPin_ConnectSpecific;
         InitializeCriticalSection(&pPinImpl->csList);
 
         *ppPin = (IPin *)(&pPinImpl->pin.pin.lpVtbl);
Index: wine/dlls/quartz/pin.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/pin.c,v
retrieving revision 1.5
diff -u -p -r1.5 pin.c
--- wine/dlls/quartz/pin.c	16 Aug 2004 21:07:22 -0000	1.5
+++ wine/dlls/quartz/pin.c	19 Aug 2004 00:43:07 -0000
@@ -52,7 +52,7 @@ static void Copy_PinInfo(PIN_INFO * pDes
     IBaseFilter_AddRef(pDest->pFilter);
 }
 
-/* Internal function called as a helper to IPin_Connect */
+/* Function called as a helper to IPin_Connect */
 /* specific AM_MEDIA_TYPE - it cannot be NULL */
 /* NOTE: not part of standard interface */
 static HRESULT OutputPin_ConnectSpecific(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
@@ -842,14 +842,9 @@ HRESULT OutputPin_GetDeliveryBuffer(Outp
             hr = VFW_E_NOT_CONNECTED;
         else
         {
-            IMemInputPin * pMemInputPin = NULL;
             IMemAllocator * pAlloc = NULL;
             
-            /* FIXME: should we cache this? */
-            hr = IPin_QueryInterface(This->pin.pConnectedTo, &IID_IMemInputPin, (LPVOID *)&pMemInputPin);
-
-            if (SUCCEEDED(hr))
-                hr = IMemInputPin_GetAllocator(pMemInputPin, &pAlloc);
+            hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc);
 
             if (SUCCEEDED(hr))
                 hr = IMemAllocator_GetBuffer(pAlloc, ppSample, (REFERENCE_TIME *)tStart, (REFERENCE_TIME *)tStop, dwFlags);
@@ -859,8 +854,6 @@ HRESULT OutputPin_GetDeliveryBuffer(Outp
 
             if (pAlloc)
                 IMemAllocator_Release(pAlloc);
-            if (pMemInputPin)
-                IMemInputPin_Release(pMemInputPin);
         }
     }
     LeaveCriticalSection(This->pin.pCritSec);
@@ -870,23 +863,25 @@ HRESULT OutputPin_GetDeliveryBuffer(Outp
 
 HRESULT OutputPin_SendSample(OutputPin * This, IMediaSample * pSample)
 {
-    HRESULT hr;
+    HRESULT hr = S_OK;
     IMemInputPin * pMemConnected = NULL;
 
     EnterCriticalSection(This->pin.pCritSec);
     {
-        if (!This->pin.pConnectedTo)
+        if (!This->pin.pConnectedTo || !This->pMemInputPin)
             hr = VFW_E_NOT_CONNECTED;
         else
         {
-            /* FIXME: should we cache this? - if we do, then we need to keep the local version
-             * and AddRef here instead */
-            hr = IPin_QueryInterface(This->pin.pConnectedTo, &IID_IMemInputPin, (LPVOID *)&pMemConnected);
+            /* we don't have the lock held when using This->pMemInputPin,
+             * so we need to AddRef it to stop it being deleted while we are
+             * using it. */
+            pMemConnected = This->pMemInputPin;
+            IMemInputPin_AddRef(pMemConnected);
         }
     }
     LeaveCriticalSection(This->pin.pCritSec);
 
-    if (SUCCEEDED(hr) && pMemConnected)
+    if (SUCCEEDED(hr))
     {
         /* NOTE: if we are in a critical section when Receive is called
          * then it causes some problems (most notably with the native Video
@@ -922,26 +917,19 @@ HRESULT OutputPin_CommitAllocator(Output
 
     EnterCriticalSection(This->pin.pCritSec);
     {
-        if (!This->pin.pConnectedTo)
+        if (!This->pin.pConnectedTo || !This->pMemInputPin)
             hr = VFW_E_NOT_CONNECTED;
         else
         {
-            IMemInputPin * pMemInputPin = NULL;
             IMemAllocator * pAlloc = NULL;
-            /* FIXME: should we cache this? */
-            hr = IPin_QueryInterface(This->pin.pConnectedTo, &IID_IMemInputPin, (LPVOID *)&pMemInputPin);
 
-            if (SUCCEEDED(hr))
-                hr = IMemInputPin_GetAllocator(pMemInputPin, &pAlloc);
+            hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc);
 
             if (SUCCEEDED(hr))
                 hr = IMemAllocator_Commit(pAlloc);
 
             if (pAlloc)
                 IMemAllocator_Release(pAlloc);
-
-            if (pMemInputPin)
-                IMemInputPin_Release(pMemInputPin);
         }
     }
     LeaveCriticalSection(This->pin.pCritSec);
@@ -957,26 +945,19 @@ HRESULT OutputPin_DeliverDisconnect(Outp
 
     EnterCriticalSection(This->pin.pCritSec);
     {
-        if (!This->pin.pConnectedTo)
+        if (!This->pin.pConnectedTo || !This->pMemInputPin)
             hr = VFW_E_NOT_CONNECTED;
         else
         {
-            IMemInputPin * pMemInputPin = NULL;
             IMemAllocator * pAlloc = NULL;
-            /* FIXME: should we cache this? */
-            hr = IPin_QueryInterface(This->pin.pConnectedTo, &IID_IMemInputPin, (LPVOID *)&pMemInputPin);
 
-            if (SUCCEEDED(hr))
-                hr = IMemInputPin_GetAllocator(pMemInputPin, &pAlloc);
+            hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc);
 
             if (SUCCEEDED(hr))
                 hr = IMemAllocator_Decommit(pAlloc);
 
             if (pAlloc)
                 IMemAllocator_Release(pAlloc);
-
-            if (pMemInputPin)
-                IMemInputPin_Release(pMemInputPin);
 
             if (SUCCEEDED(hr))
                 hr = IPin_Disconnect(This->pin.pConnectedTo);


More information about the wine-patches mailing list