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
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
25 #include "quartz_private.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
45 static const IBaseFilterVtbl VideoRenderer_Vtbl
;
46 static const IUnknownVtbl IInner_VTable
;
47 static const IBasicVideoVtbl IBasicVideo_VTable
;
48 static const IVideoWindowVtbl IVideoWindow_VTable
;
49 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
;
51 typedef struct VideoRendererImpl
53 BaseRenderer renderer
;
54 BaseControlWindow baseControlWindow
;
55 BaseControlVideo baseControlVideo
;
57 const IUnknownVtbl
* IInner_vtbl
;
58 const IAMFilterMiscFlagsVtbl
*IAMFilterMiscFlags_vtbl
;
65 /* hEvent == evComplete? */
77 static inline VideoRendererImpl
*impl_from_BaseWindow(BaseWindow
*iface
)
79 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlWindow
.baseWindow
);
82 static inline VideoRendererImpl
*impl_from_BaseRenderer(BaseRenderer
*iface
)
84 return CONTAINING_RECORD(iface
, VideoRendererImpl
, renderer
);
87 static inline VideoRendererImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
89 return CONTAINING_RECORD(iface
, VideoRendererImpl
, renderer
.filter
.IBaseFilter_iface
);
92 static inline VideoRendererImpl
*impl_from_IVideoWindow(IVideoWindow
*iface
)
94 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlWindow
.IVideoWindow_iface
);
97 static inline VideoRendererImpl
*impl_from_BaseControlVideo(BaseControlVideo
*iface
)
99 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlVideo
);
102 static inline VideoRendererImpl
*impl_from_IBasicVideo(IBasicVideo
*iface
)
104 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlVideo
.IBasicVideo_iface
);
107 static DWORD WINAPI
MessageLoop(LPVOID lpParameter
)
109 VideoRendererImpl
* This
= lpParameter
;
113 TRACE("Starting message loop\n");
115 if (FAILED(BaseWindowImpl_PrepareWindow(&This
->baseControlWindow
.baseWindow
)))
117 This
->ThreadResult
= FALSE
;
118 SetEvent(This
->hEvent
);
122 This
->ThreadResult
= TRUE
;
123 SetEvent(This
->hEvent
);
125 while ((fGotMessage
= GetMessageW(&msg
, NULL
, 0, 0)) != 0 && fGotMessage
!= -1)
127 TranslateMessage(&msg
);
128 DispatchMessageW(&msg
);
131 TRACE("End of message loop\n");
136 static BOOL
CreateRenderingSubsystem(VideoRendererImpl
* This
)
138 This
->hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
142 This
->hThread
= CreateThread(NULL
, 0, MessageLoop
, This
, 0, &This
->ThreadID
);
145 CloseHandle(This
->hEvent
);
149 WaitForSingleObject(This
->hEvent
, INFINITE
);
151 if (!This
->ThreadResult
)
153 CloseHandle(This
->hEvent
);
154 CloseHandle(This
->hThread
);
161 static void VideoRenderer_AutoShowWindow(VideoRendererImpl
*This
) {
162 if (!This
->init
&& (!This
->WindowPos
.right
|| !This
->WindowPos
.top
))
164 DWORD style
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
);
165 DWORD style_ex
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_EXSTYLE
);
167 if (!This
->WindowPos
.right
)
169 This
->WindowPos
.left
= This
->SourceRect
.left
;
170 This
->WindowPos
.right
= This
->SourceRect
.right
;
172 if (!This
->WindowPos
.bottom
)
174 This
->WindowPos
.top
= This
->SourceRect
.top
;
175 This
->WindowPos
.bottom
= This
->SourceRect
.bottom
;
178 AdjustWindowRectEx(&This
->WindowPos
, style
, TRUE
, style_ex
);
180 TRACE("WindowPos: %d %d %d %d\n", This
->WindowPos
.left
, This
->WindowPos
.top
, This
->WindowPos
.right
, This
->WindowPos
.bottom
);
181 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
, NULL
,
182 This
->WindowPos
.left
,
184 This
->WindowPos
.right
- This
->WindowPos
.left
,
185 This
->WindowPos
.bottom
- This
->WindowPos
.top
,
186 SWP_NOZORDER
|SWP_NOMOVE
|SWP_DEFERERASE
);
188 GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
190 else if (!This
->init
)
191 This
->DestRect
= This
->WindowPos
;
193 if (This
->baseControlWindow
.AutoShow
)
194 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_SHOW
);
197 static DWORD
VideoRenderer_SendSampleData(VideoRendererImpl
* This
, LPBYTE data
, DWORD size
)
202 BITMAPINFOHEADER
*bmiHeader
;
204 TRACE("(%p)->(%p, %d)\n", This
, data
, size
);
206 sdesc
.dwSize
= sizeof(sdesc
);
207 hr
= IPin_ConnectionMediaType(&This
->renderer
.pInputPin
->pin
.IPin_iface
, &amt
);
209 ERR("Unable to retrieve media type\n");
213 if (IsEqualIID(&amt
.formattype
, &FORMAT_VideoInfo
))
215 bmiHeader
= &((VIDEOINFOHEADER
*)amt
.pbFormat
)->bmiHeader
;
217 else if (IsEqualIID(&amt
.formattype
, &FORMAT_VideoInfo2
))
219 bmiHeader
= &((VIDEOINFOHEADER2
*)amt
.pbFormat
)->bmiHeader
;
223 FIXME("Unknown type %s\n", debugstr_guid(&amt
.subtype
));
224 return VFW_E_RUNTIME_ERROR
;
227 TRACE("biSize = %d\n", bmiHeader
->biSize
);
228 TRACE("biWidth = %d\n", bmiHeader
->biWidth
);
229 TRACE("biHeight = %d\n", bmiHeader
->biHeight
);
230 TRACE("biPlanes = %d\n", bmiHeader
->biPlanes
);
231 TRACE("biBitCount = %d\n", bmiHeader
->biBitCount
);
232 TRACE("biCompression = %s\n", debugstr_an((LPSTR
)&(bmiHeader
->biCompression
), 4));
233 TRACE("biSizeImage = %d\n", bmiHeader
->biSizeImage
);
235 if (!This
->baseControlWindow
.baseWindow
.hDC
) {
236 ERR("Cannot get DC from window!\n");
240 TRACE("Src Rect: %d %d %d %d\n", This
->SourceRect
.left
, This
->SourceRect
.top
, This
->SourceRect
.right
, This
->SourceRect
.bottom
);
241 TRACE("Dst Rect: %d %d %d %d\n", This
->DestRect
.left
, This
->DestRect
.top
, This
->DestRect
.right
, This
->DestRect
.bottom
);
243 StretchDIBits(This
->baseControlWindow
.baseWindow
.hDC
, This
->DestRect
.left
, This
->DestRect
.top
, This
->DestRect
.right
-This
->DestRect
.left
,
244 This
->DestRect
.bottom
- This
->DestRect
.top
, This
->SourceRect
.left
, This
->SourceRect
.top
,
245 This
->SourceRect
.right
- This
->SourceRect
.left
, This
->SourceRect
.bottom
- This
->SourceRect
.top
,
246 data
, (BITMAPINFO
*)bmiHeader
, DIB_RGB_COLORS
, SRCCOPY
);
251 static HRESULT WINAPI
VideoRenderer_ShouldDrawSampleNow(BaseRenderer
*This
, IMediaSample
*pSample
, REFERENCE_TIME
*pStartTime
, REFERENCE_TIME
*pEndTime
)
253 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
254 if (IMediaSample_IsPreroll(pSample
) == S_OK
)
259 static HRESULT WINAPI
VideoRenderer_DoRenderSample(BaseRenderer
* iface
, IMediaSample
* pSample
)
261 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
262 LPBYTE pbSrcStream
= NULL
;
263 LONG cbSrcStream
= 0;
266 TRACE("(%p)->(%p)\n", This
, pSample
);
268 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
271 ERR("Cannot get pointer to sample data (%x)\n", hr
);
275 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
277 TRACE("val %p %d\n", pbSrcStream
, cbSrcStream
);
279 #if 0 /* For debugging purpose */
282 for(i
= 0; i
< cbSrcStream
; i
++)
284 if ((i
!=0) && !(i
%16))
286 TRACE("%02x ", pbSrcStream
[i
]);
292 SetEvent(This
->hEvent
);
293 if (This
->renderer
.filter
.state
== State_Paused
)
295 VideoRenderer_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
296 SetEvent(This
->hEvent
);
297 if (This
->renderer
.filter
.state
== State_Paused
)
302 if (This
->renderer
.filter
.state
== State_Stopped
)
304 return VFW_E_WRONG_STATE
;
307 VideoRenderer_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
312 static HRESULT WINAPI
VideoRenderer_CheckMediaType(BaseRenderer
*iface
, const AM_MEDIA_TYPE
* pmt
)
314 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
316 if (!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
))
319 if (IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB32
) ||
320 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB24
) ||
321 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB565
) ||
322 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB8
))
326 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
))
328 VIDEOINFOHEADER
*format
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
329 This
->SourceRect
.left
= 0;
330 This
->SourceRect
.top
= 0;
331 This
->SourceRect
.right
= This
->VideoWidth
= format
->bmiHeader
.biWidth
;
332 height
= format
->bmiHeader
.biHeight
;
334 This
->SourceRect
.bottom
= This
->VideoHeight
= -height
;
336 This
->SourceRect
.bottom
= This
->VideoHeight
= height
;
338 else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
))
340 VIDEOINFOHEADER2
*format2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
342 This
->SourceRect
.left
= 0;
343 This
->SourceRect
.top
= 0;
344 This
->SourceRect
.right
= This
->VideoWidth
= format2
->bmiHeader
.biWidth
;
345 height
= format2
->bmiHeader
.biHeight
;
347 This
->SourceRect
.bottom
= This
->VideoHeight
= -height
;
349 This
->SourceRect
.bottom
= This
->VideoHeight
= height
;
353 WARN("Format type %s not supported\n", debugstr_guid(&pmt
->formattype
));
361 static HRESULT WINAPI
VideoRenderer_EndFlush(BaseRenderer
* iface
)
363 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
365 TRACE("(%p)->()\n", iface
);
367 if (This
->renderer
.pMediaSample
) {
368 ResetEvent(This
->hEvent
);
369 LeaveCriticalSection(iface
->pInputPin
->pin
.pCritSec
);
370 LeaveCriticalSection(&iface
->csRenderLock
);
371 LeaveCriticalSection(&iface
->filter
.csFilter
);
372 WaitForSingleObject(This
->hEvent
, INFINITE
);
373 EnterCriticalSection(&iface
->filter
.csFilter
);
374 EnterCriticalSection(&iface
->csRenderLock
);
375 EnterCriticalSection(iface
->pInputPin
->pin
.pCritSec
);
377 if (This
->renderer
.filter
.state
== State_Paused
) {
378 ResetEvent(This
->hEvent
);
381 return BaseRendererImpl_EndFlush(iface
);
384 static VOID WINAPI
VideoRenderer_OnStopStreaming(BaseRenderer
* iface
)
386 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
388 TRACE("(%p)->()\n", This
);
390 SetEvent(This
->hEvent
);
391 if (This
->baseControlWindow
.AutoShow
)
393 RedrawWindow(This
->baseControlWindow
.baseWindow
.hWnd
, NULL
, NULL
, RDW_INVALIDATE
|RDW_ERASE
);
396 static VOID WINAPI
VideoRenderer_OnStartStreaming(BaseRenderer
* iface
)
398 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
400 TRACE("(%p)\n", This
);
402 if (This
->renderer
.pInputPin
->pin
.pConnectedTo
&& (This
->renderer
.filter
.state
== State_Stopped
|| !This
->renderer
.pInputPin
->end_of_stream
))
404 if (This
->renderer
.filter
.state
== State_Stopped
)
406 ResetEvent(This
->hEvent
);
407 VideoRenderer_AutoShowWindow(This
);
412 static LPWSTR WINAPI
VideoRenderer_GetClassWindowStyles(BaseWindow
*This
, DWORD
*pClassStyles
, DWORD
*pWindowStyles
, DWORD
*pWindowStylesEx
)
414 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 };
417 *pWindowStyles
= WS_SIZEBOX
;
418 *pWindowStylesEx
= 0;
420 return (LPWSTR
)classnameW
;
423 static RECT WINAPI
VideoRenderer_GetDefaultRect(BaseWindow
*iface
)
425 VideoRendererImpl
*This
= impl_from_BaseWindow(iface
);
428 defRect
.left
= defRect
.top
= 0;
429 defRect
.right
= This
->VideoWidth
;
430 defRect
.bottom
= This
->VideoHeight
;
435 static BOOL WINAPI
VideoRenderer_OnSize(BaseWindow
*iface
, LONG Width
, LONG Height
)
437 VideoRendererImpl
*This
= impl_from_BaseWindow(iface
);
439 TRACE("WM_SIZE %d %d\n", Width
, Height
);
440 GetClientRect(iface
->hWnd
, &This
->DestRect
);
441 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
444 This
->DestRect
.right
- This
->DestRect
.left
,
445 This
->DestRect
.bottom
- This
->DestRect
.top
);
446 return BaseWindowImpl_OnSize(iface
, Width
, Height
);
449 static const BaseRendererFuncTable BaseFuncTable
= {
450 VideoRenderer_CheckMediaType
,
451 VideoRenderer_DoRenderSample
,
456 VideoRenderer_OnStartStreaming
,
457 VideoRenderer_OnStopStreaming
,
461 VideoRenderer_ShouldDrawSampleNow
,
468 VideoRenderer_EndFlush
,
471 static const BaseWindowFuncTable renderer_BaseWindowFuncTable
= {
472 VideoRenderer_GetClassWindowStyles
,
473 VideoRenderer_GetDefaultRect
,
475 BaseControlWindowImpl_PossiblyEatMessage
,
479 static HRESULT WINAPI
VideoRenderer_GetSourceRect(BaseControlVideo
* iface
, RECT
*pSourceRect
)
481 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
482 CopyRect(pSourceRect
,&This
->SourceRect
);
486 static HRESULT WINAPI
VideoRenderer_GetStaticImage(BaseControlVideo
* iface
, LONG
*pBufferSize
, LONG
*pDIBImage
)
488 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
489 BITMAPINFOHEADER
*bmiHeader
;
491 AM_MEDIA_TYPE
*amt
= &This
->renderer
.pInputPin
->pin
.mtCurrent
;
494 FIXME("(%p/%p)->(%p, %p): partial stub\n", This
, iface
, pBufferSize
, pDIBImage
);
496 EnterCriticalSection(&This
->renderer
.filter
.csFilter
);
498 if (!This
->renderer
.pMediaSample
)
500 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
501 return (This
->renderer
.filter
.state
== State_Paused
? E_UNEXPECTED
: VFW_E_NOT_PAUSED
);
504 if (IsEqualIID(&amt
->formattype
, &FORMAT_VideoInfo
))
506 bmiHeader
= &((VIDEOINFOHEADER
*)amt
->pbFormat
)->bmiHeader
;
508 else if (IsEqualIID(&amt
->formattype
, &FORMAT_VideoInfo2
))
510 bmiHeader
= &((VIDEOINFOHEADER2
*)amt
->pbFormat
)->bmiHeader
;
514 FIXME("Unknown type %s\n", debugstr_guid(&amt
->subtype
));
515 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
516 return VFW_E_RUNTIME_ERROR
;
519 needed_size
= bmiHeader
->biSize
;
520 needed_size
+= IMediaSample_GetActualDataLength(This
->renderer
.pMediaSample
);
524 *pBufferSize
= needed_size
;
525 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
529 if (needed_size
< *pBufferSize
)
531 ERR("Buffer too small %u/%u\n", needed_size
, *pBufferSize
);
532 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
535 *pBufferSize
= needed_size
;
537 memcpy(pDIBImage
, bmiHeader
, bmiHeader
->biSize
);
538 IMediaSample_GetPointer(This
->renderer
.pMediaSample
, (BYTE
**)&ptr
);
539 memcpy((char *)pDIBImage
+ bmiHeader
->biSize
, ptr
, IMediaSample_GetActualDataLength(This
->renderer
.pMediaSample
));
541 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
545 static HRESULT WINAPI
VideoRenderer_GetTargetRect(BaseControlVideo
* iface
, RECT
*pTargetRect
)
547 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
548 CopyRect(pTargetRect
,&This
->DestRect
);
552 static VIDEOINFOHEADER
* WINAPI
VideoRenderer_GetVideoFormat(BaseControlVideo
* iface
)
554 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
557 TRACE("(%p/%p)\n", This
, iface
);
559 pmt
= &This
->renderer
.pInputPin
->pin
.mtCurrent
;
560 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
561 return (VIDEOINFOHEADER
*)pmt
->pbFormat
;
562 } else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
)) {
563 static VIDEOINFOHEADER vih
;
564 VIDEOINFOHEADER2
*vih2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
565 memcpy(&vih
,vih2
,sizeof(VIDEOINFOHEADER
));
566 memcpy(&vih
.bmiHeader
, &vih2
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
569 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt
->formattype
));
574 static HRESULT WINAPI
VideoRenderer_IsDefaultSourceRect(BaseControlVideo
* iface
)
576 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
577 FIXME("(%p/%p)->(): stub !!!\n", This
, iface
);
582 static HRESULT WINAPI
VideoRenderer_IsDefaultTargetRect(BaseControlVideo
* iface
)
584 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
585 FIXME("(%p/%p)->(): stub !!!\n", This
, iface
);
590 static HRESULT WINAPI
VideoRenderer_SetDefaultSourceRect(BaseControlVideo
* iface
)
592 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
594 This
->SourceRect
.left
= 0;
595 This
->SourceRect
.top
= 0;
596 This
->SourceRect
.right
= This
->VideoWidth
;
597 This
->SourceRect
.bottom
= This
->VideoHeight
;
602 static HRESULT WINAPI
VideoRenderer_SetDefaultTargetRect(BaseControlVideo
* iface
)
604 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
607 if (!GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &rect
))
610 This
->SourceRect
.left
= 0;
611 This
->SourceRect
.top
= 0;
612 This
->SourceRect
.right
= rect
.right
;
613 This
->SourceRect
.bottom
= rect
.bottom
;
618 static HRESULT WINAPI
VideoRenderer_SetSourceRect(BaseControlVideo
* iface
, RECT
*pSourceRect
)
620 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
621 CopyRect(&This
->SourceRect
,pSourceRect
);
625 static HRESULT WINAPI
VideoRenderer_SetTargetRect(BaseControlVideo
* iface
, RECT
*pTargetRect
)
627 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
628 CopyRect(&This
->DestRect
,pTargetRect
);
632 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable
= {
633 VideoRenderer_GetSourceRect
,
634 VideoRenderer_GetStaticImage
,
635 VideoRenderer_GetTargetRect
,
636 VideoRenderer_GetVideoFormat
,
637 VideoRenderer_IsDefaultSourceRect
,
638 VideoRenderer_IsDefaultTargetRect
,
639 VideoRenderer_SetDefaultSourceRect
,
640 VideoRenderer_SetDefaultTargetRect
,
641 VideoRenderer_SetSourceRect
,
642 VideoRenderer_SetTargetRect
645 HRESULT
VideoRenderer_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
648 VideoRendererImpl
* pVideoRenderer
;
650 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
654 pVideoRenderer
= CoTaskMemAlloc(sizeof(VideoRendererImpl
));
655 pVideoRenderer
->pUnkOuter
= pUnkOuter
;
656 pVideoRenderer
->bUnkOuterValid
= FALSE
;
657 pVideoRenderer
->bAggregatable
= FALSE
;
658 pVideoRenderer
->IInner_vtbl
= &IInner_VTable
;
659 pVideoRenderer
->IAMFilterMiscFlags_vtbl
= &IAMFilterMiscFlags_Vtbl
;
661 pVideoRenderer
->init
= 0;
662 ZeroMemory(&pVideoRenderer
->SourceRect
, sizeof(RECT
));
663 ZeroMemory(&pVideoRenderer
->DestRect
, sizeof(RECT
));
664 ZeroMemory(&pVideoRenderer
->WindowPos
, sizeof(RECT
));
666 hr
= BaseRenderer_Init(&pVideoRenderer
->renderer
, &VideoRenderer_Vtbl
, pUnkOuter
, &CLSID_VideoRenderer
, (DWORD_PTR
)(__FILE__
": VideoRendererImpl.csFilter"), &BaseFuncTable
);
671 *ppv
= pVideoRenderer
;
673 hr
= BaseControlWindow_Init(&pVideoRenderer
->baseControlWindow
, &IVideoWindow_VTable
, &pVideoRenderer
->renderer
.filter
, &pVideoRenderer
->renderer
.filter
.csFilter
, &pVideoRenderer
->renderer
.pInputPin
->pin
, &renderer_BaseWindowFuncTable
);
677 hr
= BaseControlVideo_Init(&pVideoRenderer
->baseControlVideo
, &IBasicVideo_VTable
, &pVideoRenderer
->renderer
.filter
, &pVideoRenderer
->renderer
.filter
.csFilter
, &pVideoRenderer
->renderer
.pInputPin
->pin
, &renderer_BaseControlVideoFuncTable
);
681 if (!CreateRenderingSubsystem(pVideoRenderer
))
686 BaseRendererImpl_Release(&pVideoRenderer
->renderer
.filter
.IBaseFilter_iface
);
687 CoTaskMemFree(pVideoRenderer
);
691 HRESULT
VideoRendererDefault_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
693 /* TODO: Attempt to use the VMR-7 renderer instead when possible */
694 return VideoRenderer_create(pUnkOuter
, ppv
);
697 static HRESULT WINAPI
VideoRendererInner_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
699 ICOM_THIS_MULTI(VideoRendererImpl
, IInner_vtbl
, iface
);
700 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
702 if (This
->bAggregatable
)
703 This
->bUnkOuterValid
= TRUE
;
707 if (IsEqualIID(riid
, &IID_IUnknown
))
708 *ppv
= &This
->IInner_vtbl
;
709 else if (IsEqualIID(riid
, &IID_IBasicVideo
))
710 *ppv
= &This
->baseControlVideo
.IBasicVideo_iface
;
711 else if (IsEqualIID(riid
, &IID_IVideoWindow
))
712 *ppv
= &This
->baseControlWindow
.IVideoWindow_iface
;
713 else if (IsEqualIID(riid
, &IID_IAMFilterMiscFlags
))
714 *ppv
= &This
->IAMFilterMiscFlags_vtbl
;
718 hr
= BaseRendererImpl_QueryInterface(&This
->renderer
.filter
.IBaseFilter_iface
, riid
, ppv
);
725 IUnknown_AddRef((IUnknown
*)(*ppv
));
729 if (!IsEqualIID(riid
, &IID_IPin
))
730 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
732 return E_NOINTERFACE
;
735 static ULONG WINAPI
VideoRendererInner_AddRef(IUnknown
* iface
)
737 ICOM_THIS_MULTI(VideoRendererImpl
, IInner_vtbl
, iface
);
738 ULONG refCount
= BaseFilterImpl_AddRef(&This
->renderer
.filter
.IBaseFilter_iface
);
740 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
745 static ULONG WINAPI
VideoRendererInner_Release(IUnknown
* iface
)
747 ICOM_THIS_MULTI(VideoRendererImpl
, IInner_vtbl
, iface
);
748 ULONG refCount
= BaseRendererImpl_Release(&This
->renderer
.filter
.IBaseFilter_iface
);
750 TRACE("(%p/%p)->() Release from %d\n", This
, iface
, refCount
+ 1);
754 BaseControlWindow_Destroy(&This
->baseControlWindow
);
755 BaseControlVideo_Destroy(&This
->baseControlVideo
);
756 PostThreadMessageW(This
->ThreadID
, WM_QUIT
, 0, 0);
757 WaitForSingleObject(This
->hThread
, INFINITE
);
758 CloseHandle(This
->hThread
);
759 CloseHandle(This
->hEvent
);
761 TRACE("Destroying Video Renderer\n");
770 static const IUnknownVtbl IInner_VTable
=
772 VideoRendererInner_QueryInterface
,
773 VideoRendererInner_AddRef
,
774 VideoRendererInner_Release
777 static HRESULT WINAPI
VideoRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
779 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
781 if (This
->bAggregatable
)
782 This
->bUnkOuterValid
= TRUE
;
786 if (This
->bAggregatable
)
787 return IUnknown_QueryInterface(This
->pUnkOuter
, riid
, ppv
);
789 if (IsEqualIID(riid
, &IID_IUnknown
))
793 IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
794 hr
= IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
795 IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
796 This
->bAggregatable
= TRUE
;
801 return E_NOINTERFACE
;
804 return IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
807 static ULONG WINAPI
VideoRenderer_AddRef(IBaseFilter
* iface
)
809 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
811 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
812 return IUnknown_AddRef(This
->pUnkOuter
);
813 return IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
816 static ULONG WINAPI
VideoRenderer_Release(IBaseFilter
* iface
)
818 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
820 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
821 return IUnknown_Release(This
->pUnkOuter
);
822 return IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
825 /** IMediaFilter methods **/
827 static HRESULT WINAPI
VideoRenderer_Pause(IBaseFilter
* iface
)
829 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
831 TRACE("(%p/%p)->()\n", This
, iface
);
833 EnterCriticalSection(&This
->renderer
.csRenderLock
);
834 if (This
->renderer
.filter
.state
!= State_Paused
)
836 if (This
->renderer
.filter
.state
== State_Stopped
)
838 This
->renderer
.pInputPin
->end_of_stream
= 0;
839 ResetEvent(This
->hEvent
);
840 VideoRenderer_AutoShowWindow(This
);
843 ResetEvent(This
->renderer
.RenderEvent
);
844 This
->renderer
.filter
.state
= State_Paused
;
846 LeaveCriticalSection(&This
->renderer
.csRenderLock
);
851 static const IBaseFilterVtbl VideoRenderer_Vtbl
=
853 VideoRenderer_QueryInterface
,
854 VideoRenderer_AddRef
,
855 VideoRenderer_Release
,
856 BaseFilterImpl_GetClassID
,
857 BaseRendererImpl_Stop
,
859 BaseRendererImpl_Run
,
860 BaseRendererImpl_GetState
,
861 BaseRendererImpl_SetSyncSource
,
862 BaseFilterImpl_GetSyncSource
,
863 BaseFilterImpl_EnumPins
,
864 BaseRendererImpl_FindPin
,
865 BaseFilterImpl_QueryFilterInfo
,
866 BaseFilterImpl_JoinFilterGraph
,
867 BaseFilterImpl_QueryVendorInfo
870 /*** IUnknown methods ***/
871 static HRESULT WINAPI
Basicvideo_QueryInterface(IBasicVideo
*iface
,
874 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
876 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
878 return VideoRenderer_QueryInterface(&This
->renderer
.filter
.IBaseFilter_iface
, riid
, ppvObj
);
881 static ULONG WINAPI
Basicvideo_AddRef(IBasicVideo
*iface
) {
882 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
884 TRACE("(%p/%p)->()\n", This
, iface
);
886 return VideoRenderer_AddRef(&This
->renderer
.filter
.IBaseFilter_iface
);
889 static ULONG WINAPI
Basicvideo_Release(IBasicVideo
*iface
) {
890 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
892 TRACE("(%p/%p)->()\n", This
, iface
);
894 return VideoRenderer_Release(&This
->renderer
.filter
.IBaseFilter_iface
);
897 static const IBasicVideoVtbl IBasicVideo_VTable
=
899 Basicvideo_QueryInterface
,
902 BaseControlVideoImpl_GetTypeInfoCount
,
903 BaseControlVideoImpl_GetTypeInfo
,
904 BaseControlVideoImpl_GetIDsOfNames
,
905 BaseControlVideoImpl_Invoke
,
906 BaseControlVideoImpl_get_AvgTimePerFrame
,
907 BaseControlVideoImpl_get_BitRate
,
908 BaseControlVideoImpl_get_BitErrorRate
,
909 BaseControlVideoImpl_get_VideoWidth
,
910 BaseControlVideoImpl_get_VideoHeight
,
911 BaseControlVideoImpl_put_SourceLeft
,
912 BaseControlVideoImpl_get_SourceLeft
,
913 BaseControlVideoImpl_put_SourceWidth
,
914 BaseControlVideoImpl_get_SourceWidth
,
915 BaseControlVideoImpl_put_SourceTop
,
916 BaseControlVideoImpl_get_SourceTop
,
917 BaseControlVideoImpl_put_SourceHeight
,
918 BaseControlVideoImpl_get_SourceHeight
,
919 BaseControlVideoImpl_put_DestinationLeft
,
920 BaseControlVideoImpl_get_DestinationLeft
,
921 BaseControlVideoImpl_put_DestinationWidth
,
922 BaseControlVideoImpl_get_DestinationWidth
,
923 BaseControlVideoImpl_put_DestinationTop
,
924 BaseControlVideoImpl_get_DestinationTop
,
925 BaseControlVideoImpl_put_DestinationHeight
,
926 BaseControlVideoImpl_get_DestinationHeight
,
927 BaseControlVideoImpl_SetSourcePosition
,
928 BaseControlVideoImpl_GetSourcePosition
,
929 BaseControlVideoImpl_SetDefaultSourcePosition
,
930 BaseControlVideoImpl_SetDestinationPosition
,
931 BaseControlVideoImpl_GetDestinationPosition
,
932 BaseControlVideoImpl_SetDefaultDestinationPosition
,
933 BaseControlVideoImpl_GetVideoSize
,
934 BaseControlVideoImpl_GetVideoPaletteEntries
,
935 BaseControlVideoImpl_GetCurrentImage
,
936 BaseControlVideoImpl_IsUsingDefaultSource
,
937 BaseControlVideoImpl_IsUsingDefaultDestination
941 /*** IUnknown methods ***/
942 static HRESULT WINAPI
Videowindow_QueryInterface(IVideoWindow
*iface
,
945 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
947 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
949 return VideoRenderer_QueryInterface(&This
->renderer
.filter
.IBaseFilter_iface
, riid
, ppvObj
);
952 static ULONG WINAPI
Videowindow_AddRef(IVideoWindow
*iface
) {
953 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
955 TRACE("(%p/%p)->()\n", This
, iface
);
957 return VideoRenderer_AddRef(&This
->renderer
.filter
.IBaseFilter_iface
);
960 static ULONG WINAPI
Videowindow_Release(IVideoWindow
*iface
) {
961 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
963 TRACE("(%p/%p)->()\n", This
, iface
);
965 return VideoRenderer_Release(&This
->renderer
.filter
.IBaseFilter_iface
);
968 static HRESULT WINAPI
Videowindow_get_FullScreenMode(IVideoWindow
*iface
,
969 LONG
*FullScreenMode
) {
970 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
972 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, FullScreenMode
);
977 static HRESULT WINAPI
Videowindow_put_FullScreenMode(IVideoWindow
*iface
,
978 LONG FullScreenMode
) {
979 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
981 FIXME("(%p/%p)->(%d): stub !!!\n", This
, iface
, FullScreenMode
);
983 if (FullScreenMode
) {
984 This
->baseControlWindow
.baseWindow
.WindowStyles
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
);
985 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_HIDE
);
986 SetParent(This
->baseControlWindow
.baseWindow
.hWnd
, 0);
987 SetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
, WS_POPUP
);
988 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
,HWND_TOP
,0,0,GetSystemMetrics(SM_CXSCREEN
),GetSystemMetrics(SM_CYSCREEN
),SWP_SHOWWINDOW
);
989 GetWindowRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
990 This
->WindowPos
= This
->DestRect
;
992 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_HIDE
);
993 SetParent(This
->baseControlWindow
.baseWindow
.hWnd
, This
->baseControlWindow
.hwndOwner
);
994 SetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
, This
->baseControlWindow
.baseWindow
.WindowStyles
);
995 GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
996 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
,0,This
->DestRect
.left
,This
->DestRect
.top
,This
->DestRect
.right
,This
->DestRect
.bottom
,SWP_NOZORDER
|SWP_SHOWWINDOW
);
997 This
->WindowPos
= This
->DestRect
;
1003 static const IVideoWindowVtbl IVideoWindow_VTable
=
1005 Videowindow_QueryInterface
,
1007 Videowindow_Release
,
1008 BaseControlWindowImpl_GetTypeInfoCount
,
1009 BaseControlWindowImpl_GetTypeInfo
,
1010 BaseControlWindowImpl_GetIDsOfNames
,
1011 BaseControlWindowImpl_Invoke
,
1012 BaseControlWindowImpl_put_Caption
,
1013 BaseControlWindowImpl_get_Caption
,
1014 BaseControlWindowImpl_put_WindowStyle
,
1015 BaseControlWindowImpl_get_WindowStyle
,
1016 BaseControlWindowImpl_put_WindowStyleEx
,
1017 BaseControlWindowImpl_get_WindowStyleEx
,
1018 BaseControlWindowImpl_put_AutoShow
,
1019 BaseControlWindowImpl_get_AutoShow
,
1020 BaseControlWindowImpl_put_WindowState
,
1021 BaseControlWindowImpl_get_WindowState
,
1022 BaseControlWindowImpl_put_BackgroundPalette
,
1023 BaseControlWindowImpl_get_BackgroundPalette
,
1024 BaseControlWindowImpl_put_Visible
,
1025 BaseControlWindowImpl_get_Visible
,
1026 BaseControlWindowImpl_put_Left
,
1027 BaseControlWindowImpl_get_Left
,
1028 BaseControlWindowImpl_put_Width
,
1029 BaseControlWindowImpl_get_Width
,
1030 BaseControlWindowImpl_put_Top
,
1031 BaseControlWindowImpl_get_Top
,
1032 BaseControlWindowImpl_put_Height
,
1033 BaseControlWindowImpl_get_Height
,
1034 BaseControlWindowImpl_put_Owner
,
1035 BaseControlWindowImpl_get_Owner
,
1036 BaseControlWindowImpl_put_MessageDrain
,
1037 BaseControlWindowImpl_get_MessageDrain
,
1038 BaseControlWindowImpl_get_BorderColor
,
1039 BaseControlWindowImpl_put_BorderColor
,
1040 Videowindow_get_FullScreenMode
,
1041 Videowindow_put_FullScreenMode
,
1042 BaseControlWindowImpl_SetWindowForeground
,
1043 BaseControlWindowImpl_NotifyOwnerMessage
,
1044 BaseControlWindowImpl_SetWindowPosition
,
1045 BaseControlWindowImpl_GetWindowPosition
,
1046 BaseControlWindowImpl_GetMinIdealImageSize
,
1047 BaseControlWindowImpl_GetMaxIdealImageSize
,
1048 BaseControlWindowImpl_GetRestorePosition
,
1049 BaseControlWindowImpl_HideCursor
,
1050 BaseControlWindowImpl_IsCursorHidden
1053 static VideoRendererImpl
*from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
) {
1054 return (VideoRendererImpl
*)((char*)iface
- offsetof(VideoRendererImpl
, IAMFilterMiscFlags_vtbl
));
1057 static HRESULT WINAPI
AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
) {
1058 VideoRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
1059 return IUnknown_QueryInterface((IUnknown
*)This
, riid
, ppv
);
1062 static ULONG WINAPI
AMFilterMiscFlags_AddRef(IAMFilterMiscFlags
*iface
) {
1063 VideoRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
1064 return IUnknown_AddRef((IUnknown
*)This
);
1067 static ULONG WINAPI
AMFilterMiscFlags_Release(IAMFilterMiscFlags
*iface
) {
1068 VideoRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
1069 return IUnknown_Release((IUnknown
*)This
);
1072 static ULONG WINAPI
AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags
*iface
) {
1073 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
1076 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
= {
1077 AMFilterMiscFlags_QueryInterface
,
1078 AMFilterMiscFlags_AddRef
,
1079 AMFilterMiscFlags_Release
,
1080 AMFilterMiscFlags_GetMiscFlags