quartz: Add IAMFilterMiscFlags to VMR9 implementation.
[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
57     BITMAPINFOHEADER bmiheader;
58     IUnknown * outer_unk;
59     BOOL bUnkOuterValid;
60     BOOL bAggregatable;
61
62     RECT source_rect;
63     RECT target_rect;
64     LONG VideoWidth;
65     LONG VideoHeight;
66 } VMR9Impl;
67
68 static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface)
69 {
70     return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner);
71 }
72
73 static inline VMR9Impl *impl_from_BaseWindow( BaseWindow *wnd )
74 {
75     return CONTAINING_RECORD(wnd, VMR9Impl, baseControlWindow.baseWindow);
76 }
77
78 static inline VMR9Impl *impl_from_IVideoWindow( IVideoWindow *iface)
79 {
80     return CONTAINING_RECORD(iface, VMR9Impl, baseControlWindow.IVideoWindow_iface);
81 }
82
83 static inline VMR9Impl *impl_from_BaseControlVideo( BaseControlVideo *cvid )
84 {
85     return CONTAINING_RECORD(cvid, VMR9Impl, baseControlVideo);
86 }
87
88 static inline VMR9Impl *impl_from_IBasicVideo( IBasicVideo *iface)
89 {
90     return CONTAINING_RECORD(iface, VMR9Impl, baseControlVideo.IBasicVideo_iface);
91 }
92
93 static inline VMR9Impl *impl_from_IAMFilterMiscFlags( IAMFilterMiscFlags *iface)
94 {
95     return CONTAINING_RECORD(iface, VMR9Impl, IAMFilterMiscFlags_iface);
96 }
97
98 static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
99 {
100     VMR9Impl *This = (VMR9Impl *)iface;
101     LPBYTE pbSrcStream = NULL;
102     REFERENCE_TIME tStart, tStop;
103     VMR9PresentationInfo info;
104     HRESULT hr;
105
106     TRACE("%p %p\n", iface, pSample);
107
108     hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
109     if (FAILED(hr))
110         info.dwFlags = VMR9Sample_SrcDstRectsValid;
111     else
112         info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
113
114     if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
115         info.dwFlags |= VMR9Sample_Discontinuity;
116
117     if (IMediaSample_IsPreroll(pSample) == S_OK)
118         info.dwFlags |= VMR9Sample_Preroll;
119
120     if (IMediaSample_IsSyncPoint(pSample) == S_OK)
121         info.dwFlags |= VMR9Sample_SyncPoint;
122
123     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
124     if (FAILED(hr))
125     {
126         ERR("Cannot get pointer to sample data (%x)\n", hr);
127         return hr;
128     }
129
130     info.rtStart = tStart;
131     info.rtEnd = tStop;
132     info.szAspectRatio.cx = This->bmiheader.biWidth;
133     info.szAspectRatio.cy = This->bmiheader.biHeight;
134
135     return hr;
136 }
137
138 static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
139 {
140     VMR9Impl *This = (VMR9Impl*)iface;
141
142     if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
143         return S_FALSE;
144
145     /* Ignore subtype, test for bicompression instead */
146     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
147     {
148         VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
149
150         This->bmiheader = format->bmiHeader;
151         TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
152         This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
153         This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
154         This->source_rect.top = This->source_rect.left = 0;
155     }
156     else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
157     {
158         VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
159
160         This->bmiheader = format->bmiHeader;
161
162         TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
163         This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
164         This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
165         This->source_rect.top = This->source_rect.left = 0;
166     }
167     else
168     {
169         ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
170         return S_FALSE;
171     }
172     if (This->bmiheader.biCompression)
173         return S_FALSE;
174     return S_OK;
175 }
176
177 HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
178 {
179     /* Preroll means the sample isn't shown, this is used for key frames and things like that */
180     if (IMediaSample_IsPreroll(pSample) == S_OK)
181         return E_FAIL;
182     return S_FALSE;
183 }
184
185 static const BaseRendererFuncTable BaseFuncTable = {
186     VMR9_CheckMediaType,
187     VMR9_DoRenderSample,
188     /**/
189     NULL,
190     NULL,
191     NULL,
192     NULL,
193     NULL,
194     NULL,
195     NULL,
196     NULL,
197     VMR9_ShouldDrawSampleNow,
198     NULL,
199     /**/
200     NULL,
201     NULL,
202     NULL,
203     NULL,
204     NULL,
205 };
206
207 static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
208 {
209     static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 };
210
211     *pClassStyles = 0;
212     *pWindowStyles = WS_SIZEBOX;
213     *pWindowStylesEx = 0;
214
215     return classnameW;
216 }
217
218 static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
219 {
220     VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
221     static RECT defRect;
222
223     defRect.left = defRect.top = 0;
224     defRect.right = pVMR9->VideoWidth;
225     defRect.bottom = pVMR9->VideoHeight;
226
227     return defRect;
228 }
229
230 static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
231 {
232     VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
233
234     TRACE("WM_SIZE %d %d\n", Width, Height);
235     GetClientRect(This->hWnd, &pVMR9->target_rect);
236     TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
237         pVMR9->target_rect.left,
238         pVMR9->target_rect.top,
239         pVMR9->target_rect.right - pVMR9->target_rect.left,
240         pVMR9->target_rect.bottom - pVMR9->target_rect.top);
241     return BaseWindowImpl_OnSize(This, Width, Height);
242 }
243
244 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
245     VMR9_GetClassWindowStyles,
246     VMR9_GetDefaultRect,
247     NULL,
248     BaseControlWindowImpl_PossiblyEatMessage,
249     VMR9_OnSize,
250 };
251
252 HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
253 {
254     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
255     CopyRect(pSourceRect,&pVMR9->source_rect);
256     return S_OK;
257 }
258
259 HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage)
260 {
261     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
262     BITMAPINFOHEADER *bmiHeader;
263     LONG needed_size;
264     AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
265     char *ptr;
266
267     FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage);
268
269     EnterCriticalSection(&pVMR9->renderer.filter.csFilter);
270
271     if (!pVMR9->renderer.pMediaSample)
272     {
273          LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
274          return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
275     }
276
277     if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
278     {
279         bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
280     }
281     else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
282     {
283         bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
284     }
285     else
286     {
287         FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
288         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
289         return VFW_E_RUNTIME_ERROR;
290     }
291
292     needed_size = bmiHeader->biSize;
293     needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample);
294
295     if (!pDIBImage)
296     {
297         *pBufferSize = needed_size;
298         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
299         return S_OK;
300     }
301
302     if (needed_size < *pBufferSize)
303     {
304         ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
305         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
306         return E_FAIL;
307     }
308     *pBufferSize = needed_size;
309
310     memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
311     IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr);
312     memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample));
313
314     LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
315     return S_OK;
316 }
317
318 HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
319 {
320     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
321     CopyRect(pTargetRect,&pVMR9->target_rect);
322     return S_OK;
323 }
324
325 VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
326 {
327     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
328     AM_MEDIA_TYPE *pmt;
329
330     TRACE("(%p/%p)\n", pVMR9, This);
331
332     pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
333     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
334         return (VIDEOINFOHEADER*)pmt->pbFormat;
335     } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
336         static VIDEOINFOHEADER vih;
337         VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
338         memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
339         memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
340         return &vih;
341     } else {
342         ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
343         return NULL;
344     }
345 }
346
347 HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
348 {
349     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
350     FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
351
352     return S_OK;
353 }
354
355 HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
356 {
357     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
358     FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
359
360     return S_OK;
361 }
362
363 HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
364 {
365     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
366
367     pVMR9->source_rect.left = 0;
368     pVMR9->source_rect.top = 0;
369     pVMR9->source_rect.right = pVMR9->VideoWidth;
370     pVMR9->source_rect.bottom = pVMR9->VideoHeight;
371
372     return S_OK;
373 }
374
375 HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
376 {
377     RECT rect;
378     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
379
380     if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
381         return E_FAIL;
382
383     pVMR9->target_rect.left = 0;
384     pVMR9->target_rect.top = 0;
385     pVMR9->target_rect.right = rect.right;
386     pVMR9->target_rect.bottom = rect.bottom;
387
388     return S_OK;
389 }
390
391 HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
392 {
393     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
394     CopyRect(&pVMR9->source_rect,pSourceRect);
395     return S_OK;
396 }
397
398 HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
399 {
400     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
401     CopyRect(&pVMR9->target_rect,pTargetRect);
402     return S_OK;
403 }
404
405 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
406     VMR9_GetSourceRect,
407     VMR9_GetStaticImage,
408     VMR9_GetTargetRect,
409     VMR9_GetVideoFormat,
410     VMR9_IsDefaultSourceRect,
411     VMR9_IsDefaultTargetRect,
412     VMR9_SetDefaultSourceRect,
413     VMR9_SetDefaultTargetRect,
414     VMR9_SetSourceRect,
415     VMR9_SetTargetRect
416 };
417
418 static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
419 {
420     VMR9Impl *This = impl_from_inner_IUnknown(iface);
421     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
422
423     if (This->bAggregatable)
424         This->bUnkOuterValid = TRUE;
425
426     *ppv = NULL;
427
428     if (IsEqualIID(riid, &IID_IUnknown))
429         *ppv = &This->IUnknown_inner;
430     else if (IsEqualIID(riid, &IID_IVideoWindow))
431         *ppv = &This->baseControlWindow.IVideoWindow_iface;
432     else if (IsEqualIID(riid, &IID_IBasicVideo))
433         *ppv = &This->baseControlVideo.IBasicVideo_iface;
434     else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
435         *ppv = &This->IAMFilterMiscFlags_iface;
436     else
437     {
438         HRESULT hr;
439         hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
440         if (SUCCEEDED(hr))
441             return hr;
442     }
443
444     if (*ppv)
445     {
446         IUnknown_AddRef((IUnknown *)(*ppv));
447         return S_OK;
448     }
449
450     else if (IsEqualIID(riid, &IID_IBasicVideo2))
451         FIXME("No interface for IID_IBasicVideo2\n");
452     else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
453         ;
454     else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
455         ;
456     else if (IsEqualIID(riid, &IID_IMediaPosition))
457         FIXME("No interface for IID_IMediaPosition\n");
458     else if (IsEqualIID(riid, &IID_IQualProp))
459         FIXME("No interface for IID_IQualProp\n");
460     else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
461         FIXME("No interface for IID_IVMRAspectRatioControl9\n");
462     else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
463         FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
464     else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
465         FIXME("No interface for IID_IVMRMixerBitmap9\n");
466     else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
467         FIXME("No interface for IID_IVMRMonitorConfig9\n");
468     else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
469         FIXME("No interface for IID_IVMRMixerControl9\n");
470     else
471         FIXME("No interface for %s\n", debugstr_guid(riid));
472
473     return E_NOINTERFACE;
474 }
475
476 static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
477 {
478     VMR9Impl *This = impl_from_inner_IUnknown(iface);
479     ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
480
481     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
482
483     return refCount;
484 }
485
486 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
487 {
488     VMR9Impl *This = impl_from_inner_IUnknown(iface);
489     ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
490
491     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
492
493     if (!refCount)
494     {
495         TRACE("Destroying\n");
496
497         CoTaskMemFree(This);
498     }
499     return refCount;
500 }
501
502 static const IUnknownVtbl IInner_VTable =
503 {
504     VMR9Inner_QueryInterface,
505     VMR9Inner_AddRef,
506     VMR9Inner_Release
507 };
508
509 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
510 {
511     VMR9Impl *This = (VMR9Impl *)iface;
512
513     if (This->bAggregatable)
514         This->bUnkOuterValid = TRUE;
515
516     if (This->outer_unk)
517     {
518         if (This->bAggregatable)
519             return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
520
521         if (IsEqualIID(riid, &IID_IUnknown))
522         {
523             HRESULT hr;
524
525             IUnknown_AddRef(&This->IUnknown_inner);
526             hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
527             IUnknown_Release(&This->IUnknown_inner);
528             This->bAggregatable = TRUE;
529             return hr;
530         }
531
532         *ppv = NULL;
533         return E_NOINTERFACE;
534     }
535
536     return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
537 }
538
539 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
540 {
541     VMR9Impl *This = (VMR9Impl *)iface;
542     LONG ret;
543
544     if (This->outer_unk && This->bUnkOuterValid)
545         ret = IUnknown_AddRef(This->outer_unk);
546     else
547         ret = IUnknown_AddRef(&This->IUnknown_inner);
548
549     TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
550
551     return ret;
552 }
553
554 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
555 {
556     VMR9Impl *This = (VMR9Impl *)iface;
557     LONG ret;
558
559     if (This->outer_unk && This->bUnkOuterValid)
560         ret = IUnknown_Release(This->outer_unk);
561     else
562         ret = IUnknown_Release(&This->IUnknown_inner);
563
564     TRACE("(%p)->Release from %d\n", iface, ret + 1);
565
566     if (ret)
567         return ret;
568     return 0;
569 }
570
571 static const IBaseFilterVtbl VMR9_Vtbl =
572 {
573     VMR9_QueryInterface,
574     VMR9_AddRef,
575     VMR9_Release,
576     BaseFilterImpl_GetClassID,
577     BaseRendererImpl_Stop,
578     BaseRendererImpl_Pause,
579     BaseRendererImpl_Run,
580     BaseRendererImpl_GetState,
581     BaseRendererImpl_SetSyncSource,
582     BaseFilterImpl_GetSyncSource,
583     BaseFilterImpl_EnumPins,
584     BaseRendererImpl_FindPin,
585     BaseFilterImpl_QueryFilterInfo,
586     BaseFilterImpl_JoinFilterGraph,
587     BaseFilterImpl_QueryVendorInfo
588 };
589
590 /*** IUnknown methods ***/
591 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
592 {
593     VMR9Impl *This = impl_from_IVideoWindow(iface);
594
595     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
596
597     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
598 }
599
600 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
601 {
602     VMR9Impl *This = impl_from_IVideoWindow(iface);
603
604     TRACE("(%p/%p)->()\n", This, iface);
605
606     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
607 }
608
609 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
610 {
611     VMR9Impl *This = impl_from_IVideoWindow(iface);
612
613     TRACE("(%p/%p)->()\n", This, iface);
614
615     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
616 }
617
618 static const IVideoWindowVtbl IVideoWindow_VTable =
619 {
620     Videowindow_QueryInterface,
621     Videowindow_AddRef,
622     Videowindow_Release,
623     BaseControlWindowImpl_GetTypeInfoCount,
624     BaseControlWindowImpl_GetTypeInfo,
625     BaseControlWindowImpl_GetIDsOfNames,
626     BaseControlWindowImpl_Invoke,
627     BaseControlWindowImpl_put_Caption,
628     BaseControlWindowImpl_get_Caption,
629     BaseControlWindowImpl_put_WindowStyle,
630     BaseControlWindowImpl_get_WindowStyle,
631     BaseControlWindowImpl_put_WindowStyleEx,
632     BaseControlWindowImpl_get_WindowStyleEx,
633     BaseControlWindowImpl_put_AutoShow,
634     BaseControlWindowImpl_get_AutoShow,
635     BaseControlWindowImpl_put_WindowState,
636     BaseControlWindowImpl_get_WindowState,
637     BaseControlWindowImpl_put_BackgroundPalette,
638     BaseControlWindowImpl_get_BackgroundPalette,
639     BaseControlWindowImpl_put_Visible,
640     BaseControlWindowImpl_get_Visible,
641     BaseControlWindowImpl_put_Left,
642     BaseControlWindowImpl_get_Left,
643     BaseControlWindowImpl_put_Width,
644     BaseControlWindowImpl_get_Width,
645     BaseControlWindowImpl_put_Top,
646     BaseControlWindowImpl_get_Top,
647     BaseControlWindowImpl_put_Height,
648     BaseControlWindowImpl_get_Height,
649     BaseControlWindowImpl_put_Owner,
650     BaseControlWindowImpl_get_Owner,
651     BaseControlWindowImpl_put_MessageDrain,
652     BaseControlWindowImpl_get_MessageDrain,
653     BaseControlWindowImpl_get_BorderColor,
654     BaseControlWindowImpl_put_BorderColor,
655     BaseControlWindowImpl_get_FullScreenMode,
656     BaseControlWindowImpl_put_FullScreenMode,
657     BaseControlWindowImpl_SetWindowForeground,
658     BaseControlWindowImpl_NotifyOwnerMessage,
659     BaseControlWindowImpl_SetWindowPosition,
660     BaseControlWindowImpl_GetWindowPosition,
661     BaseControlWindowImpl_GetMinIdealImageSize,
662     BaseControlWindowImpl_GetMaxIdealImageSize,
663     BaseControlWindowImpl_GetRestorePosition,
664     BaseControlWindowImpl_HideCursor,
665     BaseControlWindowImpl_IsCursorHidden
666 };
667
668 /*** IUnknown methods ***/
669 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
670 {
671     VMR9Impl *This = impl_from_IBasicVideo(iface);
672
673     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
674
675     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
676 }
677
678 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
679 {
680     VMR9Impl *This = impl_from_IBasicVideo(iface);
681
682     TRACE("(%p/%p)->()\n", This, iface);
683
684     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
685 }
686
687 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
688 {
689     VMR9Impl *This = impl_from_IBasicVideo(iface);
690
691     TRACE("(%p/%p)->()\n", This, iface);
692
693     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
694 }
695
696 static const IBasicVideoVtbl IBasicVideo_VTable =
697 {
698     Basicvideo_QueryInterface,
699     Basicvideo_AddRef,
700     Basicvideo_Release,
701     BaseControlVideoImpl_GetTypeInfoCount,
702     BaseControlVideoImpl_GetTypeInfo,
703     BaseControlVideoImpl_GetIDsOfNames,
704     BaseControlVideoImpl_Invoke,
705     BaseControlVideoImpl_get_AvgTimePerFrame,
706     BaseControlVideoImpl_get_BitRate,
707     BaseControlVideoImpl_get_BitErrorRate,
708     BaseControlVideoImpl_get_VideoWidth,
709     BaseControlVideoImpl_get_VideoHeight,
710     BaseControlVideoImpl_put_SourceLeft,
711     BaseControlVideoImpl_get_SourceLeft,
712     BaseControlVideoImpl_put_SourceWidth,
713     BaseControlVideoImpl_get_SourceWidth,
714     BaseControlVideoImpl_put_SourceTop,
715     BaseControlVideoImpl_get_SourceTop,
716     BaseControlVideoImpl_put_SourceHeight,
717     BaseControlVideoImpl_get_SourceHeight,
718     BaseControlVideoImpl_put_DestinationLeft,
719     BaseControlVideoImpl_get_DestinationLeft,
720     BaseControlVideoImpl_put_DestinationWidth,
721     BaseControlVideoImpl_get_DestinationWidth,
722     BaseControlVideoImpl_put_DestinationTop,
723     BaseControlVideoImpl_get_DestinationTop,
724     BaseControlVideoImpl_put_DestinationHeight,
725     BaseControlVideoImpl_get_DestinationHeight,
726     BaseControlVideoImpl_SetSourcePosition,
727     BaseControlVideoImpl_GetSourcePosition,
728     BaseControlVideoImpl_SetDefaultSourcePosition,
729     BaseControlVideoImpl_SetDestinationPosition,
730     BaseControlVideoImpl_GetDestinationPosition,
731     BaseControlVideoImpl_SetDefaultDestinationPosition,
732     BaseControlVideoImpl_GetVideoSize,
733     BaseControlVideoImpl_GetVideoPaletteEntries,
734     BaseControlVideoImpl_GetCurrentImage,
735     BaseControlVideoImpl_IsUsingDefaultSource,
736     BaseControlVideoImpl_IsUsingDefaultDestination
737 };
738
739 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
740     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
741     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
742 }
743
744 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
745     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
746     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
747 }
748
749 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
750     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
751     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
752 }
753
754 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
755     return AM_FILTER_MISC_FLAGS_IS_RENDERER;
756 }
757
758 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
759     AMFilterMiscFlags_QueryInterface,
760     AMFilterMiscFlags_AddRef,
761     AMFilterMiscFlags_Release,
762     AMFilterMiscFlags_GetMiscFlags
763 };
764
765 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
766 {
767     HRESULT hr;
768     VMR9Impl * pVMR9;
769
770     TRACE("(%p, %p)\n", outer_unk, ppv);
771
772     *ppv = NULL;
773
774     pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
775
776     pVMR9->outer_unk = outer_unk;
777     pVMR9->bUnkOuterValid = FALSE;
778     pVMR9->bAggregatable = FALSE;
779     pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
780     pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
781
782     hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
783     if (FAILED(hr))
784         goto fail;
785
786     hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
787     if (FAILED(hr))
788         goto fail;
789
790     hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
791     if (FAILED(hr))
792         goto fail;
793
794     *ppv = (LPVOID)pVMR9;
795     ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
796     ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
797     TRACE("Created at %p\n", pVMR9);
798     return hr;
799
800 fail:
801     BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
802     CoTaskMemFree(pVMR9);
803     return hr;
804 }