winegstreamer: Flip YUV data before converting to RGB
[wine/multimedia.git] / dlls / quartz / vmr9.c
blobefd14a12e48b89bc9d932ce1dd0a3d6602836004
1 /*
2 * Video Mixing Renderer for dx9
4 * Copyright 2004 Christian Costa
5 * Copyright 2008 Maarten Lankhorst
6 * Copyright 2012 Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "quartz_private.h"
29 #include "uuids.h"
30 #include "vfwmsgs.h"
31 #include "amvideo.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "dshow.h"
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "ddraw.h"
38 #include "dvdmedia.h"
39 #include "d3d9.h"
40 #include "vmr9.h"
41 #include "pin.h"
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
48 typedef struct
50 BaseRenderer renderer;
51 BaseControlWindow baseControlWindow;
52 BaseControlVideo baseControlVideo;
54 IUnknown IUnknown_inner;
55 IAMFilterMiscFlags IAMFilterMiscFlags_iface;
56 IVMRFilterConfig9 IVMRFilterConfig9_iface;
57 IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
58 IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
60 IVMRSurfaceAllocatorEx9 *allocator;
61 IVMRImagePresenter9 *presenter;
62 BOOL allocator_is_ex;
64 VMR9Mode mode;
65 BITMAPINFOHEADER bmiheader;
66 IUnknown * outer_unk;
67 BOOL bUnkOuterValid;
68 BOOL bAggregatable;
70 DWORD_PTR cookie;
72 /* for Windowless Mode */
73 HWND hWndClippingWindow;
75 RECT source_rect;
76 RECT target_rect;
77 LONG VideoWidth;
78 LONG VideoHeight;
79 } VMR9Impl;
81 static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface)
83 return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner);
86 static inline VMR9Impl *impl_from_BaseWindow( BaseWindow *wnd )
88 return CONTAINING_RECORD(wnd, VMR9Impl, baseControlWindow.baseWindow);
91 static inline VMR9Impl *impl_from_IVideoWindow( IVideoWindow *iface)
93 return CONTAINING_RECORD(iface, VMR9Impl, baseControlWindow.IVideoWindow_iface);
96 static inline VMR9Impl *impl_from_BaseControlVideo( BaseControlVideo *cvid )
98 return CONTAINING_RECORD(cvid, VMR9Impl, baseControlVideo);
101 static inline VMR9Impl *impl_from_IBasicVideo( IBasicVideo *iface)
103 return CONTAINING_RECORD(iface, VMR9Impl, baseControlVideo.IBasicVideo_iface);
106 static inline VMR9Impl *impl_from_IAMFilterMiscFlags( IAMFilterMiscFlags *iface)
108 return CONTAINING_RECORD(iface, VMR9Impl, IAMFilterMiscFlags_iface);
111 static inline VMR9Impl *impl_from_IVMRFilterConfig9( IVMRFilterConfig9 *iface)
113 return CONTAINING_RECORD(iface, VMR9Impl, IVMRFilterConfig9_iface);
116 static inline VMR9Impl *impl_from_IVMRWindowlessControl9( IVMRWindowlessControl9 *iface)
118 return CONTAINING_RECORD(iface, VMR9Impl, IVMRWindowlessControl9_iface);
121 static inline VMR9Impl *impl_from_IVMRSurfaceAllocatorNotify9( IVMRSurfaceAllocatorNotify9 *iface)
123 return CONTAINING_RECORD(iface, VMR9Impl, IVMRSurfaceAllocatorNotify9_iface);
126 typedef struct
128 IVMRImagePresenter9 IVMRImagePresenter9_iface;
130 LONG refCount;
132 IDirect3DDevice9 *d3d9_dev;
133 IDirect3D9 *d3d9_ptr;
134 IDirect3DVertexBuffer9 *d3d9_vertex;
136 VMR9AllocationInfo info;
138 VMR9Impl* pVMR9;
139 } VMR9DefaultAllocatorPresenterImpl;
141 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRImagePresenter9( IVMRImagePresenter9 *iface)
143 return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRImagePresenter9_iface);
146 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv);
148 static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
150 VMR9Impl *This = (VMR9Impl *)iface;
151 LPBYTE pbSrcStream = NULL;
152 REFERENCE_TIME tStart, tStop;
153 VMR9PresentationInfo info;
154 HRESULT hr;
156 TRACE("%p %p\n", iface, pSample);
158 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
159 if (FAILED(hr))
160 info.dwFlags = VMR9Sample_SrcDstRectsValid;
161 else
162 info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
164 if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
165 info.dwFlags |= VMR9Sample_Discontinuity;
167 if (IMediaSample_IsPreroll(pSample) == S_OK)
168 info.dwFlags |= VMR9Sample_Preroll;
170 if (IMediaSample_IsSyncPoint(pSample) == S_OK)
171 info.dwFlags |= VMR9Sample_SyncPoint;
173 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
174 if (FAILED(hr))
176 ERR("Cannot get pointer to sample data (%x)\n", hr);
177 return hr;
180 info.rtStart = tStart;
181 info.rtEnd = tStop;
182 info.szAspectRatio.cx = This->bmiheader.biWidth;
183 info.szAspectRatio.cy = This->bmiheader.biHeight;
185 return hr;
188 static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
190 VMR9Impl *This = (VMR9Impl*)iface;
192 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
193 return S_FALSE;
195 /* Ignore subtype, test for bicompression instead */
196 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
198 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
200 This->bmiheader = format->bmiHeader;
201 TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
202 This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
203 This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
204 This->source_rect.top = This->source_rect.left = 0;
206 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
208 VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
210 This->bmiheader = format->bmiHeader;
212 TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
213 This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
214 This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
215 This->source_rect.top = This->source_rect.left = 0;
217 else
219 ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
220 return S_FALSE;
222 if (This->bmiheader.biCompression)
223 return S_FALSE;
224 return S_OK;
227 static HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
229 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
230 if (IMediaSample_IsPreroll(pSample) == S_OK)
231 return E_FAIL;
232 return S_FALSE;
235 static const BaseRendererFuncTable BaseFuncTable = {
236 VMR9_CheckMediaType,
237 VMR9_DoRenderSample,
238 /**/
239 NULL,
240 NULL,
241 NULL,
242 NULL,
243 NULL,
244 NULL,
245 NULL,
246 NULL,
247 VMR9_ShouldDrawSampleNow,
248 NULL,
249 /**/
250 NULL,
251 NULL,
252 NULL,
253 NULL,
254 NULL,
257 static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
259 static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 };
261 *pClassStyles = 0;
262 *pWindowStyles = WS_SIZEBOX;
263 *pWindowStylesEx = 0;
265 return classnameW;
268 static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
270 VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
271 static RECT defRect;
273 defRect.left = defRect.top = 0;
274 defRect.right = pVMR9->VideoWidth;
275 defRect.bottom = pVMR9->VideoHeight;
277 return defRect;
280 static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
282 VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
284 TRACE("WM_SIZE %d %d\n", Width, Height);
285 GetClientRect(This->hWnd, &pVMR9->target_rect);
286 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
287 pVMR9->target_rect.left,
288 pVMR9->target_rect.top,
289 pVMR9->target_rect.right - pVMR9->target_rect.left,
290 pVMR9->target_rect.bottom - pVMR9->target_rect.top);
291 return BaseWindowImpl_OnSize(This, Width, Height);
294 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
295 VMR9_GetClassWindowStyles,
296 VMR9_GetDefaultRect,
297 NULL,
298 BaseControlWindowImpl_PossiblyEatMessage,
299 VMR9_OnSize,
302 static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
304 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
305 CopyRect(pSourceRect,&pVMR9->source_rect);
306 return S_OK;
309 static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage)
311 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
312 BITMAPINFOHEADER *bmiHeader;
313 LONG needed_size;
314 AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
315 char *ptr;
317 FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage);
319 EnterCriticalSection(&pVMR9->renderer.filter.csFilter);
321 if (!pVMR9->renderer.pMediaSample)
323 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
324 return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
327 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
329 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
331 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
333 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
335 else
337 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
338 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
339 return VFW_E_RUNTIME_ERROR;
342 needed_size = bmiHeader->biSize;
343 needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample);
345 if (!pDIBImage)
347 *pBufferSize = needed_size;
348 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
349 return S_OK;
352 if (needed_size < *pBufferSize)
354 ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
355 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
356 return E_FAIL;
358 *pBufferSize = needed_size;
360 memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
361 IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr);
362 memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample));
364 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
365 return S_OK;
368 static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
370 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
371 CopyRect(pTargetRect,&pVMR9->target_rect);
372 return S_OK;
375 static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
377 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
378 AM_MEDIA_TYPE *pmt;
380 TRACE("(%p/%p)\n", pVMR9, This);
382 pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
383 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
384 return (VIDEOINFOHEADER*)pmt->pbFormat;
385 } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
386 static VIDEOINFOHEADER vih;
387 VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
388 memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
389 memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
390 return &vih;
391 } else {
392 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
393 return NULL;
397 static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
399 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
400 FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
402 return S_OK;
405 static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
407 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
408 FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
410 return S_OK;
413 static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
415 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
417 pVMR9->source_rect.left = 0;
418 pVMR9->source_rect.top = 0;
419 pVMR9->source_rect.right = pVMR9->VideoWidth;
420 pVMR9->source_rect.bottom = pVMR9->VideoHeight;
422 return S_OK;
425 static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
427 RECT rect;
428 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
430 if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
431 return E_FAIL;
433 pVMR9->target_rect.left = 0;
434 pVMR9->target_rect.top = 0;
435 pVMR9->target_rect.right = rect.right;
436 pVMR9->target_rect.bottom = rect.bottom;
438 return S_OK;
441 static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
443 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
444 CopyRect(&pVMR9->source_rect,pSourceRect);
445 return S_OK;
448 static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
450 VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
451 CopyRect(&pVMR9->target_rect,pTargetRect);
452 return S_OK;
455 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
456 VMR9_GetSourceRect,
457 VMR9_GetStaticImage,
458 VMR9_GetTargetRect,
459 VMR9_GetVideoFormat,
460 VMR9_IsDefaultSourceRect,
461 VMR9_IsDefaultTargetRect,
462 VMR9_SetDefaultSourceRect,
463 VMR9_SetDefaultTargetRect,
464 VMR9_SetSourceRect,
465 VMR9_SetTargetRect
468 static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
470 VMR9Impl *This = impl_from_inner_IUnknown(iface);
471 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
473 if (This->bAggregatable)
474 This->bUnkOuterValid = TRUE;
476 *ppv = NULL;
478 if (IsEqualIID(riid, &IID_IUnknown))
479 *ppv = &This->IUnknown_inner;
480 else if (IsEqualIID(riid, &IID_IVideoWindow))
481 *ppv = &This->baseControlWindow.IVideoWindow_iface;
482 else if (IsEqualIID(riid, &IID_IBasicVideo))
483 *ppv = &This->baseControlVideo.IBasicVideo_iface;
484 else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
485 *ppv = &This->IAMFilterMiscFlags_iface;
486 else if (IsEqualIID(riid, &IID_IVMRFilterConfig9))
487 *ppv = &This->IVMRFilterConfig9_iface;
488 else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9) && This->mode == VMR9Mode_Windowless)
489 *ppv = &This->IVMRWindowlessControl9_iface;
490 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9) && This->mode == VMR9Mode_Renderless)
491 *ppv = &This->IVMRSurfaceAllocatorNotify9_iface;
492 else
494 HRESULT hr;
495 hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
496 if (SUCCEEDED(hr))
497 return hr;
500 if (*ppv)
502 IUnknown_AddRef((IUnknown *)(*ppv));
503 return S_OK;
506 else if (IsEqualIID(riid, &IID_IBasicVideo2))
507 FIXME("No interface for IID_IBasicVideo2\n");
508 else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
510 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
512 else if (IsEqualIID(riid, &IID_IMediaPosition))
513 FIXME("No interface for IID_IMediaPosition\n");
514 else if (IsEqualIID(riid, &IID_IQualProp))
515 FIXME("No interface for IID_IQualProp\n");
516 else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
517 FIXME("No interface for IID_IVMRAspectRatioControl9\n");
518 else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
519 FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
520 else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
521 FIXME("No interface for IID_IVMRMixerBitmap9\n");
522 else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
523 FIXME("No interface for IID_IVMRMonitorConfig9\n");
524 else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
525 FIXME("No interface for IID_IVMRMixerControl9\n");
526 else
527 FIXME("No interface for %s\n", debugstr_guid(riid));
529 return E_NOINTERFACE;
532 static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
534 VMR9Impl *This = impl_from_inner_IUnknown(iface);
535 ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
537 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
539 return refCount;
542 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
544 VMR9Impl *This = impl_from_inner_IUnknown(iface);
545 ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
547 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
549 if (!refCount)
551 TRACE("Destroying\n");
552 BaseControlWindow_Destroy(&This->baseControlWindow);
554 if (This->allocator)
555 IVMRSurfaceAllocator9_Release(This->allocator);
556 if (This->presenter)
557 IVMRImagePresenter9_Release(This->presenter);
559 CoTaskMemFree(This);
561 return refCount;
564 static const IUnknownVtbl IInner_VTable =
566 VMR9Inner_QueryInterface,
567 VMR9Inner_AddRef,
568 VMR9Inner_Release
571 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
573 VMR9Impl *This = (VMR9Impl *)iface;
575 if (This->bAggregatable)
576 This->bUnkOuterValid = TRUE;
578 if (This->outer_unk)
580 if (This->bAggregatable)
581 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
583 if (IsEqualIID(riid, &IID_IUnknown))
585 HRESULT hr;
587 IUnknown_AddRef(&This->IUnknown_inner);
588 hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
589 IUnknown_Release(&This->IUnknown_inner);
590 This->bAggregatable = TRUE;
591 return hr;
594 *ppv = NULL;
595 return E_NOINTERFACE;
598 return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
601 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
603 VMR9Impl *This = (VMR9Impl *)iface;
604 LONG ret;
606 if (This->outer_unk && This->bUnkOuterValid)
607 ret = IUnknown_AddRef(This->outer_unk);
608 else
609 ret = IUnknown_AddRef(&This->IUnknown_inner);
611 TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
613 return ret;
616 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
618 VMR9Impl *This = (VMR9Impl *)iface;
619 LONG ret;
621 if (This->outer_unk && This->bUnkOuterValid)
622 ret = IUnknown_Release(This->outer_unk);
623 else
624 ret = IUnknown_Release(&This->IUnknown_inner);
626 TRACE("(%p)->Release from %d\n", iface, ret + 1);
628 if (ret)
629 return ret;
630 return 0;
633 static const IBaseFilterVtbl VMR9_Vtbl =
635 VMR9_QueryInterface,
636 VMR9_AddRef,
637 VMR9_Release,
638 BaseFilterImpl_GetClassID,
639 BaseRendererImpl_Stop,
640 BaseRendererImpl_Pause,
641 BaseRendererImpl_Run,
642 BaseRendererImpl_GetState,
643 BaseRendererImpl_SetSyncSource,
644 BaseFilterImpl_GetSyncSource,
645 BaseFilterImpl_EnumPins,
646 BaseRendererImpl_FindPin,
647 BaseFilterImpl_QueryFilterInfo,
648 BaseFilterImpl_JoinFilterGraph,
649 BaseFilterImpl_QueryVendorInfo
652 /*** IUnknown methods ***/
653 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
655 VMR9Impl *This = impl_from_IVideoWindow(iface);
657 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
659 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
662 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
664 VMR9Impl *This = impl_from_IVideoWindow(iface);
666 TRACE("(%p/%p)->()\n", This, iface);
668 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
671 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
673 VMR9Impl *This = impl_from_IVideoWindow(iface);
675 TRACE("(%p/%p)->()\n", This, iface);
677 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
680 static const IVideoWindowVtbl IVideoWindow_VTable =
682 Videowindow_QueryInterface,
683 Videowindow_AddRef,
684 Videowindow_Release,
685 BaseControlWindowImpl_GetTypeInfoCount,
686 BaseControlWindowImpl_GetTypeInfo,
687 BaseControlWindowImpl_GetIDsOfNames,
688 BaseControlWindowImpl_Invoke,
689 BaseControlWindowImpl_put_Caption,
690 BaseControlWindowImpl_get_Caption,
691 BaseControlWindowImpl_put_WindowStyle,
692 BaseControlWindowImpl_get_WindowStyle,
693 BaseControlWindowImpl_put_WindowStyleEx,
694 BaseControlWindowImpl_get_WindowStyleEx,
695 BaseControlWindowImpl_put_AutoShow,
696 BaseControlWindowImpl_get_AutoShow,
697 BaseControlWindowImpl_put_WindowState,
698 BaseControlWindowImpl_get_WindowState,
699 BaseControlWindowImpl_put_BackgroundPalette,
700 BaseControlWindowImpl_get_BackgroundPalette,
701 BaseControlWindowImpl_put_Visible,
702 BaseControlWindowImpl_get_Visible,
703 BaseControlWindowImpl_put_Left,
704 BaseControlWindowImpl_get_Left,
705 BaseControlWindowImpl_put_Width,
706 BaseControlWindowImpl_get_Width,
707 BaseControlWindowImpl_put_Top,
708 BaseControlWindowImpl_get_Top,
709 BaseControlWindowImpl_put_Height,
710 BaseControlWindowImpl_get_Height,
711 BaseControlWindowImpl_put_Owner,
712 BaseControlWindowImpl_get_Owner,
713 BaseControlWindowImpl_put_MessageDrain,
714 BaseControlWindowImpl_get_MessageDrain,
715 BaseControlWindowImpl_get_BorderColor,
716 BaseControlWindowImpl_put_BorderColor,
717 BaseControlWindowImpl_get_FullScreenMode,
718 BaseControlWindowImpl_put_FullScreenMode,
719 BaseControlWindowImpl_SetWindowForeground,
720 BaseControlWindowImpl_NotifyOwnerMessage,
721 BaseControlWindowImpl_SetWindowPosition,
722 BaseControlWindowImpl_GetWindowPosition,
723 BaseControlWindowImpl_GetMinIdealImageSize,
724 BaseControlWindowImpl_GetMaxIdealImageSize,
725 BaseControlWindowImpl_GetRestorePosition,
726 BaseControlWindowImpl_HideCursor,
727 BaseControlWindowImpl_IsCursorHidden
730 /*** IUnknown methods ***/
731 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
733 VMR9Impl *This = impl_from_IBasicVideo(iface);
735 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
737 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
740 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
742 VMR9Impl *This = impl_from_IBasicVideo(iface);
744 TRACE("(%p/%p)->()\n", This, iface);
746 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
749 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
751 VMR9Impl *This = impl_from_IBasicVideo(iface);
753 TRACE("(%p/%p)->()\n", This, iface);
755 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
758 static const IBasicVideoVtbl IBasicVideo_VTable =
760 Basicvideo_QueryInterface,
761 Basicvideo_AddRef,
762 Basicvideo_Release,
763 BaseControlVideoImpl_GetTypeInfoCount,
764 BaseControlVideoImpl_GetTypeInfo,
765 BaseControlVideoImpl_GetIDsOfNames,
766 BaseControlVideoImpl_Invoke,
767 BaseControlVideoImpl_get_AvgTimePerFrame,
768 BaseControlVideoImpl_get_BitRate,
769 BaseControlVideoImpl_get_BitErrorRate,
770 BaseControlVideoImpl_get_VideoWidth,
771 BaseControlVideoImpl_get_VideoHeight,
772 BaseControlVideoImpl_put_SourceLeft,
773 BaseControlVideoImpl_get_SourceLeft,
774 BaseControlVideoImpl_put_SourceWidth,
775 BaseControlVideoImpl_get_SourceWidth,
776 BaseControlVideoImpl_put_SourceTop,
777 BaseControlVideoImpl_get_SourceTop,
778 BaseControlVideoImpl_put_SourceHeight,
779 BaseControlVideoImpl_get_SourceHeight,
780 BaseControlVideoImpl_put_DestinationLeft,
781 BaseControlVideoImpl_get_DestinationLeft,
782 BaseControlVideoImpl_put_DestinationWidth,
783 BaseControlVideoImpl_get_DestinationWidth,
784 BaseControlVideoImpl_put_DestinationTop,
785 BaseControlVideoImpl_get_DestinationTop,
786 BaseControlVideoImpl_put_DestinationHeight,
787 BaseControlVideoImpl_get_DestinationHeight,
788 BaseControlVideoImpl_SetSourcePosition,
789 BaseControlVideoImpl_GetSourcePosition,
790 BaseControlVideoImpl_SetDefaultSourcePosition,
791 BaseControlVideoImpl_SetDestinationPosition,
792 BaseControlVideoImpl_GetDestinationPosition,
793 BaseControlVideoImpl_SetDefaultDestinationPosition,
794 BaseControlVideoImpl_GetVideoSize,
795 BaseControlVideoImpl_GetVideoPaletteEntries,
796 BaseControlVideoImpl_GetCurrentImage,
797 BaseControlVideoImpl_IsUsingDefaultSource,
798 BaseControlVideoImpl_IsUsingDefaultDestination
801 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
802 VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
803 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
806 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
807 VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
808 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
811 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
812 VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
813 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
816 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
817 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
820 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
821 AMFilterMiscFlags_QueryInterface,
822 AMFilterMiscFlags_AddRef,
823 AMFilterMiscFlags_Release,
824 AMFilterMiscFlags_GetMiscFlags
827 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
829 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
830 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
833 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
835 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
836 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
839 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
841 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
842 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
845 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
847 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
849 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
850 return E_NOTIMPL;
853 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max)
855 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
857 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
858 return E_NOTIMPL;
861 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
863 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
865 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
866 return E_NOTIMPL;
869 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
871 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
873 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
874 return E_NOTIMPL;
877 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
879 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
881 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
882 return E_NOTIMPL;
885 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
887 HRESULT hr = S_OK;
888 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
890 TRACE("(%p/%p)->(%u)\n", iface, This, mode);
892 EnterCriticalSection(&This->renderer.filter.csFilter);
893 if (This->mode)
895 LeaveCriticalSection(&This->renderer.filter.csFilter);
896 return VFW_E_WRONG_STATE;
899 if (This->allocator)
900 IVMRSurfaceAllocator9_Release(This->allocator);
901 if (This->presenter)
902 IVMRImagePresenter9_Release(This->presenter);
904 This->allocator = NULL;
905 This->presenter = NULL;
907 switch (mode)
909 case VMR9Mode_Windowed:
910 case VMR9Mode_Windowless:
911 This->allocator_is_ex = 0;
912 This->cookie = ~0;
914 hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter);
915 if (SUCCEEDED(hr))
916 hr = IVMRImagePresenter9_QueryInterface(This->presenter, &IID_IVMRSurfaceAllocatorEx9, (LPVOID*)&This->allocator);
917 if (FAILED(hr))
919 ERR("Unable to find Presenter interface\n");
920 IVMRSurfaceAllocatorEx9_Release(This->presenter);
921 This->allocator = NULL;
922 This->presenter = NULL;
924 else
925 hr = IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
926 break;
927 case VMR9Mode_Renderless:
928 break;
929 default:
930 LeaveCriticalSection(&This->renderer.filter.csFilter);
931 return E_INVALIDARG;
934 This->mode = mode;
935 LeaveCriticalSection(&This->renderer.filter.csFilter);
936 return hr;
939 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
941 VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
943 TRACE("(%p/%p)->(%p) stub\n", iface, This, mode);
944 if (!mode)
945 return E_POINTER;
947 if (This->mode)
948 *mode = This->mode;
949 else
950 *mode = VMR9Mode_Windowed;
952 return S_OK;
955 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
957 VMR9FilterConfig_QueryInterface,
958 VMR9FilterConfig_AddRef,
959 VMR9FilterConfig_Release,
960 VMR9FilterConfig_SetImageCompositor,
961 VMR9FilterConfig_SetNumberOfStreams,
962 VMR9FilterConfig_GetNumberOfStreams,
963 VMR9FilterConfig_SetRenderingPrefs,
964 VMR9FilterConfig_GetRenderingPrefs,
965 VMR9FilterConfig_SetRenderingMode,
966 VMR9FilterConfig_GetRenderingMode
969 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
971 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
972 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
975 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
977 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
978 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
981 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
983 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
984 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
987 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
989 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
990 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
992 if (!width || !height || !arwidth || !arheight)
994 ERR("Got no pointer\n");
995 return E_POINTER;
998 *width = This->bmiheader.biWidth;
999 *height = This->bmiheader.biHeight;
1000 *arwidth = This->bmiheader.biWidth;
1001 *arheight = This->bmiheader.biHeight;
1003 return S_OK;
1006 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1008 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1010 FIXME("(%p/%p)->(...) stub\n", iface, This);
1011 return E_NOTIMPL;
1014 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1016 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1018 FIXME("(%p/%p)->(...) stub\n", iface, This);
1019 return E_NOTIMPL;
1022 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
1024 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1026 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1028 EnterCriticalSection(&This->renderer.filter.csFilter);
1030 if (source)
1031 This->source_rect = *source;
1032 if (dest)
1034 This->target_rect = *dest;
1035 if (This->baseControlWindow.baseWindow.hWnd)
1037 FIXME("Output rectangle: starting at %dx%d, up to point %dx%d\n", dest->left, dest->top, dest->right, dest->bottom);
1038 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
1039 dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
1043 LeaveCriticalSection(&This->renderer.filter.csFilter);
1045 return S_OK;
1048 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
1050 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1052 if (source)
1053 *source = This->source_rect;
1055 if (dest)
1056 *dest = This->target_rect;
1058 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1059 return S_OK;
1062 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1064 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1066 FIXME("(%p/%p)->(...) stub\n", iface, This);
1067 return E_NOTIMPL;
1070 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1072 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1074 FIXME("(%p/%p)->(...) stub\n", iface, This);
1075 return E_NOTIMPL;
1078 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
1080 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1082 TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
1084 EnterCriticalSection(&This->renderer.filter.csFilter);
1085 This->hWndClippingWindow = hwnd;
1086 if (!hwnd)
1087 IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
1088 LeaveCriticalSection(&This->renderer.filter.csFilter);
1089 return S_OK;
1092 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1094 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1096 FIXME("(%p/%p)->(...) stub\n", iface, This);
1097 return E_NOTIMPL;
1100 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1102 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1104 FIXME("(%p/%p)->(...) stub\n", iface, This);
1105 return E_NOTIMPL;
1108 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1110 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1112 FIXME("(%p/%p)->(...) stub\n", iface, This);
1113 return E_NOTIMPL;
1116 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1118 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1120 FIXME("(%p/%p)->(...) stub\n", iface, This);
1121 return E_NOTIMPL;
1124 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1126 VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1128 FIXME("(%p/%p)->(...) stub\n", iface, This);
1129 return E_NOTIMPL;
1132 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1134 VMR9WindowlessControl_QueryInterface,
1135 VMR9WindowlessControl_AddRef,
1136 VMR9WindowlessControl_Release,
1137 VMR9WindowlessControl_GetNativeVideoSize,
1138 VMR9WindowlessControl_GetMinIdealVideoSize,
1139 VMR9WindowlessControl_GetMaxIdealVideoSize,
1140 VMR9WindowlessControl_SetVideoPosition,
1141 VMR9WindowlessControl_GetVideoPosition,
1142 VMR9WindowlessControl_GetAspectRatioMode,
1143 VMR9WindowlessControl_SetAspectRatioMode,
1144 VMR9WindowlessControl_SetVideoClippingWindow,
1145 VMR9WindowlessControl_RepaintVideo,
1146 VMR9WindowlessControl_DisplayModeChanged,
1147 VMR9WindowlessControl_GetCurrentImage,
1148 VMR9WindowlessControl_SetBorderColor,
1149 VMR9WindowlessControl_GetBorderColor
1152 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1154 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1155 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1158 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1160 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1161 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1164 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1166 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1167 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1170 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
1172 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1174 /* FIXME: This code is not tested!!! */
1175 FIXME("(%p/%p)->(...) stub\n", iface, This);
1176 This->cookie = id;
1178 if (This->presenter)
1179 return VFW_E_WRONG_STATE;
1181 if (FAILED(IUnknown_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
1182 return E_NOINTERFACE;
1184 if (SUCCEEDED(IUnknown_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
1185 This->allocator_is_ex = 1;
1186 else
1188 This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
1189 IUnknown_AddRef(alloc);
1190 This->allocator_is_ex = 0;
1193 return S_OK;
1196 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1198 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1200 FIXME("(%p/%p)->(...) stub\n", iface, This);
1201 return E_NOTIMPL;
1204 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1206 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1208 FIXME("(%p/%p)->(...) stub\n", iface, This);
1209 return E_NOTIMPL;
1212 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
1214 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1216 FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
1218 if (!allocinfo || !numbuffers || !surface)
1219 return E_POINTER;
1221 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
1223 ERR("Invalid number of buffers?\n");
1224 return E_INVALIDARG;
1227 return E_NOTIMPL;
1230 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
1232 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1234 FIXME("(%p/%p)->(...) stub\n", iface, This);
1235 return E_NOTIMPL;
1238 static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl =
1240 VMR9SurfaceAllocatorNotify_QueryInterface,
1241 VMR9SurfaceAllocatorNotify_AddRef,
1242 VMR9SurfaceAllocatorNotify_Release,
1243 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1244 VMR9SurfaceAllocatorNotify_SetD3DDevice,
1245 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
1246 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
1247 VMR9SurfaceAllocatorNotify_NotifyEvent
1250 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
1252 HRESULT hr;
1253 VMR9Impl * pVMR9;
1255 TRACE("(%p, %p)\n", outer_unk, ppv);
1257 *ppv = NULL;
1259 pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
1261 pVMR9->outer_unk = outer_unk;
1262 pVMR9->bUnkOuterValid = FALSE;
1263 pVMR9->bAggregatable = FALSE;
1264 pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
1265 pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1267 pVMR9->mode = 0;
1268 pVMR9->allocator = NULL;
1269 pVMR9->presenter = NULL;
1270 pVMR9->hWndClippingWindow = NULL;
1271 pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
1272 pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
1273 pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl;
1275 hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
1276 if (FAILED(hr))
1277 goto fail;
1279 hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1280 if (FAILED(hr))
1281 goto fail;
1283 hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1284 if (FAILED(hr))
1285 goto fail;
1287 *ppv = (LPVOID)pVMR9;
1288 ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
1289 ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
1290 TRACE("Created at %p\n", pVMR9);
1291 return hr;
1293 fail:
1294 BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
1295 CoTaskMemFree(pVMR9);
1296 return hr;
1301 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, LPVOID * ppv)
1303 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1304 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
1306 *ppv = NULL;
1308 if (IsEqualIID(riid, &IID_IUnknown))
1309 *ppv = (LPVOID)&(This->IVMRImagePresenter9_iface);
1310 else if (IsEqualIID(riid, &IID_IVMRImagePresenter9))
1311 *ppv = &This->IVMRImagePresenter9_iface;
1313 if (*ppv)
1315 IUnknown_AddRef((IUnknown *)(*ppv));
1316 return S_OK;
1319 FIXME("No interface for %s\n", debugstr_guid(riid));
1321 return E_NOINTERFACE;
1324 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
1326 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1327 ULONG refCount = InterlockedIncrement(&This->refCount);
1329 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
1331 return refCount;
1334 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
1336 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1337 ULONG refCount = InterlockedDecrement(&This->refCount);
1339 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
1341 if (!refCount)
1343 TRACE("Destroying\n");
1344 IUnknown_Release(This->d3d9_ptr);
1346 if (This->d3d9_vertex)
1348 IUnknown_Release(This->d3d9_vertex);
1349 This->d3d9_vertex = NULL;
1351 CoTaskMemFree(This);
1352 return 0;
1354 return refCount;
1357 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
1359 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1361 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
1362 return S_OK;
1365 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
1367 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1369 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
1370 return S_OK;
1373 #define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
1374 struct VERTEX { float x, y, z, rhw, u, v; };
1376 static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
1378 IDirect3DTexture9 *texture = NULL;
1379 HRESULT hr;
1381 hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF);
1382 if (FAILED(hr))
1384 FIXME("SetFVF: %08x\n", hr);
1385 return hr;
1388 hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX));
1389 if (FAILED(hr))
1391 FIXME("SetStreamSource: %08x\n", hr);
1392 return hr;
1395 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture);
1396 if (FAILED(hr))
1398 FIXME("IDirect3DSurface9_GetContainer failed\n");
1399 return hr;
1401 hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture);
1402 IDirect3DTexture9_Release(texture);
1403 if (FAILED(hr))
1405 FIXME("SetTexture: %08x\n", hr);
1406 return hr;
1409 hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2);
1410 if (FAILED(hr))
1412 FIXME("DrawPrimitive: %08x\n", hr);
1413 return hr;
1416 return S_OK;
1419 static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
1421 HRESULT hr;
1422 IDirect3DSurface9 *target = NULL;
1423 RECT target_rect;
1425 hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target);
1426 if (FAILED(hr))
1428 ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr);
1429 return hr;
1432 target_rect = This->pVMR9->target_rect;
1433 target_rect.right -= target_rect.left;
1434 target_rect.bottom -= target_rect.top;
1435 target_rect.left = target_rect.top = 0;
1437 /* Flip */
1438 target_rect.top = target_rect.bottom;
1439 target_rect.bottom = 0;
1441 hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR);
1442 if (FAILED(hr))
1443 ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr);
1444 IDirect3DSurface9_Release(target);
1446 return hr;
1449 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info)
1451 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1452 HRESULT hr;
1453 RECT output;
1454 BOOL render = FALSE;
1456 TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9);
1457 GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output);
1458 TRACE("Output rectangle: starting at %dx%d, up to point %dx%d\n", output.left, output.top, output.right, output.bottom);
1460 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
1461 if (!This->d3d9_dev)
1462 return S_OK;
1464 /* Display image here */
1465 hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
1466 if (FAILED(hr))
1467 FIXME("hr: %08x\n", hr);
1468 hr = IDirect3DDevice9_BeginScene(This->d3d9_dev);
1469 if (SUCCEEDED(hr))
1471 if (This->d3d9_vertex)
1472 hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf);
1473 else
1474 hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf);
1475 render = SUCCEEDED(hr);
1477 else
1478 FIXME("BeginScene: %08x\n", hr);
1479 hr = IDirect3DDevice9_EndScene(This->d3d9_dev);
1480 if (render && SUCCEEDED(hr))
1482 hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL);
1483 if (FAILED(hr))
1484 FIXME("Presenting image: %08x\n", hr);
1487 return S_OK;
1490 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
1492 VMR9_ImagePresenter_QueryInterface,
1493 VMR9_ImagePresenter_AddRef,
1494 VMR9_ImagePresenter_Release,
1495 VMR9_ImagePresenter_StartPresenting,
1496 VMR9_ImagePresenter_StopPresenting,
1497 VMR9_ImagePresenter_PresentImage
1500 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv)
1502 HRESULT hr = S_OK;
1503 int i;
1504 VMR9DefaultAllocatorPresenterImpl* This;
1506 This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl));
1507 if (!This)
1508 return E_OUTOFMEMORY;
1510 This->d3d9_ptr = NULL;
1511 if (!This->d3d9_ptr)
1513 WARN("Could not initialize d3d9.dll\n");
1514 CoTaskMemFree(This);
1515 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
1518 i = 0;
1521 D3DDISPLAYMODE mode;
1523 hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
1524 } while (FAILED(hr));
1525 if (FAILED(hr))
1526 ERR("HR: %08x\n", hr);
1527 if (hr == D3DERR_NOTAVAILABLE)
1529 ERR("Format not supported\n");
1530 IUnknown_Release(This->d3d9_ptr);
1531 CoTaskMemFree(This);
1532 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
1535 This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
1537 This->refCount = 1;
1538 This->pVMR9 = parent;
1539 This->d3d9_dev = NULL;
1540 This->d3d9_vertex = NULL;
1542 *ppv = This;
1543 return S_OK;