[QUARTZ] Added ACM Wrapper filter

Christian Costa titan.costa at wanadoo.fr
Mon Jan 31 17:17:17 CST 2005


Hi,

Changelog:
Added ACM Wrapper filter.
Cleaned up AVIDec.

Christian Costa   titan.costa at wanadoo.fr

-------------- next part --------------
Index: dlls/quartz/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/quartz/Makefile.in,v
retrieving revision 1.41
diff -u -r1.41 Makefile.in
--- dlls/quartz/Makefile.in	31 Jan 2005 16:24:00 -0000	1.41
+++ dlls/quartz/Makefile.in	31 Jan 2005 22:04:51 -0000
@@ -3,10 +3,11 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = quartz.dll
-IMPORTS   = dsound ddraw msvfw32 ole32 oleaut32 user32 advapi32 kernel32
+IMPORTS   = dsound ddraw msacm32 msvfw32 ole32 oleaut32 user32 advapi32 kernel32
 EXTRALIBS = -lstrmiids -luuid $(LIBUNICODE)
 
 C_SRCS = \
+	acmwrapper.c \
 	avidec.c \
 	avisplit.c \
 	control.c \
Index: dlls/quartz/regsvr.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/regsvr.c,v
retrieving revision 1.17
diff -u -r1.17 regsvr.c
--- dlls/quartz/regsvr.c	31 Jan 2005 16:24:00 -0000	1.17
+++ dlls/quartz/regsvr.c	31 Jan 2005 22:04:54 -0000
@@ -874,6 +874,12 @@
 	"quartz.dll",
 	"Both"
     },
+    {   &CLSID_SeekingPassThru,
+       "Seeking",
+       NULL,
+       "quartz.dll",
+       "Both"
+    },
     {   &CLSID_AsyncReader,
 	"File Source Filter",
 	NULL,
@@ -904,11 +910,11 @@
 	"quartz.dll",
 	"Both"
     },
-    {   &CLSID_SeekingPassThru,
-       "Seeking",
-       NULL,
-       "quartz.dll",
-       "Both"
+    {   &CLSID_ACMWrapper,
+	"ACM wrapper",
+	NULL,
+	"quartz.dll",
+	"Both"
     },
     { NULL }			/* list terminator */
 };
@@ -1058,6 +1064,23 @@
 	0x400000,
 	{   {   REG_PINFLAG_B_OUTPUT,
 		{   { &MEDIATYPE_Stream, &GUID_NULL },
+		    { NULL }
+		},
+	    },
+	    { 0xFFFFFFFF },
+	}
+    },
+    {   &CLSID_ACMWrapper,
+	&CLSID_LegacyAmFilterCategory,
+	{'A','C','M',' ','W','r','a','p','p','e','r',0},
+	0x600000,
+	{   {   0,
+		{   { &MEDIATYPE_Audio, &GUID_NULL },
+		    { NULL }
+		},
+	    },
+	    {   REG_PINFLAG_B_OUTPUT,
+		{   { &MEDIATYPE_Audio, &GUID_NULL },
 		    { NULL }
 		},
 	    },
Index: dlls/quartz/avidec.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/avidec.c,v
retrieving revision 1.15
diff -u -r1.15 avidec.c
--- dlls/quartz/avidec.c	31 Jan 2005 16:24:00 -0000	1.15
+++ dlls/quartz/avidec.c	31 Jan 2005 22:04:56 -0000
@@ -54,9 +54,9 @@
     BITMAPINFOHEADER* pBihOut;
 } AVIDecImpl;
 
-static DWORD AVIDec_SendSampleData(TransformFilterImpl* sub, LPBYTE data, DWORD size)
+static DWORD AVIDec_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
 {
-    AVIDecImpl* This = (AVIDecImpl*)sub;
+    AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
     VIDEOINFOHEADER* format;
     AM_MEDIA_TYPE amt;
     HRESULT hr;
@@ -65,7 +65,7 @@
     DWORD cbDstStream;
     LPBYTE pbDstStream;
 
-    TRACE("%p %p %ld\n", sub, data, size);
+    TRACE("(%p)->(%p,%ld)\n", This, data, size);
     
     hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt);
     if (FAILED(hr)) {
@@ -115,11 +115,11 @@
     return hr;
 }
 
-static HRESULT AVIDec_ConnectInput(TransformFilterImpl* iface, const AM_MEDIA_TYPE * pmt)
+static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt)
 {
-    AVIDecImpl* pAVIDec = (AVIDecImpl*)iface;
-    TRACE("%p\n", iface);
-    dump_AM_MEDIA_TYPE(pmt);
+    AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
+
+    TRACE("(%p)->(%p)\n", This, pmt);
 
     if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
         (!memcmp(((char*)&pmt->subtype)+4, ((char*)&MEDIATYPE_Video)+4, sizeof(GUID)-4)) && /* Check root (GUID w/o FOURCC) */
@@ -131,7 +131,7 @@
         drv = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS);
         if (drv)
         {
-            AM_MEDIA_TYPE* outpmt = &((OutputPin*)pAVIDec->tf.ppPins[1])->pin.mtCurrent;
+            AM_MEDIA_TYPE* outpmt = &((OutputPin*)This->tf.ppPins[1])->pin.mtCurrent;
             const CLSID* outsubtype;
             DWORD bih_size;
 
@@ -148,37 +148,37 @@
             }
             CopyMediaType(outpmt, pmt);
             outpmt->subtype = *outsubtype;
-            pAVIDec->hvid = drv;
+            This->hvid = drv;
 
             /* Copy bitmap header from media type to 1 for input and 1 for output */
-            if (pAVIDec->pBihIn) {
-                CoTaskMemFree(pAVIDec->pBihIn);
-                CoTaskMemFree(pAVIDec->pBihOut);
+            if (This->pBihIn) {
+                CoTaskMemFree(This->pBihIn);
+                CoTaskMemFree(This->pBihOut);
             }
             bih_size = format->bmiHeader.biSize + format->bmiHeader.biClrUsed * 4;
-            pAVIDec->pBihIn = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
-            if (!pAVIDec->pBihIn)
+            This->pBihIn = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
+            if (!This->pBihIn)
             {
                 ICClose(drv);
                 return E_OUTOFMEMORY;
             }
-            pAVIDec->pBihOut = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
-            if (!pAVIDec->pBihOut)
+            This->pBihOut = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
+            if (!This->pBihOut)
             {
-                CoTaskMemFree(pAVIDec->pBihIn);
-                pAVIDec->pBihIn = NULL;
+                CoTaskMemFree(This->pBihIn);
+                This->pBihIn = NULL;
                 ICClose(drv);
                 return E_OUTOFMEMORY;
             }
-            memcpy(pAVIDec->pBihIn, &format->bmiHeader, bih_size);
-            memcpy(pAVIDec->pBihOut, &format->bmiHeader, bih_size);
+            memcpy(This->pBihIn, &format->bmiHeader, bih_size);
+            memcpy(This->pBihOut, &format->bmiHeader, bih_size);
 
             /* Update output format as non compressed bitmap */
-            pAVIDec->pBihOut->biCompression = 0;
-            pAVIDec->pBihOut->biSizeImage = pAVIDec->pBihOut->biWidth * pAVIDec->pBihOut->biHeight * pAVIDec->pBihOut->biBitCount / 8;
+            This->pBihOut->biCompression = 0;
+            This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8;
 
             /* Update buffer size of media samples in output */
-            ((OutputPin*)pAVIDec->tf.ppPins[1])->allocProps.cbBuffer = pAVIDec->pBihOut->biSizeImage;
+            ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage;
 
             TRACE("Connection accepted\n");
             return S_OK;
@@ -190,20 +190,22 @@
     return S_FALSE;
 }
 
-static HRESULT AVIDec_Cleanup(TransformFilterImpl* This)
+static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter)
 {
-    AVIDecImpl* pAVIDec = (AVIDecImpl*)This;
-	
-    if (pAVIDec->hvid)
-        ICClose(pAVIDec->hvid);
-
-    if (pAVIDec->pBihIn) {
-        CoTaskMemFree(pAVIDec->pBihIn);
-        CoTaskMemFree(pAVIDec->pBihOut);
+    AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
+
+    TRACE("(%p)->()\n", This);
+    
+    if (This->hvid)
+        ICClose(This->hvid);
+
+    if (This->pBihIn) {
+        CoTaskMemFree(This->pBihIn);
+        CoTaskMemFree(This->pBihOut);
     }
 
-    pAVIDec->hvid = NULL;
-    pAVIDec->pBihIn = NULL;
+    This->hvid = NULL;
+    This->pBihIn = NULL;
 
     return S_OK;
 }
@@ -211,7 +213,7 @@
 HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
 {
     HRESULT hr;
-    AVIDecImpl * pAVIDec;
+    AVIDecImpl * This;
 
     TRACE("(%p, %p)\n", pUnkOuter, ppv);
 
@@ -221,17 +223,17 @@
         return CLASS_E_NOAGGREGATION;
 
     /* Note: This memory is managed by the transform filter once created */
-    pAVIDec = CoTaskMemAlloc(sizeof(AVIDecImpl));
+    This = CoTaskMemAlloc(sizeof(AVIDecImpl));
 
-    pAVIDec->hvid = NULL;
-    pAVIDec->pBihIn = NULL;
+    This->hvid = NULL;
+    This->pBihIn = NULL;
 
-    hr = TransformFilter_Create(&(pAVIDec->tf), &CLSID_AVIDec, AVIDec_SendSampleData, AVIDec_ConnectInput, AVIDec_Cleanup);
+    hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, AVIDec_SendSampleData, AVIDec_ConnectInput, AVIDec_Cleanup);
 
     if (FAILED(hr))
         return hr;
 
-    *ppv = (LPVOID)pAVIDec;
+    *ppv = (LPVOID)This;
 
     return hr;
 }
Index: dlls/quartz/quartz_private.h
===================================================================
RCS file: /home/wine/wine/dlls/quartz/quartz_private.h,v
retrieving revision 1.20
diff -u -r1.20 quartz_private.h
--- dlls/quartz/quartz_private.h	7 Oct 2004 03:06:49 -0000	1.20
+++ dlls/quartz/quartz_private.h	31 Jan 2005 22:04:57 -0000
@@ -50,6 +50,7 @@
 HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv);
 HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv);
 HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv);
+HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv);
 
 HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum);
 
Index: dlls/quartz/main.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/main.c,v
retrieving revision 1.41
diff -u -r1.41 main.c
--- dlls/quartz/main.c	8 Oct 2004 21:01:44 -0000	1.41
+++ dlls/quartz/main.c	31 Jan 2005 22:04:59 -0000
@@ -69,7 +69,8 @@
     { &CLSID_VideoRenderer, VideoRenderer_create },
     { &CLSID_DSoundRender, DSoundRender_create },
     { &CLSID_AVIDec, AVIDec_create },
-    { &CLSID_SystemClock, &QUARTZ_CreateSystemClock }
+    { &CLSID_SystemClock, &QUARTZ_CreateSystemClock },
+    { &CLSID_ACMWrapper, &ACMWrapper_create }
 };
 
 static HRESULT WINAPI
--- /dev/null	1970-01-01 01:00:00.000000000 +0100
+++ dlls/quartz/acmwrapper.c	2005-01-31 23:13:30.000000000 +0000
@@ -0,0 +1,259 @@
+/*
+ * ACM Wrapper
+ *
+ * Copyright 2005 Christian Costa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include "quartz_private.h"
+#include "control_private.h"
+#include "pin.h"
+
+#include "uuids.h"
+#include "mmreg.h"
+#include "windef.h"
+#include "winbase.h"
+#include "dshow.h"
+#include "strmif.h"
+#include "vfwmsgs.h"
+#include "evcode.h"
+#include "msacm.h"
+
+#include <assert.h>
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#include "transform.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+
+/* FIXME: Improve buffers management */
+#define OUTPUT_BUFFER_SIZE 15000
+#define INPUT_BUFFER_SIZE 4096
+
+typedef struct ACMWrapperImpl
+{
+    TransformFilterImpl tf;
+    HACMSTREAM has;
+    LPWAVEFORMATEX pWfIn;
+    LPWAVEFORMATEX pWfOut;
+    BYTE buffer[INPUT_BUFFER_SIZE];
+    DWORD max_size;
+    DWORD current_size;
+    BOOL reinit_codec; /* FIXME: Should use sync points instead */
+} ACMWrapperImpl;
+
+static DWORD ACMWrapper_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
+{
+    ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
+    AM_MEDIA_TYPE amt;
+    HRESULT hr;
+    IMediaSample* pSample = NULL;
+    DWORD cbDstStream;
+    LPBYTE pbDstStream;
+    ACMSTREAMHEADER ash;
+    DWORD offset = 0;
+    BOOL stop = FALSE;
+    BOOL unprepare_header = FALSE;
+    MMRESULT res;
+
+    TRACE("(%p)->(%p,%ld)\n", This, data, size);
+
+    hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt);
+    if (FAILED(hr)) {
+	ERR("Unable to retrieve media type\n");
+	goto error;
+    }
+
+    while(!stop)
+    {
+	DWORD rem_buf = This->max_size - This->current_size;
+	DWORD rem_smp = size - offset;
+	DWORD copy_size = min(rem_buf, rem_smp);
+
+	memcpy(This->buffer + This->current_size, data + offset, copy_size);
+	This->current_size += copy_size;
+	offset += copy_size;
+
+	if (offset == size)
+	    stop = TRUE;
+	if (This->current_size < This->max_size)
+	    break;
+  
+	hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pSample, NULL, NULL, 0);
+	if (FAILED(hr)) {
+	    ERR("Unable to get delivery buffer (%lx)\n", hr);
+	    goto error;
+	}
+
+	hr = IMediaSample_SetActualDataLength(pSample, 0);
+	assert(hr == S_OK);
+
+	hr = IMediaSample_GetPointer(pSample, &pbDstStream);
+	if (FAILED(hr)) {
+	    ERR("Unable to get pointer to buffer (%lx)\n", hr);
+	    goto error;
+	}
+	cbDstStream = IMediaSample_GetSize(pSample);
+
+	ash.cbStruct = sizeof(ash);
+	ash.fdwStatus = 0;
+	ash.dwUser = 0;
+	ash.pbSrc = This->buffer;
+	ash.cbSrcLength = This->current_size;
+	ash.pbDst = pbDstStream;
+	ash.cbDstLength = cbDstStream;
+
+	if ((res = acmStreamPrepareHeader(This->has, &ash, 0))) {
+	    ERR("Cannot prepare header %d\n", res);
+	    goto error;
+	}
+
+	unprepare_header = TRUE;
+
+	if ((res = acmStreamConvert(This->has, &ash, This->reinit_codec ? ACM_STREAMCONVERTF_START : 0))) {
+	    ERR("Cannot convert data header %d\n", res);
+	    goto error;
+	}
+	This->reinit_codec = FALSE;
+
+	TRACE("used in %lu, used out %lu\n", ash.cbSrcLengthUsed, ash.cbDstLengthUsed);
+
+	hr = IMediaSample_SetActualDataLength(pSample, ash.cbDstLengthUsed);
+	assert(hr == S_OK);
+
+	if (ash.cbSrcLengthUsed < ash.cbSrcLength) {
+	    This->current_size = ash.cbSrcLength - ash.cbSrcLengthUsed;
+	    memmove(This->buffer, This->buffer + ash.cbSrcLengthUsed, This->current_size);
+	}
+	else
+	    This->current_size = 0;
+
+	hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pSample);
+	if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
+	    ERR("Error sending sample (%lx)\n", hr);
+	    goto error;
+        }
+
+error:
+	if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0)))
+	    ERR("Cannot unprepare header %d\n", res);
+
+	if (pSample)
+	    IMediaSample_Release(pSample);
+    }
+
+    return hr;
+}
+
+static HRESULT ACMWrapper_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt)
+{
+    ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
+    MMRESULT res;
+
+    TRACE("(%p)->(%p)\n", This, pmt);
+
+    if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio)) &&
+        (!memcmp(((char*)&pmt->subtype)+4, ((char*)&MEDIATYPE_Audio)+4, sizeof(GUID)-4)) && /* Check root (GUID w/o FOURCC) */
+        (IsEqualIID(&pmt->formattype, &FORMAT_WaveFormatEx)))
+    {
+        HACMSTREAM drv;
+        This->pWfIn = (LPWAVEFORMATEX)pmt->pbFormat;
+
+	/* HACK */
+	/* TRACE("ALIGN = %d\n", pACMWrapper->pWfIn->nBlockAlign); */
+	/* pACMWrapper->pWfIn->nBlockAlign = 1; */
+
+        AM_MEDIA_TYPE* outpmt = &((OutputPin*)This->tf.ppPins[1])->pin.mtCurrent;
+	/* Set output audio data to PCM */
+        CopyMediaType(outpmt, pmt);
+        outpmt->subtype.Data1 = WAVE_FORMAT_PCM;
+	This->pWfOut = (WAVEFORMATEX*)outpmt->pbFormat;
+	This->pWfOut->wFormatTag = WAVE_FORMAT_PCM;
+	This->pWfOut->wBitsPerSample = 16;
+	This->pWfOut->nBlockAlign = 1;
+	This->pWfOut->cbSize = 0;
+	This->pWfOut->nAvgBytesPerSec = This->pWfOut->nChannels * This->pWfOut->nSamplesPerSec
+						* (This->pWfOut->wBitsPerSample/8);
+
+        if (!(res = acmStreamOpen(&drv, NULL, This->pWfIn, This->pWfOut, NULL, 0, 0, 0)))
+        {
+            This->has = drv;
+
+	    if ((res = acmStreamSize(drv, OUTPUT_BUFFER_SIZE, &This->max_size, ACM_STREAMSIZEF_DESTINATION))) {
+		ERR("Cannot retreive input buffer size error %d!\n", res);
+		This->max_size = INPUT_BUFFER_SIZE;
+	    }
+
+	    TRACE("input buffer size %ld\n", This->max_size);
+	    
+            TRACE("Connection accepted\n");
+            return S_OK;
+        }
+	else
+	    FIXME("acmStreamOpen returned %d\n", res);
+	DeleteMediaType(outpmt);
+        TRACE("Unable to find a suitable ACM decompressor\n");
+    }
+
+    TRACE("Connection refused\n");
+    return S_FALSE;
+}
+
+static HRESULT ACMWrapper_Cleanup(TransformFilterImpl* pTransformFilter)
+{
+    ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
+
+    TRACE("(%p)->()\n", This);
+    
+    if (This->has)
+	acmStreamClose(This->has, 0);
+
+    This->has = 0;
+    
+    return S_OK;
+}
+
+HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
+{
+    HRESULT hr;
+    ACMWrapperImpl* This;
+
+    TRACE("(%p, %p)\n", pUnkOuter, ppv);
+
+    *ppv = NULL;
+
+    if (pUnkOuter)
+        return CLASS_E_NOAGGREGATION;
+
+    /* Note: This memory is managed by the transform filter once created */
+    This = CoTaskMemAlloc(sizeof(ACMWrapperImpl));
+
+    This->has = 0;
+    This->reinit_codec = TRUE;
+
+    hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, ACMWrapper_SendSampleData, ACMWrapper_ConnectInput, ACMWrapper_Cleanup);
+
+    if (FAILED(hr))
+        return hr;
+
+    *ppv = (LPVOID)This;
+
+    return hr;
+}


More information about the wine-patches mailing list