d3dx9/tests: Add basic tests for ID3DXRenderToEnvMap.
[wine/multimedia.git] / dlls / quartz / videorenderer.c
bloba045ba824ff7ffcf416364908aa573a8b07e9496
1 /*
2 * Video Renderer (Fullscreen and Windowed using Direct Draw)
4 * Copyright 2004 Christian Costa
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.
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.
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
21 #include "config.h"
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
25 #include "quartz_private.h"
26 #include "pin.h"
28 #include "uuids.h"
29 #include "vfwmsgs.h"
30 #include "amvideo.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "dshow.h"
34 #include "evcode.h"
35 #include "strmif.h"
36 #include "ddraw.h"
37 #include "dvdmedia.h"
39 #include <assert.h>
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 typedef struct VideoRendererImpl
47 BaseRenderer renderer;
48 BaseControlWindow baseControlWindow;
49 BaseControlVideo baseControlVideo;
51 IUnknown IUnknown_inner;
52 IAMFilterMiscFlags IAMFilterMiscFlags_iface;
53 IUnknown *outer_unk;
55 BOOL init;
56 HANDLE hThread;
58 DWORD ThreadID;
59 HANDLE hEvent;
60 /* hEvent == evComplete? */
61 BOOL ThreadResult;
62 RECT SourceRect;
63 RECT DestRect;
64 RECT WindowPos;
65 LONG VideoWidth;
66 LONG VideoHeight;
67 } VideoRendererImpl;
69 static inline VideoRendererImpl *impl_from_BaseWindow(BaseWindow *iface)
71 return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlWindow.baseWindow);
74 static inline VideoRendererImpl *impl_from_BaseRenderer(BaseRenderer *iface)
76 return CONTAINING_RECORD(iface, VideoRendererImpl, renderer);
79 static inline VideoRendererImpl *impl_from_IBaseFilter(IBaseFilter *iface)
81 return CONTAINING_RECORD(iface, VideoRendererImpl, renderer.filter.IBaseFilter_iface);
84 static inline VideoRendererImpl *impl_from_IVideoWindow(IVideoWindow *iface)
86 return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlWindow.IVideoWindow_iface);
89 static inline VideoRendererImpl *impl_from_BaseControlVideo(BaseControlVideo *iface)
91 return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlVideo);
94 static inline VideoRendererImpl *impl_from_IBasicVideo(IBasicVideo *iface)
96 return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlVideo.IBasicVideo_iface);
99 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
101 VideoRendererImpl* This = lpParameter;
102 MSG msg;
103 BOOL fGotMessage;
105 TRACE("Starting message loop\n");
107 if (FAILED(BaseWindowImpl_PrepareWindow(&This->baseControlWindow.baseWindow)))
109 This->ThreadResult = FALSE;
110 SetEvent(This->hEvent);
111 return 0;
114 This->ThreadResult = TRUE;
115 SetEvent(This->hEvent);
117 while ((fGotMessage = GetMessageW(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1)
119 TranslateMessage(&msg);
120 DispatchMessageW(&msg);
123 TRACE("End of message loop\n");
125 return msg.wParam;
128 static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
130 This->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
131 if (!This->hEvent)
132 return FALSE;
134 This->hThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->ThreadID);
135 if (!This->hThread)
137 CloseHandle(This->hEvent);
138 return FALSE;
141 WaitForSingleObject(This->hEvent, INFINITE);
143 if (!This->ThreadResult)
145 CloseHandle(This->hEvent);
146 CloseHandle(This->hThread);
147 return FALSE;
150 return TRUE;
153 static void VideoRenderer_AutoShowWindow(VideoRendererImpl *This) {
154 if (!This->init && (!This->WindowPos.right || !This->WindowPos.top))
156 DWORD style = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE);
157 DWORD style_ex = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_EXSTYLE);
159 if (!This->WindowPos.right)
161 This->WindowPos.left = This->SourceRect.left;
162 This->WindowPos.right = This->SourceRect.right;
164 if (!This->WindowPos.bottom)
166 This->WindowPos.top = This->SourceRect.top;
167 This->WindowPos.bottom = This->SourceRect.bottom;
170 AdjustWindowRectEx(&This->WindowPos, style, TRUE, style_ex);
172 TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom);
173 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
174 This->WindowPos.left,
175 This->WindowPos.top,
176 This->WindowPos.right - This->WindowPos.left,
177 This->WindowPos.bottom - This->WindowPos.top,
178 SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
180 GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect);
182 else if (!This->init)
183 This->DestRect = This->WindowPos;
184 This->init = TRUE;
185 if (This->baseControlWindow.AutoShow)
186 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_SHOW);
189 static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size)
191 AM_MEDIA_TYPE amt;
192 HRESULT hr = S_OK;
193 DDSURFACEDESC sdesc;
194 BITMAPINFOHEADER *bmiHeader;
196 TRACE("(%p)->(%p, %d)\n", This, data, size);
198 sdesc.dwSize = sizeof(sdesc);
199 hr = IPin_ConnectionMediaType(&This->renderer.pInputPin->pin.IPin_iface, &amt);
200 if (FAILED(hr)) {
201 ERR("Unable to retrieve media type\n");
202 return hr;
205 if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo))
207 bmiHeader = &((VIDEOINFOHEADER *)amt.pbFormat)->bmiHeader;
209 else if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo2))
211 bmiHeader = &((VIDEOINFOHEADER2 *)amt.pbFormat)->bmiHeader;
213 else
215 FIXME("Unknown type %s\n", debugstr_guid(&amt.subtype));
216 return VFW_E_RUNTIME_ERROR;
219 TRACE("biSize = %d\n", bmiHeader->biSize);
220 TRACE("biWidth = %d\n", bmiHeader->biWidth);
221 TRACE("biHeight = %d\n", bmiHeader->biHeight);
222 TRACE("biPlanes = %d\n", bmiHeader->biPlanes);
223 TRACE("biBitCount = %d\n", bmiHeader->biBitCount);
224 TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
225 TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
227 if (!This->baseControlWindow.baseWindow.hDC) {
228 ERR("Cannot get DC from window!\n");
229 return E_FAIL;
232 TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom);
233 TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom);
235 StretchDIBits(This->baseControlWindow.baseWindow.hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left,
236 This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top,
237 This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top,
238 data, (BITMAPINFO *)bmiHeader, DIB_RGB_COLORS, SRCCOPY);
240 return S_OK;
243 static HRESULT WINAPI VideoRenderer_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
245 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
246 if (IMediaSample_IsPreroll(pSample) == S_OK)
247 return E_FAIL;
248 return S_FALSE;
251 static HRESULT WINAPI VideoRenderer_DoRenderSample(BaseRenderer* iface, IMediaSample * pSample)
253 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
254 LPBYTE pbSrcStream = NULL;
255 LONG cbSrcStream = 0;
256 HRESULT hr;
258 TRACE("(%p)->(%p)\n", This, pSample);
260 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
261 if (FAILED(hr))
263 ERR("Cannot get pointer to sample data (%x)\n", hr);
264 return hr;
267 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
269 TRACE("val %p %d\n", pbSrcStream, cbSrcStream);
271 #if 0 /* For debugging purpose */
273 int i;
274 for(i = 0; i < cbSrcStream; i++)
276 if ((i!=0) && !(i%16))
277 TRACE("\n");
278 TRACE("%02x ", pbSrcStream[i]);
280 TRACE("\n");
282 #endif
284 SetEvent(This->hEvent);
285 if (This->renderer.filter.state == State_Paused)
287 VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
288 SetEvent(This->hEvent);
289 if (This->renderer.filter.state == State_Paused)
291 /* Flushing */
292 return S_OK;
294 if (This->renderer.filter.state == State_Stopped)
296 return VFW_E_WRONG_STATE;
298 } else {
299 VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
301 return S_OK;
304 static HRESULT WINAPI VideoRenderer_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
306 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
308 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
309 return S_FALSE;
311 if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
312 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
313 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
314 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
316 LONG height;
318 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
320 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
321 This->SourceRect.left = 0;
322 This->SourceRect.top = 0;
323 This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
324 height = format->bmiHeader.biHeight;
325 if (height < 0)
326 This->SourceRect.bottom = This->VideoHeight = -height;
327 else
328 This->SourceRect.bottom = This->VideoHeight = height;
330 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
332 VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat;
334 This->SourceRect.left = 0;
335 This->SourceRect.top = 0;
336 This->SourceRect.right = This->VideoWidth = format2->bmiHeader.biWidth;
337 height = format2->bmiHeader.biHeight;
338 if (height < 0)
339 This->SourceRect.bottom = This->VideoHeight = -height;
340 else
341 This->SourceRect.bottom = This->VideoHeight = height;
343 else
345 WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
346 return S_FALSE;
348 return S_OK;
350 return S_FALSE;
353 static HRESULT WINAPI VideoRenderer_EndFlush(BaseRenderer* iface)
355 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
357 TRACE("(%p)->()\n", iface);
359 if (This->renderer.pMediaSample) {
360 ResetEvent(This->hEvent);
361 LeaveCriticalSection(iface->pInputPin->pin.pCritSec);
362 LeaveCriticalSection(&iface->csRenderLock);
363 LeaveCriticalSection(&iface->filter.csFilter);
364 WaitForSingleObject(This->hEvent, INFINITE);
365 EnterCriticalSection(&iface->filter.csFilter);
366 EnterCriticalSection(&iface->csRenderLock);
367 EnterCriticalSection(iface->pInputPin->pin.pCritSec);
369 if (This->renderer.filter.state == State_Paused) {
370 ResetEvent(This->hEvent);
373 return BaseRendererImpl_EndFlush(iface);
376 static VOID WINAPI VideoRenderer_OnStopStreaming(BaseRenderer* iface)
378 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
380 TRACE("(%p)->()\n", This);
382 SetEvent(This->hEvent);
383 if (This->baseControlWindow.AutoShow)
384 /* Black it out */
385 RedrawWindow(This->baseControlWindow.baseWindow.hWnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE);
388 static VOID WINAPI VideoRenderer_OnStartStreaming(BaseRenderer* iface)
390 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
392 TRACE("(%p)\n", This);
394 if (This->renderer.pInputPin->pin.pConnectedTo && (This->renderer.filter.state == State_Stopped || !This->renderer.pInputPin->end_of_stream))
396 if (This->renderer.filter.state == State_Stopped)
398 ResetEvent(This->hEvent);
399 VideoRenderer_AutoShowWindow(This);
404 static LPWSTR WINAPI VideoRenderer_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
406 static const WCHAR classnameW[] = { 'W','i','n','e',' ','A','c','t','i','v','e','M','o','v','i','e',' ','C','l','a','s','s',0 };
408 *pClassStyles = 0;
409 *pWindowStyles = WS_SIZEBOX;
410 *pWindowStylesEx = 0;
412 return (LPWSTR)classnameW;
415 static RECT WINAPI VideoRenderer_GetDefaultRect(BaseWindow *iface)
417 VideoRendererImpl *This = impl_from_BaseWindow(iface);
418 static RECT defRect;
420 defRect.left = defRect.top = 0;
421 defRect.right = This->VideoWidth;
422 defRect.bottom = This->VideoHeight;
424 return defRect;
427 static BOOL WINAPI VideoRenderer_OnSize(BaseWindow *iface, LONG Width, LONG Height)
429 VideoRendererImpl *This = impl_from_BaseWindow(iface);
431 TRACE("WM_SIZE %d %d\n", Width, Height);
432 GetClientRect(iface->hWnd, &This->DestRect);
433 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
434 This->DestRect.left,
435 This->DestRect.top,
436 This->DestRect.right - This->DestRect.left,
437 This->DestRect.bottom - This->DestRect.top);
438 return BaseWindowImpl_OnSize(iface, Width, Height);
441 static const BaseRendererFuncTable BaseFuncTable = {
442 VideoRenderer_CheckMediaType,
443 VideoRenderer_DoRenderSample,
444 /**/
445 NULL,
446 NULL,
447 NULL,
448 VideoRenderer_OnStartStreaming,
449 VideoRenderer_OnStopStreaming,
450 NULL,
451 NULL,
452 NULL,
453 VideoRenderer_ShouldDrawSampleNow,
454 NULL,
455 /**/
456 NULL,
457 NULL,
458 NULL,
459 NULL,
460 VideoRenderer_EndFlush,
463 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
464 VideoRenderer_GetClassWindowStyles,
465 VideoRenderer_GetDefaultRect,
466 NULL,
467 BaseControlWindowImpl_PossiblyEatMessage,
468 VideoRenderer_OnSize
471 static HRESULT WINAPI VideoRenderer_GetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
473 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
474 CopyRect(pSourceRect,&This->SourceRect);
475 return S_OK;
478 static HRESULT WINAPI VideoRenderer_GetStaticImage(BaseControlVideo* iface, LONG *pBufferSize, LONG *pDIBImage)
480 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
481 BITMAPINFOHEADER *bmiHeader;
482 LONG needed_size;
483 AM_MEDIA_TYPE *amt = &This->renderer.pInputPin->pin.mtCurrent;
484 char *ptr;
486 FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage);
488 EnterCriticalSection(&This->renderer.filter.csFilter);
490 if (!This->renderer.pMediaSample)
492 LeaveCriticalSection(&This->renderer.filter.csFilter);
493 return (This->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
496 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
498 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
500 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
502 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
504 else
506 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
507 LeaveCriticalSection(&This->renderer.filter.csFilter);
508 return VFW_E_RUNTIME_ERROR;
511 needed_size = bmiHeader->biSize;
512 needed_size += IMediaSample_GetActualDataLength(This->renderer.pMediaSample);
514 if (!pDIBImage)
516 *pBufferSize = needed_size;
517 LeaveCriticalSection(&This->renderer.filter.csFilter);
518 return S_OK;
521 if (needed_size < *pBufferSize)
523 ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
524 LeaveCriticalSection(&This->renderer.filter.csFilter);
525 return E_FAIL;
527 *pBufferSize = needed_size;
529 memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
530 IMediaSample_GetPointer(This->renderer.pMediaSample, (BYTE **)&ptr);
531 memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->renderer.pMediaSample));
533 LeaveCriticalSection(&This->renderer.filter.csFilter);
534 return S_OK;
537 static HRESULT WINAPI VideoRenderer_GetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
539 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
540 CopyRect(pTargetRect,&This->DestRect);
541 return S_OK;
544 static VIDEOINFOHEADER* WINAPI VideoRenderer_GetVideoFormat(BaseControlVideo* iface)
546 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
547 AM_MEDIA_TYPE *pmt;
549 TRACE("(%p/%p)\n", This, iface);
551 pmt = &This->renderer.pInputPin->pin.mtCurrent;
552 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
553 return (VIDEOINFOHEADER*)pmt->pbFormat;
554 } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
555 static VIDEOINFOHEADER vih;
556 VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
557 memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
558 memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
559 return &vih;
560 } else {
561 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
562 return NULL;
566 static HRESULT WINAPI VideoRenderer_IsDefaultSourceRect(BaseControlVideo* iface)
568 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
569 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
571 return S_OK;
574 static HRESULT WINAPI VideoRenderer_IsDefaultTargetRect(BaseControlVideo* iface)
576 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
577 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
579 return S_OK;
582 static HRESULT WINAPI VideoRenderer_SetDefaultSourceRect(BaseControlVideo* iface)
584 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
586 This->SourceRect.left = 0;
587 This->SourceRect.top = 0;
588 This->SourceRect.right = This->VideoWidth;
589 This->SourceRect.bottom = This->VideoHeight;
591 return S_OK;
594 static HRESULT WINAPI VideoRenderer_SetDefaultTargetRect(BaseControlVideo* iface)
596 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
597 RECT rect;
599 if (!GetClientRect(This->baseControlWindow.baseWindow.hWnd, &rect))
600 return E_FAIL;
602 This->SourceRect.left = 0;
603 This->SourceRect.top = 0;
604 This->SourceRect.right = rect.right;
605 This->SourceRect.bottom = rect.bottom;
607 return S_OK;
610 static HRESULT WINAPI VideoRenderer_SetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
612 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
613 CopyRect(&This->SourceRect,pSourceRect);
614 return S_OK;
617 static HRESULT WINAPI VideoRenderer_SetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
619 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
620 CopyRect(&This->DestRect,pTargetRect);
621 return S_OK;
624 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
625 VideoRenderer_GetSourceRect,
626 VideoRenderer_GetStaticImage,
627 VideoRenderer_GetTargetRect,
628 VideoRenderer_GetVideoFormat,
629 VideoRenderer_IsDefaultSourceRect,
630 VideoRenderer_IsDefaultTargetRect,
631 VideoRenderer_SetDefaultSourceRect,
632 VideoRenderer_SetDefaultTargetRect,
633 VideoRenderer_SetSourceRect,
634 VideoRenderer_SetTargetRect
637 static inline VideoRendererImpl *impl_from_IUnknown(IUnknown *iface)
639 return CONTAINING_RECORD(iface, VideoRendererImpl, IUnknown_inner);
642 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
644 VideoRendererImpl *This = impl_from_IUnknown(iface);
646 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
648 *ppv = NULL;
650 if (IsEqualIID(riid, &IID_IUnknown))
651 *ppv = &This->IUnknown_inner;
652 else if (IsEqualIID(riid, &IID_IBasicVideo))
653 *ppv = &This->baseControlVideo.IBasicVideo_iface;
654 else if (IsEqualIID(riid, &IID_IVideoWindow))
655 *ppv = &This->baseControlWindow.IVideoWindow_iface;
656 else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
657 *ppv = &This->IAMFilterMiscFlags_iface;
658 else
660 HRESULT hr;
661 hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
662 if (SUCCEEDED(hr))
663 return hr;
666 if (*ppv)
668 IUnknown_AddRef((IUnknown *)*ppv);
669 return S_OK;
672 if (!IsEqualIID(riid, &IID_IPin))
673 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
675 return E_NOINTERFACE;
678 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown *iface)
680 VideoRendererImpl *This = impl_from_IUnknown(iface);
681 ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
683 TRACE("(%p)->(): new ref = %d\n", This, refCount);
685 return refCount;
688 static ULONG WINAPI VideoRendererInner_Release(IUnknown *iface)
690 VideoRendererImpl *This = impl_from_IUnknown(iface);
691 ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
693 TRACE("(%p)->(): new ref = %d\n", This, refCount);
695 if (!refCount)
697 BaseControlWindow_Destroy(&This->baseControlWindow);
698 BaseControlVideo_Destroy(&This->baseControlVideo);
699 PostThreadMessageW(This->ThreadID, WM_QUIT, 0, 0);
700 WaitForSingleObject(This->hThread, INFINITE);
701 CloseHandle(This->hThread);
702 CloseHandle(This->hEvent);
704 TRACE("Destroying Video Renderer\n");
705 CoTaskMemFree(This);
707 return 0;
709 else
710 return refCount;
713 static const IUnknownVtbl IInner_VTable =
715 VideoRendererInner_QueryInterface,
716 VideoRendererInner_AddRef,
717 VideoRendererInner_Release
720 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
722 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
723 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
726 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
728 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
729 return IUnknown_AddRef(This->outer_unk);
732 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
734 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
735 return IUnknown_Release(This->outer_unk);
738 /** IMediaFilter methods **/
740 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
742 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
744 TRACE("(%p/%p)->()\n", This, iface);
746 EnterCriticalSection(&This->renderer.csRenderLock);
747 if (This->renderer.filter.state != State_Paused)
749 if (This->renderer.filter.state == State_Stopped)
751 This->renderer.pInputPin->end_of_stream = 0;
752 ResetEvent(This->hEvent);
753 VideoRenderer_AutoShowWindow(This);
756 ResetEvent(This->renderer.RenderEvent);
757 This->renderer.filter.state = State_Paused;
759 LeaveCriticalSection(&This->renderer.csRenderLock);
761 return S_OK;
764 static const IBaseFilterVtbl VideoRenderer_Vtbl =
766 VideoRenderer_QueryInterface,
767 VideoRenderer_AddRef,
768 VideoRenderer_Release,
769 BaseFilterImpl_GetClassID,
770 BaseRendererImpl_Stop,
771 VideoRenderer_Pause,
772 BaseRendererImpl_Run,
773 BaseRendererImpl_GetState,
774 BaseRendererImpl_SetSyncSource,
775 BaseFilterImpl_GetSyncSource,
776 BaseFilterImpl_EnumPins,
777 BaseRendererImpl_FindPin,
778 BaseFilterImpl_QueryFilterInfo,
779 BaseFilterImpl_JoinFilterGraph,
780 BaseFilterImpl_QueryVendorInfo
783 /*** IUnknown methods ***/
784 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
785 REFIID riid,
786 LPVOID*ppvObj) {
787 VideoRendererImpl *This = impl_from_IBasicVideo(iface);
789 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
791 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
794 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
795 VideoRendererImpl *This = impl_from_IBasicVideo(iface);
797 TRACE("(%p/%p)->()\n", This, iface);
799 return IUnknown_AddRef(This->outer_unk);
802 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
803 VideoRendererImpl *This = impl_from_IBasicVideo(iface);
805 TRACE("(%p/%p)->()\n", This, iface);
807 return IUnknown_Release(This->outer_unk);
810 static const IBasicVideoVtbl IBasicVideo_VTable =
812 Basicvideo_QueryInterface,
813 Basicvideo_AddRef,
814 Basicvideo_Release,
815 BaseControlVideoImpl_GetTypeInfoCount,
816 BaseControlVideoImpl_GetTypeInfo,
817 BaseControlVideoImpl_GetIDsOfNames,
818 BaseControlVideoImpl_Invoke,
819 BaseControlVideoImpl_get_AvgTimePerFrame,
820 BaseControlVideoImpl_get_BitRate,
821 BaseControlVideoImpl_get_BitErrorRate,
822 BaseControlVideoImpl_get_VideoWidth,
823 BaseControlVideoImpl_get_VideoHeight,
824 BaseControlVideoImpl_put_SourceLeft,
825 BaseControlVideoImpl_get_SourceLeft,
826 BaseControlVideoImpl_put_SourceWidth,
827 BaseControlVideoImpl_get_SourceWidth,
828 BaseControlVideoImpl_put_SourceTop,
829 BaseControlVideoImpl_get_SourceTop,
830 BaseControlVideoImpl_put_SourceHeight,
831 BaseControlVideoImpl_get_SourceHeight,
832 BaseControlVideoImpl_put_DestinationLeft,
833 BaseControlVideoImpl_get_DestinationLeft,
834 BaseControlVideoImpl_put_DestinationWidth,
835 BaseControlVideoImpl_get_DestinationWidth,
836 BaseControlVideoImpl_put_DestinationTop,
837 BaseControlVideoImpl_get_DestinationTop,
838 BaseControlVideoImpl_put_DestinationHeight,
839 BaseControlVideoImpl_get_DestinationHeight,
840 BaseControlVideoImpl_SetSourcePosition,
841 BaseControlVideoImpl_GetSourcePosition,
842 BaseControlVideoImpl_SetDefaultSourcePosition,
843 BaseControlVideoImpl_SetDestinationPosition,
844 BaseControlVideoImpl_GetDestinationPosition,
845 BaseControlVideoImpl_SetDefaultDestinationPosition,
846 BaseControlVideoImpl_GetVideoSize,
847 BaseControlVideoImpl_GetVideoPaletteEntries,
848 BaseControlVideoImpl_GetCurrentImage,
849 BaseControlVideoImpl_IsUsingDefaultSource,
850 BaseControlVideoImpl_IsUsingDefaultDestination
854 /*** IUnknown methods ***/
855 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
856 REFIID riid,
857 LPVOID*ppvObj) {
858 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
860 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
862 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
865 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
866 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
868 TRACE("(%p/%p)->()\n", This, iface);
870 return IUnknown_AddRef(This->outer_unk);
873 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
874 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
876 TRACE("(%p/%p)->()\n", This, iface);
878 return IUnknown_Release(This->outer_unk);
881 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
882 LONG *FullScreenMode) {
883 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
885 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
887 return S_OK;
890 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
891 LONG FullScreenMode) {
892 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
894 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, FullScreenMode);
896 if (FullScreenMode) {
897 This->baseControlWindow.baseWindow.WindowStyles = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE);
898 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_HIDE);
899 SetParent(This->baseControlWindow.baseWindow.hWnd, 0);
900 SetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE, WS_POPUP);
901 SetWindowPos(This->baseControlWindow.baseWindow.hWnd,HWND_TOP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),SWP_SHOWWINDOW);
902 GetWindowRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect);
903 This->WindowPos = This->DestRect;
904 } else {
905 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_HIDE);
906 SetParent(This->baseControlWindow.baseWindow.hWnd, This->baseControlWindow.hwndOwner);
907 SetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE, This->baseControlWindow.baseWindow.WindowStyles);
908 GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect);
909 SetWindowPos(This->baseControlWindow.baseWindow.hWnd,0,This->DestRect.left,This->DestRect.top,This->DestRect.right,This->DestRect.bottom,SWP_NOZORDER|SWP_SHOWWINDOW);
910 This->WindowPos = This->DestRect;
913 return S_OK;
916 static const IVideoWindowVtbl IVideoWindow_VTable =
918 Videowindow_QueryInterface,
919 Videowindow_AddRef,
920 Videowindow_Release,
921 BaseControlWindowImpl_GetTypeInfoCount,
922 BaseControlWindowImpl_GetTypeInfo,
923 BaseControlWindowImpl_GetIDsOfNames,
924 BaseControlWindowImpl_Invoke,
925 BaseControlWindowImpl_put_Caption,
926 BaseControlWindowImpl_get_Caption,
927 BaseControlWindowImpl_put_WindowStyle,
928 BaseControlWindowImpl_get_WindowStyle,
929 BaseControlWindowImpl_put_WindowStyleEx,
930 BaseControlWindowImpl_get_WindowStyleEx,
931 BaseControlWindowImpl_put_AutoShow,
932 BaseControlWindowImpl_get_AutoShow,
933 BaseControlWindowImpl_put_WindowState,
934 BaseControlWindowImpl_get_WindowState,
935 BaseControlWindowImpl_put_BackgroundPalette,
936 BaseControlWindowImpl_get_BackgroundPalette,
937 BaseControlWindowImpl_put_Visible,
938 BaseControlWindowImpl_get_Visible,
939 BaseControlWindowImpl_put_Left,
940 BaseControlWindowImpl_get_Left,
941 BaseControlWindowImpl_put_Width,
942 BaseControlWindowImpl_get_Width,
943 BaseControlWindowImpl_put_Top,
944 BaseControlWindowImpl_get_Top,
945 BaseControlWindowImpl_put_Height,
946 BaseControlWindowImpl_get_Height,
947 BaseControlWindowImpl_put_Owner,
948 BaseControlWindowImpl_get_Owner,
949 BaseControlWindowImpl_put_MessageDrain,
950 BaseControlWindowImpl_get_MessageDrain,
951 BaseControlWindowImpl_get_BorderColor,
952 BaseControlWindowImpl_put_BorderColor,
953 Videowindow_get_FullScreenMode,
954 Videowindow_put_FullScreenMode,
955 BaseControlWindowImpl_SetWindowForeground,
956 BaseControlWindowImpl_NotifyOwnerMessage,
957 BaseControlWindowImpl_SetWindowPosition,
958 BaseControlWindowImpl_GetWindowPosition,
959 BaseControlWindowImpl_GetMinIdealImageSize,
960 BaseControlWindowImpl_GetMaxIdealImageSize,
961 BaseControlWindowImpl_GetRestorePosition,
962 BaseControlWindowImpl_HideCursor,
963 BaseControlWindowImpl_IsCursorHidden
966 static VideoRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
968 return CONTAINING_RECORD(iface, VideoRendererImpl, IAMFilterMiscFlags_iface);
971 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid,
972 void **ppv)
974 VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
975 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
978 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface)
980 VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
981 return IUnknown_AddRef(This->outer_unk);
984 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface)
986 VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
987 return IUnknown_Release(This->outer_unk);
990 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface)
992 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
995 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
996 AMFilterMiscFlags_QueryInterface,
997 AMFilterMiscFlags_AddRef,
998 AMFilterMiscFlags_Release,
999 AMFilterMiscFlags_GetMiscFlags
1002 HRESULT VideoRenderer_create(IUnknown *pUnkOuter, void **ppv)
1004 HRESULT hr;
1005 VideoRendererImpl * pVideoRenderer;
1007 TRACE("(%p, %p)\n", pUnkOuter, ppv);
1009 *ppv = NULL;
1011 pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
1012 pVideoRenderer->IUnknown_inner.lpVtbl = &IInner_VTable;
1013 pVideoRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1015 pVideoRenderer->init = 0;
1016 ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
1017 ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
1018 ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
1020 if (pUnkOuter)
1021 pVideoRenderer->outer_unk = pUnkOuter;
1022 else
1023 pVideoRenderer->outer_unk = &pVideoRenderer->IUnknown_inner;
1025 hr = BaseRenderer_Init(&pVideoRenderer->renderer, &VideoRenderer_Vtbl, pUnkOuter,
1026 &CLSID_VideoRenderer, (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"),
1027 &BaseFuncTable);
1029 if (FAILED(hr))
1030 goto fail;
1032 hr = BaseControlWindow_Init(&pVideoRenderer->baseControlWindow, &IVideoWindow_VTable,
1033 &pVideoRenderer->renderer.filter, &pVideoRenderer->renderer.filter.csFilter,
1034 &pVideoRenderer->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1035 if (FAILED(hr))
1036 goto fail;
1038 hr = BaseControlVideo_Init(&pVideoRenderer->baseControlVideo, &IBasicVideo_VTable,
1039 &pVideoRenderer->renderer.filter, &pVideoRenderer->renderer.filter.csFilter,
1040 &pVideoRenderer->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1041 if (FAILED(hr))
1042 goto fail;
1044 if (!CreateRenderingSubsystem(pVideoRenderer)) {
1045 hr = E_FAIL;
1046 goto fail;
1049 *ppv = &pVideoRenderer->IUnknown_inner;
1050 return S_OK;
1052 fail:
1053 BaseRendererImpl_Release(&pVideoRenderer->renderer.filter.IBaseFilter_iface);
1054 CoTaskMemFree(pVideoRenderer);
1055 return hr;
1058 HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
1060 /* TODO: Attempt to use the VMR-7 renderer instead when possible */
1061 return VideoRenderer_create(pUnkOuter, ppv);