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 typedef struct VideoRendererImpl
47 BaseRenderer renderer
;
48 BaseControlWindow baseControlWindow
;
49 BaseControlVideo baseControlVideo
;
51 IUnknown IUnknown_inner
;
52 IAMFilterMiscFlags IAMFilterMiscFlags_iface
;
60 /* hEvent == evComplete? */
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
;
105 TRACE("Starting message loop\n");
107 if (FAILED(BaseWindowImpl_PrepareWindow(&This
->baseControlWindow
.baseWindow
)))
109 This
->ThreadResult
= FALSE
;
110 SetEvent(This
->hEvent
);
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");
128 static BOOL
CreateRenderingSubsystem(VideoRendererImpl
* This
)
130 This
->hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
134 This
->hThread
= CreateThread(NULL
, 0, MessageLoop
, This
, 0, &This
->ThreadID
);
137 CloseHandle(This
->hEvent
);
141 WaitForSingleObject(This
->hEvent
, INFINITE
);
143 if (!This
->ThreadResult
)
145 CloseHandle(This
->hEvent
);
146 CloseHandle(This
->hThread
);
153 static void VideoRenderer_AutoShowWindow(VideoRendererImpl
*This
)
155 if (!This
->init
&& (!This
->WindowPos
.right
|| !This
->WindowPos
.top
))
157 DWORD style
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
);
158 DWORD style_ex
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_EXSTYLE
);
160 if (!This
->WindowPos
.right
)
162 if (This
->DestRect
.right
)
164 This
->WindowPos
.left
= This
->DestRect
.left
;
165 This
->WindowPos
.right
= This
->DestRect
.right
;
169 This
->WindowPos
.left
= This
->SourceRect
.left
;
170 This
->WindowPos
.right
= This
->SourceRect
.right
;
173 if (!This
->WindowPos
.bottom
)
175 if (This
->DestRect
.bottom
)
177 This
->WindowPos
.top
= This
->DestRect
.top
;
178 This
->WindowPos
.bottom
= This
->DestRect
.bottom
;
182 This
->WindowPos
.top
= This
->SourceRect
.top
;
183 This
->WindowPos
.bottom
= This
->SourceRect
.bottom
;
187 AdjustWindowRectEx(&This
->WindowPos
, style
, FALSE
, style_ex
);
189 TRACE("WindowPos: %d %d %d %d\n", This
->WindowPos
.left
, This
->WindowPos
.top
, This
->WindowPos
.right
, This
->WindowPos
.bottom
);
190 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
, NULL
,
191 This
->WindowPos
.left
,
193 This
->WindowPos
.right
- This
->WindowPos
.left
,
194 This
->WindowPos
.bottom
- This
->WindowPos
.top
,
195 SWP_NOZORDER
|SWP_NOMOVE
|SWP_DEFERERASE
);
197 GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
199 else if (!This
->init
)
200 This
->DestRect
= This
->WindowPos
;
202 if (This
->baseControlWindow
.AutoShow
)
203 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_SHOW
);
206 static DWORD
VideoRenderer_SendSampleData(VideoRendererImpl
* This
, LPBYTE data
, DWORD size
)
210 BITMAPINFOHEADER
*bmiHeader
;
212 TRACE("(%p)->(%p, %d)\n", This
, data
, size
);
214 hr
= IPin_ConnectionMediaType(&This
->renderer
.pInputPin
->pin
.IPin_iface
, &amt
);
216 ERR("Unable to retrieve media type\n");
220 if (IsEqualIID(&amt
.formattype
, &FORMAT_VideoInfo
))
222 bmiHeader
= &((VIDEOINFOHEADER
*)amt
.pbFormat
)->bmiHeader
;
224 else if (IsEqualIID(&amt
.formattype
, &FORMAT_VideoInfo2
))
226 bmiHeader
= &((VIDEOINFOHEADER2
*)amt
.pbFormat
)->bmiHeader
;
230 FIXME("Unknown type %s\n", debugstr_guid(&amt
.subtype
));
231 return VFW_E_RUNTIME_ERROR
;
234 TRACE("biSize = %d\n", bmiHeader
->biSize
);
235 TRACE("biWidth = %d\n", bmiHeader
->biWidth
);
236 TRACE("biHeight = %d\n", bmiHeader
->biHeight
);
237 TRACE("biPlanes = %d\n", bmiHeader
->biPlanes
);
238 TRACE("biBitCount = %d\n", bmiHeader
->biBitCount
);
239 TRACE("biCompression = %s\n", debugstr_an((LPSTR
)&(bmiHeader
->biCompression
), 4));
240 TRACE("biSizeImage = %d\n", bmiHeader
->biSizeImage
);
242 if (!This
->baseControlWindow
.baseWindow
.hDC
) {
243 ERR("Cannot get DC from window!\n");
247 TRACE("Src Rect: %d %d %d %d\n", This
->SourceRect
.left
, This
->SourceRect
.top
, This
->SourceRect
.right
, This
->SourceRect
.bottom
);
248 TRACE("Dst Rect: %d %d %d %d\n", This
->DestRect
.left
, This
->DestRect
.top
, This
->DestRect
.right
, This
->DestRect
.bottom
);
250 StretchDIBits(This
->baseControlWindow
.baseWindow
.hDC
, This
->DestRect
.left
, This
->DestRect
.top
, This
->DestRect
.right
-This
->DestRect
.left
,
251 This
->DestRect
.bottom
- This
->DestRect
.top
, This
->SourceRect
.left
, This
->SourceRect
.top
,
252 This
->SourceRect
.right
- This
->SourceRect
.left
, This
->SourceRect
.bottom
- This
->SourceRect
.top
,
253 data
, (BITMAPINFO
*)bmiHeader
, DIB_RGB_COLORS
, SRCCOPY
);
258 static HRESULT WINAPI
VideoRenderer_ShouldDrawSampleNow(BaseRenderer
*This
, IMediaSample
*pSample
, REFERENCE_TIME
*pStartTime
, REFERENCE_TIME
*pEndTime
)
260 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
261 if (IMediaSample_IsPreroll(pSample
) == S_OK
)
266 static HRESULT WINAPI
VideoRenderer_DoRenderSample(BaseRenderer
* iface
, IMediaSample
* pSample
)
268 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
269 LPBYTE pbSrcStream
= NULL
;
270 LONG cbSrcStream
= 0;
273 TRACE("(%p)->(%p)\n", This
, pSample
);
275 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
278 ERR("Cannot get pointer to sample data (%x)\n", hr
);
282 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
284 TRACE("val %p %d\n", pbSrcStream
, cbSrcStream
);
286 #if 0 /* For debugging purpose */
289 for(i
= 0; i
< cbSrcStream
; i
++)
291 if ((i
!=0) && !(i
%16))
293 TRACE("%02x ", pbSrcStream
[i
]);
299 SetEvent(This
->hEvent
);
300 if (This
->renderer
.filter
.state
== State_Paused
)
302 VideoRenderer_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
303 SetEvent(This
->hEvent
);
304 if (This
->renderer
.filter
.state
== State_Paused
)
309 if (This
->renderer
.filter
.state
== State_Stopped
)
311 return VFW_E_WRONG_STATE
;
314 VideoRenderer_SendSampleData(This
, pbSrcStream
, cbSrcStream
);
319 static HRESULT WINAPI
VideoRenderer_CheckMediaType(BaseRenderer
*iface
, const AM_MEDIA_TYPE
* pmt
)
321 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
323 if (!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
))
326 if (IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB32
) ||
327 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB24
) ||
328 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB565
) ||
329 IsEqualIID(&pmt
->subtype
, &MEDIASUBTYPE_RGB8
))
333 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
))
335 VIDEOINFOHEADER
*format
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
336 This
->SourceRect
.left
= 0;
337 This
->SourceRect
.top
= 0;
338 This
->SourceRect
.right
= This
->VideoWidth
= format
->bmiHeader
.biWidth
;
339 height
= format
->bmiHeader
.biHeight
;
341 This
->SourceRect
.bottom
= This
->VideoHeight
= -height
;
343 This
->SourceRect
.bottom
= This
->VideoHeight
= height
;
345 else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
))
347 VIDEOINFOHEADER2
*format2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
349 This
->SourceRect
.left
= 0;
350 This
->SourceRect
.top
= 0;
351 This
->SourceRect
.right
= This
->VideoWidth
= format2
->bmiHeader
.biWidth
;
352 height
= format2
->bmiHeader
.biHeight
;
354 This
->SourceRect
.bottom
= This
->VideoHeight
= -height
;
356 This
->SourceRect
.bottom
= This
->VideoHeight
= height
;
360 WARN("Format type %s not supported\n", debugstr_guid(&pmt
->formattype
));
368 static HRESULT WINAPI
VideoRenderer_EndFlush(BaseRenderer
* iface
)
370 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
372 TRACE("(%p)->()\n", iface
);
374 if (This
->renderer
.pMediaSample
) {
375 ResetEvent(This
->hEvent
);
376 LeaveCriticalSection(iface
->pInputPin
->pin
.pCritSec
);
377 LeaveCriticalSection(&iface
->filter
.csFilter
);
378 LeaveCriticalSection(&iface
->csRenderLock
);
379 WaitForSingleObject(This
->hEvent
, INFINITE
);
380 EnterCriticalSection(&iface
->csRenderLock
);
381 EnterCriticalSection(&iface
->filter
.csFilter
);
382 EnterCriticalSection(iface
->pInputPin
->pin
.pCritSec
);
384 if (This
->renderer
.filter
.state
== State_Paused
) {
385 ResetEvent(This
->hEvent
);
388 return BaseRendererImpl_EndFlush(iface
);
391 static VOID WINAPI
VideoRenderer_OnStopStreaming(BaseRenderer
* iface
)
393 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
395 TRACE("(%p)->()\n", This
);
397 SetEvent(This
->hEvent
);
398 if (This
->baseControlWindow
.AutoShow
)
400 RedrawWindow(This
->baseControlWindow
.baseWindow
.hWnd
, NULL
, NULL
, RDW_INVALIDATE
|RDW_ERASE
);
403 static VOID WINAPI
VideoRenderer_OnStartStreaming(BaseRenderer
* iface
)
405 VideoRendererImpl
*This
= impl_from_BaseRenderer(iface
);
407 TRACE("(%p)\n", This
);
409 if (This
->renderer
.pInputPin
->pin
.pConnectedTo
&& (This
->renderer
.filter
.state
== State_Stopped
|| !This
->renderer
.pInputPin
->end_of_stream
))
411 if (This
->renderer
.filter
.state
== State_Stopped
)
413 ResetEvent(This
->hEvent
);
414 VideoRenderer_AutoShowWindow(This
);
419 static LPWSTR WINAPI
VideoRenderer_GetClassWindowStyles(BaseWindow
*This
, DWORD
*pClassStyles
, DWORD
*pWindowStyles
, DWORD
*pWindowStylesEx
)
421 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 };
424 *pWindowStyles
= WS_SIZEBOX
;
425 *pWindowStylesEx
= 0;
427 return (LPWSTR
)classnameW
;
430 static RECT WINAPI
VideoRenderer_GetDefaultRect(BaseWindow
*iface
)
432 VideoRendererImpl
*This
= impl_from_BaseWindow(iface
);
435 defRect
.left
= defRect
.top
= 0;
436 defRect
.right
= This
->VideoWidth
;
437 defRect
.bottom
= This
->VideoHeight
;
442 static BOOL WINAPI
VideoRenderer_OnSize(BaseWindow
*iface
, LONG Width
, LONG Height
)
444 VideoRendererImpl
*This
= impl_from_BaseWindow(iface
);
446 TRACE("WM_SIZE %d %d\n", Width
, Height
);
447 GetClientRect(iface
->hWnd
, &This
->DestRect
);
448 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
451 This
->DestRect
.right
- This
->DestRect
.left
,
452 This
->DestRect
.bottom
- This
->DestRect
.top
);
453 return BaseWindowImpl_OnSize(iface
, Width
, Height
);
456 static const BaseRendererFuncTable BaseFuncTable
= {
457 VideoRenderer_CheckMediaType
,
458 VideoRenderer_DoRenderSample
,
463 VideoRenderer_OnStartStreaming
,
464 VideoRenderer_OnStopStreaming
,
468 VideoRenderer_ShouldDrawSampleNow
,
475 VideoRenderer_EndFlush
,
478 static const BaseWindowFuncTable renderer_BaseWindowFuncTable
= {
479 VideoRenderer_GetClassWindowStyles
,
480 VideoRenderer_GetDefaultRect
,
482 BaseControlWindowImpl_PossiblyEatMessage
,
486 static HRESULT WINAPI
VideoRenderer_GetSourceRect(BaseControlVideo
* iface
, RECT
*pSourceRect
)
488 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
489 CopyRect(pSourceRect
,&This
->SourceRect
);
493 static HRESULT WINAPI
VideoRenderer_GetStaticImage(BaseControlVideo
* iface
, LONG
*pBufferSize
, LONG
*pDIBImage
)
495 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
496 BITMAPINFOHEADER
*bmiHeader
;
498 AM_MEDIA_TYPE
*amt
= &This
->renderer
.pInputPin
->pin
.mtCurrent
;
501 FIXME("(%p/%p)->(%p, %p): partial stub\n", This
, iface
, pBufferSize
, pDIBImage
);
503 EnterCriticalSection(&This
->renderer
.filter
.csFilter
);
505 if (!This
->renderer
.pMediaSample
)
507 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
508 return (This
->renderer
.filter
.state
== State_Paused
? E_UNEXPECTED
: VFW_E_NOT_PAUSED
);
511 if (IsEqualIID(&amt
->formattype
, &FORMAT_VideoInfo
))
513 bmiHeader
= &((VIDEOINFOHEADER
*)amt
->pbFormat
)->bmiHeader
;
515 else if (IsEqualIID(&amt
->formattype
, &FORMAT_VideoInfo2
))
517 bmiHeader
= &((VIDEOINFOHEADER2
*)amt
->pbFormat
)->bmiHeader
;
521 FIXME("Unknown type %s\n", debugstr_guid(&amt
->subtype
));
522 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
523 return VFW_E_RUNTIME_ERROR
;
526 needed_size
= bmiHeader
->biSize
;
527 needed_size
+= IMediaSample_GetActualDataLength(This
->renderer
.pMediaSample
);
531 *pBufferSize
= needed_size
;
532 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
536 if (needed_size
< *pBufferSize
)
538 ERR("Buffer too small %u/%u\n", needed_size
, *pBufferSize
);
539 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
542 *pBufferSize
= needed_size
;
544 memcpy(pDIBImage
, bmiHeader
, bmiHeader
->biSize
);
545 IMediaSample_GetPointer(This
->renderer
.pMediaSample
, (BYTE
**)&ptr
);
546 memcpy((char *)pDIBImage
+ bmiHeader
->biSize
, ptr
, IMediaSample_GetActualDataLength(This
->renderer
.pMediaSample
));
548 LeaveCriticalSection(&This
->renderer
.filter
.csFilter
);
552 static HRESULT WINAPI
VideoRenderer_GetTargetRect(BaseControlVideo
* iface
, RECT
*pTargetRect
)
554 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
555 CopyRect(pTargetRect
,&This
->DestRect
);
559 static VIDEOINFOHEADER
* WINAPI
VideoRenderer_GetVideoFormat(BaseControlVideo
* iface
)
561 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
564 TRACE("(%p/%p)\n", This
, iface
);
566 pmt
= &This
->renderer
.pInputPin
->pin
.mtCurrent
;
567 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
568 return (VIDEOINFOHEADER
*)pmt
->pbFormat
;
569 } else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
)) {
570 static VIDEOINFOHEADER vih
;
571 VIDEOINFOHEADER2
*vih2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
572 memcpy(&vih
,vih2
,sizeof(VIDEOINFOHEADER
));
573 memcpy(&vih
.bmiHeader
, &vih2
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
576 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt
->formattype
));
581 static HRESULT WINAPI
VideoRenderer_IsDefaultSourceRect(BaseControlVideo
* iface
)
583 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
584 FIXME("(%p/%p)->(): stub !!!\n", This
, iface
);
589 static HRESULT WINAPI
VideoRenderer_IsDefaultTargetRect(BaseControlVideo
* iface
)
591 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
592 FIXME("(%p/%p)->(): stub !!!\n", This
, iface
);
597 static HRESULT WINAPI
VideoRenderer_SetDefaultSourceRect(BaseControlVideo
* iface
)
599 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
601 This
->SourceRect
.left
= 0;
602 This
->SourceRect
.top
= 0;
603 This
->SourceRect
.right
= This
->VideoWidth
;
604 This
->SourceRect
.bottom
= This
->VideoHeight
;
609 static HRESULT WINAPI
VideoRenderer_SetDefaultTargetRect(BaseControlVideo
* iface
)
611 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
614 if (!GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &rect
))
617 This
->DestRect
.left
= 0;
618 This
->DestRect
.top
= 0;
619 This
->DestRect
.right
= rect
.right
;
620 This
->DestRect
.bottom
= rect
.bottom
;
625 static HRESULT WINAPI
VideoRenderer_SetSourceRect(BaseControlVideo
* iface
, RECT
*pSourceRect
)
627 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
628 CopyRect(&This
->SourceRect
,pSourceRect
);
632 static HRESULT WINAPI
VideoRenderer_SetTargetRect(BaseControlVideo
* iface
, RECT
*pTargetRect
)
634 VideoRendererImpl
*This
= impl_from_BaseControlVideo(iface
);
635 CopyRect(&This
->DestRect
,pTargetRect
);
639 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable
= {
640 VideoRenderer_GetSourceRect
,
641 VideoRenderer_GetStaticImage
,
642 VideoRenderer_GetTargetRect
,
643 VideoRenderer_GetVideoFormat
,
644 VideoRenderer_IsDefaultSourceRect
,
645 VideoRenderer_IsDefaultTargetRect
,
646 VideoRenderer_SetDefaultSourceRect
,
647 VideoRenderer_SetDefaultTargetRect
,
648 VideoRenderer_SetSourceRect
,
649 VideoRenderer_SetTargetRect
652 static inline VideoRendererImpl
*impl_from_IUnknown(IUnknown
*iface
)
654 return CONTAINING_RECORD(iface
, VideoRendererImpl
, IUnknown_inner
);
657 static HRESULT WINAPI
VideoRendererInner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
659 VideoRendererImpl
*This
= impl_from_IUnknown(iface
);
661 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
665 if (IsEqualIID(riid
, &IID_IUnknown
))
666 *ppv
= &This
->IUnknown_inner
;
667 else if (IsEqualIID(riid
, &IID_IBasicVideo
))
668 *ppv
= &This
->baseControlVideo
.IBasicVideo_iface
;
669 else if (IsEqualIID(riid
, &IID_IVideoWindow
))
670 *ppv
= &This
->baseControlWindow
.IVideoWindow_iface
;
671 else if (IsEqualIID(riid
, &IID_IAMFilterMiscFlags
))
672 *ppv
= &This
->IAMFilterMiscFlags_iface
;
676 hr
= BaseRendererImpl_QueryInterface(&This
->renderer
.filter
.IBaseFilter_iface
, riid
, ppv
);
683 IUnknown_AddRef((IUnknown
*)*ppv
);
687 if (!IsEqualIID(riid
, &IID_IPin
))
688 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
690 return E_NOINTERFACE
;
693 static ULONG WINAPI
VideoRendererInner_AddRef(IUnknown
*iface
)
695 VideoRendererImpl
*This
= impl_from_IUnknown(iface
);
696 ULONG refCount
= BaseFilterImpl_AddRef(&This
->renderer
.filter
.IBaseFilter_iface
);
698 TRACE("(%p)->(): new ref = %d\n", This
, refCount
);
703 static ULONG WINAPI
VideoRendererInner_Release(IUnknown
*iface
)
705 VideoRendererImpl
*This
= impl_from_IUnknown(iface
);
706 ULONG refCount
= BaseRendererImpl_Release(&This
->renderer
.filter
.IBaseFilter_iface
);
708 TRACE("(%p)->(): new ref = %d\n", This
, refCount
);
712 BaseControlWindow_Destroy(&This
->baseControlWindow
);
713 BaseControlVideo_Destroy(&This
->baseControlVideo
);
714 PostThreadMessageW(This
->ThreadID
, WM_QUIT
, 0, 0);
715 WaitForSingleObject(This
->hThread
, INFINITE
);
716 CloseHandle(This
->hThread
);
717 CloseHandle(This
->hEvent
);
719 TRACE("Destroying Video Renderer\n");
728 static const IUnknownVtbl IInner_VTable
=
730 VideoRendererInner_QueryInterface
,
731 VideoRendererInner_AddRef
,
732 VideoRendererInner_Release
735 static HRESULT WINAPI
VideoRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
737 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
738 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
741 static ULONG WINAPI
VideoRenderer_AddRef(IBaseFilter
* iface
)
743 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
744 return IUnknown_AddRef(This
->outer_unk
);
747 static ULONG WINAPI
VideoRenderer_Release(IBaseFilter
* iface
)
749 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
750 return IUnknown_Release(This
->outer_unk
);
753 /** IMediaFilter methods **/
755 static HRESULT WINAPI
VideoRenderer_Pause(IBaseFilter
* iface
)
757 VideoRendererImpl
*This
= impl_from_IBaseFilter(iface
);
759 TRACE("(%p/%p)->()\n", This
, iface
);
761 EnterCriticalSection(&This
->renderer
.csRenderLock
);
762 if (This
->renderer
.filter
.state
!= State_Paused
)
764 if (This
->renderer
.filter
.state
== State_Stopped
)
766 This
->renderer
.pInputPin
->end_of_stream
= 0;
767 ResetEvent(This
->hEvent
);
768 VideoRenderer_AutoShowWindow(This
);
771 ResetEvent(This
->renderer
.RenderEvent
);
772 This
->renderer
.filter
.state
= State_Paused
;
774 LeaveCriticalSection(&This
->renderer
.csRenderLock
);
779 static const IBaseFilterVtbl VideoRenderer_Vtbl
=
781 VideoRenderer_QueryInterface
,
782 VideoRenderer_AddRef
,
783 VideoRenderer_Release
,
784 BaseFilterImpl_GetClassID
,
785 BaseRendererImpl_Stop
,
787 BaseRendererImpl_Run
,
788 BaseRendererImpl_GetState
,
789 BaseRendererImpl_SetSyncSource
,
790 BaseFilterImpl_GetSyncSource
,
791 BaseFilterImpl_EnumPins
,
792 BaseRendererImpl_FindPin
,
793 BaseFilterImpl_QueryFilterInfo
,
794 BaseFilterImpl_JoinFilterGraph
,
795 BaseFilterImpl_QueryVendorInfo
798 /*** IUnknown methods ***/
799 static HRESULT WINAPI
BasicVideo_QueryInterface(IBasicVideo
*iface
, REFIID riid
, LPVOID
*ppvObj
)
801 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
803 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
805 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppvObj
);
808 static ULONG WINAPI
BasicVideo_AddRef(IBasicVideo
*iface
)
810 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
812 TRACE("(%p/%p)->()\n", This
, iface
);
814 return IUnknown_AddRef(This
->outer_unk
);
817 static ULONG WINAPI
BasicVideo_Release(IBasicVideo
*iface
)
819 VideoRendererImpl
*This
= impl_from_IBasicVideo(iface
);
821 TRACE("(%p/%p)->()\n", This
, iface
);
823 return IUnknown_Release(This
->outer_unk
);
826 static const IBasicVideoVtbl IBasicVideo_VTable
=
828 BasicVideo_QueryInterface
,
831 BaseControlVideoImpl_GetTypeInfoCount
,
832 BaseControlVideoImpl_GetTypeInfo
,
833 BaseControlVideoImpl_GetIDsOfNames
,
834 BaseControlVideoImpl_Invoke
,
835 BaseControlVideoImpl_get_AvgTimePerFrame
,
836 BaseControlVideoImpl_get_BitRate
,
837 BaseControlVideoImpl_get_BitErrorRate
,
838 BaseControlVideoImpl_get_VideoWidth
,
839 BaseControlVideoImpl_get_VideoHeight
,
840 BaseControlVideoImpl_put_SourceLeft
,
841 BaseControlVideoImpl_get_SourceLeft
,
842 BaseControlVideoImpl_put_SourceWidth
,
843 BaseControlVideoImpl_get_SourceWidth
,
844 BaseControlVideoImpl_put_SourceTop
,
845 BaseControlVideoImpl_get_SourceTop
,
846 BaseControlVideoImpl_put_SourceHeight
,
847 BaseControlVideoImpl_get_SourceHeight
,
848 BaseControlVideoImpl_put_DestinationLeft
,
849 BaseControlVideoImpl_get_DestinationLeft
,
850 BaseControlVideoImpl_put_DestinationWidth
,
851 BaseControlVideoImpl_get_DestinationWidth
,
852 BaseControlVideoImpl_put_DestinationTop
,
853 BaseControlVideoImpl_get_DestinationTop
,
854 BaseControlVideoImpl_put_DestinationHeight
,
855 BaseControlVideoImpl_get_DestinationHeight
,
856 BaseControlVideoImpl_SetSourcePosition
,
857 BaseControlVideoImpl_GetSourcePosition
,
858 BaseControlVideoImpl_SetDefaultSourcePosition
,
859 BaseControlVideoImpl_SetDestinationPosition
,
860 BaseControlVideoImpl_GetDestinationPosition
,
861 BaseControlVideoImpl_SetDefaultDestinationPosition
,
862 BaseControlVideoImpl_GetVideoSize
,
863 BaseControlVideoImpl_GetVideoPaletteEntries
,
864 BaseControlVideoImpl_GetCurrentImage
,
865 BaseControlVideoImpl_IsUsingDefaultSource
,
866 BaseControlVideoImpl_IsUsingDefaultDestination
870 /*** IUnknown methods ***/
871 static HRESULT WINAPI
VideoWindow_QueryInterface(IVideoWindow
*iface
, REFIID riid
, LPVOID
*ppvObj
)
873 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
875 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
877 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppvObj
);
880 static ULONG WINAPI
VideoWindow_AddRef(IVideoWindow
*iface
)
882 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
884 TRACE("(%p/%p)->()\n", This
, iface
);
886 return IUnknown_AddRef(This
->outer_unk
);
889 static ULONG WINAPI
VideoWindow_Release(IVideoWindow
*iface
)
891 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
893 TRACE("(%p/%p)->()\n", This
, iface
);
895 return IUnknown_Release(This
->outer_unk
);
898 static HRESULT WINAPI
VideoWindow_get_FullScreenMode(IVideoWindow
*iface
,
899 LONG
*FullScreenMode
)
901 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
903 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, FullScreenMode
);
908 static HRESULT WINAPI
VideoWindow_put_FullScreenMode(IVideoWindow
*iface
,
911 VideoRendererImpl
*This
= impl_from_IVideoWindow(iface
);
913 FIXME("(%p/%p)->(%d): stub !!!\n", This
, iface
, FullScreenMode
);
915 if (FullScreenMode
) {
916 This
->baseControlWindow
.baseWindow
.WindowStyles
= GetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
);
917 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_HIDE
);
918 SetParent(This
->baseControlWindow
.baseWindow
.hWnd
, 0);
919 SetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
, WS_POPUP
);
920 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
,HWND_TOP
,0,0,GetSystemMetrics(SM_CXSCREEN
),GetSystemMetrics(SM_CYSCREEN
),SWP_SHOWWINDOW
);
921 GetWindowRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
922 This
->WindowPos
= This
->DestRect
;
924 ShowWindow(This
->baseControlWindow
.baseWindow
.hWnd
, SW_HIDE
);
925 SetParent(This
->baseControlWindow
.baseWindow
.hWnd
, This
->baseControlWindow
.hwndOwner
);
926 SetWindowLongW(This
->baseControlWindow
.baseWindow
.hWnd
, GWL_STYLE
, This
->baseControlWindow
.baseWindow
.WindowStyles
);
927 GetClientRect(This
->baseControlWindow
.baseWindow
.hWnd
, &This
->DestRect
);
928 SetWindowPos(This
->baseControlWindow
.baseWindow
.hWnd
,0,This
->DestRect
.left
,This
->DestRect
.top
,This
->DestRect
.right
,This
->DestRect
.bottom
,SWP_NOZORDER
|SWP_SHOWWINDOW
);
929 This
->WindowPos
= This
->DestRect
;
935 static const IVideoWindowVtbl IVideoWindow_VTable
=
937 VideoWindow_QueryInterface
,
940 BaseControlWindowImpl_GetTypeInfoCount
,
941 BaseControlWindowImpl_GetTypeInfo
,
942 BaseControlWindowImpl_GetIDsOfNames
,
943 BaseControlWindowImpl_Invoke
,
944 BaseControlWindowImpl_put_Caption
,
945 BaseControlWindowImpl_get_Caption
,
946 BaseControlWindowImpl_put_WindowStyle
,
947 BaseControlWindowImpl_get_WindowStyle
,
948 BaseControlWindowImpl_put_WindowStyleEx
,
949 BaseControlWindowImpl_get_WindowStyleEx
,
950 BaseControlWindowImpl_put_AutoShow
,
951 BaseControlWindowImpl_get_AutoShow
,
952 BaseControlWindowImpl_put_WindowState
,
953 BaseControlWindowImpl_get_WindowState
,
954 BaseControlWindowImpl_put_BackgroundPalette
,
955 BaseControlWindowImpl_get_BackgroundPalette
,
956 BaseControlWindowImpl_put_Visible
,
957 BaseControlWindowImpl_get_Visible
,
958 BaseControlWindowImpl_put_Left
,
959 BaseControlWindowImpl_get_Left
,
960 BaseControlWindowImpl_put_Width
,
961 BaseControlWindowImpl_get_Width
,
962 BaseControlWindowImpl_put_Top
,
963 BaseControlWindowImpl_get_Top
,
964 BaseControlWindowImpl_put_Height
,
965 BaseControlWindowImpl_get_Height
,
966 BaseControlWindowImpl_put_Owner
,
967 BaseControlWindowImpl_get_Owner
,
968 BaseControlWindowImpl_put_MessageDrain
,
969 BaseControlWindowImpl_get_MessageDrain
,
970 BaseControlWindowImpl_get_BorderColor
,
971 BaseControlWindowImpl_put_BorderColor
,
972 VideoWindow_get_FullScreenMode
,
973 VideoWindow_put_FullScreenMode
,
974 BaseControlWindowImpl_SetWindowForeground
,
975 BaseControlWindowImpl_NotifyOwnerMessage
,
976 BaseControlWindowImpl_SetWindowPosition
,
977 BaseControlWindowImpl_GetWindowPosition
,
978 BaseControlWindowImpl_GetMinIdealImageSize
,
979 BaseControlWindowImpl_GetMaxIdealImageSize
,
980 BaseControlWindowImpl_GetRestorePosition
,
981 BaseControlWindowImpl_HideCursor
,
982 BaseControlWindowImpl_IsCursorHidden
985 static VideoRendererImpl
*impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
)
987 return CONTAINING_RECORD(iface
, VideoRendererImpl
, IAMFilterMiscFlags_iface
);
990 static HRESULT WINAPI
AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
,
993 VideoRendererImpl
*This
= impl_from_IAMFilterMiscFlags(iface
);
994 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
997 static ULONG WINAPI
AMFilterMiscFlags_AddRef(IAMFilterMiscFlags
*iface
)
999 VideoRendererImpl
*This
= impl_from_IAMFilterMiscFlags(iface
);
1000 return IUnknown_AddRef(This
->outer_unk
);
1003 static ULONG WINAPI
AMFilterMiscFlags_Release(IAMFilterMiscFlags
*iface
)
1005 VideoRendererImpl
*This
= impl_from_IAMFilterMiscFlags(iface
);
1006 return IUnknown_Release(This
->outer_unk
);
1009 static ULONG WINAPI
AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
1011 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
1014 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
= {
1015 AMFilterMiscFlags_QueryInterface
,
1016 AMFilterMiscFlags_AddRef
,
1017 AMFilterMiscFlags_Release
,
1018 AMFilterMiscFlags_GetMiscFlags
1021 HRESULT
VideoRenderer_create(IUnknown
*pUnkOuter
, void **ppv
)
1024 VideoRendererImpl
* pVideoRenderer
;
1026 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
1030 pVideoRenderer
= CoTaskMemAlloc(sizeof(VideoRendererImpl
));
1031 pVideoRenderer
->IUnknown_inner
.lpVtbl
= &IInner_VTable
;
1032 pVideoRenderer
->IAMFilterMiscFlags_iface
.lpVtbl
= &IAMFilterMiscFlags_Vtbl
;
1034 pVideoRenderer
->init
= FALSE
;
1035 ZeroMemory(&pVideoRenderer
->SourceRect
, sizeof(RECT
));
1036 ZeroMemory(&pVideoRenderer
->DestRect
, sizeof(RECT
));
1037 ZeroMemory(&pVideoRenderer
->WindowPos
, sizeof(RECT
));
1040 pVideoRenderer
->outer_unk
= pUnkOuter
;
1042 pVideoRenderer
->outer_unk
= &pVideoRenderer
->IUnknown_inner
;
1044 hr
= BaseRenderer_Init(&pVideoRenderer
->renderer
, &VideoRenderer_Vtbl
, pUnkOuter
,
1045 &CLSID_VideoRenderer
, (DWORD_PTR
)(__FILE__
": VideoRendererImpl.csFilter"),
1051 hr
= BaseControlWindow_Init(&pVideoRenderer
->baseControlWindow
, &IVideoWindow_VTable
,
1052 &pVideoRenderer
->renderer
.filter
, &pVideoRenderer
->renderer
.filter
.csFilter
,
1053 &pVideoRenderer
->renderer
.pInputPin
->pin
, &renderer_BaseWindowFuncTable
);
1057 hr
= BaseControlVideo_Init(&pVideoRenderer
->baseControlVideo
, &IBasicVideo_VTable
,
1058 &pVideoRenderer
->renderer
.filter
, &pVideoRenderer
->renderer
.filter
.csFilter
,
1059 &pVideoRenderer
->renderer
.pInputPin
->pin
, &renderer_BaseControlVideoFuncTable
);
1063 if (!CreateRenderingSubsystem(pVideoRenderer
)) {
1068 *ppv
= &pVideoRenderer
->IUnknown_inner
;
1072 BaseRendererImpl_Release(&pVideoRenderer
->renderer
.filter
.IBaseFilter_iface
);
1073 CoTaskMemFree(pVideoRenderer
);
1077 HRESULT
VideoRendererDefault_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
1079 /* TODO: Attempt to use the VMR-7 renderer instead when possible */
1080 return VideoRenderer_create(pUnkOuter
, ppv
);