mshtml: Improved error handling in HTMLElement_Create calls.
[wine] / dlls / quartz / videorenderer.c
1 /*
2  * Video Renderer (Fullscreen and Windowed using Direct Draw)
3  *
4  * Copyright 2004 Christian Costa
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
25 #include "quartz_private.h"
26 #include "control_private.h"
27 #include "pin.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
40 #include <assert.h>
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45
46 static BOOL wnd_class_registered = FALSE;
47
48 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
49
50 static const IBaseFilterVtbl VideoRenderer_Vtbl;
51 static const IUnknownVtbl IInner_VTable;
52 static const IBasicVideoVtbl IBasicVideo_VTable;
53 static const IVideoWindowVtbl IVideoWindow_VTable;
54 static const IPinVtbl VideoRenderer_InputPin_Vtbl;
55 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl;
56 static const IQualityControlVtbl VideoRenderer_QualityControl_Vtbl = {
57     QualityControlImpl_QueryInterface,
58     QualityControlImpl_AddRef,
59     QualityControlImpl_Release,
60     QualityControlImpl_Notify,
61     QualityControlImpl_SetSink
62 };
63
64 typedef struct VideoRendererImpl
65 {
66     BaseFilter filter;
67     const IBasicVideoVtbl * IBasicVideo_vtbl;
68     const IVideoWindowVtbl * IVideoWindow_vtbl;
69     const IUnknownVtbl * IInner_vtbl;
70     const IAMFilterMiscFlagsVtbl *IAMFilterMiscFlags_vtbl;
71     IUnknown *seekthru_unk;
72     QualityControlImpl qcimpl;
73
74     BaseInputPin *pInputPin;
75
76     BOOL init;
77     HANDLE hThread;
78     HANDLE blocked;
79
80     DWORD ThreadID;
81     HANDLE hEvent;
82     BOOL ThreadResult;
83     HWND hWnd;
84     HWND hWndMsgDrain;
85     HWND hWndOwner;
86     BOOL AutoShow;
87     RECT SourceRect;
88     RECT DestRect;
89     RECT WindowPos;
90     LONG VideoWidth;
91     LONG VideoHeight;
92     IUnknown * pUnkOuter;
93     BOOL bUnkOuterValid;
94     BOOL bAggregatable;
95     LONG WindowStyle;
96
97     /* During pause we can hold a single sample, for use in GetCurrentImage */
98     IMediaSample *sample_held;
99 } VideoRendererImpl;
100
101 static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
102 {
103     VideoRendererImpl* pVideoRenderer = (VideoRendererImpl*)GetWindowLongPtrW(hwnd, 0);
104     LPRECT lprect = (LPRECT)lParam;
105
106     if (pVideoRenderer && pVideoRenderer->hWndMsgDrain)
107     {
108         switch(uMsg)
109         {
110             case WM_KEYDOWN:
111             case WM_KEYUP:
112             case WM_LBUTTONDBLCLK:
113             case WM_LBUTTONDOWN:
114             case WM_LBUTTONUP:
115             case WM_MBUTTONDBLCLK:
116             case WM_MBUTTONDOWN:
117             case WM_MBUTTONUP:
118             case WM_MOUSEACTIVATE:
119             case WM_MOUSEMOVE:
120             case WM_NCLBUTTONDBLCLK:
121             case WM_NCLBUTTONDOWN:
122             case WM_NCLBUTTONUP:
123             case WM_NCMBUTTONDBLCLK:
124             case WM_NCMBUTTONDOWN:
125             case WM_NCMBUTTONUP:
126             case WM_NCMOUSEMOVE:
127             case WM_NCRBUTTONDBLCLK:
128             case WM_NCRBUTTONDOWN:
129             case WM_NCRBUTTONUP:
130             case WM_RBUTTONDBLCLK:
131             case WM_RBUTTONDOWN:
132             case WM_RBUTTONUP:
133                 PostMessageA(pVideoRenderer->hWndMsgDrain, uMsg, wParam, lParam);
134                 break;
135             default:
136                 break;
137         }
138     }
139
140     switch(uMsg)
141     {
142         case WM_SIZING:
143             /* TRACE("WM_SIZING %d %d %d %d\n", lprect->left, lprect->top, lprect->right, lprect->bottom); */
144             SetWindowPos(hwnd, NULL, lprect->left, lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top, SWP_NOZORDER);
145             GetClientRect(hwnd, &pVideoRenderer->DestRect);
146             TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
147                 pVideoRenderer->DestRect.left,
148                 pVideoRenderer->DestRect.top,
149                 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
150                 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
151             return TRUE;
152         case WM_SIZE:
153             TRACE("WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam));
154             GetClientRect(hwnd, &pVideoRenderer->DestRect);
155             TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
156                 pVideoRenderer->DestRect.left,
157                 pVideoRenderer->DestRect.top,
158                 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
159                 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
160             return TRUE;
161         default:
162             return DefWindowProcA(hwnd, uMsg, wParam, lParam);
163     }
164     return 0;
165 }
166
167 static BOOL video_register_windowclass(void) {
168     WNDCLASSA winclass;
169     if (wnd_class_registered)
170         return 1;
171
172     winclass.style = 0;
173     winclass.lpfnWndProc = VideoWndProcA;
174     winclass.cbClsExtra = 0;
175     winclass.cbWndExtra = sizeof(VideoRendererImpl*);
176     winclass.hInstance = NULL;
177     winclass.hIcon = NULL;
178     winclass.hCursor = NULL;
179     winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
180     winclass.lpszMenuName = NULL;
181     winclass.lpszClassName = "Wine ActiveMovie Class";
182     if (!RegisterClassA(&winclass))
183     {
184         ERR("Unable to register window class: %u\n", GetLastError());
185         return FALSE;
186     }
187     wnd_class_registered = 1;
188     return 1;
189 }
190
191 void video_unregister_windowclass(void) {
192     if (!wnd_class_registered)
193         return;
194     UnregisterClassA("Wine ActiveMovie Class", NULL);
195 }
196
197 static BOOL CreateRenderingWindow(VideoRendererImpl* This)
198 {
199     TRACE("(%p)->()\n", This);
200     if (!video_register_windowclass())
201         return FALSE;
202     This->hWnd = CreateWindowExA(0, "Wine ActiveMovie Class", "Wine ActiveMovie Window", WS_SIZEBOX,
203                                  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
204                                  NULL, NULL, NULL);
205
206     if (!This->hWnd)
207     {
208         ERR("Unable to create window\n");
209         return FALSE;
210     }
211
212     SetWindowLongPtrW(This->hWnd, 0, (LONG_PTR)This);
213
214     return TRUE;
215 }
216
217 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
218 {
219     VideoRendererImpl* This = lpParameter;
220     MSG msg; 
221     BOOL fGotMessage;
222
223     TRACE("Starting message loop\n");
224
225     if (!CreateRenderingWindow(This))
226     {
227         This->ThreadResult = FALSE;
228         SetEvent(This->hEvent);
229         return 0;
230     }
231
232     This->ThreadResult = TRUE;
233     SetEvent(This->hEvent);
234
235     while ((fGotMessage = GetMessageA(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1) 
236     {
237         TranslateMessage(&msg); 
238         DispatchMessageA(&msg); 
239     }
240
241     TRACE("End of message loop\n");
242
243     return msg.wParam;
244 }
245
246 static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
247 {
248     This->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
249     if (!This->hEvent)
250         return FALSE;
251
252     This->hThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->ThreadID);
253     if (!This->hThread)
254     {
255         CloseHandle(This->hEvent);
256         return FALSE;
257     }
258
259     WaitForSingleObject(This->hEvent, INFINITE);
260
261     if (!This->ThreadResult)
262     {
263         CloseHandle(This->hEvent);
264         CloseHandle(This->hThread);
265         return FALSE;
266     }
267
268     return TRUE;
269 }
270
271 static void VideoRenderer_AutoShowWindow(VideoRendererImpl *This) {
272     if (!This->init && (!This->WindowPos.right || !This->WindowPos.top))
273     {
274         DWORD style = GetWindowLongW(This->hWnd, GWL_STYLE);
275         DWORD style_ex = GetWindowLongW(This->hWnd, GWL_EXSTYLE);
276
277         if (!This->WindowPos.right)
278         {
279             This->WindowPos.left = This->SourceRect.left;
280             This->WindowPos.right = This->SourceRect.right;
281         }
282         if (!This->WindowPos.bottom)
283         {
284             This->WindowPos.top = This->SourceRect.top;
285             This->WindowPos.bottom = This->SourceRect.bottom;
286         }
287
288         AdjustWindowRectEx(&This->WindowPos, style, TRUE, style_ex);
289
290         TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom);
291         SetWindowPos(This->hWnd, NULL,
292             This->WindowPos.left,
293             This->WindowPos.top,
294             This->WindowPos.right - This->WindowPos.left,
295             This->WindowPos.bottom - This->WindowPos.top,
296             SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
297
298         GetClientRect(This->hWnd, &This->DestRect);
299     }
300     else if (!This->init)
301         This->DestRect = This->WindowPos;
302     This->init = TRUE;
303     if (This->AutoShow)
304         ShowWindow(This->hWnd, SW_SHOW);
305 }
306
307 static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size)
308 {
309     AM_MEDIA_TYPE amt;
310     HRESULT hr = S_OK;
311     DDSURFACEDESC sdesc;
312     HDC hDC;
313     BITMAPINFOHEADER *bmiHeader;
314
315     TRACE("(%p)->(%p, %d)\n", This, data, size);
316
317     sdesc.dwSize = sizeof(sdesc);
318     hr = IPin_ConnectionMediaType((IPin *)This->pInputPin, &amt);
319     if (FAILED(hr)) {
320         ERR("Unable to retrieve media type\n");
321         return hr;
322     }
323
324     if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo))
325     {
326         bmiHeader = &((VIDEOINFOHEADER *)amt.pbFormat)->bmiHeader;
327     }
328     else if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo2))
329     {
330         bmiHeader = &((VIDEOINFOHEADER2 *)amt.pbFormat)->bmiHeader;
331     }
332     else
333     {
334         FIXME("Unknown type %s\n", debugstr_guid(&amt.subtype));
335         return VFW_E_RUNTIME_ERROR;
336     }
337
338     TRACE("biSize = %d\n", bmiHeader->biSize);
339     TRACE("biWidth = %d\n", bmiHeader->biWidth);
340     TRACE("biHeight = %d\n", bmiHeader->biHeight);
341     TRACE("biPlanes = %d\n", bmiHeader->biPlanes);
342     TRACE("biBitCount = %d\n", bmiHeader->biBitCount);
343     TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
344     TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
345
346     hDC = GetDC(This->hWnd);
347
348     if (!hDC) {
349         ERR("Cannot get DC from window!\n");
350         return E_FAIL;
351     }
352
353     TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom);
354     TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom);
355
356     StretchDIBits(hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left,
357                   This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top,
358                   This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top,
359                   data, (BITMAPINFO *)bmiHeader, DIB_RGB_COLORS, SRCCOPY);
360
361     ReleaseDC(This->hWnd, hDC);
362
363     return S_OK;
364 }
365
366 static HRESULT WINAPI VideoRenderer_Receive(BaseInputPin* pin, IMediaSample * pSample)
367 {
368     VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter;
369     LPBYTE pbSrcStream = NULL;
370     LONG cbSrcStream = 0;
371     REFERENCE_TIME tStart, tStop;
372     HRESULT hr;
373
374     TRACE("(%p)->(%p)\n", pin, pSample);
375
376     EnterCriticalSection(&This->filter.csFilter);
377
378     if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
379     {
380         LeaveCriticalSection(&This->filter.csFilter);
381         return S_FALSE;
382     }
383
384     if (This->filter.state == State_Stopped)
385     {
386         LeaveCriticalSection(&This->filter.csFilter);
387         return VFW_E_WRONG_STATE;
388     }
389
390     if (IMediaSample_GetMediaTime(pSample, &tStart, &tStop) == S_OK)
391         MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, tStart);
392
393     /* Preroll means the sample isn't shown, this is used for key frames and things like that */
394     if (IMediaSample_IsPreroll(pSample) == S_OK) {
395         LeaveCriticalSection(&This->filter.csFilter);
396         return S_OK;
397     }
398
399     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
400     if (FAILED(hr))
401     {
402         ERR("Cannot get pointer to sample data (%x)\n", hr);
403         LeaveCriticalSection(&This->filter.csFilter);
404         return hr;
405     }
406
407     cbSrcStream = IMediaSample_GetActualDataLength(pSample);
408
409     TRACE("val %p %d\n", pbSrcStream, cbSrcStream);
410
411 #if 0 /* For debugging purpose */
412     {
413         int i;
414         for(i = 0; i < cbSrcStream; i++)
415         {
416             if ((i!=0) && !(i%16))
417                 TRACE("\n");
418                 TRACE("%02x ", pbSrcStream[i]);
419         }
420         TRACE("\n");
421     }
422 #endif
423
424     SetEvent(This->hEvent);
425     if (This->filter.state == State_Paused)
426     {
427         VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
428         This->sample_held = pSample;
429         LeaveCriticalSection(&This->filter.csFilter);
430         WaitForSingleObject(This->blocked, INFINITE);
431         EnterCriticalSection(&This->filter.csFilter);
432         This->sample_held = NULL;
433         if (This->filter.state == State_Paused)
434         {
435             /* Flushing */
436             LeaveCriticalSection(&This->filter.csFilter);
437             return S_OK;
438         }
439         if (This->filter.state == State_Stopped)
440         {
441             LeaveCriticalSection(&This->filter.csFilter);
442             return VFW_E_WRONG_STATE;
443         }
444     } else {
445         hr = QualityControlRender_WaitFor(&This->qcimpl, pSample, This->blocked);
446         if (hr == S_OK) {
447             QualityControlRender_BeginRender(&This->qcimpl);
448             VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
449             QualityControlRender_EndRender(&This->qcimpl);
450         }
451         QualityControlRender_DoQOS(&This->qcimpl);
452     }
453     LeaveCriticalSection(&This->filter.csFilter);
454     return S_OK;
455 }
456
457 static HRESULT WINAPI VideoRenderer_CheckMediaType(BasePin *iface, const AM_MEDIA_TYPE * pmt)
458 {
459     BaseInputPin* pin = (BaseInputPin*)iface;
460     VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter;
461
462     if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
463         return S_FALSE;
464
465     if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
466         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
467         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
468         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
469     {
470         LONG height;
471
472         if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
473         {
474             VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
475             This->SourceRect.left = 0;
476             This->SourceRect.top = 0;
477             This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
478             height = format->bmiHeader.biHeight;
479             if (height < 0)
480                 This->SourceRect.bottom = This->VideoHeight = -height;
481             else
482                 This->SourceRect.bottom = This->VideoHeight = height;
483         }
484         else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
485         {
486             VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat;
487
488             This->SourceRect.left = 0;
489             This->SourceRect.top = 0;
490             This->SourceRect.right = This->VideoWidth = format2->bmiHeader.biWidth;
491             height = format2->bmiHeader.biHeight;
492             if (height < 0)
493                 This->SourceRect.bottom = This->VideoHeight = -height;
494             else
495                 This->SourceRect.bottom = This->VideoHeight = height;
496         }
497         else
498         {
499             WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
500             return S_FALSE;
501         }
502         return S_OK;
503     }
504     return S_FALSE;
505 }
506
507 static IPin* WINAPI VideoRenderer_GetPin(BaseFilter *iface, int pos)
508 {
509     VideoRendererImpl *This = (VideoRendererImpl *)iface;
510
511     if (pos >= 1 || pos < 0)
512         return NULL;
513
514     IPin_AddRef((IPin *)This->pInputPin);
515     return (IPin *)This->pInputPin;
516 }
517
518 static LONG WINAPI VideoRenderer_GetPinCount(BaseFilter *iface)
519 {
520     return 1;
521 }
522
523 static const BaseFilterFuncTable BaseFuncTable = {
524     VideoRenderer_GetPin,
525     VideoRenderer_GetPinCount
526 };
527
528 static const  BasePinFuncTable input_BaseFuncTable = {
529     VideoRenderer_CheckMediaType,
530     NULL,
531     BasePinImpl_GetMediaTypeVersion,
532     BasePinImpl_GetMediaType
533 };
534
535 static const BaseInputPinFuncTable input_BaseInputFuncTable = {
536     VideoRenderer_Receive
537 };
538
539 HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
540 {
541     HRESULT hr;
542     PIN_INFO piInput;
543     VideoRendererImpl * pVideoRenderer;
544     ISeekingPassThru *passthru;
545
546     TRACE("(%p, %p)\n", pUnkOuter, ppv);
547
548     *ppv = NULL;
549
550     pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
551     pVideoRenderer->pUnkOuter = pUnkOuter;
552     pVideoRenderer->bUnkOuterValid = FALSE;
553     pVideoRenderer->bAggregatable = FALSE;
554     pVideoRenderer->IInner_vtbl = &IInner_VTable;
555     pVideoRenderer->IAMFilterMiscFlags_vtbl = &IAMFilterMiscFlags_Vtbl;
556
557     BaseFilter_Init(&pVideoRenderer->filter, &VideoRenderer_Vtbl, &CLSID_VideoRenderer, (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"), &BaseFuncTable);
558
559     pVideoRenderer->IBasicVideo_vtbl = &IBasicVideo_VTable;
560     pVideoRenderer->IVideoWindow_vtbl = &IVideoWindow_VTable;
561
562     pVideoRenderer->init = 0;
563     pVideoRenderer->AutoShow = 1;
564     ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
565     ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
566     ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
567     pVideoRenderer->hWndMsgDrain = pVideoRenderer->hWndOwner = NULL;
568     pVideoRenderer->WindowStyle = WS_OVERLAPPED;
569
570     /* construct input pin */
571     piInput.dir = PINDIR_INPUT;
572     piInput.pFilter = (IBaseFilter *)pVideoRenderer;
573     lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
574
575     hr = BaseInputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, &input_BaseFuncTable, &input_BaseInputFuncTable, &pVideoRenderer->filter.csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin);
576
577     if (SUCCEEDED(hr))
578     {
579         hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter ? pUnkOuter : (IUnknown*)&pVideoRenderer->IInner_vtbl, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pVideoRenderer->seekthru_unk);
580         if (FAILED(hr)) {
581             IPin_Release((IPin*)pVideoRenderer->pInputPin);
582             goto fail;
583         }
584         IUnknown_QueryInterface(pVideoRenderer->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
585         ISeekingPassThru_Init(passthru, TRUE, (IPin*)pVideoRenderer->pInputPin);
586         ISeekingPassThru_Release(passthru);
587         pVideoRenderer->sample_held = NULL;
588         *ppv = pVideoRenderer;
589     }
590     if (FAILED(hr))
591         goto fail;
592
593     QualityControlImpl_init(&pVideoRenderer->qcimpl, (IPin*)pVideoRenderer->pInputPin, (IBaseFilter*)pVideoRenderer);
594     pVideoRenderer->qcimpl.lpVtbl = &VideoRenderer_QualityControl_Vtbl;
595
596     if (!CreateRenderingSubsystem(pVideoRenderer))
597         return E_FAIL;
598
599     pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
600     if (!pVideoRenderer->blocked)
601     {
602         hr = HRESULT_FROM_WIN32(GetLastError());
603         IUnknown_Release((IUnknown *)pVideoRenderer);
604     }
605
606     return hr;
607 fail:
608     BaseFilterImpl_Release((IBaseFilter*)pVideoRenderer);
609     CoTaskMemFree(pVideoRenderer);
610     return hr;
611 }
612
613 HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
614 {
615     /* TODO: Attempt to use the VMR-7 renderer instead when possible */
616     return VideoRenderer_create(pUnkOuter, ppv);
617 }
618
619 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
620 {
621     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
622     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
623
624     if (This->bAggregatable)
625         This->bUnkOuterValid = TRUE;
626
627     *ppv = NULL;
628
629     if (IsEqualIID(riid, &IID_IUnknown))
630         *ppv = &This->IInner_vtbl;
631     else if (IsEqualIID(riid, &IID_IPersist))
632         *ppv = This;
633     else if (IsEqualIID(riid, &IID_IMediaFilter))
634         *ppv = This;
635     else if (IsEqualIID(riid, &IID_IBaseFilter))
636         *ppv = This;
637     else if (IsEqualIID(riid, &IID_IBasicVideo))
638         *ppv = &This->IBasicVideo_vtbl;
639     else if (IsEqualIID(riid, &IID_IVideoWindow))
640         *ppv = &This->IVideoWindow_vtbl;
641     else if (IsEqualIID(riid, &IID_IMediaSeeking))
642         return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
643     else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
644         *ppv = &This->IAMFilterMiscFlags_vtbl;
645     else if (IsEqualIID(riid, &IID_IQualityControl))
646         *ppv = &This->qcimpl;
647
648     if (*ppv)
649     {
650         IUnknown_AddRef((IUnknown *)(*ppv));
651         return S_OK;
652     }
653
654     if (!IsEqualIID(riid, &IID_IPin))
655         FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
656
657     return E_NOINTERFACE;
658 }
659
660 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown * iface)
661 {
662     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
663     ULONG refCount = InterlockedIncrement(&This->filter.refCount);
664
665     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
666
667     return refCount;
668 }
669
670 static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
671 {
672     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
673     ULONG refCount = InterlockedDecrement(&This->filter.refCount);
674
675     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
676
677     if (!refCount)
678     {
679         IPin *pConnectedTo;
680
681         DestroyWindow(This->hWnd);
682         PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
683         WaitForSingleObject(This->hThread, INFINITE);
684         CloseHandle(This->hThread);
685         CloseHandle(This->hEvent);
686
687         if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
688         {
689             IPin_Disconnect(pConnectedTo);
690             IPin_Release(pConnectedTo);
691         }
692         IPin_Disconnect((IPin *)This->pInputPin);
693
694         IPin_Release((IPin *)This->pInputPin);
695
696         This->filter.lpVtbl = NULL;
697         IUnknown_Release(This->seekthru_unk);
698         This->filter.csFilter.DebugInfo->Spare[0] = 0;
699         DeleteCriticalSection(&This->filter.csFilter);
700
701         TRACE("Destroying Video Renderer\n");
702         CoTaskMemFree(This);
703         
704         return 0;
705     }
706     else
707         return refCount;
708 }
709
710 static const IUnknownVtbl IInner_VTable =
711 {
712     VideoRendererInner_QueryInterface,
713     VideoRendererInner_AddRef,
714     VideoRendererInner_Release
715 };
716
717 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
718 {
719     VideoRendererImpl *This = (VideoRendererImpl *)iface;
720
721     if (This->bAggregatable)
722         This->bUnkOuterValid = TRUE;
723
724     if (This->pUnkOuter)
725     {
726         if (This->bAggregatable)
727             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
728
729         if (IsEqualIID(riid, &IID_IUnknown))
730         {
731             HRESULT hr;
732
733             IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
734             hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
735             IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
736             This->bAggregatable = TRUE;
737             return hr;
738         }
739
740         *ppv = NULL;
741         return E_NOINTERFACE;
742     }
743
744     return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
745 }
746
747 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
748 {
749     VideoRendererImpl *This = (VideoRendererImpl *)iface;
750
751     if (This->pUnkOuter && This->bUnkOuterValid)
752         return IUnknown_AddRef(This->pUnkOuter);
753     return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
754 }
755
756 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
757 {
758     VideoRendererImpl *This = (VideoRendererImpl *)iface;
759
760     if (This->pUnkOuter && This->bUnkOuterValid)
761         return IUnknown_Release(This->pUnkOuter);
762     return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
763 }
764
765 /** IMediaFilter methods **/
766
767 static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
768 {
769     VideoRendererImpl *This = (VideoRendererImpl *)iface;
770
771     TRACE("(%p/%p)->()\n", This, iface);
772
773     EnterCriticalSection(&This->filter.csFilter);
774     {
775         This->filter.state = State_Stopped;
776         SetEvent(This->hEvent);
777         SetEvent(This->blocked);
778         MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk);
779         if (This->AutoShow)
780             /* Black it out */
781             RedrawWindow(This->hWnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE);
782     }
783     LeaveCriticalSection(&This->filter.csFilter);
784
785     return S_OK;
786 }
787
788 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
789 {
790     VideoRendererImpl *This = (VideoRendererImpl *)iface;
791     
792     TRACE("(%p/%p)->()\n", This, iface);
793
794     EnterCriticalSection(&This->filter.csFilter);
795     if (This->filter.state != State_Paused)
796     {
797         if (This->filter.state == State_Stopped)
798         {
799             This->pInputPin->end_of_stream = 0;
800             ResetEvent(This->hEvent);
801             VideoRenderer_AutoShowWindow(This);
802         }
803
804         This->filter.state = State_Paused;
805         ResetEvent(This->blocked);
806     }
807     LeaveCriticalSection(&This->filter.csFilter);
808
809     return S_OK;
810 }
811
812 static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock) {
813     VideoRendererImpl *This = (VideoRendererImpl *)iface;
814     HRESULT hr;
815
816     EnterCriticalSection(&This->filter.csFilter);
817     QualityControlRender_SetClock(&This->qcimpl, clock);
818     hr = BaseFilterImpl_SetSyncSource(iface, clock);
819     LeaveCriticalSection(&This->filter.csFilter);
820     return hr;
821 }
822
823 static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
824 {
825     HRESULT hr = S_OK;
826     VideoRendererImpl *This = (VideoRendererImpl *)iface;
827
828     TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
829
830     EnterCriticalSection(&This->filter.csFilter);
831     if (This->filter.state == State_Running)
832         goto out;
833     This->filter.rtStreamStart = tStart;
834     QualityControlRender_Start(&This->qcimpl, tStart);
835     if (This->pInputPin->pin.pConnectedTo && (This->filter.state == State_Stopped || !This->pInputPin->end_of_stream))
836     {
837         if (This->filter.state == State_Stopped)
838         {
839             ResetEvent(This->hEvent);
840             VideoRenderer_AutoShowWindow(This);
841             This->pInputPin->end_of_stream = 0;
842         }
843         SetEvent(This->blocked);
844     } else if (This->filter.filterInfo.pGraph) {
845         IMediaEventSink *pEventSink;
846         hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
847         if (SUCCEEDED(hr))
848         {
849             hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)This);
850             IMediaEventSink_Release(pEventSink);
851         }
852         hr = S_OK;
853     }
854     if (SUCCEEDED(hr))
855         This->filter.state = State_Running;
856 out:
857     LeaveCriticalSection(&This->filter.csFilter);
858
859     return hr;
860 }
861
862 static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
863 {
864     VideoRendererImpl *This = (VideoRendererImpl *)iface;
865     HRESULT hr;
866
867     TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
868
869     if (WaitForSingleObject(This->hEvent, dwMilliSecsTimeout) == WAIT_TIMEOUT)
870         hr = VFW_S_STATE_INTERMEDIATE;
871     else
872         hr = S_OK;
873
874     BaseFilterImpl_GetState(iface, dwMilliSecsTimeout, pState);
875
876     return hr;
877 }
878
879 /** IBaseFilter implementation **/
880
881 static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
882 {
883     VideoRendererImpl *This = (VideoRendererImpl *)iface;
884
885     FIXME("(%p/%p)->(%p,%p): stub !!!\n", This, iface, debugstr_w(Id), ppPin);
886
887     /* FIXME: critical section */
888
889     return E_NOTIMPL;
890 }
891
892 static const IBaseFilterVtbl VideoRenderer_Vtbl =
893 {
894     VideoRenderer_QueryInterface,
895     VideoRenderer_AddRef,
896     VideoRenderer_Release,
897     BaseFilterImpl_GetClassID,
898     VideoRenderer_Stop,
899     VideoRenderer_Pause,
900     VideoRenderer_Run,
901     VideoRenderer_GetState,
902     VideoRenderer_SetSyncSource,
903     BaseFilterImpl_GetSyncSource,
904     BaseFilterImpl_EnumPins,
905     VideoRenderer_FindPin,
906     BaseFilterImpl_QueryFilterInfo,
907     BaseFilterImpl_JoinFilterGraph,
908     BaseFilterImpl_QueryVendorInfo
909 };
910
911 static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
912 {
913     BaseInputPin* This = (BaseInputPin*)iface;
914     VideoRendererImpl *pFilter;
915     IMediaEventSink* pEventSink;
916     HRESULT hr = S_OK;
917
918     TRACE("(%p/%p)->()\n", This, iface);
919
920     EnterCriticalSection(This->pin.pCritSec);
921     pFilter = (VideoRendererImpl*)This->pin.pinInfo.pFilter;
922     if (This->flushing || This->end_of_stream)
923         goto out;
924     hr = IFilterGraph_QueryInterface(pFilter->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
925     if (SUCCEEDED(hr))
926     {
927         hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)pFilter);
928         IMediaEventSink_Release(pEventSink);
929     }
930     MediaSeekingPassThru_EOS(pFilter->seekthru_unk);
931     This->end_of_stream = 1;
932 out:
933     LeaveCriticalSection(This->pin.pCritSec);
934
935     return hr;
936 }
937
938 static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
939 {
940     BaseInputPin* This = (BaseInputPin*)iface;
941     VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
942
943     TRACE("(%p/%p)->()\n", This, iface);
944
945     SetEvent(pVideoRenderer->blocked);
946     return BaseInputPinImpl_BeginFlush(iface);
947 }
948
949 static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
950 {
951     BaseInputPin* This = (BaseInputPin*)iface;
952     VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
953     HRESULT hr;
954
955     TRACE("(%p/%p)->()\n", This, iface);
956
957     EnterCriticalSection(This->pin.pCritSec);
958     if (pVideoRenderer->filter.state == State_Paused) {
959         ResetEvent(pVideoRenderer->blocked);
960         ResetEvent(pVideoRenderer->hEvent);
961     }
962
963     QualityControlRender_Start(&pVideoRenderer->qcimpl, pVideoRenderer->filter.rtStreamStart);
964     hr = BaseInputPinImpl_EndFlush(iface);
965     LeaveCriticalSection(This->pin.pCritSec);
966     MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk);
967
968     return hr;
969 }
970
971 static const IPinVtbl VideoRenderer_InputPin_Vtbl = 
972 {
973     BaseInputPinImpl_QueryInterface,
974     BasePinImpl_AddRef,
975     BaseInputPinImpl_Release,
976     BaseInputPinImpl_Connect,
977     BaseInputPinImpl_ReceiveConnection,
978     BasePinImpl_Disconnect,
979     BasePinImpl_ConnectedTo,
980     BasePinImpl_ConnectionMediaType,
981     BasePinImpl_QueryPinInfo,
982     BasePinImpl_QueryDirection,
983     BasePinImpl_QueryId,
984     BaseInputPinImpl_QueryAccept,
985     BasePinImpl_EnumMediaTypes,
986     BasePinImpl_QueryInternalConnections,
987     VideoRenderer_InputPin_EndOfStream,
988     VideoRenderer_InputPin_BeginFlush,
989     VideoRenderer_InputPin_EndFlush,
990     BaseInputPinImpl_NewSegment
991 };
992
993 /*** IUnknown methods ***/
994 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
995                                                 REFIID riid,
996                                                 LPVOID*ppvObj) {
997     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
998
999     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1000
1001     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
1002 }
1003
1004 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
1005     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1006
1007     TRACE("(%p/%p)->()\n", This, iface);
1008
1009     return VideoRenderer_AddRef((IBaseFilter*)This);
1010 }
1011
1012 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
1013     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1014
1015     TRACE("(%p/%p)->()\n", This, iface);
1016
1017     return VideoRenderer_Release((IBaseFilter*)This);
1018 }
1019
1020 /*** IDispatch methods ***/
1021 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
1022                                                   UINT*pctinfo) {
1023     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1024
1025     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1026
1027     return S_OK;
1028 }
1029
1030 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
1031                                              UINT iTInfo,
1032                                              LCID lcid,
1033                                              ITypeInfo**ppTInfo) {
1034     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1035
1036     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1037
1038     return S_OK;
1039 }
1040
1041 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
1042                                                REFIID riid,
1043                                                LPOLESTR*rgszNames,
1044                                                UINT cNames,
1045                                                LCID lcid,
1046                                                DISPID*rgDispId) {
1047     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1048
1049     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1050
1051     return S_OK;
1052 }
1053
1054 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
1055                                         DISPID dispIdMember,
1056                                         REFIID riid,
1057                                         LCID lcid,
1058                                         WORD wFlags,
1059                                         DISPPARAMS*pDispParams,
1060                                         VARIANT*pVarResult,
1061                                         EXCEPINFO*pExepInfo,
1062                                         UINT*puArgErr) {
1063     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1064
1065     FIXME("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1066
1067     return S_OK;
1068 }
1069
1070 /*** IBasicVideo methods ***/
1071 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
1072                                                      REFTIME *pAvgTimePerFrame) {
1073     AM_MEDIA_TYPE *pmt;
1074     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1075
1076     if (!This->pInputPin->pin.pConnectedTo)
1077         return VFW_E_NOT_CONNECTED;
1078
1079     TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
1080
1081     pmt = &This->pInputPin->pin.mtCurrent;
1082     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
1083         VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)pmt->pbFormat;
1084         *pAvgTimePerFrame = vih->AvgTimePerFrame;
1085     } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
1086         VIDEOINFOHEADER2 *vih = (VIDEOINFOHEADER2*)pmt->pbFormat;
1087         *pAvgTimePerFrame = vih->AvgTimePerFrame;
1088     } else {
1089         ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
1090         *pAvgTimePerFrame = 0;
1091     }
1092     return S_OK;
1093 }
1094
1095 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
1096                                              LONG *pBitRate) {
1097     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1098
1099     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
1100
1101     return S_OK;
1102 }
1103
1104 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
1105                                                   LONG *pBitErrorRate) {
1106     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1107
1108     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
1109
1110     return S_OK;
1111 }
1112
1113 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
1114                                                 LONG *pVideoWidth) {
1115     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1116
1117     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
1118
1119     *pVideoWidth = This->VideoWidth;
1120
1121     return S_OK;
1122 }
1123
1124 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
1125                                                  LONG *pVideoHeight) {
1126     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1127
1128     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
1129
1130     *pVideoHeight = This->VideoHeight;
1131
1132     return S_OK;
1133 }
1134
1135 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
1136                                                 LONG SourceLeft) {
1137     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1138
1139     TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
1140
1141     This->SourceRect.left = SourceLeft;
1142
1143     return S_OK;
1144 }
1145
1146 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1147                                                 LONG *pSourceLeft) {
1148     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1149
1150     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
1151
1152     *pSourceLeft = This->SourceRect.left;
1153
1154     return S_OK;
1155 }
1156
1157 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1158                                                  LONG SourceWidth) {
1159     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1160
1161     TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
1162
1163     This->SourceRect.right = This->SourceRect.left + SourceWidth;
1164
1165     return S_OK;
1166 }
1167
1168 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1169                                                  LONG *pSourceWidth) {
1170     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1171
1172     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
1173
1174     *pSourceWidth = This->SourceRect.right - This->SourceRect.left;
1175     
1176     return S_OK;
1177 }
1178
1179 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
1180                                                LONG SourceTop) {
1181     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1182
1183     TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
1184
1185     This->SourceRect.top = SourceTop;
1186
1187     return S_OK;
1188 }
1189
1190 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
1191                                                LONG *pSourceTop) {
1192     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1193
1194     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
1195
1196     *pSourceTop = This->SourceRect.top;
1197
1198     return S_OK;
1199 }
1200
1201 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
1202                                                   LONG SourceHeight) {
1203     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1204
1205     TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
1206
1207     This->SourceRect.bottom = This->SourceRect.top + SourceHeight;
1208
1209     return S_OK;
1210 }
1211
1212 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
1213                                                   LONG *pSourceHeight) {
1214     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1215
1216     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
1217
1218     *pSourceHeight = This->SourceRect.bottom - This->SourceRect.top;
1219
1220     return S_OK;
1221 }
1222
1223 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
1224                                                      LONG DestinationLeft) {
1225     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1226
1227     TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
1228
1229     This->DestRect.left = DestinationLeft;
1230
1231     return S_OK;
1232 }
1233
1234 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
1235                                                      LONG *pDestinationLeft) {
1236     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1237
1238     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
1239
1240     *pDestinationLeft = This->DestRect.left;
1241
1242     return S_OK;
1243 }
1244
1245 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
1246                                                       LONG DestinationWidth) {
1247     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1248
1249     TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
1250
1251     This->DestRect.right = This->DestRect.left + DestinationWidth;
1252
1253     return S_OK;
1254 }
1255
1256 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
1257                                                       LONG *pDestinationWidth) {
1258     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1259
1260     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
1261
1262     *pDestinationWidth = This->DestRect.right - This->DestRect.left;
1263
1264     return S_OK;
1265 }
1266
1267 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
1268                                                     LONG DestinationTop) {
1269     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1270
1271     TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
1272
1273     This->DestRect.top = DestinationTop;
1274     
1275     return S_OK;
1276 }
1277
1278 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
1279                                                     LONG *pDestinationTop) {
1280     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1281
1282     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
1283
1284     *pDestinationTop = This->DestRect.top;
1285
1286     return S_OK;
1287 }
1288
1289 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
1290                                                        LONG DestinationHeight) {
1291     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1292
1293     TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
1294
1295     This->DestRect.right = This->DestRect.left + DestinationHeight;
1296
1297     return S_OK;
1298 }
1299
1300 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
1301                                                        LONG *pDestinationHeight) {
1302     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1303
1304     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
1305
1306     *pDestinationHeight = This->DestRect.right - This->DestRect.left;
1307
1308     return S_OK;
1309 }
1310
1311 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
1312                                                    LONG Left,
1313                                                    LONG Top,
1314                                                    LONG Width,
1315                                                    LONG Height) {
1316     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1317
1318     TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
1319
1320     This->SourceRect.left = Left;
1321     This->SourceRect.top = Top;
1322     This->SourceRect.right = Left + Width;
1323     This->SourceRect.bottom = Top + Height;
1324     
1325     return S_OK;
1326 }
1327
1328 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
1329                                                    LONG *pLeft,
1330                                                    LONG *pTop,
1331                                                    LONG *pWidth,
1332                                                    LONG *pHeight) {
1333     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1334
1335     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1336
1337     *pLeft = This->SourceRect.left;
1338     *pTop = This->SourceRect.top;
1339     *pWidth = This->SourceRect.right - This->SourceRect.left;
1340     *pHeight = This->SourceRect.bottom - This->SourceRect.top;
1341     
1342     return S_OK;
1343 }
1344
1345 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
1346     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1347
1348     TRACE("(%p/%p)->()\n", This, iface);
1349
1350     This->SourceRect.left = 0;
1351     This->SourceRect.top = 0;
1352     This->SourceRect.right = This->VideoWidth;
1353     This->SourceRect.bottom = This->VideoHeight;
1354
1355     return S_OK;
1356 }
1357
1358 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
1359                                                         LONG Left,
1360                                                         LONG Top,
1361                                                         LONG Width,
1362                                                         LONG Height) {
1363     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1364
1365     TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
1366
1367     This->DestRect.left = Left;
1368     This->DestRect.top = Top;
1369     This->DestRect.right = Left + Width;
1370     This->DestRect.bottom = Top + Height;
1371
1372     return S_OK;
1373 }
1374
1375 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
1376                                                         LONG *pLeft,
1377                                                         LONG *pTop,
1378                                                         LONG *pWidth,
1379                                                         LONG *pHeight) {
1380     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1381
1382     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1383
1384     *pLeft = This->DestRect.left;
1385     *pTop = This->DestRect.top;
1386     *pWidth = This->DestRect.right - This->DestRect.left;
1387     *pHeight = This->DestRect.bottom - This->DestRect.top;
1388
1389     return S_OK;
1390 }
1391
1392 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
1393     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1394     RECT rect;
1395
1396     TRACE("(%p/%p)->()\n", This, iface);
1397
1398     if (!GetClientRect(This->hWnd, &rect))
1399         return E_FAIL;
1400     
1401     This->SourceRect.left = 0;
1402     This->SourceRect.top = 0;
1403     This->SourceRect.right = rect.right;
1404     This->SourceRect.bottom = rect.bottom;
1405     
1406     return S_OK;
1407 }
1408
1409 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
1410                                               LONG *pWidth,
1411                                               LONG *pHeight) {
1412     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1413
1414     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
1415
1416     *pWidth = This->VideoWidth;
1417     *pHeight = This->VideoHeight;
1418     
1419     return S_OK;
1420 }
1421
1422 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
1423                                                         LONG StartIndex,
1424                                                         LONG Entries,
1425                                                         LONG *pRetrieved,
1426                                                         LONG *pPalette) {
1427     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1428
1429     TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
1430
1431     if (pRetrieved)
1432         *pRetrieved = 0;
1433     return VFW_E_NO_PALETTE_AVAILABLE;
1434 }
1435
1436 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
1437                                                  LONG *pBufferSize,
1438                                                  LONG *pDIBImage) {
1439     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1440     BITMAPINFOHEADER *bmiHeader;
1441     LONG needed_size;
1442     AM_MEDIA_TYPE *amt = &This->pInputPin->pin.mtCurrent;
1443     char *ptr;
1444
1445     FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage);
1446
1447     EnterCriticalSection(&This->filter.csFilter);
1448
1449     if (!This->sample_held)
1450     {
1451          LeaveCriticalSection(&This->filter.csFilter);
1452          return (This->filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
1453     }
1454
1455     if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
1456     {
1457         bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
1458     }
1459     else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
1460     {
1461         bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
1462     }
1463     else
1464     {
1465         FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
1466         LeaveCriticalSection(&This->filter.csFilter);
1467         return VFW_E_RUNTIME_ERROR;
1468     }
1469
1470     needed_size = bmiHeader->biSize;
1471     needed_size += IMediaSample_GetActualDataLength(This->sample_held);
1472
1473     if (!pDIBImage)
1474     {
1475         *pBufferSize = needed_size;
1476         LeaveCriticalSection(&This->filter.csFilter);
1477         return S_OK;
1478     }
1479
1480     if (needed_size < *pBufferSize)
1481     {
1482         ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
1483         LeaveCriticalSection(&This->filter.csFilter);
1484         return E_FAIL;
1485     }
1486     *pBufferSize = needed_size;
1487
1488     memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
1489     IMediaSample_GetPointer(This->sample_held, (BYTE **)&ptr);
1490     memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->sample_held));
1491
1492     LeaveCriticalSection(&This->filter.csFilter);
1493
1494     return S_OK;
1495 }
1496
1497 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
1498     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1499
1500     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1501
1502     return S_OK;
1503 }
1504
1505 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
1506     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1507
1508     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1509
1510     return S_OK;
1511 }
1512
1513
1514 static const IBasicVideoVtbl IBasicVideo_VTable =
1515 {
1516     Basicvideo_QueryInterface,
1517     Basicvideo_AddRef,
1518     Basicvideo_Release,
1519     Basicvideo_GetTypeInfoCount,
1520     Basicvideo_GetTypeInfo,
1521     Basicvideo_GetIDsOfNames,
1522     Basicvideo_Invoke,
1523     Basicvideo_get_AvgTimePerFrame,
1524     Basicvideo_get_BitRate,
1525     Basicvideo_get_BitErrorRate,
1526     Basicvideo_get_VideoWidth,
1527     Basicvideo_get_VideoHeight,
1528     Basicvideo_put_SourceLeft,
1529     Basicvideo_get_SourceLeft,
1530     Basicvideo_put_SourceWidth,
1531     Basicvideo_get_SourceWidth,
1532     Basicvideo_put_SourceTop,
1533     Basicvideo_get_SourceTop,
1534     Basicvideo_put_SourceHeight,
1535     Basicvideo_get_SourceHeight,
1536     Basicvideo_put_DestinationLeft,
1537     Basicvideo_get_DestinationLeft,
1538     Basicvideo_put_DestinationWidth,
1539     Basicvideo_get_DestinationWidth,
1540     Basicvideo_put_DestinationTop,
1541     Basicvideo_get_DestinationTop,
1542     Basicvideo_put_DestinationHeight,
1543     Basicvideo_get_DestinationHeight,
1544     Basicvideo_SetSourcePosition,
1545     Basicvideo_GetSourcePosition,
1546     Basicvideo_SetDefaultSourcePosition,
1547     Basicvideo_SetDestinationPosition,
1548     Basicvideo_GetDestinationPosition,
1549     Basicvideo_SetDefaultDestinationPosition,
1550     Basicvideo_GetVideoSize,
1551     Basicvideo_GetVideoPaletteEntries,
1552     Basicvideo_GetCurrentImage,
1553     Basicvideo_IsUsingDefaultSource,
1554     Basicvideo_IsUsingDefaultDestination
1555 };
1556
1557
1558 /*** IUnknown methods ***/
1559 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
1560                                                  REFIID riid,
1561                                                  LPVOID*ppvObj) {
1562     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1563
1564     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1565
1566     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
1567 }
1568
1569 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
1570     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1571
1572     TRACE("(%p/%p)->()\n", This, iface);
1573
1574     return VideoRenderer_AddRef((IBaseFilter*)This);
1575 }
1576
1577 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
1578     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1579
1580     TRACE("(%p/%p)->()\n", This, iface);
1581
1582     return VideoRenderer_Release((IBaseFilter*)This);
1583 }
1584
1585 /*** IDispatch methods ***/
1586 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
1587                                                    UINT*pctinfo) {
1588     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1589
1590     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1591
1592     return S_OK;
1593 }
1594
1595 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
1596                                               UINT iTInfo,
1597                                               LCID lcid,
1598                                               ITypeInfo**ppTInfo) {
1599     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1600
1601     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1602
1603     return S_OK;
1604 }
1605
1606 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
1607                                                 REFIID riid,
1608                                                 LPOLESTR*rgszNames,
1609                                                 UINT cNames,
1610                                                 LCID lcid,
1611                                                 DISPID*rgDispId) {
1612     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1613
1614     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1615
1616     return S_OK;
1617 }
1618
1619 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
1620                                          DISPID dispIdMember,
1621                                          REFIID riid,
1622                                          LCID lcid,
1623                                          WORD wFlags,
1624                                          DISPPARAMS*pDispParams,
1625                                          VARIANT*pVarResult,
1626                                          EXCEPINFO*pExepInfo,
1627                                          UINT*puArgErr) {
1628     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1629
1630     FIXME("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1631
1632     return S_OK;
1633 }
1634
1635 /*** IVideoWindow methods ***/
1636 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
1637                                               BSTR strCaption) {
1638     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1639
1640     TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
1641
1642     if (!SetWindowTextW(This->hWnd, strCaption))
1643         return E_FAIL;
1644
1645     return S_OK;
1646 }
1647
1648 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
1649                                               BSTR *strCaption) {
1650     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1651
1652     TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
1653
1654     GetWindowTextW(This->hWnd, (LPWSTR)strCaption, 100);
1655
1656     return S_OK;
1657 }
1658
1659 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
1660                                                   LONG WindowStyle) {
1661     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1662     LONG old;
1663
1664     old = GetWindowLongA(This->hWnd, GWL_STYLE);
1665
1666     TRACE("(%p/%p)->(%x -> %x)\n", This, iface, old, WindowStyle);
1667
1668     if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1669         return E_INVALIDARG;
1670
1671     SetWindowLongA(This->hWnd, GWL_STYLE, WindowStyle);
1672     SetWindowPos(This->hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOZORDER);
1673     This->WindowStyle = WindowStyle;
1674
1675     return S_OK;
1676 }
1677
1678 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
1679                                                   LONG *WindowStyle) {
1680     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1681
1682     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
1683
1684     *WindowStyle = This->WindowStyle;
1685
1686     return S_OK;
1687 }
1688
1689 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
1690                                                     LONG WindowStyleEx) {
1691     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1692
1693     TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
1694
1695     if (!SetWindowLongA(This->hWnd, GWL_EXSTYLE, WindowStyleEx))
1696         return E_FAIL;
1697
1698     return S_OK;
1699 }
1700
1701 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
1702                                                     LONG *WindowStyleEx) {
1703     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1704
1705     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
1706
1707     *WindowStyleEx = GetWindowLongA(This->hWnd, GWL_EXSTYLE);
1708
1709     return S_OK;
1710 }
1711
1712 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
1713                                                LONG AutoShow) {
1714     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1715
1716     TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
1717
1718     This->AutoShow = AutoShow;
1719
1720     return S_OK;
1721 }
1722
1723 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
1724                                                LONG *AutoShow) {
1725     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1726
1727     TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
1728
1729     *AutoShow = This->AutoShow;
1730
1731     return S_OK;
1732 }
1733
1734 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
1735                                                   LONG WindowState) {
1736     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1737
1738     TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
1739     ShowWindow(This->hWnd, WindowState);
1740     return S_OK;
1741 }
1742
1743 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
1744                                                   LONG *WindowState) {
1745     WINDOWPLACEMENT place;
1746     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1747
1748     place.length = sizeof(place);
1749     GetWindowPlacement(This->hWnd, &place);
1750     TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
1751     *WindowState = place.showCmd;
1752
1753     return S_OK;
1754 }
1755
1756 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
1757                                                         LONG BackgroundPalette) {
1758     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1759
1760     FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, BackgroundPalette);
1761
1762     return S_OK;
1763 }
1764
1765 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
1766                                                         LONG *pBackgroundPalette) {
1767     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1768
1769     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
1770
1771     return S_OK;
1772 }
1773
1774 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
1775                                               LONG Visible) {
1776     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1777
1778     TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
1779
1780     ShowWindow(This->hWnd, Visible ? SW_SHOW : SW_HIDE);
1781
1782     return S_OK;
1783 }
1784
1785 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
1786                                               LONG *pVisible) {
1787     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1788
1789     TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
1790
1791     *pVisible = IsWindowVisible(This->hWnd);
1792
1793     return S_OK;
1794 }
1795
1796 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
1797                                            LONG Left) {
1798     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1799
1800     TRACE("(%p/%p)->(%d)\n", This, iface, Left);
1801
1802     if (!SetWindowPos(This->hWnd, NULL, Left, This->WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1803         return E_FAIL;
1804
1805     This->WindowPos.left = Left;
1806
1807     return S_OK;
1808 }
1809
1810 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
1811                                            LONG *pLeft) {
1812     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1813
1814     TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
1815
1816     *pLeft = This->WindowPos.left;
1817
1818     return S_OK;
1819 }
1820
1821 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
1822                                             LONG Width) {
1823     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1824
1825     TRACE("(%p/%p)->(%d)\n", This, iface, Width);
1826
1827     if (!SetWindowPos(This->hWnd, NULL, 0, 0, Width, This->WindowPos.bottom-This->WindowPos.top, SWP_NOZORDER|SWP_NOMOVE))
1828         return E_FAIL;
1829
1830     This->WindowPos.right = This->WindowPos.left + Width;
1831
1832     return S_OK;
1833 }
1834
1835 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
1836                                             LONG *pWidth) {
1837     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1838
1839     TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
1840
1841     *pWidth = This->WindowPos.right - This->WindowPos.left;
1842
1843     return S_OK;
1844 }
1845
1846 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
1847                                           LONG Top) {
1848     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1849
1850     TRACE("(%p/%p)->(%d)\n", This, iface, Top);
1851
1852     if (!SetWindowPos(This->hWnd, NULL, This->WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1853         return E_FAIL;
1854
1855     This->WindowPos.top = Top;
1856
1857     return S_OK;
1858 }
1859
1860 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
1861                                           LONG *pTop) {
1862     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1863
1864     TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
1865
1866     *pTop = This->WindowPos.top;
1867
1868     return S_OK;
1869 }
1870
1871 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
1872                                              LONG Height) {
1873     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1874
1875     TRACE("(%p/%p)->(%d)\n", This, iface, Height);
1876
1877     if (!SetWindowPos(This->hWnd, NULL, 0, 0, This->WindowPos.right-This->WindowPos.left, Height, SWP_NOZORDER|SWP_NOMOVE))
1878         return E_FAIL;
1879
1880     This->WindowPos.bottom = This->WindowPos.top + Height;
1881
1882     return S_OK;
1883 }
1884
1885 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
1886                                              LONG *pHeight) {
1887     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1888
1889     TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
1890
1891     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1892
1893     return S_OK;
1894 }
1895
1896 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
1897                                             OAHWND Owner) {
1898     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1899
1900     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1901
1902     This->hWndOwner = (HWND)Owner;
1903     SetParent(This->hWnd, This->hWndOwner);
1904     if (This->WindowStyle & WS_CHILD)
1905     {
1906         LONG old = GetWindowLongA(This->hWnd, GWL_STYLE);
1907         if (old != This->WindowStyle)
1908         {
1909             SetWindowLongA(This->hWnd, GWL_STYLE, This->WindowStyle);
1910             SetWindowPos(This->hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOZORDER);
1911         }
1912     }
1913
1914     return S_OK;
1915 }
1916
1917 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
1918                                             OAHWND *Owner) {
1919     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1920
1921     TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
1922
1923     *(HWND*)Owner = This->hWndOwner;
1924
1925     return S_OK;
1926 }
1927
1928 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
1929                                                    OAHWND Drain) {
1930     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1931
1932     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
1933
1934     This->hWndMsgDrain = (HWND)Drain;
1935
1936     return S_OK;
1937 }
1938
1939 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
1940                                                    OAHWND *Drain) {
1941     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1942
1943     TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
1944
1945     *Drain = (OAHWND)This->hWndMsgDrain;
1946
1947     return S_OK;
1948 }
1949
1950 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
1951                                                   LONG *Color) {
1952     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1953
1954     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
1955
1956     return S_OK;
1957 }
1958
1959 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
1960                                                   LONG Color) {
1961     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1962
1963     FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, Color);
1964
1965     return S_OK;
1966 }
1967
1968 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
1969                                                      LONG *FullScreenMode) {
1970     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1971
1972     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
1973
1974     return S_OK;
1975 }
1976
1977 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
1978                                                      LONG FullScreenMode) {
1979     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1980
1981     FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, FullScreenMode);
1982
1983     if (FullScreenMode) {
1984         ShowWindow(This->hWnd, SW_HIDE);
1985         SetParent(This->hWnd, 0);
1986         SetWindowLongA(This->hWnd, GWL_STYLE, WS_POPUP);
1987         SetWindowPos(This->hWnd,HWND_TOP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),SWP_SHOWWINDOW);
1988         GetWindowRect(This->hWnd, &This->DestRect);
1989         This->WindowPos = This->DestRect;
1990     } else {
1991         ShowWindow(This->hWnd, SW_HIDE);
1992         SetParent(This->hWnd, This->hWndOwner);
1993         SetWindowLongA(This->hWnd, GWL_STYLE, This->WindowStyle);
1994         GetClientRect(This->hWnd, &This->DestRect);
1995         SetWindowPos(This->hWnd,0,This->DestRect.left,This->DestRect.top,This->DestRect.right,This->DestRect.bottom,SWP_NOZORDER|SWP_SHOWWINDOW);
1996         This->WindowPos = This->DestRect;
1997     }
1998
1999     return S_OK;
2000 }
2001
2002 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
2003                                                       LONG Focus) {
2004     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2005     BOOL ret;
2006     IPin* pPin;
2007     HRESULT hr;
2008
2009     TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
2010
2011     if ((Focus != FALSE) && (Focus != TRUE))
2012         return E_INVALIDARG;
2013
2014     hr = IPin_ConnectedTo((IPin *)This->pInputPin, &pPin);
2015     if ((hr != S_OK) || !pPin)
2016         return VFW_E_NOT_CONNECTED;
2017
2018     if (Focus)
2019         ret = SetForegroundWindow(This->hWnd);
2020     else
2021         ret = SetWindowPos(This->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2022
2023     if (!ret)
2024         return E_FAIL;
2025
2026     return S_OK;
2027 }
2028
2029 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
2030                                                      OAHWND hwnd,
2031                                                      LONG uMsg,
2032                                                      LONG_PTR wParam,
2033                                                      LONG_PTR lParam) {
2034     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2035
2036     TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
2037
2038     if (!PostMessageA(This->hWnd, uMsg, wParam, lParam))
2039         return E_FAIL;
2040     
2041     return S_OK;
2042 }
2043
2044 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
2045                                                     LONG Left,
2046                                                     LONG Top,
2047                                                     LONG Width,
2048                                                     LONG Height) {
2049     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2050
2051     TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
2052
2053     if (!SetWindowPos(This->hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER))
2054         return E_FAIL;
2055
2056     This->WindowPos.left = Left;
2057     This->WindowPos.top = Top;
2058     This->WindowPos.right = Left + Width;
2059     This->WindowPos.bottom = Top + Height;
2060     
2061     return S_OK;
2062 }
2063
2064 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
2065                                                     LONG *pLeft,
2066                                                     LONG *pTop,
2067                                                     LONG *pWidth,
2068                                                     LONG *pHeight) {
2069     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2070
2071     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
2072
2073     *pLeft = This->WindowPos.left;
2074     *pTop = This->WindowPos.top;
2075     *pWidth = This->WindowPos.right - This->WindowPos.left;
2076     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
2077
2078     return S_OK;
2079 }
2080
2081 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
2082                                                        LONG *pWidth,
2083                                                        LONG *pHeight) {
2084     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2085
2086     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
2087
2088     *pWidth = This->VideoWidth;
2089     *pHeight = This->VideoHeight;
2090
2091     return S_OK;
2092 }
2093
2094 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
2095                                                        LONG *pWidth,
2096                                                        LONG *pHeight) {
2097     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2098
2099     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
2100
2101     *pWidth = This->VideoWidth;
2102     *pHeight = This->VideoHeight;
2103
2104     return S_OK;
2105 }
2106
2107 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
2108                                                      LONG *pLeft,
2109                                                      LONG *pTop,
2110                                                      LONG *pWidth,
2111                                                      LONG *pHeight) {
2112     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2113
2114     FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2115
2116     return S_OK;
2117 }
2118
2119 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
2120                                              LONG HideCursor) {
2121     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2122
2123     FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, HideCursor);
2124
2125     return S_OK;
2126 }
2127
2128 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
2129                                                  LONG *CursorHidden) {
2130     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2131
2132     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
2133
2134     return S_OK;
2135 }
2136
2137 static const IVideoWindowVtbl IVideoWindow_VTable =
2138 {
2139     Videowindow_QueryInterface,
2140     Videowindow_AddRef,
2141     Videowindow_Release,
2142     Videowindow_GetTypeInfoCount,
2143     Videowindow_GetTypeInfo,
2144     Videowindow_GetIDsOfNames,
2145     Videowindow_Invoke,
2146     Videowindow_put_Caption,
2147     Videowindow_get_Caption,
2148     Videowindow_put_WindowStyle,
2149     Videowindow_get_WindowStyle,
2150     Videowindow_put_WindowStyleEx,
2151     Videowindow_get_WindowStyleEx,
2152     Videowindow_put_AutoShow,
2153     Videowindow_get_AutoShow,
2154     Videowindow_put_WindowState,
2155     Videowindow_get_WindowState,
2156     Videowindow_put_BackgroundPalette,
2157     Videowindow_get_BackgroundPalette,
2158     Videowindow_put_Visible,
2159     Videowindow_get_Visible,
2160     Videowindow_put_Left,
2161     Videowindow_get_Left,
2162     Videowindow_put_Width,
2163     Videowindow_get_Width,
2164     Videowindow_put_Top,
2165     Videowindow_get_Top,
2166     Videowindow_put_Height,
2167     Videowindow_get_Height,
2168     Videowindow_put_Owner,
2169     Videowindow_get_Owner,
2170     Videowindow_put_MessageDrain,
2171     Videowindow_get_MessageDrain,
2172     Videowindow_get_BorderColor,
2173     Videowindow_put_BorderColor,
2174     Videowindow_get_FullScreenMode,
2175     Videowindow_put_FullScreenMode,
2176     Videowindow_SetWindowForeground,
2177     Videowindow_NotifyOwnerMessage,
2178     Videowindow_SetWindowPosition,
2179     Videowindow_GetWindowPosition,
2180     Videowindow_GetMinIdealImageSize,
2181     Videowindow_GetMaxIdealImageSize,
2182     Videowindow_GetRestorePosition,
2183     Videowindow_HideCursor,
2184     Videowindow_IsCursorHidden
2185 };
2186
2187 static VideoRendererImpl *from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) {
2188     return (VideoRendererImpl*)((char*)iface - offsetof(VideoRendererImpl, IAMFilterMiscFlags_vtbl));
2189 }
2190
2191 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, const REFIID riid, void **ppv) {
2192     VideoRendererImpl *This = from_IAMFilterMiscFlags(iface);
2193     return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
2194 }
2195
2196 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
2197     VideoRendererImpl *This = from_IAMFilterMiscFlags(iface);
2198     return IUnknown_AddRef((IUnknown*)This);
2199 }
2200
2201 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
2202     VideoRendererImpl *This = from_IAMFilterMiscFlags(iface);
2203     return IUnknown_Release((IUnknown*)This);
2204 }
2205
2206 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
2207     return AM_FILTER_MISC_FLAGS_IS_RENDERER;
2208 }
2209
2210 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
2211     AMFilterMiscFlags_QueryInterface,
2212     AMFilterMiscFlags_AddRef,
2213     AMFilterMiscFlags_Release,
2214     AMFilterMiscFlags_GetMiscFlags
2215 };