quartz: Mark a bunch of functions as static.
[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
531         if (This->allocator)
532             IVMRSurfaceAllocator9_Release(This->allocator);
533         if (This->presenter)
534             IVMRImagePresenter9_Release(This->presenter);
535
536         CoTaskMemFree(This);
537     }
538     return refCount;
539 }
540
541 static const IUnknownVtbl IInner_VTable =
542 {
543     VMR9Inner_QueryInterface,
544     VMR9Inner_AddRef,
545     VMR9Inner_Release
546 };
547
548 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
549 {
550     VMR9Impl *This = (VMR9Impl *)iface;
551
552     if (This->bAggregatable)
553         This->bUnkOuterValid = TRUE;
554
555     if (This->outer_unk)
556     {
557         if (This->bAggregatable)
558             return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
559
560         if (IsEqualIID(riid, &IID_IUnknown))
561         {
562             HRESULT hr;
563
564             IUnknown_AddRef(&This->IUnknown_inner);
565             hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
566             IUnknown_Release(&This->IUnknown_inner);
567             This->bAggregatable = TRUE;
568             return hr;
569         }
570
571         *ppv = NULL;
572         return E_NOINTERFACE;
573     }
574
575     return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
576 }
577
578 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
579 {
580     VMR9Impl *This = (VMR9Impl *)iface;
581     LONG ret;
582
583     if (This->outer_unk && This->bUnkOuterValid)
584         ret = IUnknown_AddRef(This->outer_unk);
585     else
586         ret = IUnknown_AddRef(&This->IUnknown_inner);
587
588     TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
589
590     return ret;
591 }
592
593 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
594 {
595     VMR9Impl *This = (VMR9Impl *)iface;
596     LONG ret;
597
598     if (This->outer_unk && This->bUnkOuterValid)
599         ret = IUnknown_Release(This->outer_unk);
600     else
601         ret = IUnknown_Release(&This->IUnknown_inner);
602
603     TRACE("(%p)->Release from %d\n", iface, ret + 1);
604
605     if (ret)
606         return ret;
607     return 0;
608 }
609
610 static const IBaseFilterVtbl VMR9_Vtbl =
611 {
612     VMR9_QueryInterface,
613     VMR9_AddRef,
614     VMR9_Release,
615     BaseFilterImpl_GetClassID,
616     BaseRendererImpl_Stop,
617     BaseRendererImpl_Pause,
618     BaseRendererImpl_Run,
619     BaseRendererImpl_GetState,
620     BaseRendererImpl_SetSyncSource,
621     BaseFilterImpl_GetSyncSource,
622     BaseFilterImpl_EnumPins,
623     BaseRendererImpl_FindPin,
624     BaseFilterImpl_QueryFilterInfo,
625     BaseFilterImpl_JoinFilterGraph,
626     BaseFilterImpl_QueryVendorInfo
627 };
628
629 /*** IUnknown methods ***/
630 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
631 {
632     VMR9Impl *This = impl_from_IVideoWindow(iface);
633
634     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
635
636     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
637 }
638
639 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
640 {
641     VMR9Impl *This = impl_from_IVideoWindow(iface);
642
643     TRACE("(%p/%p)->()\n", This, iface);
644
645     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
646 }
647
648 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
649 {
650     VMR9Impl *This = impl_from_IVideoWindow(iface);
651
652     TRACE("(%p/%p)->()\n", This, iface);
653
654     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
655 }
656
657 static const IVideoWindowVtbl IVideoWindow_VTable =
658 {
659     Videowindow_QueryInterface,
660     Videowindow_AddRef,
661     Videowindow_Release,
662     BaseControlWindowImpl_GetTypeInfoCount,
663     BaseControlWindowImpl_GetTypeInfo,
664     BaseControlWindowImpl_GetIDsOfNames,
665     BaseControlWindowImpl_Invoke,
666     BaseControlWindowImpl_put_Caption,
667     BaseControlWindowImpl_get_Caption,
668     BaseControlWindowImpl_put_WindowStyle,
669     BaseControlWindowImpl_get_WindowStyle,
670     BaseControlWindowImpl_put_WindowStyleEx,
671     BaseControlWindowImpl_get_WindowStyleEx,
672     BaseControlWindowImpl_put_AutoShow,
673     BaseControlWindowImpl_get_AutoShow,
674     BaseControlWindowImpl_put_WindowState,
675     BaseControlWindowImpl_get_WindowState,
676     BaseControlWindowImpl_put_BackgroundPalette,
677     BaseControlWindowImpl_get_BackgroundPalette,
678     BaseControlWindowImpl_put_Visible,
679     BaseControlWindowImpl_get_Visible,
680     BaseControlWindowImpl_put_Left,
681     BaseControlWindowImpl_get_Left,
682     BaseControlWindowImpl_put_Width,
683     BaseControlWindowImpl_get_Width,
684     BaseControlWindowImpl_put_Top,
685     BaseControlWindowImpl_get_Top,
686     BaseControlWindowImpl_put_Height,
687     BaseControlWindowImpl_get_Height,
688     BaseControlWindowImpl_put_Owner,
689     BaseControlWindowImpl_get_Owner,
690     BaseControlWindowImpl_put_MessageDrain,
691     BaseControlWindowImpl_get_MessageDrain,
692     BaseControlWindowImpl_get_BorderColor,
693     BaseControlWindowImpl_put_BorderColor,
694     BaseControlWindowImpl_get_FullScreenMode,
695     BaseControlWindowImpl_put_FullScreenMode,
696     BaseControlWindowImpl_SetWindowForeground,
697     BaseControlWindowImpl_NotifyOwnerMessage,
698     BaseControlWindowImpl_SetWindowPosition,
699     BaseControlWindowImpl_GetWindowPosition,
700     BaseControlWindowImpl_GetMinIdealImageSize,
701     BaseControlWindowImpl_GetMaxIdealImageSize,
702     BaseControlWindowImpl_GetRestorePosition,
703     BaseControlWindowImpl_HideCursor,
704     BaseControlWindowImpl_IsCursorHidden
705 };
706
707 /*** IUnknown methods ***/
708 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
709 {
710     VMR9Impl *This = impl_from_IBasicVideo(iface);
711
712     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
713
714     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
715 }
716
717 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
718 {
719     VMR9Impl *This = impl_from_IBasicVideo(iface);
720
721     TRACE("(%p/%p)->()\n", This, iface);
722
723     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
724 }
725
726 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
727 {
728     VMR9Impl *This = impl_from_IBasicVideo(iface);
729
730     TRACE("(%p/%p)->()\n", This, iface);
731
732     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
733 }
734
735 static const IBasicVideoVtbl IBasicVideo_VTable =
736 {
737     Basicvideo_QueryInterface,
738     Basicvideo_AddRef,
739     Basicvideo_Release,
740     BaseControlVideoImpl_GetTypeInfoCount,
741     BaseControlVideoImpl_GetTypeInfo,
742     BaseControlVideoImpl_GetIDsOfNames,
743     BaseControlVideoImpl_Invoke,
744     BaseControlVideoImpl_get_AvgTimePerFrame,
745     BaseControlVideoImpl_get_BitRate,
746     BaseControlVideoImpl_get_BitErrorRate,
747     BaseControlVideoImpl_get_VideoWidth,
748     BaseControlVideoImpl_get_VideoHeight,
749     BaseControlVideoImpl_put_SourceLeft,
750     BaseControlVideoImpl_get_SourceLeft,
751     BaseControlVideoImpl_put_SourceWidth,
752     BaseControlVideoImpl_get_SourceWidth,
753     BaseControlVideoImpl_put_SourceTop,
754     BaseControlVideoImpl_get_SourceTop,
755     BaseControlVideoImpl_put_SourceHeight,
756     BaseControlVideoImpl_get_SourceHeight,
757     BaseControlVideoImpl_put_DestinationLeft,
758     BaseControlVideoImpl_get_DestinationLeft,
759     BaseControlVideoImpl_put_DestinationWidth,
760     BaseControlVideoImpl_get_DestinationWidth,
761     BaseControlVideoImpl_put_DestinationTop,
762     BaseControlVideoImpl_get_DestinationTop,
763     BaseControlVideoImpl_put_DestinationHeight,
764     BaseControlVideoImpl_get_DestinationHeight,
765     BaseControlVideoImpl_SetSourcePosition,
766     BaseControlVideoImpl_GetSourcePosition,
767     BaseControlVideoImpl_SetDefaultSourcePosition,
768     BaseControlVideoImpl_SetDestinationPosition,
769     BaseControlVideoImpl_GetDestinationPosition,
770     BaseControlVideoImpl_SetDefaultDestinationPosition,
771     BaseControlVideoImpl_GetVideoSize,
772     BaseControlVideoImpl_GetVideoPaletteEntries,
773     BaseControlVideoImpl_GetCurrentImage,
774     BaseControlVideoImpl_IsUsingDefaultSource,
775     BaseControlVideoImpl_IsUsingDefaultDestination
776 };
777
778 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
779     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
780     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
781 }
782
783 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
784     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
785     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
786 }
787
788 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
789     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
790     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
791 }
792
793 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
794     return AM_FILTER_MISC_FLAGS_IS_RENDERER;
795 }
796
797 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
798     AMFilterMiscFlags_QueryInterface,
799     AMFilterMiscFlags_AddRef,
800     AMFilterMiscFlags_Release,
801     AMFilterMiscFlags_GetMiscFlags
802 };
803
804 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
805 {
806     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
807     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
808 }
809
810 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
811 {
812     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
813     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
814 }
815
816 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
817 {
818     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
819     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
820 }
821
822 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
823 {
824     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
825
826     FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
827     return E_NOTIMPL;
828 }
829
830 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max)
831 {
832     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
833
834     FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
835     return E_NOTIMPL;
836 }
837
838 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
839 {
840     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
841
842     FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
843     return E_NOTIMPL;
844 }
845
846 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
847 {
848     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
849
850     FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
851     return E_NOTIMPL;
852 }
853
854 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
855 {
856     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
857
858     FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
859     return E_NOTIMPL;
860 }
861
862 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
863 {
864     HRESULT hr = S_OK;
865     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
866
867     TRACE("(%p/%p)->(%u)\n", iface, This, mode);
868
869     EnterCriticalSection(&This->renderer.filter.csFilter);
870     if (This->mode)
871     {
872         LeaveCriticalSection(&This->renderer.filter.csFilter);
873         return VFW_E_WRONG_STATE;
874     }
875
876     if (This->allocator)
877         IVMRSurfaceAllocator9_Release(This->allocator);
878     if (This->presenter)
879         IVMRImagePresenter9_Release(This->presenter);
880
881     This->allocator = NULL;
882     This->presenter = NULL;
883
884     switch (mode)
885     {
886     case VMR9Mode_Windowed:
887     case VMR9Mode_Windowless:
888         This->allocator = NULL;
889         This->presenter = NULL;
890         This->allocator_is_ex = 0;
891         This->cookie = ~0;
892         break;
893     case VMR9Mode_Renderless:
894         break;
895     default:
896         LeaveCriticalSection(&This->renderer.filter.csFilter);
897         return E_INVALIDARG;
898     }
899
900     This->mode = mode;
901     LeaveCriticalSection(&This->renderer.filter.csFilter);
902     return hr;
903 }
904
905 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
906 {
907     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
908
909     TRACE("(%p/%p)->(%p) stub\n", iface, This, mode);
910     if (!mode)
911         return E_POINTER;
912
913     if (This->mode)
914         *mode = This->mode;
915     else
916         *mode = VMR9Mode_Windowed;
917
918     return S_OK;
919 }
920
921 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
922 {
923     VMR9FilterConfig_QueryInterface,
924     VMR9FilterConfig_AddRef,
925     VMR9FilterConfig_Release,
926     VMR9FilterConfig_SetImageCompositor,
927     VMR9FilterConfig_SetNumberOfStreams,
928     VMR9FilterConfig_GetNumberOfStreams,
929     VMR9FilterConfig_SetRenderingPrefs,
930     VMR9FilterConfig_GetRenderingPrefs,
931     VMR9FilterConfig_SetRenderingMode,
932     VMR9FilterConfig_GetRenderingMode
933 };
934
935 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
936 {
937     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
938     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
939 }
940
941 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
942 {
943     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
944     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
945 }
946
947 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
948 {
949     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
950     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
951 }
952
953 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
954 {
955     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
956     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
957
958     if (!width || !height || !arwidth || !arheight)
959     {
960         ERR("Got no pointer\n");
961         return E_POINTER;
962     }
963
964     *width = This->bmiheader.biWidth;
965     *height = This->bmiheader.biHeight;
966     *arwidth = This->bmiheader.biWidth;
967     *arheight = This->bmiheader.biHeight;
968
969     return S_OK;
970 }
971
972 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
973 {
974     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
975
976     FIXME("(%p/%p)->(...) stub\n", iface, This);
977     return E_NOTIMPL;
978 }
979
980 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
981 {
982     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
983
984     FIXME("(%p/%p)->(...) stub\n", iface, This);
985     return E_NOTIMPL;
986 }
987
988 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
989 {
990     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
991
992     TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
993
994     EnterCriticalSection(&This->renderer.filter.csFilter);
995
996     if (source)
997         This->source_rect = *source;
998     if (dest)
999     {
1000         This->target_rect = *dest;
1001         if (This->baseControlWindow.baseWindow.hWnd)
1002         {
1003             FIXME("Output rectangle: starting at %dx%d, up to point %dx%d\n", dest->left, dest->top, dest->right, dest->bottom);
1004             SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
1005                          dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
1006         }
1007     }
1008
1009     LeaveCriticalSection(&This->renderer.filter.csFilter);
1010
1011     return S_OK;
1012 }
1013
1014 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
1015 {
1016     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1017
1018     if (source)
1019         *source = This->source_rect;
1020
1021     if (dest)
1022         *dest = This->target_rect;
1023
1024     FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1025     return S_OK;
1026 }
1027
1028 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1029 {
1030     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1031
1032     FIXME("(%p/%p)->(...) stub\n", iface, This);
1033     return E_NOTIMPL;
1034 }
1035
1036 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1037 {
1038     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1039
1040     FIXME("(%p/%p)->(...) stub\n", iface, This);
1041     return E_NOTIMPL;
1042 }
1043
1044 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
1045 {
1046     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1047
1048     TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
1049
1050     EnterCriticalSection(&This->renderer.filter.csFilter);
1051     This->hWndClippingWindow = hwnd;
1052     if (!hwnd)
1053         IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
1054     LeaveCriticalSection(&This->renderer.filter.csFilter);
1055     return S_OK;
1056 }
1057
1058 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1059 {
1060     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1061
1062     FIXME("(%p/%p)->(...) stub\n", iface, This);
1063     return E_NOTIMPL;
1064 }
1065
1066 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1067 {
1068     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1069
1070     FIXME("(%p/%p)->(...) stub\n", iface, This);
1071     return E_NOTIMPL;
1072 }
1073
1074 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1075 {
1076     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1077
1078     FIXME("(%p/%p)->(...) stub\n", iface, This);
1079     return E_NOTIMPL;
1080 }
1081
1082 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1083 {
1084     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1085
1086     FIXME("(%p/%p)->(...) stub\n", iface, This);
1087     return E_NOTIMPL;
1088 }
1089
1090 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1091 {
1092     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1093
1094     FIXME("(%p/%p)->(...) stub\n", iface, This);
1095     return E_NOTIMPL;
1096 }
1097
1098 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1099 {
1100     VMR9WindowlessControl_QueryInterface,
1101     VMR9WindowlessControl_AddRef,
1102     VMR9WindowlessControl_Release,
1103     VMR9WindowlessControl_GetNativeVideoSize,
1104     VMR9WindowlessControl_GetMinIdealVideoSize,
1105     VMR9WindowlessControl_GetMaxIdealVideoSize,
1106     VMR9WindowlessControl_SetVideoPosition,
1107     VMR9WindowlessControl_GetVideoPosition,
1108     VMR9WindowlessControl_GetAspectRatioMode,
1109     VMR9WindowlessControl_SetAspectRatioMode,
1110     VMR9WindowlessControl_SetVideoClippingWindow,
1111     VMR9WindowlessControl_RepaintVideo,
1112     VMR9WindowlessControl_DisplayModeChanged,
1113     VMR9WindowlessControl_GetCurrentImage,
1114     VMR9WindowlessControl_SetBorderColor,
1115     VMR9WindowlessControl_GetBorderColor
1116 };
1117
1118 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1119 {
1120     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1121     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1122 }
1123
1124 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1125 {
1126     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1127     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1128 }
1129
1130 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1131 {
1132     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1133     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1134 }
1135
1136 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
1137 {
1138     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1139
1140     /* FIXME: This code is not tested!!! */
1141     FIXME("(%p/%p)->(...) stub\n", iface, This);
1142     This->cookie = id;
1143
1144     if (This->presenter)
1145         return VFW_E_WRONG_STATE;
1146
1147     if (FAILED(IUnknown_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
1148         return E_NOINTERFACE;
1149
1150     if (SUCCEEDED(IUnknown_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
1151         This->allocator_is_ex = 1;
1152     else
1153     {
1154         This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
1155         IUnknown_AddRef(alloc);
1156         This->allocator_is_ex = 0;
1157     }
1158
1159     return S_OK;
1160 }
1161
1162 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1163 {
1164     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1165
1166     FIXME("(%p/%p)->(...) stub\n", iface, This);
1167     return E_NOTIMPL;
1168 }
1169
1170 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1171 {
1172     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1173
1174     FIXME("(%p/%p)->(...) stub\n", iface, This);
1175     return E_NOTIMPL;
1176 }
1177
1178 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
1179 {
1180     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1181
1182     FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
1183
1184     if (!allocinfo || !numbuffers || !surface)
1185         return E_POINTER;
1186
1187     if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
1188     {
1189         ERR("Invalid number of buffers?\n");
1190         return E_INVALIDARG;
1191     }
1192
1193     return E_NOTIMPL;
1194 }
1195
1196 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
1197 {
1198     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1199
1200     FIXME("(%p/%p)->(...) stub\n", iface, This);
1201     return E_NOTIMPL;
1202 }
1203
1204 static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl =
1205 {
1206     VMR9SurfaceAllocatorNotify_QueryInterface,
1207     VMR9SurfaceAllocatorNotify_AddRef,
1208     VMR9SurfaceAllocatorNotify_Release,
1209     VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1210     VMR9SurfaceAllocatorNotify_SetD3DDevice,
1211     VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
1212     VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
1213     VMR9SurfaceAllocatorNotify_NotifyEvent
1214 };
1215
1216 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
1217 {
1218     HRESULT hr;
1219     VMR9Impl * pVMR9;
1220
1221     TRACE("(%p, %p)\n", outer_unk, ppv);
1222
1223     *ppv = NULL;
1224
1225     pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
1226
1227     pVMR9->outer_unk = outer_unk;
1228     pVMR9->bUnkOuterValid = FALSE;
1229     pVMR9->bAggregatable = FALSE;
1230     pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
1231     pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1232
1233     pVMR9->mode = 0;
1234     pVMR9->allocator = NULL;
1235     pVMR9->presenter = NULL;
1236     pVMR9->hWndClippingWindow = NULL;
1237     pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
1238     pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
1239     pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl;
1240
1241     hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
1242     if (FAILED(hr))
1243         goto fail;
1244
1245     hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1246     if (FAILED(hr))
1247         goto fail;
1248
1249     hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1250     if (FAILED(hr))
1251         goto fail;
1252
1253     *ppv = (LPVOID)pVMR9;
1254     ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
1255     ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
1256     TRACE("Created at %p\n", pVMR9);
1257     return hr;
1258
1259 fail:
1260     BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
1261     CoTaskMemFree(pVMR9);
1262     return hr;
1263 }