diff --git a/configure b/configure
index 5abdaacce778d757b5a3db01fd41551246880b88..503c8387cf6ac82d8dd9aa2f634b2b55ae96c93f 100755
--- a/configure
+++ b/configure
@@ -657,6 +657,7 @@ FRAMEWORK_OPENAL
 COREAUDIO
 DISKARBITRATIONLIB
 LDEXECFLAGS
+QUICKTIMELIB
 IOKITLIB
 COREFOUNDATIONLIB
 SECURITYLIB
@@ -6518,6 +6519,8 @@ fi
 
     IOKITLIB="-framework IOKit -framework CoreFoundation"
 
+    QUICKTIMELIB="-framework QuickTime -framework ApplicationServices -framework CoreVideo"
+
     LDEXECFLAGS="-image_base 0x7bf00000 -Wl,-segaddr,WINE_DOS,0x00000000,-segaddr,WINE_SHAREDHEAP,0x7f000000"
 
     if test "$ac_cv_header_DiskArbitration_DiskArbitration_h" = "yes"
@@ -6564,6 +6567,7 @@ done
 
         LIBS="$ac_save_LIBS"
     fi
+    enable_wineqtdecoder=${enable_wineqtdecoder:-yes}
     case $host_cpu in
       *powerpc*)
         LDDLLFLAGS="$LDDLLFLAGS -read_only_relocs warning"          ;;
@@ -7031,6 +7035,7 @@ $as_echo "$ac_cv_c_dll_hpux" >&6; }
     ;;
 esac
 
+enable_wineqtdecoder=${enable_wineqtdecoder:-no}
 enable_winequartz_drv=${enable_winequartz_drv:-no}
 
 if test "$LIBEXT" = "a"; then
@@ -15270,6 +15275,7 @@ wine_fn_config_dll winenas.drv enable_winenas_drv
 wine_fn_config_dll wineoss.drv enable_wineoss_drv
 wine_fn_config_dll wineps.drv enable_wineps_drv
 wine_fn_config_dll wineps16.drv16 enable_win16
+wine_fn_config_dll wineqtdecoder enable_wineqtdecoder
 wine_fn_config_dll winequartz.drv enable_winequartz_drv
 wine_fn_config_dll winex11.drv enable_winex11_drv
 wine_fn_config_dll wing.dll16 enable_win16
diff --git a/configure.ac b/configure.ac
index 2431c7febdc04658420dafc1a4a3f41c1ffa8217..2dd58311cb901595ca5fbc2d6bba308e45eab137 100644
--- a/configure.ac
+++ b/configure.ac
@@ -702,6 +702,7 @@ case $host_os in
     AC_SUBST(SECURITYLIB,"-framework Security -framework CoreFoundation")
     AC_SUBST(COREFOUNDATIONLIB,"-framework CoreFoundation")
     AC_SUBST(IOKITLIB,"-framework IOKit -framework CoreFoundation")
+    AC_SUBST(QUICKTIMELIB,"-framework QuickTime -framework ApplicationServices -framework CoreVideo")
     AC_SUBST(LDEXECFLAGS,["-image_base 0x7bf00000 -Wl,-segaddr,WINE_DOS,0x00000000,-segaddr,WINE_SHAREDHEAP,0x7f000000"])
     if test "$ac_cv_header_DiskArbitration_DiskArbitration_h" = "yes"
     then
@@ -731,6 +732,7 @@ case $host_os in
         AC_CHECK_FUNCS(IOHIDManagerCreate)
         LIBS="$ac_save_LIBS"
     fi
+    enable_wineqtdecoder=${enable_wineqtdecoder:-yes}
     case $host_cpu in
       *powerpc*)
         LDDLLFLAGS="$LDDLLFLAGS -read_only_relocs warning"  dnl FIXME
@@ -838,6 +840,7 @@ case $host_os in
     ;;
 esac
 
+enable_wineqtdecoder=${enable_wineqtdecoder:-no}
 enable_winequartz_drv=${enable_winequartz_drv:-no}
 
 if test "$LIBEXT" = "a"; then
@@ -2794,6 +2797,7 @@ WINE_CONFIG_DLL(winenas.drv)
 WINE_CONFIG_DLL(wineoss.drv)
 WINE_CONFIG_DLL(wineps.drv)
 WINE_CONFIG_DLL(wineps16.drv16,enable_win16)
+WINE_CONFIG_DLL(wineqtdecoder)
 WINE_CONFIG_DLL(winequartz.drv)
 WINE_CONFIG_DLL(winex11.drv)
 WINE_CONFIG_DLL(wing.dll16,enable_win16)
diff --git a/dlls/wineqtdecoder/Makefile.in b/dlls/wineqtdecoder/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..57436b5bcf18b66b2dcdeedcfbb5116e64efa264
--- /dev/null
+++ b/dlls/wineqtdecoder/Makefile.in
@@ -0,0 +1,9 @@
+MODULE    = wineqtdecoder.dll
+IMPORTS   = strmiids strmbase uuid ole32 advapi32
+EXTRALIBS = @QUICKTIMELIB@
+
+C_SRCS = \
+	main.c \
+	qtvdecoder.c
+
+@MAKE_DLL_RULES@
diff --git a/dlls/wineqtdecoder/main.c b/dlls/wineqtdecoder/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..e36101394be2c702ef30b16c771c5c14985b3ce1
--- /dev/null
+++ b/dlls/wineqtdecoder/main.c
@@ -0,0 +1,135 @@
+/*
+ * Directshow filter for Quicktime Toolkit on mac OS/X
+ *
+ * Copyright (C) 2010 Aric Stewart, CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define COBJMACROS
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winerror.h"
+#include "objbase.h"
+#include "uuids.h"
+#include "strmif.h"
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "wine/strmbase.h"
+
+#include "initguid.h"
+DEFINE_GUID(CLSID_QTVDecoder, 0x683DDACB, 0x4354, 0x490C, 0xA0,0x58, 0xE0,0x5A,0xD0,0xF2,0x05,0x37);
+
+WINE_DEFAULT_DEBUG_CHANNEL(qtdecoder);
+
+extern IUnknown * CALLBACK QTVDecoder_create(IUnknown * pUnkOuter, HRESULT* phr);
+
+static const WCHAR wQTVName[] =
+{'Q','T',' ','V','i','d','e','o',' ','D','e','c','o','d','e','r',0};
+static WCHAR wNull[] = {'\0'};
+
+static const AMOVIESETUP_MEDIATYPE amfMTvideo[] =
+{   { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL } };
+
+static const AMOVIESETUP_PIN amfQTVPin[] =
+{   {   wNull,
+        FALSE, FALSE, FALSE, FALSE,
+        &GUID_NULL,
+        NULL,
+        1,
+        amfMTvideo
+    },
+    {
+        wNull,
+        FALSE, TRUE, FALSE, FALSE,
+        &GUID_NULL,
+        NULL,
+        1,
+        amfMTvideo
+    },
+};
+
+static const AMOVIESETUP_FILTER amfQTV =
+{   &CLSID_QTVDecoder,
+    wQTVName,
+    MERIT_NORMAL,
+    2,
+    amfQTVPin
+};
+
+FactoryTemplate const g_Templates[] = {
+    {
+        wQTVName,
+        &CLSID_QTVDecoder,
+        QTVDecoder_create,
+        NULL,
+        &amfQTV,
+    }
+};
+
+int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
+
+/***********************************************************************
+ *    Dll EntryPoint (wineqtdecoder.@)
+ */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    return STRMBASE_DllMain(hInstDLL,fdwReason,lpv);
+}
+
+/***********************************************************************
+ *    DllGetClassObject
+ */
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+    return STRMBASE_DllGetClassObject( rclsid, riid, ppv );
+}
+
+/***********************************************************************
+ *    DllRegisterServer (wineqtdecoder.@)
+ */
+HRESULT WINAPI DllRegisterServer(void)
+{
+    TRACE("()\n");
+    return AMovieDllRegisterServer2(TRUE);
+}
+
+/***********************************************************************
+ *    DllUnregisterServer (wineqtdecoder.@)
+ */
+HRESULT WINAPI DllUnregisterServer(void)
+{
+    TRACE("\n");
+    return AMovieDllRegisterServer2(FALSE);
+}
+
+/***********************************************************************
+ *    DllCanUnloadNow (wineqtdecoder.@)
+ */
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+    TRACE("\n");
+    return STRMBASE_DllCanUnloadNow();
+}
diff --git a/dlls/wineqtdecoder/qtvdecoder.c b/dlls/wineqtdecoder/qtvdecoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..b0cf12882ad9ff18af41d8763a2bdc31343cab15
--- /dev/null
+++ b/dlls/wineqtdecoder/qtvdecoder.c
@@ -0,0 +1,609 @@
+/*
+ * QuickTime Toolkit decoder filter for video
+ *
+ * Copyright 2010 Aric Stewart, CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#define ULONG CoreFoundation_ULONG
+#define HRESULT CoreFoundation_HRESULT
+
+#define LoadResource __carbon_LoadResource
+#define CompareString __carbon_CompareString
+#define GetCurrentThread __carbon_GetCurrentThread
+#define GetCurrentProcess __carbon_GetCurrentProcess
+#define AnimatePalette __carbon_AnimatePalette
+#define EqualRgn __carbon_EqualRgn
+#define FillRgn __carbon_FillRgn
+#define FrameRgn __carbon_FrameRgn
+#define GetPixel __carbon_GetPixel
+#define InvertRgn __carbon_InvertRgn
+#define LineTo __carbon_LineTo
+#define OffsetRgn __carbon_OffsetRgn
+#define PaintRgn __carbon_PaintRgn
+#define Polygon __carbon_Polygon
+#define ResizePalette __carbon_ResizePalette
+#define SetRectRgn __carbon_SetRectRgn
+
+#define CheckMenuItem __carbon_CheckMenuItem
+#define DeleteMenu __carbon_DeleteMenu
+#define DrawMenuBar __carbon_DrawMenuBar
+#define EnableMenuItem __carbon_EnableMenuItem
+#define EqualRect __carbon_EqualRect
+#define FillRect __carbon_FillRect
+#define FrameRect __carbon_FrameRect
+#define GetCursor __carbon_GetCursor
+#define GetMenu __carbon_GetMenu
+#define InvertRect __carbon_InvertRect
+#define IsWindowVisible __carbon_IsWindowVisible
+#define MoveWindow __carbon_MoveWindow
+#define OffsetRect __carbon_OffsetRect
+#define PtInRect __carbon_PtInRect
+#define SetCursor __carbon_SetCursor
+#define SetRect __carbon_SetRect
+#define ShowCursor __carbon_ShowCursor
+#define ShowWindow __carbon_ShowWindow
+#define UnionRect __carbon_UnionRect
+
+#include <QuickTime/ImageCompression.h>
+#include <CoreVideo/CVPixelBuffer.h>
+
+#undef LoadResource
+#undef CompareString
+#undef GetCurrentThread
+#undef _CDECL
+#undef DPRINTF
+#undef GetCurrentProcess
+#undef AnimatePalette
+#undef EqualRgn
+#undef FillRgn
+#undef FrameRgn
+#undef GetPixel
+#undef InvertRgn
+#undef LineTo
+#undef OffsetRgn
+#undef PaintRgn
+#undef Polygon
+#undef ResizePalette
+#undef SetRectRgn
+#undef CheckMenuItem
+#undef DeleteMenu
+#undef DrawMenuBar
+#undef EnableMenuItem
+#undef EqualRect
+#undef FillRect
+#undef FrameRect
+#undef GetCursor
+#undef GetMenu
+#undef InvertRect
+#undef IsWindowVisible
+#undef MoveWindow
+#undef OffsetRect
+#undef PtInRect
+#undef SetCursor
+#undef SetRect
+#undef ShowCursor
+#undef ShowWindow
+#undef UnionRect
+
+#undef ULONG
+#undef HRESULT
+#undef DPRINTF
+#undef STDMETHODCALLTYPE
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "wtypes.h"
+#include "winuser.h"
+#include "dshow.h"
+
+#include "uuids.h"
+#include "amvideo.h"
+#include "strmif.h"
+#include "vfwmsgs.h"
+#include "vfw.h"
+#include "dvdmedia.h"
+
+#include <assert.h>
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "wine/strmbase.h"
+
+extern CLSID CLSID_QTVDecoder;
+
+WINE_DEFAULT_DEBUG_CHANNEL(qtdecoder);
+
+typedef struct QTVDecoderImpl
+{
+    TransformFilter tf;
+    IUnknown *seekthru_unk;
+
+    ImageDescriptionHandle hImageDescription;
+    CFMutableDictionaryRef outputBufferAttributes;
+    ICMDecompressionSessionRef decompressionSession;
+    HRESULT decodeHR;
+
+    DWORD outputSize;
+    DWORD outputWidth, outputHeight, outputDepth;
+
+} QTVDecoderImpl;
+
+typedef struct {
+      UInt8 a; /* Alpha Channel */
+      UInt8 r; /* red component */
+      UInt8 g; /* green component */
+      UInt8 b; /* blue component */
+} ARGBPixelRecord, *ARGBPixelPtr, **ARGBPixelHdl;
+
+static const IBaseFilterVtbl QTVDecoder_Vtbl;
+
+static void trackingCallback(
+                    void *decompressionTrackingRefCon,
+                    OSStatus result,
+                    ICMDecompressionTrackingFlags decompressionTrackingFlags,
+                    CVPixelBufferRef pixelBuffer,
+                    TimeValue64 displayTime,
+                    TimeValue64 displayDuration,
+                    ICMValidTimeFlags validTimeFlags,
+                    void *reserved,
+                    void *sourceFrameRefCon )
+{
+    QTVDecoderImpl *This = (QTVDecoderImpl*)decompressionTrackingRefCon;
+    IMediaSample *pSample = (IMediaSample*)sourceFrameRefCon;
+    HRESULT hr  = S_OK;
+    IMediaSample* pOutSample = NULL;
+    LPBYTE pbDstStream;
+    DWORD cbDstStream;
+    LPBYTE pPixels = NULL;
+    LPBYTE out = NULL;
+    size_t bytesPerRow = 0;
+
+    int i;
+
+    if (result != noErr)
+    {
+        ERR("Error from Codec, no frame decompressed\n");
+        return;
+    }
+
+    if (!pixelBuffer)
+    {
+        ERR("No pixel buffer, no frame decompressed\n");
+        return;
+    }
+
+    EnterCriticalSection(&This->tf.filter.csFilter);
+    hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
+    if (FAILED(hr)) {
+        ERR("Unable to get delivery buffer (%x)\n", hr);
+        goto error;
+    }
+
+    hr = IMediaSample_SetActualDataLength(pOutSample, 0);
+    assert(hr == S_OK);
+
+    hr = IMediaSample_GetPointer(pOutSample, &pbDstStream);
+    if (FAILED(hr)) {
+        ERR("Unable to get pointer to buffer (%x)\n", hr);
+        goto error;
+    }
+
+    cbDstStream = IMediaSample_GetSize(pOutSample);
+    if (cbDstStream < This->outputSize) {
+        ERR("Sample size is too small %d < %d\n", cbDstStream, This->outputSize);
+        hr = E_FAIL;
+        goto error;
+    }
+
+    /* ACCESS THE PIXELS */
+    CVPixelBufferLockBaseAddress(pixelBuffer,0);
+    pPixels = (LPBYTE)CVPixelBufferGetBaseAddress(pixelBuffer);
+    bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
+
+    for (out = pbDstStream, i = 0; i < This->outputHeight; i++)
+    {
+        int j;
+        for (j = 0; j < This->outputWidth; j++)
+        {
+            *((DWORD*)out) = (((ARGBPixelPtr)pPixels)[j].r) << 16
+                          | (((ARGBPixelPtr)pPixels)[j].g) << 8
+                          | (((ARGBPixelPtr)pPixels)[j].b);
+            out+=This->outputDepth;
+        }
+        pPixels += bytesPerRow;
+    }
+    CVPixelBufferUnlockBaseAddress(pixelBuffer,0);
+
+    IMediaSample_SetActualDataLength(pOutSample, This->outputSize);
+
+    IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK));
+    IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK));
+    IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK));
+
+    if (!validTimeFlags)
+        IMediaSample_SetTime(pOutSample, NULL, NULL);
+    else
+    {
+        LONGLONG tStart, tStop;
+
+        if (validTimeFlags & kICMValidTime_DisplayTimeStampIsValid)
+            tStart = displayTime;
+         else
+            tStart = 0;
+        if (validTimeFlags & kICMValidTime_DisplayDurationIsValid)
+            tStop = tStart + displayDuration;
+        else
+            tStop = tStart;
+
+        IMediaSample_SetTime(pOutSample, &tStart, &tStop);
+    }
+
+    LeaveCriticalSection(&This->tf.filter.csFilter);
+    hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample);
+    if (hr != S_OK && hr != VFW_E_NOT_CONNECTED)
+        ERR("Error sending sample (%x)\n", hr);
+
+error:
+    if (pOutSample)
+        IMediaSample_Release(pOutSample);
+
+    This->decodeHR = hr;
+}
+
+static HRESULT WINAPI QTVDecoder_StartStreaming(TransformFilter* pTransformFilter)
+{
+    QTVDecoderImpl* This = (QTVDecoderImpl*)pTransformFilter;
+    OSErr err = noErr;
+    ICMDecompressionSessionOptionsRef sessionOptions = NULL;
+    ICMDecompressionTrackingCallbackRecord trackingCallbackRecord;
+
+    TRACE("(%p)->()\n", This);
+
+    trackingCallbackRecord.decompressionTrackingCallback = trackingCallback;
+    trackingCallbackRecord.decompressionTrackingRefCon = (void*)This;
+
+    err = ICMDecompressionSessionCreate(NULL, This->hImageDescription, sessionOptions, This->outputBufferAttributes, &trackingCallbackRecord, &This->decompressionSession);
+
+    if (err != noErr)
+    {
+        ERR("Error with ICMDecompressionSessionCreate %i\n",err);
+        return E_FAIL;
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI QTVDecoder_Receive(TransformFilter *tf, IMediaSample *pSample)
+{
+    QTVDecoderImpl* This = (QTVDecoderImpl *)tf;
+    HRESULT hr;
+    DWORD cbSrcStream;
+    LPBYTE pbSrcStream;
+
+    ICMFrameTimeRecord frameTime = {{0}};
+    TimeValue time = 1;
+    TimeScale timeScale = 1;
+    OSStatus err = noErr;
+    LONGLONG tStart, tStop;
+
+    EnterCriticalSection(&This->tf.filter.csFilter);
+    hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
+    if (FAILED(hr))
+    {
+        ERR("Cannot get pointer to sample data (%x)\n", hr);
+        goto error;
+    }
+
+    cbSrcStream = IMediaSample_GetActualDataLength(pSample);
+
+    if (IMediaSample_GetTime(pSample, &tStart, &tStop) != S_OK)
+        tStart = tStop = 0;
+
+    time = tStart;
+
+    frameTime.recordSize = sizeof(ICMFrameTimeRecord);
+    *(TimeValue64 *)&frameTime.value = tStart;
+    frameTime.scale = 1;
+    frameTime.rate = fixed1;
+    frameTime.duration = tStop - tStart;
+    frameTime.frameNumber = 0;
+    frameTime.flags = icmFrameTimeIsNonScheduledDisplayTime;
+
+    err = ICMDecompressionSessionDecodeFrame(This->decompressionSession,
+            (UInt8 *)pbSrcStream, cbSrcStream, NULL, &frameTime, pSample);
+
+    if (err != noErr)
+    {
+        ERR("Error with ICMDecompressionSessionDecodeFrame\n");
+        hr = E_FAIL;
+        goto error;
+    }
+
+    ICMDecompressionSessionSetNonScheduledDisplayTime(This->decompressionSession, time, timeScale, 0);
+    ICMDecompressionSessionFlush(This->decompressionSession);
+    hr = This->decodeHR;
+
+error:
+    LeaveCriticalSection(&This->tf.filter.csFilter);
+    return hr;
+}
+
+static HRESULT WINAPI QTVDecoder_StopStreaming(TransformFilter* pTransformFilter)
+{
+    QTVDecoderImpl* This = (QTVDecoderImpl*)pTransformFilter;
+
+    TRACE("(%p)->()\n", This);
+
+    if (This->decompressionSession)
+        ICMDecompressionSessionRelease(This->decompressionSession);
+    This->decompressionSession = NULL;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI QTVDecoder_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt)
+{
+    QTVDecoderImpl* This = (QTVDecoderImpl*)tf;
+    HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
+    OSErr err = noErr;
+    AM_MEDIA_TYPE *outpmt = &This->tf.pmt;
+    CFNumberRef n = NULL;
+
+    TRACE("(%p)->(%p)\n", This, pmt);
+
+    if (dir != PINDIR_INPUT)
+        return S_OK;
+
+    FreeMediaType(outpmt);
+    CopyMediaType(outpmt, pmt);
+
+    if (This->hImageDescription)
+        DisposeHandle((Handle)This->hImageDescription);
+
+    This->hImageDescription = (ImageDescriptionHandle)
+        NewHandleClear(sizeof(ImageDescription));
+
+    if (This->hImageDescription != NULL)
+    {
+        (**This->hImageDescription).idSize = sizeof(ImageDescription);
+        (**This->hImageDescription).spatialQuality = codecNormalQuality;
+        (**This->hImageDescription).frameCount = 1;
+        (**This->hImageDescription).clutID = -1;
+    }
+    else
+    {
+        ERR("Failed to create ImageDescription\n");
+        goto failed;
+    }
+
+    /* Check root (GUID w/o FOURCC) */
+    if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
+        (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4)))
+    {
+        VIDEOINFOHEADER *format1 = (VIDEOINFOHEADER *)outpmt->pbFormat;
+        VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)outpmt->pbFormat;
+        BITMAPINFOHEADER *bmi;
+        OSType fourCC;
+        DecompressorComponent dc;
+        OSType format;
+
+        if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
+            bmi = &format1->bmiHeader;
+        else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
+            bmi = &format2->bmiHeader;
+        else
+            goto failed;
+
+        TRACE("Fourcc: %s\n", debugstr_an((const char *)&pmt->subtype.Data1, 4));
+        fourCC = ((const char *)&pmt->subtype.Data1)[0] |
+                 (((const char *)&pmt->subtype.Data1)[1]<<8) |
+                 (((const char *)&pmt->subtype.Data1)[2]<<16) |
+                 (((const char *)&pmt->subtype.Data1)[3]<<24);
+
+        err = FindCodec(fourCC,NULL,NULL,&dc);
+        if (err != noErr || dc == 0x0)
+        {
+            TRACE("Codec not found\n");
+            goto failed;
+        }
+
+        This->outputWidth = bmi->biWidth;
+        This->outputHeight = bmi->biHeight;
+
+        (**This->hImageDescription).cType = fourCC;
+        (**This->hImageDescription).width = This->outputWidth;
+        (**This->hImageDescription).height = This->outputHeight;
+        (**This->hImageDescription).depth = bmi->biBitCount;
+        (**This->hImageDescription).hRes = 72<<16;
+        (**This->hImageDescription).vRes = 72<<16;
+
+        if (This->outputBufferAttributes)
+            CFRelease(This->outputBufferAttributes);
+
+        This->outputBufferAttributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        if (!This->outputBufferAttributes)
+        {
+            ERR("Failed to create outputBufferAttributes\n");
+            goto failed;
+        }
+
+        n = CFNumberCreate(NULL, kCFNumberIntType, &This->outputWidth);
+        CFDictionaryAddValue(This->outputBufferAttributes, kCVPixelBufferWidthKey, n);
+        CFRelease(n);
+
+        n = CFNumberCreate(NULL, kCFNumberIntType, &This->outputHeight);
+        CFDictionaryAddValue(This->outputBufferAttributes, kCVPixelBufferHeightKey, n);
+        CFRelease(n);
+
+        /* yes this looks wrong.  but 32ARGB is 24 RGB with an alpha channel */
+        format = k32ARGBPixelFormat;
+        n = CFNumberCreate(NULL, kCFNumberIntType, &format);
+        CFDictionaryAddValue(This->outputBufferAttributes, kCVPixelBufferPixelFormatTypeKey, n);
+        CFRelease(n);
+
+        CFDictionaryAddValue(This->outputBufferAttributes, kCVPixelBufferCGBitmapContextCompatibilityKey, kCFBooleanTrue);
+        CFDictionaryAddValue(This->outputBufferAttributes, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanTrue);
+
+        This->outputDepth = 3;
+        This->outputSize = This->outputWidth * This->outputHeight * This->outputDepth;
+        bmi->biCompression =  BI_RGB;
+        bmi->biBitCount =  24;
+        outpmt->subtype = MEDIASUBTYPE_RGB24;
+        if (bmi->biHeight > 0)
+            bmi->biHeight = -bmi->biHeight;
+
+        return S_OK;
+    }
+
+failed:
+    if (This->hImageDescription)
+    {
+        DisposeHandle((Handle)This->hImageDescription);
+        This->hImageDescription =  NULL;
+    }
+    if (This->outputBufferAttributes)
+    {
+        CFRelease(This->outputBufferAttributes);
+        This->outputBufferAttributes = NULL;
+    }
+
+    TRACE("Connection refused\n");
+    return hr;
+}
+
+static HRESULT WINAPI QTVDecoder_BreakConnect(TransformFilter *tf, PIN_DIRECTION dir)
+{
+    QTVDecoderImpl *This = (QTVDecoderImpl *)tf;
+
+    TRACE("(%p)->()\n", This);
+
+    if (This->hImageDescription)
+        DisposeHandle((Handle)This->hImageDescription);
+    if (This->outputBufferAttributes)
+        CFRelease(This->outputBufferAttributes);
+
+    This->hImageDescription = NULL;
+    This->outputBufferAttributes = NULL;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI QTVDecoder_DecideBufferSize(TransformFilter *tf, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
+{
+    QTVDecoderImpl *This = (QTVDecoderImpl*)tf;
+    ALLOCATOR_PROPERTIES actual;
+
+    TRACE("()\n");
+
+    if (!ppropInputRequest->cbAlign)
+        ppropInputRequest->cbAlign = 1;
+
+    if (ppropInputRequest->cbBuffer < This->outputSize)
+            ppropInputRequest->cbBuffer = This->outputSize;
+
+    if (!ppropInputRequest->cBuffers)
+        ppropInputRequest->cBuffers = 1;
+
+    return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual);
+}
+
+static const TransformFilterFuncTable QTVDecoder_FuncsTable = {
+    QTVDecoder_DecideBufferSize,
+    QTVDecoder_StartStreaming,
+    QTVDecoder_Receive,
+    QTVDecoder_StopStreaming,
+    NULL,
+    QTVDecoder_SetMediaType,
+    NULL,
+    QTVDecoder_BreakConnect,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+IUnknown * CALLBACK QTVDecoder_create(IUnknown * pUnkOuter, HRESULT* phr)
+{
+    HRESULT hr;
+    QTVDecoderImpl * This;
+
+    TRACE("(%p, %p)\n", pUnkOuter, phr);
+
+    *phr = S_OK;
+
+    if (pUnkOuter)
+    {
+        *phr = CLASS_E_NOAGGREGATION;
+        return NULL;
+    }
+
+    hr = TransformFilter_Construct(&QTVDecoder_Vtbl, sizeof(QTVDecoderImpl), &CLSID_QTVDecoder, &QTVDecoder_FuncsTable, (IBaseFilter**)&This);
+
+    if (FAILED(hr))
+    {
+        *phr = hr;
+        return NULL;
+    }
+    else
+    {
+        ISeekingPassThru *passthru;
+        hr = CoCreateInstance(&CLSID_SeekingPassThru, (IUnknown*)This, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&This->seekthru_unk);
+        IUnknown_QueryInterface(This->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
+        ISeekingPassThru_Init(passthru, FALSE, (IPin*)This->tf.ppPins[0]);
+        ISeekingPassThru_Release(passthru);
+    }
+
+    *phr = hr;
+    return (IUnknown*)This;
+}
+
+HRESULT WINAPI QTVDecoder_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
+{
+    HRESULT hr;
+    QTVDecoderImpl *This = (QTVDecoderImpl *)iface;
+    TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
+
+    if (IsEqualIID(riid, &IID_IMediaSeeking))
+        return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
+
+    hr = TransformFilterImpl_QueryInterface(iface, riid, ppv);
+
+    return hr;
+}
+
+static const IBaseFilterVtbl QTVDecoder_Vtbl =
+{
+    QTVDecoder_QueryInterface,
+    BaseFilterImpl_AddRef,
+    TransformFilterImpl_Release,
+    BaseFilterImpl_GetClassID,
+    TransformFilterImpl_Stop,
+    TransformFilterImpl_Pause,
+    TransformFilterImpl_Run,
+    BaseFilterImpl_GetState,
+    BaseFilterImpl_SetSyncSource,
+    BaseFilterImpl_GetSyncSource,
+    BaseFilterImpl_EnumPins,
+    TransformFilterImpl_FindPin,
+    BaseFilterImpl_QueryFilterInfo,
+    BaseFilterImpl_JoinFilterGraph,
+    BaseFilterImpl_QueryVendorInfo
+};
diff --git a/dlls/wineqtdecoder/wineqtdecoder.spec b/dlls/wineqtdecoder/wineqtdecoder.spec
new file mode 100644
index 0000000000000000000000000000000000000000..b16365d0c9fc216f15ba2cbb479440656177b77e
--- /dev/null
+++ b/dlls/wineqtdecoder/wineqtdecoder.spec
@@ -0,0 +1,4 @@
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()