d3drm: Implement IDirect3DRMMesh_AddGroup.
[wine] / dlls / quartz / vmr9.c
1 /*
2  * Video Mixing Renderer for dx9
3  *
4  * Copyright 2004 Christian Costa
5  * Copyright 2008 Maarten Lankhorst
6  * Copyright 2012 Aric Stewart
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include "config.h"
24
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "quartz_private.h"
28
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"
42
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
47
48 typedef struct
49 {
50     BaseRenderer renderer;
51     BaseControlWindow baseControlWindow;
52     BaseControlVideo baseControlVideo;
53
54     IUnknown IUnknown_inner;
55     IAMFilterMiscFlags IAMFilterMiscFlags_iface;
56     IVMRFilterConfig9 IVMRFilterConfig9_iface;
57     IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
58     IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
59
60     IVMRSurfaceAllocatorEx9 *allocator;
61     IVMRImagePresenter9 *presenter;
62     BOOL allocator_is_ex;
63
64     VMR9Mode mode;
65     BITMAPINFOHEADER bmiheader;
66     IUnknown * outer_unk;
67     BOOL bUnkOuterValid;
68     BOOL bAggregatable;
69
70     DWORD_PTR cookie;
71
72     /* for Windowless Mode */
73     HWND hWndClippingWindow;
74
75     RECT source_rect;
76     RECT target_rect;
77     LONG VideoWidth;
78     LONG VideoHeight;
79 } VMR9Impl;
80
81 static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface)
82 {
83     return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner);
84 }
85
86 static inline VMR9Impl *impl_from_BaseWindow( BaseWindow *wnd )
87 {
88     return CONTAINING_RECORD(wnd, VMR9Impl, baseControlWindow.baseWindow);
89 }
90
91 static inline VMR9Impl *impl_from_IVideoWindow( IVideoWindow *iface)
92 {
93     return CONTAINING_RECORD(iface, VMR9Impl, baseControlWindow.IVideoWindow_iface);
94 }
95
96 static inline VMR9Impl *impl_from_BaseControlVideo( BaseControlVideo *cvid )
97 {
98     return CONTAINING_RECORD(cvid, VMR9Impl, baseControlVideo);
99 }
100
101 static inline VMR9Impl *impl_from_IBasicVideo( IBasicVideo *iface)
102 {
103     return CONTAINING_RECORD(iface, VMR9Impl, baseControlVideo.IBasicVideo_iface);
104 }
105
106 static inline VMR9Impl *impl_from_IAMFilterMiscFlags( IAMFilterMiscFlags *iface)
107 {
108     return CONTAINING_RECORD(iface, VMR9Impl, IAMFilterMiscFlags_iface);
109 }
110
111 static inline VMR9Impl *impl_from_IVMRFilterConfig9( IVMRFilterConfig9 *iface)
112 {
113     return CONTAINING_RECORD(iface, VMR9Impl, IVMRFilterConfig9_iface);
114 }
115
116 static inline VMR9Impl *impl_from_IVMRWindowlessControl9( IVMRWindowlessControl9 *iface)
117 {
118     return CONTAINING_RECORD(iface, VMR9Impl, IVMRWindowlessControl9_iface);
119 }
120
121 static inline VMR9Impl *impl_from_IVMRSurfaceAllocatorNotify9( IVMRSurfaceAllocatorNotify9 *iface)
122 {
123     return CONTAINING_RECORD(iface, VMR9Impl, IVMRSurfaceAllocatorNotify9_iface);
124 }
125
126 static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
127 {
128     VMR9Impl *This = (VMR9Impl *)iface;
129     LPBYTE pbSrcStream = NULL;
130     REFERENCE_TIME tStart, tStop;
131     VMR9PresentationInfo info;
132     HRESULT hr;
133
134     TRACE("%p %p\n", iface, pSample);
135
136     hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
137     if (FAILED(hr))
138         info.dwFlags = VMR9Sample_SrcDstRectsValid;
139     else
140         info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
141
142     if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
143         info.dwFlags |= VMR9Sample_Discontinuity;
144
145     if (IMediaSample_IsPreroll(pSample) == S_OK)
146         info.dwFlags |= VMR9Sample_Preroll;
147
148     if (IMediaSample_IsSyncPoint(pSample) == S_OK)
149         info.dwFlags |= VMR9Sample_SyncPoint;
150
151     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
152     if (FAILED(hr))
153     {
154         ERR("Cannot get pointer to sample data (%x)\n", hr);
155         return hr;
156     }
157
158     info.rtStart = tStart;
159     info.rtEnd = tStop;
160     info.szAspectRatio.cx = This->bmiheader.biWidth;
161     info.szAspectRatio.cy = This->bmiheader.biHeight;
162
163     return hr;
164 }
165
166 static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
167 {
168     VMR9Impl *This = (VMR9Impl*)iface;
169
170     if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
171         return S_FALSE;
172
173     /* Ignore subtype, test for bicompression instead */
174     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
175     {
176         VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
177
178         This->bmiheader = format->bmiHeader;
179         TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
180         This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
181         This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
182         This->source_rect.top = This->source_rect.left = 0;
183     }
184     else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
185     {
186         VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
187
188         This->bmiheader = format->bmiHeader;
189
190         TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
191         This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
192         This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
193         This->source_rect.top = This->source_rect.left = 0;
194     }
195     else
196     {
197         ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
198         return S_FALSE;
199     }
200     if (This->bmiheader.biCompression)
201         return S_FALSE;
202     return S_OK;
203 }
204
205 static HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
206 {
207     /* Preroll means the sample isn't shown, this is used for key frames and things like that */
208     if (IMediaSample_IsPreroll(pSample) == S_OK)
209         return E_FAIL;
210     return S_FALSE;
211 }
212
213 static const BaseRendererFuncTable BaseFuncTable = {
214     VMR9_CheckMediaType,
215     VMR9_DoRenderSample,
216     /**/
217     NULL,
218     NULL,
219     NULL,
220     NULL,
221     NULL,
222     NULL,
223     NULL,
224     NULL,
225     VMR9_ShouldDrawSampleNow,
226     NULL,
227     /**/
228     NULL,
229     NULL,
230     NULL,
231     NULL,
232     NULL,
233 };
234
235 static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
236 {
237     static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 };
238
239     *pClassStyles = 0;
240     *pWindowStyles = WS_SIZEBOX;
241     *pWindowStylesEx = 0;
242
243     return classnameW;
244 }
245
246 static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
247 {
248     VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
249     static RECT defRect;
250
251     defRect.left = defRect.top = 0;
252     defRect.right = pVMR9->VideoWidth;
253     defRect.bottom = pVMR9->VideoHeight;
254
255     return defRect;
256 }
257
258 static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
259 {
260     VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
261
262     TRACE("WM_SIZE %d %d\n", Width, Height);
263     GetClientRect(This->hWnd, &pVMR9->target_rect);
264     TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
265         pVMR9->target_rect.left,
266         pVMR9->target_rect.top,
267         pVMR9->target_rect.right - pVMR9->target_rect.left,
268         pVMR9->target_rect.bottom - pVMR9->target_rect.top);
269     return BaseWindowImpl_OnSize(This, Width, Height);
270 }
271
272 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
273     VMR9_GetClassWindowStyles,
274     VMR9_GetDefaultRect,
275     NULL,
276     BaseControlWindowImpl_PossiblyEatMessage,
277     VMR9_OnSize,
278 };
279
280 static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
281 {
282     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
283     CopyRect(pSourceRect,&pVMR9->source_rect);
284     return S_OK;
285 }
286
287 static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage)
288 {
289     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
290     BITMAPINFOHEADER *bmiHeader;
291     LONG needed_size;
292     AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
293     char *ptr;
294
295     FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage);
296
297     EnterCriticalSection(&pVMR9->renderer.filter.csFilter);
298
299     if (!pVMR9->renderer.pMediaSample)
300     {
301          LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
302          return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
303     }
304
305     if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
306     {
307         bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
308     }
309     else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
310     {
311         bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
312     }
313     else
314     {
315         FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
316         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
317         return VFW_E_RUNTIME_ERROR;
318     }
319
320     needed_size = bmiHeader->biSize;
321     needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample);
322
323     if (!pDIBImage)
324     {
325         *pBufferSize = needed_size;
326         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
327         return S_OK;
328     }
329
330     if (needed_size < *pBufferSize)
331     {
332         ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
333         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
334         return E_FAIL;
335     }
336     *pBufferSize = needed_size;
337
338     memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
339     IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr);
340     memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample));
341
342     LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
343     return S_OK;
344 }
345
346 static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
347 {
348     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
349     CopyRect(pTargetRect,&pVMR9->target_rect);
350     return S_OK;
351 }
352
353 static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
354 {
355     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
356     AM_MEDIA_TYPE *pmt;
357
358     TRACE("(%p/%p)\n", pVMR9, This);
359
360     pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
361     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
362         return (VIDEOINFOHEADER*)pmt->pbFormat;
363     } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
364         static VIDEOINFOHEADER vih;
365         VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
366         memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
367         memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
368         return &vih;
369     } else {
370         ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
371         return NULL;
372     }
373 }
374
375 static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
376 {
377     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
378     FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
379
380     return S_OK;
381 }
382
383 static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
384 {
385     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
386     FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
387
388     return S_OK;
389 }
390
391 static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
392 {
393     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
394
395     pVMR9->source_rect.left = 0;
396     pVMR9->source_rect.top = 0;
397     pVMR9->source_rect.right = pVMR9->VideoWidth;
398     pVMR9->source_rect.bottom = pVMR9->VideoHeight;
399
400     return S_OK;
401 }
402
403 static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
404 {
405     RECT rect;
406     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
407
408     if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
409         return E_FAIL;
410
411     pVMR9->target_rect.left = 0;
412     pVMR9->target_rect.top = 0;
413     pVMR9->target_rect.right = rect.right;
414     pVMR9->target_rect.bottom = rect.bottom;
415
416     return S_OK;
417 }
418
419 static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
420 {
421     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
422     CopyRect(&pVMR9->source_rect,pSourceRect);
423     return S_OK;
424 }
425
426 static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
427 {
428     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
429     CopyRect(&pVMR9->target_rect,pTargetRect);
430     return S_OK;
431 }
432
433 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
434     VMR9_GetSourceRect,
435     VMR9_GetStaticImage,
436     VMR9_GetTargetRect,
437     VMR9_GetVideoFormat,
438     VMR9_IsDefaultSourceRect,
439     VMR9_IsDefaultTargetRect,
440     VMR9_SetDefaultSourceRect,
441     VMR9_SetDefaultTargetRect,
442     VMR9_SetSourceRect,
443     VMR9_SetTargetRect
444 };
445
446 static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
447 {
448     VMR9Impl *This = impl_from_inner_IUnknown(iface);
449     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
450
451     if (This->bAggregatable)
452         This->bUnkOuterValid = TRUE;
453
454     *ppv = NULL;
455
456     if (IsEqualIID(riid, &IID_IUnknown))
457         *ppv = &This->IUnknown_inner;
458     else if (IsEqualIID(riid, &IID_IVideoWindow))
459         *ppv = &This->baseControlWindow.IVideoWindow_iface;
460     else if (IsEqualIID(riid, &IID_IBasicVideo))
461         *ppv = &This->baseControlVideo.IBasicVideo_iface;
462     else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
463         *ppv = &This->IAMFilterMiscFlags_iface;
464     else if (IsEqualIID(riid, &IID_IVMRFilterConfig9))
465         *ppv = &This->IVMRFilterConfig9_iface;
466     else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9) && This->mode == VMR9Mode_Windowless)
467         *ppv = &This->IVMRWindowlessControl9_iface;
468     else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9) && This->mode == VMR9Mode_Renderless)
469         *ppv = &This->IVMRSurfaceAllocatorNotify9_iface;
470     else
471     {
472         HRESULT hr;
473         hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
474         if (SUCCEEDED(hr))
475             return hr;
476     }
477
478     if (*ppv)
479     {
480         IUnknown_AddRef((IUnknown *)(*ppv));
481         return S_OK;
482     }
483
484     else if (IsEqualIID(riid, &IID_IBasicVideo2))
485         FIXME("No interface for IID_IBasicVideo2\n");
486     else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
487         ;
488     else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
489         ;
490     else if (IsEqualIID(riid, &IID_IMediaPosition))
491         FIXME("No interface for IID_IMediaPosition\n");
492     else if (IsEqualIID(riid, &IID_IQualProp))
493         FIXME("No interface for IID_IQualProp\n");
494     else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
495         FIXME("No interface for IID_IVMRAspectRatioControl9\n");
496     else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
497         FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
498     else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
499         FIXME("No interface for IID_IVMRMixerBitmap9\n");
500     else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
501         FIXME("No interface for IID_IVMRMonitorConfig9\n");
502     else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
503         FIXME("No interface for IID_IVMRMixerControl9\n");
504     else
505         FIXME("No interface for %s\n", debugstr_guid(riid));
506
507     return E_NOINTERFACE;
508 }
509
510 static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
511 {
512     VMR9Impl *This = impl_from_inner_IUnknown(iface);
513     ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
514
515     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
516
517     return refCount;
518 }
519
520 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
521 {
522     VMR9Impl *This = impl_from_inner_IUnknown(iface);
523     ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
524
525     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
526
527     if (!refCount)
528     {
529         TRACE("Destroying\n");
530         BaseControlWindow_Destroy(&This->baseControlWindow);
531
532         if (This->allocator)
533             IVMRSurfaceAllocator9_Release(This->allocator);
534         if (This->presenter)
535             IVMRImagePresenter9_Release(This->presenter);
536
537         CoTaskMemFree(This);
538     }
539     return refCount;
540 }
541
542 static const IUnknownVtbl IInner_VTable =
543 {
544     VMR9Inner_QueryInterface,
545     VMR9Inner_AddRef,
546     VMR9Inner_Release
547 };
548
549 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
550 {
551     VMR9Impl *This = (VMR9Impl *)iface;
552
553     if (This->bAggregatable)
554         This->bUnkOuterValid = TRUE;
555
556     if (This->outer_unk)
557     {
558         if (This->bAggregatable)
559             return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
560
561         if (IsEqualIID(riid, &IID_IUnknown))
562         {
563             HRESULT hr;
564
565             IUnknown_AddRef(&This->IUnknown_inner);
566             hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
567             IUnknown_Release(&This->IUnknown_inner);
568             This->bAggregatable = TRUE;
569             return hr;
570         }
571
572         *ppv = NULL;
573         return E_NOINTERFACE;
574     }
575
576     return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
577 }
578
579 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
580 {
581     VMR9Impl *This = (VMR9Impl *)iface;
582     LONG ret;
583
584     if (This->outer_unk && This->bUnkOuterValid)
585         ret = IUnknown_AddRef(This->outer_unk);
586     else
587         ret = IUnknown_AddRef(&This->IUnknown_inner);
588
589     TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
590
591     return ret;
592 }
593
594 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
595 {
596     VMR9Impl *This = (VMR9Impl *)iface;
597     LONG ret;
598
599     if (This->outer_unk && This->bUnkOuterValid)
600         ret = IUnknown_Release(This->outer_unk);
601     else
602         ret = IUnknown_Release(&This->IUnknown_inner);
603
604     TRACE("(%p)->Release from %d\n", iface, ret + 1);
605
606     if (ret)
607         return ret;
608     return 0;
609 }
610
611 static const IBaseFilterVtbl VMR9_Vtbl =
612 {
613     VMR9_QueryInterface,
614     VMR9_AddRef,
615     VMR9_Release,
616     BaseFilterImpl_GetClassID,
617     BaseRendererImpl_Stop,
618     BaseRendererImpl_Pause,
619     BaseRendererImpl_Run,
620     BaseRendererImpl_GetState,
621     BaseRendererImpl_SetSyncSource,
622     BaseFilterImpl_GetSyncSource,
623     BaseFilterImpl_EnumPins,
624     BaseRendererImpl_FindPin,
625     BaseFilterImpl_QueryFilterInfo,
626     BaseFilterImpl_JoinFilterGraph,
627     BaseFilterImpl_QueryVendorInfo
628 };
629
630 /*** IUnknown methods ***/
631 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
632 {
633     VMR9Impl *This = impl_from_IVideoWindow(iface);
634
635     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
636
637     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
638 }
639
640 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
641 {
642     VMR9Impl *This = impl_from_IVideoWindow(iface);
643
644     TRACE("(%p/%p)->()\n", This, iface);
645
646     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
647 }
648
649 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
650 {
651     VMR9Impl *This = impl_from_IVideoWindow(iface);
652
653     TRACE("(%p/%p)->()\n", This, iface);
654
655     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
656 }
657
658 static const IVideoWindowVtbl IVideoWindow_VTable =
659 {
660     Videowindow_QueryInterface,
661     Videowindow_AddRef,
662     Videowindow_Release,
663     BaseControlWindowImpl_GetTypeInfoCount,
664     BaseControlWindowImpl_GetTypeInfo,
665     BaseControlWindowImpl_GetIDsOfNames,
666     BaseControlWindowImpl_Invoke,
667     BaseControlWindowImpl_put_Caption,
668     BaseControlWindowImpl_get_Caption,
669     BaseControlWindowImpl_put_WindowStyle,
670     BaseControlWindowImpl_get_WindowStyle,
671     BaseControlWindowImpl_put_WindowStyleEx,
672     BaseControlWindowImpl_get_WindowStyleEx,
673     BaseControlWindowImpl_put_AutoShow,
674     BaseControlWindowImpl_get_AutoShow,
675     BaseControlWindowImpl_put_WindowState,
676     BaseControlWindowImpl_get_WindowState,
677     BaseControlWindowImpl_put_BackgroundPalette,
678     BaseControlWindowImpl_get_BackgroundPalette,
679     BaseControlWindowImpl_put_Visible,
680     BaseControlWindowImpl_get_Visible,
681     BaseControlWindowImpl_put_Left,
682     BaseControlWindowImpl_get_Left,
683     BaseControlWindowImpl_put_Width,
684     BaseControlWindowImpl_get_Width,
685     BaseControlWindowImpl_put_Top,
686     BaseControlWindowImpl_get_Top,
687     BaseControlWindowImpl_put_Height,
688     BaseControlWindowImpl_get_Height,
689     BaseControlWindowImpl_put_Owner,
690     BaseControlWindowImpl_get_Owner,
691     BaseControlWindowImpl_put_MessageDrain,
692     BaseControlWindowImpl_get_MessageDrain,
693     BaseControlWindowImpl_get_BorderColor,
694     BaseControlWindowImpl_put_BorderColor,
695     BaseControlWindowImpl_get_FullScreenMode,
696     BaseControlWindowImpl_put_FullScreenMode,
697     BaseControlWindowImpl_SetWindowForeground,
698     BaseControlWindowImpl_NotifyOwnerMessage,
699     BaseControlWindowImpl_SetWindowPosition,
700     BaseControlWindowImpl_GetWindowPosition,
701     BaseControlWindowImpl_GetMinIdealImageSize,
702     BaseControlWindowImpl_GetMaxIdealImageSize,
703     BaseControlWindowImpl_GetRestorePosition,
704     BaseControlWindowImpl_HideCursor,
705     BaseControlWindowImpl_IsCursorHidden
706 };
707
708 /*** IUnknown methods ***/
709 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
710 {
711     VMR9Impl *This = impl_from_IBasicVideo(iface);
712
713     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
714
715     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
716 }
717
718 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
719 {
720     VMR9Impl *This = impl_from_IBasicVideo(iface);
721
722     TRACE("(%p/%p)->()\n", This, iface);
723
724     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
725 }
726
727 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
728 {
729     VMR9Impl *This = impl_from_IBasicVideo(iface);
730
731     TRACE("(%p/%p)->()\n", This, iface);
732
733     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
734 }
735
736 static const IBasicVideoVtbl IBasicVideo_VTable =
737 {
738     Basicvideo_QueryInterface,
739     Basicvideo_AddRef,
740     Basicvideo_Release,
741     BaseControlVideoImpl_GetTypeInfoCount,
742     BaseControlVideoImpl_GetTypeInfo,
743     BaseControlVideoImpl_GetIDsOfNames,
744     BaseControlVideoImpl_Invoke,
745     BaseControlVideoImpl_get_AvgTimePerFrame,
746     BaseControlVideoImpl_get_BitRate,
747     BaseControlVideoImpl_get_BitErrorRate,
748     BaseControlVideoImpl_get_VideoWidth,
749     BaseControlVideoImpl_get_VideoHeight,
750     BaseControlVideoImpl_put_SourceLeft,
751     BaseControlVideoImpl_get_SourceLeft,
752     BaseControlVideoImpl_put_SourceWidth,
753     BaseControlVideoImpl_get_SourceWidth,
754     BaseControlVideoImpl_put_SourceTop,
755     BaseControlVideoImpl_get_SourceTop,
756     BaseControlVideoImpl_put_SourceHeight,
757     BaseControlVideoImpl_get_SourceHeight,
758     BaseControlVideoImpl_put_DestinationLeft,
759     BaseControlVideoImpl_get_DestinationLeft,
760     BaseControlVideoImpl_put_DestinationWidth,
761     BaseControlVideoImpl_get_DestinationWidth,
762     BaseControlVideoImpl_put_DestinationTop,
763     BaseControlVideoImpl_get_DestinationTop,
764     BaseControlVideoImpl_put_DestinationHeight,
765     BaseControlVideoImpl_get_DestinationHeight,
766     BaseControlVideoImpl_SetSourcePosition,
767     BaseControlVideoImpl_GetSourcePosition,
768     BaseControlVideoImpl_SetDefaultSourcePosition,
769     BaseControlVideoImpl_SetDestinationPosition,
770     BaseControlVideoImpl_GetDestinationPosition,
771     BaseControlVideoImpl_SetDefaultDestinationPosition,
772     BaseControlVideoImpl_GetVideoSize,
773     BaseControlVideoImpl_GetVideoPaletteEntries,
774     BaseControlVideoImpl_GetCurrentImage,
775     BaseControlVideoImpl_IsUsingDefaultSource,
776     BaseControlVideoImpl_IsUsingDefaultDestination
777 };
778
779 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
780     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
781     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
782 }
783
784 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
785     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
786     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
787 }
788
789 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
790     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
791     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
792 }
793
794 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
795     return AM_FILTER_MISC_FLAGS_IS_RENDERER;
796 }
797
798 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
799     AMFilterMiscFlags_QueryInterface,
800     AMFilterMiscFlags_AddRef,
801     AMFilterMiscFlags_Release,
802     AMFilterMiscFlags_GetMiscFlags
803 };
804
805 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
806 {
807     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
808     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
809 }
810
811 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
812 {
813     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
814     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
815 }
816
817 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
818 {
819     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
820     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
821 }
822
823 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
824 {
825     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
826
827     FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
828     return E_NOTIMPL;
829 }
830
831 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max)
832 {
833     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
834
835     FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
836     return E_NOTIMPL;
837 }
838
839 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
840 {
841     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
842
843     FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
844     return E_NOTIMPL;
845 }
846
847 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
848 {
849     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
850
851     FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
852     return E_NOTIMPL;
853 }
854
855 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
856 {
857     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
858
859     FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
860     return E_NOTIMPL;
861 }
862
863 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
864 {
865     HRESULT hr = S_OK;
866     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
867
868     TRACE("(%p/%p)->(%u)\n", iface, This, mode);
869
870     EnterCriticalSection(&This->renderer.filter.csFilter);
871     if (This->mode)
872     {
873         LeaveCriticalSection(&This->renderer.filter.csFilter);
874         return VFW_E_WRONG_STATE;
875     }
876
877     if (This->allocator)
878         IVMRSurfaceAllocator9_Release(This->allocator);
879     if (This->presenter)
880         IVMRImagePresenter9_Release(This->presenter);
881
882     This->allocator = NULL;
883     This->presenter = NULL;
884
885     switch (mode)
886     {
887     case VMR9Mode_Windowed:
888     case VMR9Mode_Windowless:
889         This->allocator = NULL;
890         This->presenter = NULL;
891         This->allocator_is_ex = 0;
892         This->cookie = ~0;
893         break;
894     case VMR9Mode_Renderless:
895         break;
896     default:
897         LeaveCriticalSection(&This->renderer.filter.csFilter);
898         return E_INVALIDARG;
899     }
900
901     This->mode = mode;
902     LeaveCriticalSection(&This->renderer.filter.csFilter);
903     return hr;
904 }
905
906 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
907 {
908     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
909
910     TRACE("(%p/%p)->(%p) stub\n", iface, This, mode);
911     if (!mode)
912         return E_POINTER;
913
914     if (This->mode)
915         *mode = This->mode;
916     else
917         *mode = VMR9Mode_Windowed;
918
919     return S_OK;
920 }
921
922 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
923 {
924     VMR9FilterConfig_QueryInterface,
925     VMR9FilterConfig_AddRef,
926     VMR9FilterConfig_Release,
927     VMR9FilterConfig_SetImageCompositor,
928     VMR9FilterConfig_SetNumberOfStreams,
929     VMR9FilterConfig_GetNumberOfStreams,
930     VMR9FilterConfig_SetRenderingPrefs,
931     VMR9FilterConfig_GetRenderingPrefs,
932     VMR9FilterConfig_SetRenderingMode,
933     VMR9FilterConfig_GetRenderingMode
934 };
935
936 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
937 {
938     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
939     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
940 }
941
942 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
943 {
944     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
945     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
946 }
947
948 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
949 {
950     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
951     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
952 }
953
954 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
955 {
956     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
957     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
958
959     if (!width || !height || !arwidth || !arheight)
960     {
961         ERR("Got no pointer\n");
962         return E_POINTER;
963     }
964
965     *width = This->bmiheader.biWidth;
966     *height = This->bmiheader.biHeight;
967     *arwidth = This->bmiheader.biWidth;
968     *arheight = This->bmiheader.biHeight;
969
970     return S_OK;
971 }
972
973 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
974 {
975     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
976
977     FIXME("(%p/%p)->(...) stub\n", iface, This);
978     return E_NOTIMPL;
979 }
980
981 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
982 {
983     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
984
985     FIXME("(%p/%p)->(...) stub\n", iface, This);
986     return E_NOTIMPL;
987 }
988
989 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
990 {
991     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
992
993     TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
994
995     EnterCriticalSection(&This->renderer.filter.csFilter);
996
997     if (source)
998         This->source_rect = *source;
999     if (dest)
1000     {
1001         This->target_rect = *dest;
1002         if (This->baseControlWindow.baseWindow.hWnd)
1003         {
1004             FIXME("Output rectangle: starting at %dx%d, up to point %dx%d\n", dest->left, dest->top, dest->right, dest->bottom);
1005             SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
1006                          dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
1007         }
1008     }
1009
1010     LeaveCriticalSection(&This->renderer.filter.csFilter);
1011
1012     return S_OK;
1013 }
1014
1015 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
1016 {
1017     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1018
1019     if (source)
1020         *source = This->source_rect;
1021
1022     if (dest)
1023         *dest = This->target_rect;
1024
1025     FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1026     return S_OK;
1027 }
1028
1029 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1030 {
1031     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1032
1033     FIXME("(%p/%p)->(...) stub\n", iface, This);
1034     return E_NOTIMPL;
1035 }
1036
1037 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1038 {
1039     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1040
1041     FIXME("(%p/%p)->(...) stub\n", iface, This);
1042     return E_NOTIMPL;
1043 }
1044
1045 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
1046 {
1047     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1048
1049     TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
1050
1051     EnterCriticalSection(&This->renderer.filter.csFilter);
1052     This->hWndClippingWindow = hwnd;
1053     if (!hwnd)
1054         IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
1055     LeaveCriticalSection(&This->renderer.filter.csFilter);
1056     return S_OK;
1057 }
1058
1059 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1060 {
1061     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1062
1063     FIXME("(%p/%p)->(...) stub\n", iface, This);
1064     return E_NOTIMPL;
1065 }
1066
1067 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1068 {
1069     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1070
1071     FIXME("(%p/%p)->(...) stub\n", iface, This);
1072     return E_NOTIMPL;
1073 }
1074
1075 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1076 {
1077     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1078
1079     FIXME("(%p/%p)->(...) stub\n", iface, This);
1080     return E_NOTIMPL;
1081 }
1082
1083 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1084 {
1085     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1086
1087     FIXME("(%p/%p)->(...) stub\n", iface, This);
1088     return E_NOTIMPL;
1089 }
1090
1091 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1092 {
1093     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1094
1095     FIXME("(%p/%p)->(...) stub\n", iface, This);
1096     return E_NOTIMPL;
1097 }
1098
1099 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1100 {
1101     VMR9WindowlessControl_QueryInterface,
1102     VMR9WindowlessControl_AddRef,
1103     VMR9WindowlessControl_Release,
1104     VMR9WindowlessControl_GetNativeVideoSize,
1105     VMR9WindowlessControl_GetMinIdealVideoSize,
1106     VMR9WindowlessControl_GetMaxIdealVideoSize,
1107     VMR9WindowlessControl_SetVideoPosition,
1108     VMR9WindowlessControl_GetVideoPosition,
1109     VMR9WindowlessControl_GetAspectRatioMode,
1110     VMR9WindowlessControl_SetAspectRatioMode,
1111     VMR9WindowlessControl_SetVideoClippingWindow,
1112     VMR9WindowlessControl_RepaintVideo,
1113     VMR9WindowlessControl_DisplayModeChanged,
1114     VMR9WindowlessControl_GetCurrentImage,
1115     VMR9WindowlessControl_SetBorderColor,
1116     VMR9WindowlessControl_GetBorderColor
1117 };
1118
1119 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1120 {
1121     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1122     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1123 }
1124
1125 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1126 {
1127     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1128     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1129 }
1130
1131 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1132 {
1133     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1134     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1135 }
1136
1137 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
1138 {
1139     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1140
1141     /* FIXME: This code is not tested!!! */
1142     FIXME("(%p/%p)->(...) stub\n", iface, This);
1143     This->cookie = id;
1144
1145     if (This->presenter)
1146         return VFW_E_WRONG_STATE;
1147
1148     if (FAILED(IUnknown_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
1149         return E_NOINTERFACE;
1150
1151     if (SUCCEEDED(IUnknown_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
1152         This->allocator_is_ex = 1;
1153     else
1154     {
1155         This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
1156         IUnknown_AddRef(alloc);
1157         This->allocator_is_ex = 0;
1158     }
1159
1160     return S_OK;
1161 }
1162
1163 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1164 {
1165     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1166
1167     FIXME("(%p/%p)->(...) stub\n", iface, This);
1168     return E_NOTIMPL;
1169 }
1170
1171 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1172 {
1173     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1174
1175     FIXME("(%p/%p)->(...) stub\n", iface, This);
1176     return E_NOTIMPL;
1177 }
1178
1179 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
1180 {
1181     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1182
1183     FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
1184
1185     if (!allocinfo || !numbuffers || !surface)
1186         return E_POINTER;
1187
1188     if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
1189     {
1190         ERR("Invalid number of buffers?\n");
1191         return E_INVALIDARG;
1192     }
1193
1194     return E_NOTIMPL;
1195 }
1196
1197 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
1198 {
1199     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1200
1201     FIXME("(%p/%p)->(...) stub\n", iface, This);
1202     return E_NOTIMPL;
1203 }
1204
1205 static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl =
1206 {
1207     VMR9SurfaceAllocatorNotify_QueryInterface,
1208     VMR9SurfaceAllocatorNotify_AddRef,
1209     VMR9SurfaceAllocatorNotify_Release,
1210     VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1211     VMR9SurfaceAllocatorNotify_SetD3DDevice,
1212     VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
1213     VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
1214     VMR9SurfaceAllocatorNotify_NotifyEvent
1215 };
1216
1217 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
1218 {
1219     HRESULT hr;
1220     VMR9Impl * pVMR9;
1221
1222     TRACE("(%p, %p)\n", outer_unk, ppv);
1223
1224     *ppv = NULL;
1225
1226     pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
1227
1228     pVMR9->outer_unk = outer_unk;
1229     pVMR9->bUnkOuterValid = FALSE;
1230     pVMR9->bAggregatable = FALSE;
1231     pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
1232     pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1233
1234     pVMR9->mode = 0;
1235     pVMR9->allocator = NULL;
1236     pVMR9->presenter = NULL;
1237     pVMR9->hWndClippingWindow = NULL;
1238     pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
1239     pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
1240     pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl;
1241
1242     hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
1243     if (FAILED(hr))
1244         goto fail;
1245
1246     hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1247     if (FAILED(hr))
1248         goto fail;
1249
1250     hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1251     if (FAILED(hr))
1252         goto fail;
1253
1254     *ppv = (LPVOID)pVMR9;
1255     ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
1256     ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
1257     TRACE("Created at %p\n", pVMR9);
1258     return hr;
1259
1260 fail:
1261     BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
1262     CoTaskMemFree(pVMR9);
1263     return hr;
1264 }