1545 lines
48 KiB
C
1545 lines
48 KiB
C
/*
|
|
* Video Mixing Renderer for dx9
|
|
*
|
|
* Copyright 2004 Christian Costa
|
|
* Copyright 2008 Maarten Lankhorst
|
|
* Copyright 2012 Aric Stewart
|
|
*
|
|
* 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 NONAMELESSSTRUCT
|
|
#define NONAMELESSUNION
|
|
#include "quartz_private.h"
|
|
|
|
#include "uuids.h"
|
|
#include "vfwmsgs.h"
|
|
#include "amvideo.h"
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "dshow.h"
|
|
#include "evcode.h"
|
|
#include "strmif.h"
|
|
#include "ddraw.h"
|
|
#include "dvdmedia.h"
|
|
#include "d3d9.h"
|
|
#include "vmr9.h"
|
|
#include "pin.h"
|
|
|
|
#include "wine/unicode.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
|
|
|
typedef struct
|
|
{
|
|
BaseRenderer renderer;
|
|
BaseControlWindow baseControlWindow;
|
|
BaseControlVideo baseControlVideo;
|
|
|
|
IUnknown IUnknown_inner;
|
|
IAMFilterMiscFlags IAMFilterMiscFlags_iface;
|
|
IVMRFilterConfig9 IVMRFilterConfig9_iface;
|
|
IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
|
|
IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
|
|
|
|
IVMRSurfaceAllocatorEx9 *allocator;
|
|
IVMRImagePresenter9 *presenter;
|
|
BOOL allocator_is_ex;
|
|
|
|
VMR9Mode mode;
|
|
BITMAPINFOHEADER bmiheader;
|
|
IUnknown * outer_unk;
|
|
BOOL bUnkOuterValid;
|
|
BOOL bAggregatable;
|
|
|
|
DWORD_PTR cookie;
|
|
|
|
/* for Windowless Mode */
|
|
HWND hWndClippingWindow;
|
|
|
|
RECT source_rect;
|
|
RECT target_rect;
|
|
LONG VideoWidth;
|
|
LONG VideoHeight;
|
|
} VMR9Impl;
|
|
|
|
static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_BaseWindow( BaseWindow *wnd )
|
|
{
|
|
return CONTAINING_RECORD(wnd, VMR9Impl, baseControlWindow.baseWindow);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_IVideoWindow( IVideoWindow *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, baseControlWindow.IVideoWindow_iface);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_BaseControlVideo( BaseControlVideo *cvid )
|
|
{
|
|
return CONTAINING_RECORD(cvid, VMR9Impl, baseControlVideo);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_IBasicVideo( IBasicVideo *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, baseControlVideo.IBasicVideo_iface);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_IAMFilterMiscFlags( IAMFilterMiscFlags *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, IAMFilterMiscFlags_iface);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_IVMRFilterConfig9( IVMRFilterConfig9 *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, IVMRFilterConfig9_iface);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_IVMRWindowlessControl9( IVMRWindowlessControl9 *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, IVMRWindowlessControl9_iface);
|
|
}
|
|
|
|
static inline VMR9Impl *impl_from_IVMRSurfaceAllocatorNotify9( IVMRSurfaceAllocatorNotify9 *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9Impl, IVMRSurfaceAllocatorNotify9_iface);
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
IVMRImagePresenter9 IVMRImagePresenter9_iface;
|
|
|
|
LONG refCount;
|
|
|
|
IDirect3DDevice9 *d3d9_dev;
|
|
IDirect3D9 *d3d9_ptr;
|
|
IDirect3DVertexBuffer9 *d3d9_vertex;
|
|
|
|
VMR9AllocationInfo info;
|
|
|
|
VMR9Impl* pVMR9;
|
|
} VMR9DefaultAllocatorPresenterImpl;
|
|
|
|
static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRImagePresenter9( IVMRImagePresenter9 *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRImagePresenter9_iface);
|
|
}
|
|
|
|
static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv);
|
|
|
|
static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
|
|
{
|
|
VMR9Impl *This = (VMR9Impl *)iface;
|
|
LPBYTE pbSrcStream = NULL;
|
|
REFERENCE_TIME tStart, tStop;
|
|
VMR9PresentationInfo info;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p %p\n", iface, pSample);
|
|
|
|
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
|
|
if (FAILED(hr))
|
|
info.dwFlags = VMR9Sample_SrcDstRectsValid;
|
|
else
|
|
info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
|
|
|
|
if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
|
|
info.dwFlags |= VMR9Sample_Discontinuity;
|
|
|
|
if (IMediaSample_IsPreroll(pSample) == S_OK)
|
|
info.dwFlags |= VMR9Sample_Preroll;
|
|
|
|
if (IMediaSample_IsSyncPoint(pSample) == S_OK)
|
|
info.dwFlags |= VMR9Sample_SyncPoint;
|
|
|
|
hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
|
|
if (FAILED(hr))
|
|
{
|
|
ERR("Cannot get pointer to sample data (%x)\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
info.rtStart = tStart;
|
|
info.rtEnd = tStop;
|
|
info.szAspectRatio.cx = This->bmiheader.biWidth;
|
|
info.szAspectRatio.cy = This->bmiheader.biHeight;
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
|
|
{
|
|
VMR9Impl *This = (VMR9Impl*)iface;
|
|
|
|
if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
|
|
return S_FALSE;
|
|
|
|
/* Ignore subtype, test for bicompression instead */
|
|
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
|
|
{
|
|
VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
|
|
|
|
This->bmiheader = format->bmiHeader;
|
|
TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
|
|
This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
|
|
This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
|
|
This->source_rect.top = This->source_rect.left = 0;
|
|
}
|
|
else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
|
|
{
|
|
VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
|
|
|
|
This->bmiheader = format->bmiHeader;
|
|
|
|
TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
|
|
This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
|
|
This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
|
|
This->source_rect.top = This->source_rect.left = 0;
|
|
}
|
|
else
|
|
{
|
|
ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
|
|
return S_FALSE;
|
|
}
|
|
if (This->bmiheader.biCompression)
|
|
return S_FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
|
|
{
|
|
/* Preroll means the sample isn't shown, this is used for key frames and things like that */
|
|
if (IMediaSample_IsPreroll(pSample) == S_OK)
|
|
return E_FAIL;
|
|
return S_FALSE;
|
|
}
|
|
|
|
static const BaseRendererFuncTable BaseFuncTable = {
|
|
VMR9_CheckMediaType,
|
|
VMR9_DoRenderSample,
|
|
/**/
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
VMR9_ShouldDrawSampleNow,
|
|
NULL,
|
|
/**/
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
|
|
static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
|
|
{
|
|
static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 };
|
|
|
|
*pClassStyles = 0;
|
|
*pWindowStyles = WS_SIZEBOX;
|
|
*pWindowStylesEx = 0;
|
|
|
|
return classnameW;
|
|
}
|
|
|
|
static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
|
|
static RECT defRect;
|
|
|
|
defRect.left = defRect.top = 0;
|
|
defRect.right = pVMR9->VideoWidth;
|
|
defRect.bottom = pVMR9->VideoHeight;
|
|
|
|
return defRect;
|
|
}
|
|
|
|
static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
|
|
|
|
TRACE("WM_SIZE %d %d\n", Width, Height);
|
|
GetClientRect(This->hWnd, &pVMR9->target_rect);
|
|
TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
|
|
pVMR9->target_rect.left,
|
|
pVMR9->target_rect.top,
|
|
pVMR9->target_rect.right - pVMR9->target_rect.left,
|
|
pVMR9->target_rect.bottom - pVMR9->target_rect.top);
|
|
return BaseWindowImpl_OnSize(This, Width, Height);
|
|
}
|
|
|
|
static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
|
|
VMR9_GetClassWindowStyles,
|
|
VMR9_GetDefaultRect,
|
|
NULL,
|
|
BaseControlWindowImpl_PossiblyEatMessage,
|
|
VMR9_OnSize,
|
|
};
|
|
|
|
static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
CopyRect(pSourceRect,&pVMR9->source_rect);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
BITMAPINFOHEADER *bmiHeader;
|
|
LONG needed_size;
|
|
AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
|
|
char *ptr;
|
|
|
|
FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage);
|
|
|
|
EnterCriticalSection(&pVMR9->renderer.filter.csFilter);
|
|
|
|
if (!pVMR9->renderer.pMediaSample)
|
|
{
|
|
LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
|
|
return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
|
|
}
|
|
|
|
if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
|
|
{
|
|
bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
|
|
}
|
|
else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
|
|
{
|
|
bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
|
|
}
|
|
else
|
|
{
|
|
FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
|
|
LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
|
|
return VFW_E_RUNTIME_ERROR;
|
|
}
|
|
|
|
needed_size = bmiHeader->biSize;
|
|
needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample);
|
|
|
|
if (!pDIBImage)
|
|
{
|
|
*pBufferSize = needed_size;
|
|
LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
|
|
return S_OK;
|
|
}
|
|
|
|
if (needed_size < *pBufferSize)
|
|
{
|
|
ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
|
|
LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
|
|
return E_FAIL;
|
|
}
|
|
*pBufferSize = needed_size;
|
|
|
|
memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
|
|
IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr);
|
|
memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample));
|
|
|
|
LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
CopyRect(pTargetRect,&pVMR9->target_rect);
|
|
return S_OK;
|
|
}
|
|
|
|
static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
AM_MEDIA_TYPE *pmt;
|
|
|
|
TRACE("(%p/%p)\n", pVMR9, This);
|
|
|
|
pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
|
|
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
|
|
return (VIDEOINFOHEADER*)pmt->pbFormat;
|
|
} else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
|
|
static VIDEOINFOHEADER vih;
|
|
VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
|
|
memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
|
|
memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
|
|
return &vih;
|
|
} else {
|
|
ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
|
|
pVMR9->source_rect.left = 0;
|
|
pVMR9->source_rect.top = 0;
|
|
pVMR9->source_rect.right = pVMR9->VideoWidth;
|
|
pVMR9->source_rect.bottom = pVMR9->VideoHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
|
|
{
|
|
RECT rect;
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
|
|
if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
|
|
return E_FAIL;
|
|
|
|
pVMR9->target_rect.left = 0;
|
|
pVMR9->target_rect.top = 0;
|
|
pVMR9->target_rect.right = rect.right;
|
|
pVMR9->target_rect.bottom = rect.bottom;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
CopyRect(&pVMR9->source_rect,pSourceRect);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
|
|
{
|
|
VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
|
|
CopyRect(&pVMR9->target_rect,pTargetRect);
|
|
return S_OK;
|
|
}
|
|
|
|
static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
|
|
VMR9_GetSourceRect,
|
|
VMR9_GetStaticImage,
|
|
VMR9_GetTargetRect,
|
|
VMR9_GetVideoFormat,
|
|
VMR9_IsDefaultSourceRect,
|
|
VMR9_IsDefaultTargetRect,
|
|
VMR9_SetDefaultSourceRect,
|
|
VMR9_SetDefaultTargetRect,
|
|
VMR9_SetSourceRect,
|
|
VMR9_SetTargetRect
|
|
};
|
|
|
|
static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
|
|
{
|
|
VMR9Impl *This = impl_from_inner_IUnknown(iface);
|
|
TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
|
|
|
|
if (This->bAggregatable)
|
|
This->bUnkOuterValid = TRUE;
|
|
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = &This->IUnknown_inner;
|
|
else if (IsEqualIID(riid, &IID_IVideoWindow))
|
|
*ppv = &This->baseControlWindow.IVideoWindow_iface;
|
|
else if (IsEqualIID(riid, &IID_IBasicVideo))
|
|
*ppv = &This->baseControlVideo.IBasicVideo_iface;
|
|
else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
|
|
*ppv = &This->IAMFilterMiscFlags_iface;
|
|
else if (IsEqualIID(riid, &IID_IVMRFilterConfig9))
|
|
*ppv = &This->IVMRFilterConfig9_iface;
|
|
else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9) && This->mode == VMR9Mode_Windowless)
|
|
*ppv = &This->IVMRWindowlessControl9_iface;
|
|
else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9) && This->mode == VMR9Mode_Renderless)
|
|
*ppv = &This->IVMRSurfaceAllocatorNotify9_iface;
|
|
else
|
|
{
|
|
HRESULT hr;
|
|
hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
|
|
if (SUCCEEDED(hr))
|
|
return hr;
|
|
}
|
|
|
|
if (*ppv)
|
|
{
|
|
IUnknown_AddRef((IUnknown *)(*ppv));
|
|
return S_OK;
|
|
}
|
|
|
|
else if (IsEqualIID(riid, &IID_IBasicVideo2))
|
|
FIXME("No interface for IID_IBasicVideo2\n");
|
|
else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
|
|
;
|
|
else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
|
|
;
|
|
else if (IsEqualIID(riid, &IID_IMediaPosition))
|
|
FIXME("No interface for IID_IMediaPosition\n");
|
|
else if (IsEqualIID(riid, &IID_IQualProp))
|
|
FIXME("No interface for IID_IQualProp\n");
|
|
else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
|
|
FIXME("No interface for IID_IVMRAspectRatioControl9\n");
|
|
else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
|
|
FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
|
|
else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
|
|
FIXME("No interface for IID_IVMRMixerBitmap9\n");
|
|
else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
|
|
FIXME("No interface for IID_IVMRMonitorConfig9\n");
|
|
else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
|
|
FIXME("No interface for IID_IVMRMixerControl9\n");
|
|
else
|
|
FIXME("No interface for %s\n", debugstr_guid(riid));
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
|
|
{
|
|
VMR9Impl *This = impl_from_inner_IUnknown(iface);
|
|
ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
|
|
TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
|
|
|
|
return refCount;
|
|
}
|
|
|
|
static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
|
|
{
|
|
VMR9Impl *This = impl_from_inner_IUnknown(iface);
|
|
ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
|
|
TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
|
|
|
|
if (!refCount)
|
|
{
|
|
TRACE("Destroying\n");
|
|
BaseControlWindow_Destroy(&This->baseControlWindow);
|
|
|
|
if (This->allocator)
|
|
IVMRSurfaceAllocator9_Release(This->allocator);
|
|
if (This->presenter)
|
|
IVMRImagePresenter9_Release(This->presenter);
|
|
|
|
CoTaskMemFree(This);
|
|
}
|
|
return refCount;
|
|
}
|
|
|
|
static const IUnknownVtbl IInner_VTable =
|
|
{
|
|
VMR9Inner_QueryInterface,
|
|
VMR9Inner_AddRef,
|
|
VMR9Inner_Release
|
|
};
|
|
|
|
static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
|
|
{
|
|
VMR9Impl *This = (VMR9Impl *)iface;
|
|
|
|
if (This->bAggregatable)
|
|
This->bUnkOuterValid = TRUE;
|
|
|
|
if (This->outer_unk)
|
|
{
|
|
if (This->bAggregatable)
|
|
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown))
|
|
{
|
|
HRESULT hr;
|
|
|
|
IUnknown_AddRef(&This->IUnknown_inner);
|
|
hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
|
|
IUnknown_Release(&This->IUnknown_inner);
|
|
This->bAggregatable = TRUE;
|
|
return hr;
|
|
}
|
|
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
|
|
{
|
|
VMR9Impl *This = (VMR9Impl *)iface;
|
|
LONG ret;
|
|
|
|
if (This->outer_unk && This->bUnkOuterValid)
|
|
ret = IUnknown_AddRef(This->outer_unk);
|
|
else
|
|
ret = IUnknown_AddRef(&This->IUnknown_inner);
|
|
|
|
TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
|
|
{
|
|
VMR9Impl *This = (VMR9Impl *)iface;
|
|
LONG ret;
|
|
|
|
if (This->outer_unk && This->bUnkOuterValid)
|
|
ret = IUnknown_Release(This->outer_unk);
|
|
else
|
|
ret = IUnknown_Release(&This->IUnknown_inner);
|
|
|
|
TRACE("(%p)->Release from %d\n", iface, ret + 1);
|
|
|
|
if (ret)
|
|
return ret;
|
|
return 0;
|
|
}
|
|
|
|
static const IBaseFilterVtbl VMR9_Vtbl =
|
|
{
|
|
VMR9_QueryInterface,
|
|
VMR9_AddRef,
|
|
VMR9_Release,
|
|
BaseFilterImpl_GetClassID,
|
|
BaseRendererImpl_Stop,
|
|
BaseRendererImpl_Pause,
|
|
BaseRendererImpl_Run,
|
|
BaseRendererImpl_GetState,
|
|
BaseRendererImpl_SetSyncSource,
|
|
BaseFilterImpl_GetSyncSource,
|
|
BaseFilterImpl_EnumPins,
|
|
BaseRendererImpl_FindPin,
|
|
BaseFilterImpl_QueryFilterInfo,
|
|
BaseFilterImpl_JoinFilterGraph,
|
|
BaseFilterImpl_QueryVendorInfo
|
|
};
|
|
|
|
/*** IUnknown methods ***/
|
|
static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
|
|
{
|
|
VMR9Impl *This = impl_from_IVideoWindow(iface);
|
|
|
|
TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
|
|
|
|
return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
|
|
}
|
|
|
|
static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVideoWindow(iface);
|
|
|
|
TRACE("(%p/%p)->()\n", This, iface);
|
|
|
|
return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVideoWindow(iface);
|
|
|
|
TRACE("(%p/%p)->()\n", This, iface);
|
|
|
|
return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static const IVideoWindowVtbl IVideoWindow_VTable =
|
|
{
|
|
Videowindow_QueryInterface,
|
|
Videowindow_AddRef,
|
|
Videowindow_Release,
|
|
BaseControlWindowImpl_GetTypeInfoCount,
|
|
BaseControlWindowImpl_GetTypeInfo,
|
|
BaseControlWindowImpl_GetIDsOfNames,
|
|
BaseControlWindowImpl_Invoke,
|
|
BaseControlWindowImpl_put_Caption,
|
|
BaseControlWindowImpl_get_Caption,
|
|
BaseControlWindowImpl_put_WindowStyle,
|
|
BaseControlWindowImpl_get_WindowStyle,
|
|
BaseControlWindowImpl_put_WindowStyleEx,
|
|
BaseControlWindowImpl_get_WindowStyleEx,
|
|
BaseControlWindowImpl_put_AutoShow,
|
|
BaseControlWindowImpl_get_AutoShow,
|
|
BaseControlWindowImpl_put_WindowState,
|
|
BaseControlWindowImpl_get_WindowState,
|
|
BaseControlWindowImpl_put_BackgroundPalette,
|
|
BaseControlWindowImpl_get_BackgroundPalette,
|
|
BaseControlWindowImpl_put_Visible,
|
|
BaseControlWindowImpl_get_Visible,
|
|
BaseControlWindowImpl_put_Left,
|
|
BaseControlWindowImpl_get_Left,
|
|
BaseControlWindowImpl_put_Width,
|
|
BaseControlWindowImpl_get_Width,
|
|
BaseControlWindowImpl_put_Top,
|
|
BaseControlWindowImpl_get_Top,
|
|
BaseControlWindowImpl_put_Height,
|
|
BaseControlWindowImpl_get_Height,
|
|
BaseControlWindowImpl_put_Owner,
|
|
BaseControlWindowImpl_get_Owner,
|
|
BaseControlWindowImpl_put_MessageDrain,
|
|
BaseControlWindowImpl_get_MessageDrain,
|
|
BaseControlWindowImpl_get_BorderColor,
|
|
BaseControlWindowImpl_put_BorderColor,
|
|
BaseControlWindowImpl_get_FullScreenMode,
|
|
BaseControlWindowImpl_put_FullScreenMode,
|
|
BaseControlWindowImpl_SetWindowForeground,
|
|
BaseControlWindowImpl_NotifyOwnerMessage,
|
|
BaseControlWindowImpl_SetWindowPosition,
|
|
BaseControlWindowImpl_GetWindowPosition,
|
|
BaseControlWindowImpl_GetMinIdealImageSize,
|
|
BaseControlWindowImpl_GetMaxIdealImageSize,
|
|
BaseControlWindowImpl_GetRestorePosition,
|
|
BaseControlWindowImpl_HideCursor,
|
|
BaseControlWindowImpl_IsCursorHidden
|
|
};
|
|
|
|
/*** IUnknown methods ***/
|
|
static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
VMR9Impl *This = impl_from_IBasicVideo(iface);
|
|
|
|
TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
|
|
|
|
return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
|
|
}
|
|
|
|
static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IBasicVideo(iface);
|
|
|
|
TRACE("(%p/%p)->()\n", This, iface);
|
|
|
|
return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IBasicVideo(iface);
|
|
|
|
TRACE("(%p/%p)->()\n", This, iface);
|
|
|
|
return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static const IBasicVideoVtbl IBasicVideo_VTable =
|
|
{
|
|
Basicvideo_QueryInterface,
|
|
Basicvideo_AddRef,
|
|
Basicvideo_Release,
|
|
BaseControlVideoImpl_GetTypeInfoCount,
|
|
BaseControlVideoImpl_GetTypeInfo,
|
|
BaseControlVideoImpl_GetIDsOfNames,
|
|
BaseControlVideoImpl_Invoke,
|
|
BaseControlVideoImpl_get_AvgTimePerFrame,
|
|
BaseControlVideoImpl_get_BitRate,
|
|
BaseControlVideoImpl_get_BitErrorRate,
|
|
BaseControlVideoImpl_get_VideoWidth,
|
|
BaseControlVideoImpl_get_VideoHeight,
|
|
BaseControlVideoImpl_put_SourceLeft,
|
|
BaseControlVideoImpl_get_SourceLeft,
|
|
BaseControlVideoImpl_put_SourceWidth,
|
|
BaseControlVideoImpl_get_SourceWidth,
|
|
BaseControlVideoImpl_put_SourceTop,
|
|
BaseControlVideoImpl_get_SourceTop,
|
|
BaseControlVideoImpl_put_SourceHeight,
|
|
BaseControlVideoImpl_get_SourceHeight,
|
|
BaseControlVideoImpl_put_DestinationLeft,
|
|
BaseControlVideoImpl_get_DestinationLeft,
|
|
BaseControlVideoImpl_put_DestinationWidth,
|
|
BaseControlVideoImpl_get_DestinationWidth,
|
|
BaseControlVideoImpl_put_DestinationTop,
|
|
BaseControlVideoImpl_get_DestinationTop,
|
|
BaseControlVideoImpl_put_DestinationHeight,
|
|
BaseControlVideoImpl_get_DestinationHeight,
|
|
BaseControlVideoImpl_SetSourcePosition,
|
|
BaseControlVideoImpl_GetSourcePosition,
|
|
BaseControlVideoImpl_SetDefaultSourcePosition,
|
|
BaseControlVideoImpl_SetDestinationPosition,
|
|
BaseControlVideoImpl_GetDestinationPosition,
|
|
BaseControlVideoImpl_SetDefaultDestinationPosition,
|
|
BaseControlVideoImpl_GetVideoSize,
|
|
BaseControlVideoImpl_GetVideoPaletteEntries,
|
|
BaseControlVideoImpl_GetCurrentImage,
|
|
BaseControlVideoImpl_IsUsingDefaultSource,
|
|
BaseControlVideoImpl_IsUsingDefaultDestination
|
|
};
|
|
|
|
static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
|
|
VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
|
|
return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
|
|
}
|
|
|
|
static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
|
|
VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
|
|
return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
|
|
VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
|
|
return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
|
|
return AM_FILTER_MISC_FLAGS_IS_RENDERER;
|
|
}
|
|
|
|
static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
|
|
AMFilterMiscFlags_QueryInterface,
|
|
AMFilterMiscFlags_AddRef,
|
|
AMFilterMiscFlags_Release,
|
|
AMFilterMiscFlags_GetMiscFlags
|
|
};
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
TRACE("(%p/%p)->(%u)\n", iface, This, mode);
|
|
|
|
EnterCriticalSection(&This->renderer.filter.csFilter);
|
|
if (This->mode)
|
|
{
|
|
LeaveCriticalSection(&This->renderer.filter.csFilter);
|
|
return VFW_E_WRONG_STATE;
|
|
}
|
|
|
|
if (This->allocator)
|
|
IVMRSurfaceAllocator9_Release(This->allocator);
|
|
if (This->presenter)
|
|
IVMRImagePresenter9_Release(This->presenter);
|
|
|
|
This->allocator = NULL;
|
|
This->presenter = NULL;
|
|
|
|
switch (mode)
|
|
{
|
|
case VMR9Mode_Windowed:
|
|
case VMR9Mode_Windowless:
|
|
This->allocator_is_ex = 0;
|
|
This->cookie = ~0;
|
|
|
|
hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter);
|
|
if (SUCCEEDED(hr))
|
|
hr = IVMRImagePresenter9_QueryInterface(This->presenter, &IID_IVMRSurfaceAllocatorEx9, (LPVOID*)&This->allocator);
|
|
if (FAILED(hr))
|
|
{
|
|
ERR("Unable to find Presenter interface\n");
|
|
IVMRSurfaceAllocatorEx9_Release(This->presenter);
|
|
This->allocator = NULL;
|
|
This->presenter = NULL;
|
|
}
|
|
else
|
|
hr = IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
|
|
break;
|
|
case VMR9Mode_Renderless:
|
|
break;
|
|
default:
|
|
LeaveCriticalSection(&This->renderer.filter.csFilter);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
This->mode = mode;
|
|
LeaveCriticalSection(&This->renderer.filter.csFilter);
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
|
|
|
|
TRACE("(%p/%p)->(%p) stub\n", iface, This, mode);
|
|
if (!mode)
|
|
return E_POINTER;
|
|
|
|
if (This->mode)
|
|
*mode = This->mode;
|
|
else
|
|
*mode = VMR9Mode_Windowed;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
|
|
{
|
|
VMR9FilterConfig_QueryInterface,
|
|
VMR9FilterConfig_AddRef,
|
|
VMR9FilterConfig_Release,
|
|
VMR9FilterConfig_SetImageCompositor,
|
|
VMR9FilterConfig_SetNumberOfStreams,
|
|
VMR9FilterConfig_GetNumberOfStreams,
|
|
VMR9FilterConfig_SetRenderingPrefs,
|
|
VMR9FilterConfig_GetRenderingPrefs,
|
|
VMR9FilterConfig_SetRenderingMode,
|
|
VMR9FilterConfig_GetRenderingMode
|
|
};
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
|
|
|
|
if (!width || !height || !arwidth || !arheight)
|
|
{
|
|
ERR("Got no pointer\n");
|
|
return E_POINTER;
|
|
}
|
|
|
|
*width = This->bmiheader.biWidth;
|
|
*height = This->bmiheader.biHeight;
|
|
*arwidth = This->bmiheader.biWidth;
|
|
*arheight = This->bmiheader.biHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
|
|
|
|
EnterCriticalSection(&This->renderer.filter.csFilter);
|
|
|
|
if (source)
|
|
This->source_rect = *source;
|
|
if (dest)
|
|
{
|
|
This->target_rect = *dest;
|
|
if (This->baseControlWindow.baseWindow.hWnd)
|
|
{
|
|
FIXME("Output rectangle: starting at %dx%d, up to point %dx%d\n", dest->left, dest->top, dest->right, dest->bottom);
|
|
SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
|
|
dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&This->renderer.filter.csFilter);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
if (source)
|
|
*source = This->source_rect;
|
|
|
|
if (dest)
|
|
*dest = This->target_rect;
|
|
|
|
FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
|
|
|
|
EnterCriticalSection(&This->renderer.filter.csFilter);
|
|
This->hWndClippingWindow = hwnd;
|
|
if (!hwnd)
|
|
IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
|
|
LeaveCriticalSection(&This->renderer.filter.csFilter);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
|
|
{
|
|
VMR9WindowlessControl_QueryInterface,
|
|
VMR9WindowlessControl_AddRef,
|
|
VMR9WindowlessControl_Release,
|
|
VMR9WindowlessControl_GetNativeVideoSize,
|
|
VMR9WindowlessControl_GetMinIdealVideoSize,
|
|
VMR9WindowlessControl_GetMaxIdealVideoSize,
|
|
VMR9WindowlessControl_SetVideoPosition,
|
|
VMR9WindowlessControl_GetVideoPosition,
|
|
VMR9WindowlessControl_GetAspectRatioMode,
|
|
VMR9WindowlessControl_SetAspectRatioMode,
|
|
VMR9WindowlessControl_SetVideoClippingWindow,
|
|
VMR9WindowlessControl_RepaintVideo,
|
|
VMR9WindowlessControl_DisplayModeChanged,
|
|
VMR9WindowlessControl_GetCurrentImage,
|
|
VMR9WindowlessControl_SetBorderColor,
|
|
VMR9WindowlessControl_GetBorderColor
|
|
};
|
|
|
|
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
|
|
/* FIXME: This code is not tested!!! */
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
This->cookie = id;
|
|
|
|
if (This->presenter)
|
|
return VFW_E_WRONG_STATE;
|
|
|
|
if (FAILED(IUnknown_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
|
|
return E_NOINTERFACE;
|
|
|
|
if (SUCCEEDED(IUnknown_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
|
|
This->allocator_is_ex = 1;
|
|
else
|
|
{
|
|
This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
|
|
IUnknown_AddRef(alloc);
|
|
This->allocator_is_ex = 0;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
|
|
FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
|
|
|
|
if (!allocinfo || !numbuffers || !surface)
|
|
return E_POINTER;
|
|
|
|
if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
|
|
{
|
|
ERR("Invalid number of buffers?\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
|
|
{
|
|
VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
|
|
|
|
FIXME("(%p/%p)->(...) stub\n", iface, This);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl =
|
|
{
|
|
VMR9SurfaceAllocatorNotify_QueryInterface,
|
|
VMR9SurfaceAllocatorNotify_AddRef,
|
|
VMR9SurfaceAllocatorNotify_Release,
|
|
VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
|
|
VMR9SurfaceAllocatorNotify_SetD3DDevice,
|
|
VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
|
|
VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
|
|
VMR9SurfaceAllocatorNotify_NotifyEvent
|
|
};
|
|
|
|
HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
|
|
{
|
|
HRESULT hr;
|
|
VMR9Impl * pVMR9;
|
|
|
|
TRACE("(%p, %p)\n", outer_unk, ppv);
|
|
|
|
*ppv = NULL;
|
|
|
|
pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
|
|
|
|
pVMR9->outer_unk = outer_unk;
|
|
pVMR9->bUnkOuterValid = FALSE;
|
|
pVMR9->bAggregatable = FALSE;
|
|
pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
|
|
pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
|
|
|
|
pVMR9->mode = 0;
|
|
pVMR9->allocator = NULL;
|
|
pVMR9->presenter = NULL;
|
|
pVMR9->hWndClippingWindow = NULL;
|
|
pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
|
|
pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
|
|
pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl;
|
|
|
|
hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
|
|
if (FAILED(hr))
|
|
goto fail;
|
|
|
|
hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
|
|
if (FAILED(hr))
|
|
goto fail;
|
|
|
|
hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
|
|
if (FAILED(hr))
|
|
goto fail;
|
|
|
|
*ppv = (LPVOID)pVMR9;
|
|
ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
|
|
ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
|
|
TRACE("Created at %p\n", pVMR9);
|
|
return hr;
|
|
|
|
fail:
|
|
BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
|
|
CoTaskMemFree(pVMR9);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, LPVOID * ppv)
|
|
{
|
|
VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
|
|
TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
|
|
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = (LPVOID)&(This->IVMRImagePresenter9_iface);
|
|
else if (IsEqualIID(riid, &IID_IVMRImagePresenter9))
|
|
*ppv = &This->IVMRImagePresenter9_iface;
|
|
|
|
if (*ppv)
|
|
{
|
|
IUnknown_AddRef((IUnknown *)(*ppv));
|
|
return S_OK;
|
|
}
|
|
|
|
FIXME("No interface for %s\n", debugstr_guid(riid));
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
|
|
{
|
|
VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
|
|
ULONG refCount = InterlockedIncrement(&This->refCount);
|
|
|
|
TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
|
|
|
|
return refCount;
|
|
}
|
|
|
|
static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
|
|
{
|
|
VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
|
|
ULONG refCount = InterlockedDecrement(&This->refCount);
|
|
|
|
TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
|
|
|
|
if (!refCount)
|
|
{
|
|
TRACE("Destroying\n");
|
|
IUnknown_Release(This->d3d9_ptr);
|
|
|
|
if (This->d3d9_vertex)
|
|
{
|
|
IUnknown_Release(This->d3d9_vertex);
|
|
This->d3d9_vertex = NULL;
|
|
}
|
|
CoTaskMemFree(This);
|
|
return 0;
|
|
}
|
|
return refCount;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
|
|
{
|
|
VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
|
|
|
|
TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
|
|
{
|
|
VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
|
|
|
|
TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
|
|
return S_OK;
|
|
}
|
|
|
|
#define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
|
|
struct VERTEX { float x, y, z, rhw, u, v; };
|
|
|
|
static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
|
|
{
|
|
IDirect3DTexture9 *texture = NULL;
|
|
HRESULT hr;
|
|
|
|
hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF);
|
|
if (FAILED(hr))
|
|
{
|
|
FIXME("SetFVF: %08x\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX));
|
|
if (FAILED(hr))
|
|
{
|
|
FIXME("SetStreamSource: %08x\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture);
|
|
if (FAILED(hr))
|
|
{
|
|
FIXME("IDirect3DSurface9_GetContainer failed\n");
|
|
return hr;
|
|
}
|
|
hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture);
|
|
IDirect3DTexture9_Release(texture);
|
|
if (FAILED(hr))
|
|
{
|
|
FIXME("SetTexture: %08x\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2);
|
|
if (FAILED(hr))
|
|
{
|
|
FIXME("DrawPrimitive: %08x\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
|
|
{
|
|
HRESULT hr;
|
|
IDirect3DSurface9 *target = NULL;
|
|
RECT target_rect;
|
|
|
|
hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target);
|
|
if (FAILED(hr))
|
|
{
|
|
ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
target_rect = This->pVMR9->target_rect;
|
|
target_rect.right -= target_rect.left;
|
|
target_rect.bottom -= target_rect.top;
|
|
target_rect.left = target_rect.top = 0;
|
|
|
|
/* Flip */
|
|
target_rect.top = target_rect.bottom;
|
|
target_rect.bottom = 0;
|
|
|
|
hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR);
|
|
if (FAILED(hr))
|
|
ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr);
|
|
IDirect3DSurface9_Release(target);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info)
|
|
{
|
|
VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
|
|
HRESULT hr;
|
|
RECT output;
|
|
BOOL render = FALSE;
|
|
|
|
TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9);
|
|
GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output);
|
|
TRACE("Output rectangle: starting at %dx%d, up to point %dx%d\n", output.left, output.top, output.right, output.bottom);
|
|
|
|
/* This might happen if we don't have active focus (eg on a different virtual desktop) */
|
|
if (!This->d3d9_dev)
|
|
return S_OK;
|
|
|
|
/* Display image here */
|
|
hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
|
|
if (FAILED(hr))
|
|
FIXME("hr: %08x\n", hr);
|
|
hr = IDirect3DDevice9_BeginScene(This->d3d9_dev);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (This->d3d9_vertex)
|
|
hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf);
|
|
else
|
|
hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf);
|
|
render = SUCCEEDED(hr);
|
|
}
|
|
else
|
|
FIXME("BeginScene: %08x\n", hr);
|
|
hr = IDirect3DDevice9_EndScene(This->d3d9_dev);
|
|
if (render && SUCCEEDED(hr))
|
|
{
|
|
hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL);
|
|
if (FAILED(hr))
|
|
FIXME("Presenting image: %08x\n", hr);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
|
|
{
|
|
VMR9_ImagePresenter_QueryInterface,
|
|
VMR9_ImagePresenter_AddRef,
|
|
VMR9_ImagePresenter_Release,
|
|
VMR9_ImagePresenter_StartPresenting,
|
|
VMR9_ImagePresenter_StopPresenting,
|
|
VMR9_ImagePresenter_PresentImage
|
|
};
|
|
|
|
static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int i;
|
|
VMR9DefaultAllocatorPresenterImpl* This;
|
|
|
|
This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl));
|
|
if (!This)
|
|
return E_OUTOFMEMORY;
|
|
|
|
This->d3d9_ptr = NULL;
|
|
if (!This->d3d9_ptr)
|
|
{
|
|
WARN("Could not initialize d3d9.dll\n");
|
|
CoTaskMemFree(This);
|
|
return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
}
|
|
|
|
i = 0;
|
|
do
|
|
{
|
|
D3DDISPLAYMODE mode;
|
|
|
|
hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
|
|
} while (FAILED(hr));
|
|
if (FAILED(hr))
|
|
ERR("HR: %08x\n", hr);
|
|
if (hr == D3DERR_NOTAVAILABLE)
|
|
{
|
|
ERR("Format not supported\n");
|
|
IUnknown_Release(This->d3d9_ptr);
|
|
CoTaskMemFree(This);
|
|
return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
}
|
|
|
|
This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
|
|
|
|
This->refCount = 1;
|
|
This->pVMR9 = parent;
|
|
This->d3d9_dev = NULL;
|
|
This->d3d9_vertex = NULL;
|
|
|
|
*ppv = This;
|
|
return S_OK;
|
|
}
|