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)
211 BITMAPINFOHEADER *bmiHeader;
213 TRACE("(%p)->(%p, %d)\n", This, data, size);
215 sdesc.dwSize = sizeof(sdesc);
216 hr = IPin_ConnectionMediaType(&This->renderer.pInputPin->pin.IPin_iface, &amt);
218 ERR("Unable to retrieve media type\n");
222 if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo))
224 bmiHeader = &((VIDEOINFOHEADER *)amt.pbFormat)->bmiHeader;
226 else if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo2))
228 bmiHeader = &((VIDEOINFOHEADER2 *)amt.pbFormat)->bmiHeader;
232 FIXME("Unknown type %s\n", debugstr_guid(&amt.subtype));
233 return VFW_E_RUNTIME_ERROR;
236 TRACE("biSize = %d\n", bmiHeader->biSize);
237 TRACE("biWidth = %d\n", bmiHeader->biWidth);
238 TRACE("biHeight = %d\n", bmiHeader->biHeight);
239 TRACE("biPlanes = %d\n", bmiHeader->biPlanes);
240 TRACE("biBitCount = %d\n", bmiHeader->biBitCount);
241 TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
242 TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
244 if (!This->baseControlWindow.baseWindow.hDC) {
245 ERR("Cannot get DC from window!\n");
249 TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom);
250 TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom);
252 StretchDIBits(This->baseControlWindow.baseWindow.hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left,
253 This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top,
254 This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top,
255 data, (BITMAPINFO *)bmiHeader, DIB_RGB_COLORS, SRCCOPY);
260 static HRESULT WINAPI VideoRenderer_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
262 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
263 if (IMediaSample_IsPreroll(pSample) == S_OK)
268 static HRESULT WINAPI VideoRenderer_DoRenderSample(BaseRenderer* iface, IMediaSample * pSample)
270 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
271 LPBYTE pbSrcStream = NULL;
272 LONG cbSrcStream = 0;
275 TRACE("(%p)->(%p)\n", This, pSample);
277 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
280 ERR("Cannot get pointer to sample data (%x)\n", hr);
284 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
286 TRACE("val %p %d\n", pbSrcStream, cbSrcStream);
288 #if 0 /* For debugging purpose */
291 for(i = 0; i < cbSrcStream; i++)
293 if ((i!=0) && !(i%16))
295 TRACE("%02x ", pbSrcStream[i]);
301 SetEvent(This->hEvent);
302 if (This->renderer.filter.state == State_Paused)
304 VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
305 SetEvent(This->hEvent);
306 if (This->renderer.filter.state == State_Paused)
311 if (This->renderer.filter.state == State_Stopped)
313 return VFW_E_WRONG_STATE;
316 VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
321 static HRESULT WINAPI VideoRenderer_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
323 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
325 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
328 if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
329 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
330 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
331 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
335 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
337 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
338 This->SourceRect.left = 0;
339 This->SourceRect.top = 0;
340 This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
341 height = format->bmiHeader.biHeight;
343 This->SourceRect.bottom = This->VideoHeight = -height;
345 This->SourceRect.bottom = This->VideoHeight = height;
347 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
349 VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat;
351 This->SourceRect.left = 0;
352 This->SourceRect.top = 0;
353 This->SourceRect.right = This->VideoWidth = format2->bmiHeader.biWidth;
354 height = format2->bmiHeader.biHeight;
356 This->SourceRect.bottom = This->VideoHeight = -height;
358 This->SourceRect.bottom = This->VideoHeight = height;
362 WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
370 static HRESULT WINAPI VideoRenderer_EndFlush(BaseRenderer* iface)
372 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
374 TRACE("(%p)->()\n", iface);
376 if (This->renderer.pMediaSample) {
377 ResetEvent(This->hEvent);
378 LeaveCriticalSection(iface->pInputPin->pin.pCritSec);
379 LeaveCriticalSection(&iface->csRenderLock);
380 LeaveCriticalSection(&iface->filter.csFilter);
381 WaitForSingleObject(This->hEvent, INFINITE);
382 EnterCriticalSection(&iface->filter.csFilter);
383 EnterCriticalSection(&iface->csRenderLock);
384 EnterCriticalSection(iface->pInputPin->pin.pCritSec);
386 if (This->renderer.filter.state == State_Paused) {
387 ResetEvent(This->hEvent);
390 return BaseRendererImpl_EndFlush(iface);
393 static VOID WINAPI VideoRenderer_OnStopStreaming(BaseRenderer* iface)
395 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
397 TRACE("(%p)->()\n", This);
399 SetEvent(This->hEvent);
400 if (This->baseControlWindow.AutoShow)
402 RedrawWindow(This->baseControlWindow.baseWindow.hWnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE);
405 static VOID WINAPI VideoRenderer_OnStartStreaming(BaseRenderer* iface)
407 VideoRendererImpl *This = impl_from_BaseRenderer(iface);
409 TRACE("(%p)\n", This);
411 if (This->renderer.pInputPin->pin.pConnectedTo && (This->renderer.filter.state == State_Stopped || !This->renderer.pInputPin->end_of_stream))
413 if (This->renderer.filter.state == State_Stopped)
415 ResetEvent(This->hEvent);
416 VideoRenderer_AutoShowWindow(This);
421 static LPWSTR WINAPI VideoRenderer_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
423 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 };
426 *pWindowStyles = WS_SIZEBOX;
427 *pWindowStylesEx = 0;
429 return (LPWSTR)classnameW;
432 static RECT WINAPI VideoRenderer_GetDefaultRect(BaseWindow *iface)
434 VideoRendererImpl *This = impl_from_BaseWindow(iface);
437 defRect.left = defRect.top = 0;
438 defRect.right = This->VideoWidth;
439 defRect.bottom = This->VideoHeight;
444 static BOOL WINAPI VideoRenderer_OnSize(BaseWindow *iface, LONG Width, LONG Height)
446 VideoRendererImpl *This = impl_from_BaseWindow(iface);
448 TRACE("WM_SIZE %d %d\n", Width, Height);
449 GetClientRect(iface->hWnd, &This->DestRect);
450 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
453 This->DestRect.right - This->DestRect.left,
454 This->DestRect.bottom - This->DestRect.top);
455 return BaseWindowImpl_OnSize(iface, Width, Height);
458 static const BaseRendererFuncTable BaseFuncTable = {
459 VideoRenderer_CheckMediaType,
460 VideoRenderer_DoRenderSample,
465 VideoRenderer_OnStartStreaming,
466 VideoRenderer_OnStopStreaming,
470 VideoRenderer_ShouldDrawSampleNow,
477 VideoRenderer_EndFlush,
480 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
481 VideoRenderer_GetClassWindowStyles,
482 VideoRenderer_GetDefaultRect,
484 BaseControlWindowImpl_PossiblyEatMessage,
488 static HRESULT WINAPI VideoRenderer_GetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
490 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
491 CopyRect(pSourceRect,&This->SourceRect);
495 static HRESULT WINAPI VideoRenderer_GetStaticImage(BaseControlVideo* iface, LONG *pBufferSize, LONG *pDIBImage)
497 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
498 BITMAPINFOHEADER *bmiHeader;
500 AM_MEDIA_TYPE *amt = &This->renderer.pInputPin->pin.mtCurrent;
503 FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage);
505 EnterCriticalSection(&This->renderer.filter.csFilter);
507 if (!This->renderer.pMediaSample)
509 LeaveCriticalSection(&This->renderer.filter.csFilter);
510 return (This->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
513 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
515 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
517 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
519 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
523 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
524 LeaveCriticalSection(&This->renderer.filter.csFilter);
525 return VFW_E_RUNTIME_ERROR;
528 needed_size = bmiHeader->biSize;
529 needed_size += IMediaSample_GetActualDataLength(This->renderer.pMediaSample);
533 *pBufferSize = needed_size;
534 LeaveCriticalSection(&This->renderer.filter.csFilter);
538 if (needed_size < *pBufferSize)
540 ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
541 LeaveCriticalSection(&This->renderer.filter.csFilter);
544 *pBufferSize = needed_size;
546 memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
547 IMediaSample_GetPointer(This->renderer.pMediaSample, (BYTE **)&ptr);
548 memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->renderer.pMediaSample));
550 LeaveCriticalSection(&This->renderer.filter.csFilter);
554 static HRESULT WINAPI VideoRenderer_GetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
556 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
557 CopyRect(pTargetRect,&This->DestRect);
561 static VIDEOINFOHEADER* WINAPI VideoRenderer_GetVideoFormat(BaseControlVideo* iface)
563 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
566 TRACE("(%p/%p)\n", This, iface);
568 pmt = &This->renderer.pInputPin->pin.mtCurrent;
569 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
570 return (VIDEOINFOHEADER*)pmt->pbFormat;
571 } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
572 static VIDEOINFOHEADER vih;
573 VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
574 memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
575 memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
578 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
583 static HRESULT WINAPI VideoRenderer_IsDefaultSourceRect(BaseControlVideo* iface)
585 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
586 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
591 static HRESULT WINAPI VideoRenderer_IsDefaultTargetRect(BaseControlVideo* iface)
593 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
594 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
599 static HRESULT WINAPI VideoRenderer_SetDefaultSourceRect(BaseControlVideo* iface)
601 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
603 This->SourceRect.left = 0;
604 This->SourceRect.top = 0;
605 This->SourceRect.right = This->VideoWidth;
606 This->SourceRect.bottom = This->VideoHeight;
611 static HRESULT WINAPI VideoRenderer_SetDefaultTargetRect(BaseControlVideo* iface)
613 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
616 if (!GetClientRect(This->baseControlWindow.baseWindow.hWnd, &rect))
619 This->DestRect.left = 0;
620 This->DestRect.top = 0;
621 This->DestRect.right = rect.right;
622 This->DestRect.bottom = rect.bottom;
627 static HRESULT WINAPI VideoRenderer_SetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
629 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
630 CopyRect(&This->SourceRect,pSourceRect);
634 static HRESULT WINAPI VideoRenderer_SetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
636 VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
637 CopyRect(&This->DestRect,pTargetRect);
641 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
642 VideoRenderer_GetSourceRect,
643 VideoRenderer_GetStaticImage,
644 VideoRenderer_GetTargetRect,
645 VideoRenderer_GetVideoFormat,
646 VideoRenderer_IsDefaultSourceRect,
647 VideoRenderer_IsDefaultTargetRect,
648 VideoRenderer_SetDefaultSourceRect,
649 VideoRenderer_SetDefaultTargetRect,
650 VideoRenderer_SetSourceRect,
651 VideoRenderer_SetTargetRect
654 static inline VideoRendererImpl *impl_from_IUnknown(IUnknown *iface)
656 return CONTAINING_RECORD(iface, VideoRendererImpl, IUnknown_inner);
659 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
661 VideoRendererImpl *This = impl_from_IUnknown(iface);
663 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
667 if (IsEqualIID(riid, &IID_IUnknown))
668 *ppv = &This->IUnknown_inner;
669 else if (IsEqualIID(riid, &IID_IBasicVideo))
670 *ppv = &This->baseControlVideo.IBasicVideo_iface;
671 else if (IsEqualIID(riid, &IID_IVideoWindow))
672 *ppv = &This->baseControlWindow.IVideoWindow_iface;
673 else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
674 *ppv = &This->IAMFilterMiscFlags_iface;
678 hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
685 IUnknown_AddRef((IUnknown *)*ppv);
689 if (!IsEqualIID(riid, &IID_IPin))
690 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
692 return E_NOINTERFACE;
695 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown *iface)
697 VideoRendererImpl *This = impl_from_IUnknown(iface);
698 ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
700 TRACE("(%p)->(): new ref = %d\n", This, refCount);
705 static ULONG WINAPI VideoRendererInner_Release(IUnknown *iface)
707 VideoRendererImpl *This = impl_from_IUnknown(iface);
708 ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
710 TRACE("(%p)->(): new ref = %d\n", This, refCount);
714 BaseControlWindow_Destroy(&This->baseControlWindow);
715 BaseControlVideo_Destroy(&This->baseControlVideo);
716 PostThreadMessageW(This->ThreadID, WM_QUIT, 0, 0);
717 WaitForSingleObject(This->hThread, INFINITE);
718 CloseHandle(This->hThread);
719 CloseHandle(This->hEvent);
721 TRACE("Destroying Video Renderer\n");
730 static const IUnknownVtbl IInner_VTable =
732 VideoRendererInner_QueryInterface,
733 VideoRendererInner_AddRef,
734 VideoRendererInner_Release
737 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
739 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
740 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
743 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
745 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
746 return IUnknown_AddRef(This->outer_unk);
749 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
751 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
752 return IUnknown_Release(This->outer_unk);
755 /** IMediaFilter methods **/
757 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
759 VideoRendererImpl *This = impl_from_IBaseFilter(iface);
761 TRACE("(%p/%p)->()\n", This, iface);
763 EnterCriticalSection(&This->renderer.csRenderLock);
764 if (This->renderer.filter.state != State_Paused)
766 if (This->renderer.filter.state == State_Stopped)
768 This->renderer.pInputPin->end_of_stream = 0;
769 ResetEvent(This->hEvent);
770 VideoRenderer_AutoShowWindow(This);
773 ResetEvent(This->renderer.RenderEvent);
774 This->renderer.filter.state = State_Paused;
776 LeaveCriticalSection(&This->renderer.csRenderLock);
781 static const IBaseFilterVtbl VideoRenderer_Vtbl =
783 VideoRenderer_QueryInterface,
784 VideoRenderer_AddRef,
785 VideoRenderer_Release,
786 BaseFilterImpl_GetClassID,
787 BaseRendererImpl_Stop,
789 BaseRendererImpl_Run,
790 BaseRendererImpl_GetState,
791 BaseRendererImpl_SetSyncSource,
792 BaseFilterImpl_GetSyncSource,
793 BaseFilterImpl_EnumPins,
794 BaseRendererImpl_FindPin,
795 BaseFilterImpl_QueryFilterInfo,
796 BaseFilterImpl_JoinFilterGraph,
797 BaseFilterImpl_QueryVendorInfo
800 /*** IUnknown methods ***/
801 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID *ppvObj)
803 VideoRendererImpl *This = impl_from_IBasicVideo(iface);
805 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
807 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
810 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
811 VideoRendererImpl *This = impl_from_IBasicVideo(iface);
813 TRACE("(%p/%p)->()\n", This, iface);
815 return IUnknown_AddRef(This->outer_unk);
818 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) {
881 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
883 TRACE("(%p/%p)->()\n", This, iface);
885 return IUnknown_AddRef(This->outer_unk);
888 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
889 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
891 TRACE("(%p/%p)->()\n", This, iface);
893 return IUnknown_Release(This->outer_unk);
896 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
897 LONG *FullScreenMode) {
898 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
900 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
905 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
906 LONG FullScreenMode) {
907 VideoRendererImpl *This = impl_from_IVideoWindow(iface);
909 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, FullScreenMode);
911 if (FullScreenMode) {
912 This->baseControlWindow.baseWindow.WindowStyles = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE);
913 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_HIDE);
914 SetParent(This->baseControlWindow.baseWindow.hWnd, 0);
915 SetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE, WS_POPUP);
916 SetWindowPos(This->baseControlWindow.baseWindow.hWnd,HWND_TOP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),SWP_SHOWWINDOW);
917 GetWindowRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect);
918 This->WindowPos = This->DestRect;
920 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_HIDE);
921 SetParent(This->baseControlWindow.baseWindow.hWnd, This->baseControlWindow.hwndOwner);
922 SetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE, This->baseControlWindow.baseWindow.WindowStyles);
923 GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect);
924 SetWindowPos(This->baseControlWindow.baseWindow.hWnd,0,This->DestRect.left,This->DestRect.top,This->DestRect.right,This->DestRect.bottom,SWP_NOZORDER|SWP_SHOWWINDOW);
925 This->WindowPos = This->DestRect;
931 static const IVideoWindowVtbl IVideoWindow_VTable =
933 Videowindow_QueryInterface,
936 BaseControlWindowImpl_GetTypeInfoCount,
937 BaseControlWindowImpl_GetTypeInfo,
938 BaseControlWindowImpl_GetIDsOfNames,
939 BaseControlWindowImpl_Invoke,
940 BaseControlWindowImpl_put_Caption,
941 BaseControlWindowImpl_get_Caption,
942 BaseControlWindowImpl_put_WindowStyle,
943 BaseControlWindowImpl_get_WindowStyle,
944 BaseControlWindowImpl_put_WindowStyleEx,
945 BaseControlWindowImpl_get_WindowStyleEx,
946 BaseControlWindowImpl_put_AutoShow,
947 BaseControlWindowImpl_get_AutoShow,
948 BaseControlWindowImpl_put_WindowState,
949 BaseControlWindowImpl_get_WindowState,
950 BaseControlWindowImpl_put_BackgroundPalette,
951 BaseControlWindowImpl_get_BackgroundPalette,
952 BaseControlWindowImpl_put_Visible,
953 BaseControlWindowImpl_get_Visible,
954 BaseControlWindowImpl_put_Left,
955 BaseControlWindowImpl_get_Left,
956 BaseControlWindowImpl_put_Width,
957 BaseControlWindowImpl_get_Width,
958 BaseControlWindowImpl_put_Top,
959 BaseControlWindowImpl_get_Top,
960 BaseControlWindowImpl_put_Height,
961 BaseControlWindowImpl_get_Height,
962 BaseControlWindowImpl_put_Owner,
963 BaseControlWindowImpl_get_Owner,
964 BaseControlWindowImpl_put_MessageDrain,
965 BaseControlWindowImpl_get_MessageDrain,
966 BaseControlWindowImpl_get_BorderColor,
967 BaseControlWindowImpl_put_BorderColor,
968 Videowindow_get_FullScreenMode,
969 Videowindow_put_FullScreenMode,
970 BaseControlWindowImpl_SetWindowForeground,
971 BaseControlWindowImpl_NotifyOwnerMessage,
972 BaseControlWindowImpl_SetWindowPosition,
973 BaseControlWindowImpl_GetWindowPosition,
974 BaseControlWindowImpl_GetMinIdealImageSize,
975 BaseControlWindowImpl_GetMaxIdealImageSize,
976 BaseControlWindowImpl_GetRestorePosition,
977 BaseControlWindowImpl_HideCursor,
978 BaseControlWindowImpl_IsCursorHidden
981 static VideoRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
983 return CONTAINING_RECORD(iface, VideoRendererImpl, IAMFilterMiscFlags_iface);
986 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid,
989 VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
990 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
993 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface)
995 VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
996 return IUnknown_AddRef(This->outer_unk);
999 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface)
1001 VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
1002 return IUnknown_Release(This->outer_unk);
1005 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface)
1007 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
1010 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
1011 AMFilterMiscFlags_QueryInterface,
1012 AMFilterMiscFlags_AddRef,
1013 AMFilterMiscFlags_Release,
1014 AMFilterMiscFlags_GetMiscFlags
1017 HRESULT VideoRenderer_create(IUnknown *pUnkOuter, void **ppv)
1020 VideoRendererImpl * pVideoRenderer;
1022 TRACE("(%p, %p)\n", pUnkOuter, ppv);
1026 pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
1027 pVideoRenderer->IUnknown_inner.lpVtbl = &IInner_VTable;
1028 pVideoRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1030 pVideoRenderer->init = 0;
1031 ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
1032 ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
1033 ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
1036 pVideoRenderer->outer_unk = pUnkOuter;
1038 pVideoRenderer->outer_unk = &pVideoRenderer->IUnknown_inner;
1040 hr = BaseRenderer_Init(&pVideoRenderer->renderer, &VideoRenderer_Vtbl, pUnkOuter,
1041 &CLSID_VideoRenderer, (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"),
1047 hr = BaseControlWindow_Init(&pVideoRenderer->baseControlWindow, &IVideoWindow_VTable,
1048 &pVideoRenderer->renderer.filter, &pVideoRenderer->renderer.filter.csFilter,
1049 &pVideoRenderer->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1053 hr = BaseControlVideo_Init(&pVideoRenderer->baseControlVideo, &IBasicVideo_VTable,
1054 &pVideoRenderer->renderer.filter, &pVideoRenderer->renderer.filter.csFilter,
1055 &pVideoRenderer->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1059 if (!CreateRenderingSubsystem(pVideoRenderer)) {
1064 *ppv = &pVideoRenderer->IUnknown_inner;
1068 BaseRendererImpl_Release(&pVideoRenderer->renderer.filter.IBaseFilter_iface);
1069 CoTaskMemFree(pVideoRenderer);
1073 HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
1075 /* TODO: Attempt to use the VMR-7 renderer instead when possible */
1076 return VideoRenderer_create(pUnkOuter, ppv);