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"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
41 struct strmbase_renderer renderer
;
42 struct video_window window
;
44 IOverlay IOverlay_iface
;
53 static inline struct video_renderer
*impl_from_video_window(struct video_window
*iface
)
55 return CONTAINING_RECORD(iface
, struct video_renderer
, window
);
58 static inline struct video_renderer
*impl_from_strmbase_renderer(struct strmbase_renderer
*iface
)
60 return CONTAINING_RECORD(iface
, struct video_renderer
, renderer
);
63 static inline struct video_renderer
*impl_from_IVideoWindow(IVideoWindow
*iface
)
65 return CONTAINING_RECORD(iface
, struct video_renderer
, window
.IVideoWindow_iface
);
68 static const BITMAPINFOHEADER
*get_bitmap_header(const AM_MEDIA_TYPE
*mt
)
70 if (IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
71 return &((VIDEOINFOHEADER
*)mt
->pbFormat
)->bmiHeader
;
73 return &((VIDEOINFOHEADER2
*)mt
->pbFormat
)->bmiHeader
;
76 static void VideoRenderer_AutoShowWindow(struct video_renderer
*This
)
78 if (This
->window
.AutoShow
)
79 ShowWindow(This
->window
.hwnd
, SW_SHOW
);
82 static HRESULT
video_renderer_render(struct strmbase_renderer
*iface
, IMediaSample
*pSample
)
84 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
85 RECT src
= filter
->window
.src
, dst
= filter
->window
.dst
;
86 LPBYTE pbSrcStream
= NULL
;
90 TRACE("filter %p, sample %p.\n", filter
, pSample
);
92 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
95 ERR("Cannot get pointer to sample data (%x)\n", hr
);
99 dc
= GetDC(filter
->window
.hwnd
);
100 StretchDIBits(dc
, dst
.left
, dst
.top
, dst
.right
- dst
.left
, dst
.bottom
- dst
.top
,
101 src
.left
, src
.top
, src
.right
- src
.left
, src
.bottom
- src
.top
, pbSrcStream
,
102 (BITMAPINFO
*)get_bitmap_header(&filter
->renderer
.sink
.pin
.mt
), DIB_RGB_COLORS
, SRCCOPY
);
103 ReleaseDC(filter
->window
.hwnd
, dc
);
108 static HRESULT
video_renderer_query_accept(struct strmbase_renderer
*iface
, const AM_MEDIA_TYPE
*mt
)
110 if (!IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
))
113 if (!IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB32
)
114 && !IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB24
)
115 && !IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB565
)
116 && !IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
))
119 if (!IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
)
120 && !IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo2
))
126 static void video_renderer_destroy(struct strmbase_renderer
*iface
)
128 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
130 video_window_cleanup(&filter
->window
);
131 strmbase_renderer_cleanup(&filter
->renderer
);
134 InterlockedDecrement(&object_locks
);
137 static HRESULT
video_renderer_query_interface(struct strmbase_renderer
*iface
, REFIID iid
, void **out
)
139 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
141 if (IsEqualGUID(iid
, &IID_IBasicVideo
))
142 *out
= &filter
->window
.IBasicVideo_iface
;
143 else if (IsEqualGUID(iid
, &IID_IVideoWindow
))
144 *out
= &filter
->window
.IVideoWindow_iface
;
146 return E_NOINTERFACE
;
148 IUnknown_AddRef((IUnknown
*)*out
);
152 static HRESULT
video_renderer_pin_query_interface(struct strmbase_renderer
*iface
, REFIID iid
, void **out
)
154 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
156 if (IsEqualGUID(iid
, &IID_IOverlay
))
157 *out
= &filter
->IOverlay_iface
;
159 return E_NOINTERFACE
;
161 IUnknown_AddRef((IUnknown
*)*out
);
165 static void video_renderer_stop_stream(struct strmbase_renderer
*iface
)
167 struct video_renderer
*This
= impl_from_strmbase_renderer(iface
);
169 TRACE("(%p)->()\n", This
);
171 if (This
->window
.AutoShow
)
173 RedrawWindow(This
->window
.hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_ERASE
);
176 static void video_renderer_init_stream(struct strmbase_renderer
*iface
)
178 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
180 VideoRenderer_AutoShowWindow(filter
);
183 static HRESULT
video_renderer_connect(struct strmbase_renderer
*iface
, const AM_MEDIA_TYPE
*mt
)
185 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
186 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(mt
);
187 HWND window
= filter
->window
.hwnd
;
190 filter
->VideoWidth
= bitmap_header
->biWidth
;
191 filter
->VideoHeight
= abs(bitmap_header
->biHeight
);
192 SetRect(&rect
, 0, 0, filter
->VideoWidth
, filter
->VideoHeight
);
193 filter
->window
.src
= rect
;
195 AdjustWindowRectEx(&rect
, GetWindowLongW(window
, GWL_STYLE
), FALSE
,
196 GetWindowLongW(window
, GWL_EXSTYLE
));
197 SetWindowPos(window
, NULL
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
198 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
199 GetClientRect(window
, &filter
->window
.dst
);
204 static RECT
video_renderer_get_default_rect(struct video_window
*iface
)
206 struct video_renderer
*This
= impl_from_video_window(iface
);
209 SetRect(&defRect
, 0, 0, This
->VideoWidth
, This
->VideoHeight
);
214 static const struct strmbase_renderer_ops renderer_ops
=
216 .renderer_query_accept
= video_renderer_query_accept
,
217 .renderer_render
= video_renderer_render
,
218 .renderer_init_stream
= video_renderer_init_stream
,
219 .renderer_stop_stream
= video_renderer_stop_stream
,
220 .renderer_destroy
= video_renderer_destroy
,
221 .renderer_query_interface
= video_renderer_query_interface
,
222 .renderer_pin_query_interface
= video_renderer_pin_query_interface
,
223 .renderer_connect
= video_renderer_connect
,
226 static HRESULT
video_renderer_get_current_image(struct video_window
*iface
, LONG
*size
, LONG
*image
)
228 struct video_renderer
*filter
= impl_from_video_window(iface
);
229 const BITMAPINFOHEADER
*bih
;
233 EnterCriticalSection(&filter
->renderer
.filter
.stream_cs
);
235 bih
= get_bitmap_header(&filter
->renderer
.sink
.pin
.mt
);
236 image_size
= bih
->biWidth
* bih
->biHeight
* bih
->biBitCount
/ 8;
240 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
241 *size
= sizeof(BITMAPINFOHEADER
) + image_size
;
245 if (filter
->renderer
.filter
.state
!= State_Paused
)
247 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
248 return VFW_E_NOT_PAUSED
;
251 if (!filter
->renderer
.current_sample
)
253 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
257 if (*size
< sizeof(BITMAPINFOHEADER
) + image_size
)
259 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
260 return E_OUTOFMEMORY
;
263 memcpy(image
, bih
, sizeof(BITMAPINFOHEADER
));
264 IMediaSample_GetPointer(filter
->renderer
.current_sample
, &sample_data
);
265 memcpy((char *)image
+ sizeof(BITMAPINFOHEADER
), sample_data
, image_size
);
267 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
271 static const struct video_window_ops window_ops
=
273 .get_default_rect
= video_renderer_get_default_rect
,
274 .get_current_image
= video_renderer_get_current_image
,
277 static HRESULT WINAPI
VideoWindow_get_FullScreenMode(IVideoWindow
*iface
,
278 LONG
*FullScreenMode
)
280 struct video_renderer
*This
= impl_from_IVideoWindow(iface
);
282 TRACE("(%p/%p)->(%p): %d\n", This
, iface
, FullScreenMode
, This
->FullScreenMode
);
287 *FullScreenMode
= This
->FullScreenMode
;
292 static HRESULT WINAPI
VideoWindow_put_FullScreenMode(IVideoWindow
*iface
, LONG fullscreen
)
294 struct video_renderer
*filter
= impl_from_IVideoWindow(iface
);
295 HWND window
= filter
->window
.hwnd
;
297 FIXME("filter %p, fullscreen %d.\n", filter
, fullscreen
);
301 filter
->saved_style
= GetWindowLongW(window
, GWL_STYLE
);
302 ShowWindow(window
, SW_HIDE
);
303 SetParent(window
, NULL
);
304 SetWindowLongW(window
, GWL_STYLE
, WS_POPUP
);
305 SetWindowPos(window
, HWND_TOP
, 0, 0,
306 GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
), SWP_SHOWWINDOW
);
307 GetWindowRect(window
, &filter
->window
.dst
);
311 ShowWindow(window
, SW_HIDE
);
312 SetParent(window
, filter
->window
.hwndOwner
);
313 SetWindowLongW(window
, GWL_STYLE
, filter
->saved_style
);
314 GetClientRect(window
, &filter
->window
.dst
);
315 SetWindowPos(window
, 0, filter
->window
.dst
.left
, filter
->window
.dst
.top
,
316 filter
->window
.dst
.right
, filter
->window
.dst
.bottom
, SWP_NOZORDER
| SWP_SHOWWINDOW
);
318 filter
->FullScreenMode
= fullscreen
;
323 static const IVideoWindowVtbl IVideoWindow_VTable
=
325 BaseControlWindowImpl_QueryInterface
,
326 BaseControlWindowImpl_AddRef
,
327 BaseControlWindowImpl_Release
,
328 BaseControlWindowImpl_GetTypeInfoCount
,
329 BaseControlWindowImpl_GetTypeInfo
,
330 BaseControlWindowImpl_GetIDsOfNames
,
331 BaseControlWindowImpl_Invoke
,
332 BaseControlWindowImpl_put_Caption
,
333 BaseControlWindowImpl_get_Caption
,
334 BaseControlWindowImpl_put_WindowStyle
,
335 BaseControlWindowImpl_get_WindowStyle
,
336 BaseControlWindowImpl_put_WindowStyleEx
,
337 BaseControlWindowImpl_get_WindowStyleEx
,
338 BaseControlWindowImpl_put_AutoShow
,
339 BaseControlWindowImpl_get_AutoShow
,
340 BaseControlWindowImpl_put_WindowState
,
341 BaseControlWindowImpl_get_WindowState
,
342 BaseControlWindowImpl_put_BackgroundPalette
,
343 BaseControlWindowImpl_get_BackgroundPalette
,
344 BaseControlWindowImpl_put_Visible
,
345 BaseControlWindowImpl_get_Visible
,
346 BaseControlWindowImpl_put_Left
,
347 BaseControlWindowImpl_get_Left
,
348 BaseControlWindowImpl_put_Width
,
349 BaseControlWindowImpl_get_Width
,
350 BaseControlWindowImpl_put_Top
,
351 BaseControlWindowImpl_get_Top
,
352 BaseControlWindowImpl_put_Height
,
353 BaseControlWindowImpl_get_Height
,
354 BaseControlWindowImpl_put_Owner
,
355 BaseControlWindowImpl_get_Owner
,
356 BaseControlWindowImpl_put_MessageDrain
,
357 BaseControlWindowImpl_get_MessageDrain
,
358 BaseControlWindowImpl_get_BorderColor
,
359 BaseControlWindowImpl_put_BorderColor
,
360 VideoWindow_get_FullScreenMode
,
361 VideoWindow_put_FullScreenMode
,
362 BaseControlWindowImpl_SetWindowForeground
,
363 BaseControlWindowImpl_NotifyOwnerMessage
,
364 BaseControlWindowImpl_SetWindowPosition
,
365 BaseControlWindowImpl_GetWindowPosition
,
366 BaseControlWindowImpl_GetMinIdealImageSize
,
367 BaseControlWindowImpl_GetMaxIdealImageSize
,
368 BaseControlWindowImpl_GetRestorePosition
,
369 BaseControlWindowImpl_HideCursor
,
370 BaseControlWindowImpl_IsCursorHidden
373 static inline struct video_renderer
*impl_from_IOverlay(IOverlay
*iface
)
375 return CONTAINING_RECORD(iface
, struct video_renderer
, IOverlay_iface
);
378 static HRESULT WINAPI
overlay_QueryInterface(IOverlay
*iface
, REFIID iid
, void **out
)
380 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
381 return IPin_QueryInterface(&filter
->renderer
.sink
.pin
.IPin_iface
, iid
, out
);
384 static ULONG WINAPI
overlay_AddRef(IOverlay
*iface
)
386 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
387 return IPin_AddRef(&filter
->renderer
.sink
.pin
.IPin_iface
);
390 static ULONG WINAPI
overlay_Release(IOverlay
*iface
)
392 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
393 return IPin_Release(&filter
->renderer
.sink
.pin
.IPin_iface
);
396 static HRESULT WINAPI
overlay_GetPalette(IOverlay
*iface
, DWORD
*count
, PALETTEENTRY
**palette
)
398 FIXME("iface %p, count %p, palette %p, stub!\n", iface
, count
, palette
);
402 static HRESULT WINAPI
overlay_SetPalette(IOverlay
*iface
, DWORD count
, PALETTEENTRY
*palette
)
404 FIXME("iface %p, count %u, palette %p, stub!\n", iface
, count
, palette
);
408 static HRESULT WINAPI
overlay_GetDefaultColorKey(IOverlay
*iface
, COLORKEY
*key
)
410 FIXME("iface %p, key %p, stub!\n", iface
, key
);
414 static HRESULT WINAPI
overlay_GetColorKey(IOverlay
*iface
, COLORKEY
*key
)
416 FIXME("iface %p, key %p, stub!\n", iface
, key
);
420 static HRESULT WINAPI
overlay_SetColorKey(IOverlay
*iface
, COLORKEY
*key
)
422 FIXME("iface %p, key %p, stub!\n", iface
, key
);
426 static HRESULT WINAPI
overlay_GetWindowHandle(IOverlay
*iface
, HWND
*window
)
428 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
430 TRACE("filter %p, window %p.\n", filter
, window
);
432 *window
= filter
->window
.hwnd
;
436 static HRESULT WINAPI
overlay_GetClipList(IOverlay
*iface
, RECT
*source
, RECT
*dest
, RGNDATA
**region
)
438 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface
, source
, dest
, region
);
442 static HRESULT WINAPI
overlay_GetVideoPosition(IOverlay
*iface
, RECT
*source
, RECT
*dest
)
444 FIXME("iface %p, source %p, dest %p, stub!\n", iface
, source
, dest
);
448 static HRESULT WINAPI
overlay_Advise(IOverlay
*iface
, IOverlayNotify
*sink
, DWORD flags
)
450 FIXME("iface %p, sink %p, flags %#x, stub!\n", iface
, sink
, flags
);
454 static HRESULT WINAPI
overlay_Unadvise(IOverlay
*iface
)
456 FIXME("iface %p, stub!\n", iface
);
460 static const IOverlayVtbl overlay_vtbl
=
462 overlay_QueryInterface
,
467 overlay_GetDefaultColorKey
,
470 overlay_GetWindowHandle
,
472 overlay_GetVideoPosition
,
477 HRESULT
video_renderer_create(IUnknown
*outer
, IUnknown
**out
)
479 struct video_renderer
*object
;
482 if (!(object
= calloc(1, sizeof(*object
))))
483 return E_OUTOFMEMORY
;
485 strmbase_renderer_init(&object
->renderer
, outer
, &CLSID_VideoRenderer
, L
"In", &renderer_ops
);
486 object
->IOverlay_iface
.lpVtbl
= &overlay_vtbl
;
488 video_window_init(&object
->window
, &IVideoWindow_VTable
,
489 &object
->renderer
.filter
, &object
->renderer
.sink
.pin
, &window_ops
);
491 if (FAILED(hr
= video_window_create_window(&object
->window
)))
493 video_window_cleanup(&object
->window
);
494 strmbase_renderer_cleanup(&object
->renderer
);
499 TRACE("Created video renderer %p.\n", object
);
500 *out
= &object
->renderer
.filter
.IUnknown_inner
;
504 HRESULT
video_renderer_default_create(IUnknown
*outer
, IUnknown
**out
)
508 if (SUCCEEDED(hr
= vmr7_create(outer
, out
)))
511 return video_renderer_create(outer
, out
);