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 "quartz_private.h"
23 typedef struct VideoRendererImpl
25 BaseRenderer renderer
;
26 BaseControlWindow baseControlWindow
;
27 BaseControlVideo baseControlVideo
;
29 IUnknown IUnknown_inner
;
30 IAMFilterMiscFlags IAMFilterMiscFlags_iface
;
38 /* hEvent == evComplete? */
48 static inline VideoRendererImpl
*impl_from_BaseWindow(BaseWindow
*iface
)
50 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlWindow
.baseWindow
);
53 static inline VideoRendererImpl
*impl_from_BaseRenderer(BaseRenderer
*iface
)
55 return CONTAINING_RECORD(iface
, VideoRendererImpl
, renderer
);
58 static inline VideoRendererImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
60 return CONTAINING_RECORD(iface
, VideoRendererImpl
, renderer
.filter
.IBaseFilter_iface
);
63 static inline VideoRendererImpl
*impl_from_IVideoWindow(IVideoWindow
*iface
)
65 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlWindow
.IVideoWindow_iface
);
68 static inline VideoRendererImpl
*impl_from_BaseControlVideo(BaseControlVideo
*iface
)
70 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlVideo
);
73 static inline VideoRendererImpl
*impl_from_IBasicVideo(IBasicVideo
*iface
)
75 return CONTAINING_RECORD(iface
, VideoRendererImpl
, baseControlVideo
.IBasicVideo_iface
);
78 static DWORD WINAPI
MessageLoop(LPVOID lpParameter
)
80 VideoRendererImpl
* This
= lpParameter
;
84 TRACE("Starting message loop\n");
86 if (FAILED(BaseWindowImpl_PrepareWindow(&This
->baseControlWindow
.baseWindow
)))
88 This
->ThreadResult
= FALSE
;
89 SetEvent(This
->hEvent
);
93 This
->ThreadResult
= TRUE
;
94 SetEvent(This
->hEvent
);
96 while ((fGotMessage
= GetMessageW(&msg
, NULL
, 0, 0)) != 0 && fGotMessage
!= -1)
98 TranslateMessage(&msg
);
99 DispatchMessageW(&msg
);
102 TRACE("End of message loop\n");
107 static BOOL
CreateRenderingSubsystem(VideoRendererImpl
* This
)
109 This
->hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
113 This
->hThread
= CreateThread(NULL
, 0, MessageLoop
, This
, 0, &This
->ThreadID
);
116 CloseHandle(This
->hEvent
);
120 WaitForSingleObject(This
->hEvent
, INFINITE
);
122 if (!This
->ThreadResult
)
124 CloseHandle(This
->hEvent
);
125 CloseHandle(This
->hThread
);
132 static void VideoRenderer_AutoShowWindow(VideoRendererImpl
*This
)
134 if (!This
->init
&& (!This
->WindowPos
.right
|| !This
->WindowPos
.top
))
136 DWORD style
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
);
137 DWORD style_ex
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_EXSTYLE
);
139 if (!This
->WindowPos
.right
)
141 if (This
->DestRect
.right
)
143 This
->WindowPos
.left
= This
->DestRect
.left
;
144 This
->WindowPos
.right
= This
->DestRect
.right
;
148 This
->WindowPos
.left
= This
->SourceRect
.left
;
149 This
->WindowPos
.right
= This
->SourceRect
.right
;
152 if (!This
->WindowPos
.bottom
)
154 if (This
->DestRect
.bottom
)
156 This
->WindowPos
.top
= This
->DestRect
.top
;
157 This
->WindowPos
.bottom
= This
->DestRect
.bottom
;
161 This
->WindowPos
.top
= This
->SourceRect
.top
;
162 This
->WindowPos
.bottom
= This
->SourceRect
.bottom
;
166 AdjustWindowRectEx(&This
->WindowPos
, style
, FALSE
, style_ex
);
168 TRACE("WindowPos: %s\n", wine_dbgstr_rect(&This
->WindowPos
));
169 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
, NULL
,
170 This
->WindowPos
.left
,
172 This
->WindowPos
.right
- This
->WindowPos
.left
,
173 This
->WindowPos
.bottom
- This
->WindowPos
.top
,
174 SWP_NOZORDER
|SWP_NOMOVE
|SWP_DEFERERASE
);
176 GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
178 else if (!This
->init
)
179 This
->DestRect
= This
->WindowPos
;
181 if (This
->baseControlWindow
.AutoShow
)
182 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_SHOW
);
185 static DWORD
VideoRenderer_SendSampleData(VideoRendererImpl
* This
, LPBYTE data
, DWORD size
)
189 BITMAPINFOHEADER
*bmiHeader
;
191 TRACE("(%p)->(%p, %d)\n", This
, data
, size
);
193 hr
= IPin_ConnectionMediaType(&This
->renderer
.pInputPin
->pin
.IPin_iface
, &amt
);
195 ERR("Unable to retrieve media type\n");
199 if (IsEqualIID(&amt
.formattype
, &FORMAT_VideoInfo
))
201 bmiHeader
= &((VIDEOINFOHEADER
*)amt
.pbFormat
)->bmiHeader
;
203 else if (IsEqualIID(&amt
.formattype
, &FORMAT_VideoInfo2
))
205 bmiHeader
= &((VIDEOINFOHEADER2
*)amt
.pbFormat
)->bmiHeader
;
209 FIXME("Unknown type %s\n", debugstr_guid(&amt
.subtype
));
210 return VFW_E_RUNTIME_ERROR
;
213 TRACE("biSize = %d\n", bmiHeader
->biSize
);
214 TRACE("biWidth = %d\n", bmiHeader
->biWidth
);
215 TRACE("biHeight = %d\n", bmiHeader
->biHeight
);
216 TRACE("biPlanes = %d\n", bmiHeader
->biPlanes
);
217 TRACE("biBitCount = %d\n", bmiHeader
->biBitCount
);
218 TRACE("biCompression = %s\n", debugstr_an((LPSTR
)&(bmiHeader
->biCompression
), 4));
219 TRACE("biSizeImage = %d\n", bmiHeader
->biSizeImage
);
221 if (!This
->baseControlWindow
.baseWindow
.hDC
) {
222 ERR("Cannot get DC from window!\n");
226 TRACE("Src Rect: %s\n", wine_dbgstr_rect(&This
->SourceRect
));
227 TRACE("Dst Rect: %s\n", wine_dbgstr_rect(&This
->DestRect
));
229 StretchDIBits(This
->baseControlWindow
.baseWindow
.hDC
, This
->DestRect
.left
, This
->DestRect
.top
, This
->DestRect
.right
-This
->DestRect
.left
,
230 This
->DestRect
.bottom
- This
->DestRect
.top
, This
->SourceRect
.left
, This
->SourceRect
.top
,
231 This
->SourceRect
.right
- This
->SourceRect
.left
, This
->SourceRect
.bottom
- This
->SourceRect
.top
,
232 data
, (BITMAPINFO
*)bmiHeader
, DIB_RGB_COLORS
, SRCCOPY
);
237 static HRESULT WINAPI
VideoRenderer_ShouldDrawSampleNow(BaseRenderer
*This
, IMediaSample
*pSample
, REFERENCE_TIME
*pStartTime
, REFERENCE_TIME
*pEndTime
)
239 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
240 if (IMediaSample_IsPreroll(pSample
) == S_OK
)
245 static HRESULT WINAPI
VideoRenderer_DoRenderSample(BaseRenderer
* iface
, IMediaSample
* pSample
)
247 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
248 LPBYTE pbSrcStream
= NULL
;
249 LONG cbSrcStream
= 0;
252 TRACE("(%p)->(%p)\n", This
, pSample
);
254 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
257 ERR("Cannot get pointer to sample data (%x)\n", hr
);
261 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
263 TRACE("val %p %d\n", pbSrcStream
, cbSrcStream
);
265 #if 0 /* For debugging purpose */
268 for(i
= 0; i
< cbSrcStream
; i
++)
270 if ((i
!=0) && !(i
%16))
272 TRACE("%02x ", pbSrcStream
[i
]);
278 SetEvent(This
->hEvent
);
279 if (This
->renderer
.filter
.state
== State_Paused
)
281 VideoRenderer_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
282 SetEvent(This
->hEvent
);
283 if (This
->renderer
.filter
.state
== State_Paused
)
288 if (This
->renderer
.filter
.state
== State_Stopped
)
290 return VFW_E_WRONG_STATE
;
293 VideoRenderer_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
298 static HRESULT WINAPI
VideoRenderer_CheckMediaType(BaseRenderer
*iface
, const AM_MEDIA_TYPE
* pmt
)
300 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
302 if (!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
))
305 if (IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB32
) ||
306 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB24
) ||
307 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB565
) ||
308 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB8
))
312 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
))
314 VIDEOINFOHEADER
*format
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
315 This
->SourceRect
.left
= 0;
316 This
->SourceRect
.top
= 0;
317 This
->SourceRect
.right
= This
->VideoWidth
= format
->bmiHeader
.biWidth
;
318 height
= format
->bmiHeader
.biHeight
;
320 This
->SourceRect
.bottom
= This
->VideoHeight
= -height
;
322 This
->SourceRect
.bottom
= This
->VideoHeight
= height
;
324 else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
))
326 VIDEOINFOHEADER2
*format2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
328 This
->SourceRect
.left
= 0;
329 This
->SourceRect
.top
= 0;
330 This
->SourceRect
.right
= This
->VideoWidth
= format2
->bmiHeader
.biWidth
;
331 height
= format2
->bmiHeader
.biHeight
;
333 This
->SourceRect
.bottom
= This
->VideoHeight
= -height
;
335 This
->SourceRect
.bottom
= This
->VideoHeight
= height
;
339 WARN("Format type %s not supported\n", debugstr_guid(&pmt
->formattype
));
347 static HRESULT WINAPI
VideoRenderer_EndFlush(BaseRenderer
* iface
)
349 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
351 TRACE("(%p)->()\n", iface
);
353 if (This
->renderer
.pMediaSample
) {
354 ResetEvent(This
->hEvent
);
355 LeaveCriticalSection(iface
->pInputPin
->pin
.pCritSec
);
356 LeaveCriticalSection(&iface
->filter
.csFilter
);
357 LeaveCriticalSection(&iface
->csRenderLock
);
358 WaitForSingleObject(This
->hEvent
, INFINITE
);
359 EnterCriticalSection(&iface
->csRenderLock
);
360 EnterCriticalSection(&iface
->filter
.csFilter
);
361 EnterCriticalSection(iface
->pInputPin
->pin
.pCritSec
);
363 if (This
->renderer
.filter
.state
== State_Paused
) {
364 ResetEvent(This
->hEvent
);
367 return BaseRendererImpl_EndFlush(iface
);
370 static VOID WINAPI
VideoRenderer_OnStopStreaming(BaseRenderer
* iface
)
372 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
374 TRACE("(%p)->()\n", This
);
376 SetEvent(This
->hEvent
);
377 if (This
->baseControlWindow
.AutoShow
)
379 RedrawWindow(This
->baseControlWindow
.baseWindow
.hWnd
, NULL
, NULL
, RDW_INVALIDATE
|RDW_ERASE
);
382 static VOID WINAPI
VideoRenderer_OnStartStreaming(BaseRenderer
* iface
)
384 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
386 TRACE("(%p)\n", This
);
388 if (This
->renderer
.pInputPin
->pin
.pConnectedTo
&& (This
->renderer
.filter
.state
== State_Stopped
|| !This
->renderer
.pInputPin
->end_of_stream
))
390 if (This
->renderer
.filter
.state
== State_Stopped
)
392 ResetEvent(This
->hEvent
);
393 VideoRenderer_AutoShowWindow(This
);
398 static LPWSTR WINAPI
VideoRenderer_GetClassWindowStyles(BaseWindow
*This
, DWORD
*pClassStyles
, DWORD
*pWindowStyles
, DWORD
*pWindowStylesEx
)
400 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 };
403 *pWindowStyles
= WS_SIZEBOX
;
404 *pWindowStylesEx
= 0;
406 return (LPWSTR
)classnameW
;
409 static RECT WINAPI
VideoRenderer_GetDefaultRect(BaseWindow
*iface
)
411 VideoRendererImpl
*This
= impl_from_BaseWindow(iface
);
414 SetRect(&defRect
, 0, 0, This
->VideoWidth
, This
->VideoHeight
);
419 static BOOL WINAPI
VideoRenderer_OnSize(BaseWindow
*iface
, LONG Width
, LONG Height
)
421 VideoRendererImpl
*This
= impl_from_BaseWindow(iface
);
423 TRACE("WM_SIZE %d %d\n", Width
, Height
);
424 GetClientRect(iface
->hWnd
, &This
->DestRect
);
425 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
428 This
->DestRect
.right
- This
->DestRect
.left
,
429 This
->DestRect
.bottom
- This
->DestRect
.top
);
430 return BaseWindowImpl_OnSize(iface
, Width
, Height
);
433 static const BaseRendererFuncTable BaseFuncTable
= {
434 VideoRenderer_CheckMediaType
,
435 VideoRenderer_DoRenderSample
,
440 VideoRenderer_OnStartStreaming
,
441 VideoRenderer_OnStopStreaming
,
445 VideoRenderer_ShouldDrawSampleNow
,
452 VideoRenderer_EndFlush
,
455 static const BaseWindowFuncTable renderer_BaseWindowFuncTable
= {
456 VideoRenderer_GetClassWindowStyles
,
457 VideoRenderer_GetDefaultRect
,
459 BaseControlWindowImpl_PossiblyEatMessage
,
463 static HRESULT WINAPI
VideoRenderer_GetSourceRect(BaseControlVideo
* iface
, RECT
*pSourceRect
)
465 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
466 CopyRect(pSourceRect
,&This
->SourceRect
);
470 static HRESULT WINAPI
VideoRenderer_GetStaticImage(BaseControlVideo
* iface
, LONG
*pBufferSize
, LONG
*pDIBImage
)
472 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
473 BITMAPINFOHEADER
*bmiHeader
;
475 AM_MEDIA_TYPE
*amt
= &This
->renderer
.pInputPin
->pin
.mtCurrent
;
478 FIXME("(%p/%p)->(%p, %p): partial stub\n", This
, iface
, pBufferSize
, pDIBImage
);
480 EnterCriticalSection(&This
->renderer
.filter
.csFilter
);
482 if (!This
->renderer
.pMediaSample
)
484 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
485 return (This
->renderer
.filter
.state
== State_Paused
? E_UNEXPECTED
: VFW_E_NOT_PAUSED
);
488 if (IsEqualIID(&amt
->formattype
, &FORMAT_VideoInfo
))
490 bmiHeader
= &((VIDEOINFOHEADER
*)amt
->pbFormat
)->bmiHeader
;
492 else if (IsEqualIID(&amt
->formattype
, &FORMAT_VideoInfo2
))
494 bmiHeader
= &((VIDEOINFOHEADER2
*)amt
->pbFormat
)->bmiHeader
;
498 FIXME("Unknown type %s\n", debugstr_guid(&amt
->subtype
));
499 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
500 return VFW_E_RUNTIME_ERROR
;
503 needed_size
= bmiHeader
->biSize
;
504 needed_size
+= IMediaSample_GetActualDataLength(This
->renderer
.pMediaSample
);
508 *pBufferSize
= needed_size
;
509 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
513 if (needed_size
< *pBufferSize
)
515 ERR("Buffer too small %u/%u\n", needed_size
, *pBufferSize
);
516 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
519 *pBufferSize
= needed_size
;
521 memcpy(pDIBImage
, bmiHeader
, bmiHeader
->biSize
);
522 IMediaSample_GetPointer(This
->renderer
.pMediaSample
, (BYTE
**)&ptr
);
523 memcpy((char *)pDIBImage
+ bmiHeader
->biSize
, ptr
, IMediaSample_GetActualDataLength(This
->renderer
.pMediaSample
));
525 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
529 static HRESULT WINAPI
VideoRenderer_GetTargetRect(BaseControlVideo
* iface
, RECT
*pTargetRect
)
531 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
532 CopyRect(pTargetRect
,&This
->DestRect
);
536 static VIDEOINFOHEADER
* WINAPI
VideoRenderer_GetVideoFormat(BaseControlVideo
* iface
)
538 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
541 TRACE("(%p/%p)\n", This
, iface
);
543 pmt
= &This
->renderer
.pInputPin
->pin
.mtCurrent
;
544 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
545 return (VIDEOINFOHEADER
*)pmt
->pbFormat
;
546 } else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
)) {
547 static VIDEOINFOHEADER vih
;
548 VIDEOINFOHEADER2
*vih2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
549 memcpy(&vih
,vih2
,sizeof(VIDEOINFOHEADER
));
550 memcpy(&vih
.bmiHeader
, &vih2
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
553 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt
->formattype
));
558 static HRESULT WINAPI
VideoRenderer_IsDefaultSourceRect(BaseControlVideo
* iface
)
560 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
561 FIXME("(%p/%p)->(): stub !!!\n", This
, iface
);
566 static HRESULT WINAPI
VideoRenderer_IsDefaultTargetRect(BaseControlVideo
* iface
)
568 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
569 FIXME("(%p/%p)->(): stub !!!\n", This
, iface
);
574 static HRESULT WINAPI
VideoRenderer_SetDefaultSourceRect(BaseControlVideo
* iface
)
576 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
578 SetRect(&This
->SourceRect
, 0, 0, This
->VideoWidth
, This
->VideoHeight
);
583 static HRESULT WINAPI
VideoRenderer_SetDefaultTargetRect(BaseControlVideo
* iface
)
585 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
588 if (!GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &rect
))
591 SetRect(&This
->DestRect
, 0, 0, rect
.right
, rect
.bottom
);
596 static HRESULT WINAPI
VideoRenderer_SetSourceRect(BaseControlVideo
* iface
, RECT
*pSourceRect
)
598 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
599 CopyRect(&This
->SourceRect
,pSourceRect
);
603 static HRESULT WINAPI
VideoRenderer_SetTargetRect(BaseControlVideo
* iface
, RECT
*pTargetRect
)
605 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
606 CopyRect(&This
->DestRect
,pTargetRect
);
610 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable
= {
611 VideoRenderer_GetSourceRect
,
612 VideoRenderer_GetStaticImage
,
613 VideoRenderer_GetTargetRect
,
614 VideoRenderer_GetVideoFormat
,
615 VideoRenderer_IsDefaultSourceRect
,
616 VideoRenderer_IsDefaultTargetRect
,
617 VideoRenderer_SetDefaultSourceRect
,
618 VideoRenderer_SetDefaultTargetRect
,
619 VideoRenderer_SetSourceRect
,
620 VideoRenderer_SetTargetRect
623 static inline VideoRendererImpl
*impl_from_IUnknown(IUnknown
*iface
)
625 return CONTAINING_RECORD(iface
, VideoRendererImpl
, IUnknown_inner
);
628 static HRESULT WINAPI
VideoRendererInner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
630 VideoRendererImpl
*This
= impl_from_IUnknown(iface
);
632 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
636 if (IsEqualIID(riid
, &IID_IUnknown
))
637 *ppv
= &This
->IUnknown_inner
;
638 else if (IsEqualIID(riid
, &IID_IBasicVideo
))
639 *ppv
= &This
->baseControlVideo
.IBasicVideo_iface
;
640 else if (IsEqualIID(riid
, &IID_IVideoWindow
))
641 *ppv
= &This
->baseControlWindow
.IVideoWindow_iface
;
642 else if (IsEqualIID(riid
, &IID_IAMFilterMiscFlags
))
643 *ppv
= &This
->IAMFilterMiscFlags_iface
;
647 hr
= BaseRendererImpl_QueryInterface(&This
->renderer
.filter
.IBaseFilter_iface
, riid
, ppv
);
654 IUnknown_AddRef((IUnknown
*)*ppv
);
658 if (!IsEqualIID(riid
, &IID_IPin
))
659 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
661 return E_NOINTERFACE
;
664 static ULONG WINAPI
VideoRendererInner_AddRef(IUnknown
*iface
)
666 VideoRendererImpl
*This
= impl_from_IUnknown(iface
);
667 ULONG refCount
= BaseFilterImpl_AddRef(&This
->renderer
.filter
.IBaseFilter_iface
);
669 TRACE("(%p)->(): new ref = %d\n", This
, refCount
);
674 static ULONG WINAPI
VideoRendererInner_Release(IUnknown
*iface
)
676 VideoRendererImpl
*This
= impl_from_IUnknown(iface
);
677 ULONG refCount
= BaseRendererImpl_Release(&This
->renderer
.filter
.IBaseFilter_iface
);
679 TRACE("(%p)->(): new ref = %d\n", This
, refCount
);
683 BaseControlWindow_Destroy(&This
->baseControlWindow
);
684 BaseControlVideo_Destroy(&This
->baseControlVideo
);
685 PostThreadMessageW(This
->ThreadID
, WM_QUIT
, 0, 0);
686 WaitForSingleObject(This
->hThread
, INFINITE
);
687 CloseHandle(This
->hThread
);
688 CloseHandle(This
->hEvent
);
690 TRACE("Destroying Video Renderer\n");
699 static const IUnknownVtbl IInner_VTable
=
701 VideoRendererInner_QueryInterface
,
702 VideoRendererInner_AddRef
,
703 VideoRendererInner_Release
706 static HRESULT WINAPI
VideoRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
708 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
709 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
712 static ULONG WINAPI
VideoRenderer_AddRef(IBaseFilter
* iface
)
714 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
715 return IUnknown_AddRef(This
->outer_unk
);
718 static ULONG WINAPI
VideoRenderer_Release(IBaseFilter
* iface
)
720 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
721 return IUnknown_Release(This
->outer_unk
);
724 /** IMediaFilter methods **/
726 static HRESULT WINAPI
VideoRenderer_Pause(IBaseFilter
* iface
)
728 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
730 TRACE("(%p/%p)->()\n", This
, iface
);
732 EnterCriticalSection(&This
->renderer
.csRenderLock
);
733 if (This
->renderer
.filter
.state
!= State_Paused
)
735 if (This
->renderer
.filter
.state
== State_Stopped
)
737 This
->renderer
.pInputPin
->end_of_stream
= 0;
738 ResetEvent(This
->hEvent
);
739 VideoRenderer_AutoShowWindow(This
);
742 ResetEvent(This
->renderer
.RenderEvent
);
743 This
->renderer
.filter
.state
= State_Paused
;
745 LeaveCriticalSection(&This
->renderer
.csRenderLock
);
750 static const IBaseFilterVtbl VideoRenderer_Vtbl
=
752 VideoRenderer_QueryInterface
,
753 VideoRenderer_AddRef
,
754 VideoRenderer_Release
,
755 BaseFilterImpl_GetClassID
,
756 BaseRendererImpl_Stop
,
758 BaseRendererImpl_Run
,
759 BaseRendererImpl_GetState
,
760 BaseRendererImpl_SetSyncSource
,
761 BaseFilterImpl_GetSyncSource
,
762 BaseFilterImpl_EnumPins
,
763 BaseRendererImpl_FindPin
,
764 BaseFilterImpl_QueryFilterInfo
,
765 BaseFilterImpl_JoinFilterGraph
,
766 BaseFilterImpl_QueryVendorInfo
769 /*** IUnknown methods ***/
770 static HRESULT WINAPI
BasicVideo_QueryInterface(IBasicVideo
*iface
, REFIID riid
, LPVOID
*ppvObj
)
772 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
774 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
776 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppvObj
);
779 static ULONG WINAPI
BasicVideo_AddRef(IBasicVideo
*iface
)
781 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
783 TRACE("(%p/%p)->()\n", This
, iface
);
785 return IUnknown_AddRef(This
->outer_unk
);
788 static ULONG WINAPI
BasicVideo_Release(IBasicVideo
*iface
)
790 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
792 TRACE("(%p/%p)->()\n", This
, iface
);
794 return IUnknown_Release(This
->outer_unk
);
797 static const IBasicVideoVtbl IBasicVideo_VTable
=
799 BasicVideo_QueryInterface
,
802 BaseControlVideoImpl_GetTypeInfoCount
,
803 BaseControlVideoImpl_GetTypeInfo
,
804 BaseControlVideoImpl_GetIDsOfNames
,
805 BaseControlVideoImpl_Invoke
,
806 BaseControlVideoImpl_get_AvgTimePerFrame
,
807 BaseControlVideoImpl_get_BitRate
,
808 BaseControlVideoImpl_get_BitErrorRate
,
809 BaseControlVideoImpl_get_VideoWidth
,
810 BaseControlVideoImpl_get_VideoHeight
,
811 BaseControlVideoImpl_put_SourceLeft
,
812 BaseControlVideoImpl_get_SourceLeft
,
813 BaseControlVideoImpl_put_SourceWidth
,
814 BaseControlVideoImpl_get_SourceWidth
,
815 BaseControlVideoImpl_put_SourceTop
,
816 BaseControlVideoImpl_get_SourceTop
,
817 BaseControlVideoImpl_put_SourceHeight
,
818 BaseControlVideoImpl_get_SourceHeight
,
819 BaseControlVideoImpl_put_DestinationLeft
,
820 BaseControlVideoImpl_get_DestinationLeft
,
821 BaseControlVideoImpl_put_DestinationWidth
,
822 BaseControlVideoImpl_get_DestinationWidth
,
823 BaseControlVideoImpl_put_DestinationTop
,
824 BaseControlVideoImpl_get_DestinationTop
,
825 BaseControlVideoImpl_put_DestinationHeight
,
826 BaseControlVideoImpl_get_DestinationHeight
,
827 BaseControlVideoImpl_SetSourcePosition
,
828 BaseControlVideoImpl_GetSourcePosition
,
829 BaseControlVideoImpl_SetDefaultSourcePosition
,
830 BaseControlVideoImpl_SetDestinationPosition
,
831 BaseControlVideoImpl_GetDestinationPosition
,
832 BaseControlVideoImpl_SetDefaultDestinationPosition
,
833 BaseControlVideoImpl_GetVideoSize
,
834 BaseControlVideoImpl_GetVideoPaletteEntries
,
835 BaseControlVideoImpl_GetCurrentImage
,
836 BaseControlVideoImpl_IsUsingDefaultSource
,
837 BaseControlVideoImpl_IsUsingDefaultDestination
841 /*** IUnknown methods ***/
842 static HRESULT WINAPI
VideoWindow_QueryInterface(IVideoWindow
*iface
, REFIID riid
, LPVOID
*ppvObj
)
844 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
846 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
848 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppvObj
);
851 static ULONG WINAPI
VideoWindow_AddRef(IVideoWindow
*iface
)
853 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
855 TRACE("(%p/%p)->()\n", This
, iface
);
857 return IUnknown_AddRef(This
->outer_unk
);
860 static ULONG WINAPI
VideoWindow_Release(IVideoWindow
*iface
)
862 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
864 TRACE("(%p/%p)->()\n", This
, iface
);
866 return IUnknown_Release(This
->outer_unk
);
869 static HRESULT WINAPI
VideoWindow_get_FullScreenMode(IVideoWindow
*iface
,
870 LONG
*FullScreenMode
)
872 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
874 TRACE("(%p/%p)->(%p): %d\n", This
, iface
, FullScreenMode
, This
->FullScreenMode
);
879 *FullScreenMode
= This
->FullScreenMode
;
884 static HRESULT WINAPI
VideoWindow_put_FullScreenMode(IVideoWindow
*iface
,
887 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
889 FIXME("(%p/%p)->(%d): stub !!!\n", This
, iface
, FullScreenMode
);
891 if (FullScreenMode
) {
892 This
->baseControlWindow
.baseWindow
.WindowStyles
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
);
893 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_HIDE
);
894 SetParent(This
->baseControlWindow
.baseWindow
.hWnd
, 0);
895 SetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
, WS_POPUP
);
896 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
,HWND_TOP
,0,0,GetSystemMetrics(SM_CXSCREEN
),GetSystemMetrics(SM_CYSCREEN
),SWP_SHOWWINDOW
);
897 GetWindowRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
898 This
->WindowPos
= This
->DestRect
;
900 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_HIDE
);
901 SetParent(This
->baseControlWindow
.baseWindow
.hWnd
, This
->baseControlWindow
.hwndOwner
);
902 SetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
, This
->baseControlWindow
.baseWindow
.WindowStyles
);
903 GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
904 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
,0,This
->DestRect
.left
,This
->DestRect
.top
,This
->DestRect
.right
,This
->DestRect
.bottom
,SWP_NOZORDER
|SWP_SHOWWINDOW
);
905 This
->WindowPos
= This
->DestRect
;
907 This
->FullScreenMode
= FullScreenMode
;
912 static const IVideoWindowVtbl IVideoWindow_VTable
=
914 VideoWindow_QueryInterface
,
917 BaseControlWindowImpl_GetTypeInfoCount
,
918 BaseControlWindowImpl_GetTypeInfo
,
919 BaseControlWindowImpl_GetIDsOfNames
,
920 BaseControlWindowImpl_Invoke
,
921 BaseControlWindowImpl_put_Caption
,
922 BaseControlWindowImpl_get_Caption
,
923 BaseControlWindowImpl_put_WindowStyle
,
924 BaseControlWindowImpl_get_WindowStyle
,
925 BaseControlWindowImpl_put_WindowStyleEx
,
926 BaseControlWindowImpl_get_WindowStyleEx
,
927 BaseControlWindowImpl_put_AutoShow
,
928 BaseControlWindowImpl_get_AutoShow
,
929 BaseControlWindowImpl_put_WindowState
,
930 BaseControlWindowImpl_get_WindowState
,
931 BaseControlWindowImpl_put_BackgroundPalette
,
932 BaseControlWindowImpl_get_BackgroundPalette
,
933 BaseControlWindowImpl_put_Visible
,
934 BaseControlWindowImpl_get_Visible
,
935 BaseControlWindowImpl_put_Left
,
936 BaseControlWindowImpl_get_Left
,
937 BaseControlWindowImpl_put_Width
,
938 BaseControlWindowImpl_get_Width
,
939 BaseControlWindowImpl_put_Top
,
940 BaseControlWindowImpl_get_Top
,
941 BaseControlWindowImpl_put_Height
,
942 BaseControlWindowImpl_get_Height
,
943 BaseControlWindowImpl_put_Owner
,
944 BaseControlWindowImpl_get_Owner
,
945 BaseControlWindowImpl_put_MessageDrain
,
946 BaseControlWindowImpl_get_MessageDrain
,
947 BaseControlWindowImpl_get_BorderColor
,
948 BaseControlWindowImpl_put_BorderColor
,
949 VideoWindow_get_FullScreenMode
,
950 VideoWindow_put_FullScreenMode
,
951 BaseControlWindowImpl_SetWindowForeground
,
952 BaseControlWindowImpl_NotifyOwnerMessage
,
953 BaseControlWindowImpl_SetWindowPosition
,
954 BaseControlWindowImpl_GetWindowPosition
,
955 BaseControlWindowImpl_GetMinIdealImageSize
,
956 BaseControlWindowImpl_GetMaxIdealImageSize
,
957 BaseControlWindowImpl_GetRestorePosition
,
958 BaseControlWindowImpl_HideCursor
,
959 BaseControlWindowImpl_IsCursorHidden
962 static VideoRendererImpl
*impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
)
964 return CONTAINING_RECORD(iface
, VideoRendererImpl
, IAMFilterMiscFlags_iface
);
967 static HRESULT WINAPI
AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
,
970 VideoRendererImpl
*This
= impl_from_IAMFilterMiscFlags(iface
);
971 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
974 static ULONG WINAPI
AMFilterMiscFlags_AddRef(IAMFilterMiscFlags
*iface
)
976 VideoRendererImpl
*This
= impl_from_IAMFilterMiscFlags(iface
);
977 return IUnknown_AddRef(This
->outer_unk
);
980 static ULONG WINAPI
AMFilterMiscFlags_Release(IAMFilterMiscFlags
*iface
)
982 VideoRendererImpl
*This
= impl_from_IAMFilterMiscFlags(iface
);
983 return IUnknown_Release(This
->outer_unk
);
986 static ULONG WINAPI
AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
988 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
991 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
= {
992 AMFilterMiscFlags_QueryInterface
,
993 AMFilterMiscFlags_AddRef
,
994 AMFilterMiscFlags_Release
,
995 AMFilterMiscFlags_GetMiscFlags
998 HRESULT
VideoRenderer_create(IUnknown
*pUnkOuter
, void **ppv
)
1001 VideoRendererImpl
* pVideoRenderer
;
1003 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
1007 pVideoRenderer
= CoTaskMemAlloc(sizeof(VideoRendererImpl
));
1008 pVideoRenderer
->IUnknown_inner
.lpVtbl
= &IInner_VTable
;
1009 pVideoRenderer
->IAMFilterMiscFlags_iface
.lpVtbl
= &IAMFilterMiscFlags_Vtbl
;
1011 pVideoRenderer
->init
= FALSE
;
1012 ZeroMemory(&pVideoRenderer
->SourceRect
, sizeof(RECT
));
1013 ZeroMemory(&pVideoRenderer
->DestRect
, sizeof(RECT
));
1014 ZeroMemory(&pVideoRenderer
->WindowPos
, sizeof(RECT
));
1015 pVideoRenderer
->FullScreenMode
= OAFALSE
;
1018 pVideoRenderer
->outer_unk
= pUnkOuter
;
1020 pVideoRenderer
->outer_unk
= &pVideoRenderer
->IUnknown_inner
;
1022 hr
= BaseRenderer_Init(&pVideoRenderer
->renderer
, &VideoRenderer_Vtbl
, pUnkOuter
,
1023 &CLSID_VideoRenderer
, (DWORD_PTR
)(__FILE__
": VideoRendererImpl.csFilter"),
1029 hr
= BaseControlWindow_Init(&pVideoRenderer
->baseControlWindow
, &IVideoWindow_VTable
,
1030 &pVideoRenderer
->renderer
.filter
, &pVideoRenderer
->renderer
.filter
.csFilter
,
1031 &pVideoRenderer
->renderer
.pInputPin
->pin
, &renderer_BaseWindowFuncTable
);
1035 hr
= BaseControlVideo_Init(&pVideoRenderer
->baseControlVideo
, &IBasicVideo_VTable
,
1036 &pVideoRenderer
->renderer
.filter
, &pVideoRenderer
->renderer
.filter
.csFilter
,
1037 &pVideoRenderer
->renderer
.pInputPin
->pin
, &renderer_BaseControlVideoFuncTable
);
1041 if (!CreateRenderingSubsystem(pVideoRenderer
)) {
1046 *ppv
= &pVideoRenderer
->IUnknown_inner
;
1050 BaseRendererImpl_Release(&pVideoRenderer
->renderer
.filter
.IBaseFilter_iface
);
1051 CoTaskMemFree(pVideoRenderer
);
1055 HRESULT
VideoRendererDefault_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
1057 /* TODO: Attempt to use the VMR-7 renderer instead when possible */
1058 return VideoRenderer_create(pUnkOuter
, ppv
);