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("Failed to get buffer pointer, hr %#lx.\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
);
135 static HRESULT
video_renderer_query_interface(struct strmbase_renderer
*iface
, REFIID iid
, void **out
)
137 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
139 if (IsEqualGUID(iid
, &IID_IBasicVideo
))
140 *out
= &filter
->window
.IBasicVideo_iface
;
141 else if (IsEqualGUID(iid
, &IID_IVideoWindow
))
142 *out
= &filter
->window
.IVideoWindow_iface
;
144 return E_NOINTERFACE
;
146 IUnknown_AddRef((IUnknown
*)*out
);
150 static HRESULT
video_renderer_pin_query_interface(struct strmbase_renderer
*iface
, REFIID iid
, void **out
)
152 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
154 if (IsEqualGUID(iid
, &IID_IOverlay
))
155 *out
= &filter
->IOverlay_iface
;
157 return E_NOINTERFACE
;
159 IUnknown_AddRef((IUnknown
*)*out
);
163 static void video_renderer_stop_stream(struct strmbase_renderer
*iface
)
165 struct video_renderer
*This
= impl_from_strmbase_renderer(iface
);
167 TRACE("(%p)->()\n", This
);
169 if (This
->window
.AutoShow
)
171 RedrawWindow(This
->window
.hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_ERASE
);
174 static void video_renderer_init_stream(struct strmbase_renderer
*iface
)
176 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
178 VideoRenderer_AutoShowWindow(filter
);
181 static HRESULT
video_renderer_connect(struct strmbase_renderer
*iface
, const AM_MEDIA_TYPE
*mt
)
183 struct video_renderer
*filter
= impl_from_strmbase_renderer(iface
);
184 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(mt
);
185 HWND window
= filter
->window
.hwnd
;
188 filter
->VideoWidth
= bitmap_header
->biWidth
;
189 filter
->VideoHeight
= abs(bitmap_header
->biHeight
);
190 SetRect(&rect
, 0, 0, filter
->VideoWidth
, filter
->VideoHeight
);
191 filter
->window
.src
= rect
;
193 AdjustWindowRectEx(&rect
, GetWindowLongW(window
, GWL_STYLE
), FALSE
,
194 GetWindowLongW(window
, GWL_EXSTYLE
));
195 SetWindowPos(window
, NULL
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
196 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
197 GetClientRect(window
, &filter
->window
.dst
);
202 static RECT
video_renderer_get_default_rect(struct video_window
*iface
)
204 struct video_renderer
*This
= impl_from_video_window(iface
);
207 SetRect(&defRect
, 0, 0, This
->VideoWidth
, This
->VideoHeight
);
212 static const struct strmbase_renderer_ops renderer_ops
=
214 .renderer_query_accept
= video_renderer_query_accept
,
215 .renderer_render
= video_renderer_render
,
216 .renderer_init_stream
= video_renderer_init_stream
,
217 .renderer_stop_stream
= video_renderer_stop_stream
,
218 .renderer_destroy
= video_renderer_destroy
,
219 .renderer_query_interface
= video_renderer_query_interface
,
220 .renderer_pin_query_interface
= video_renderer_pin_query_interface
,
221 .renderer_connect
= video_renderer_connect
,
224 static HRESULT
video_renderer_get_current_image(struct video_window
*iface
, LONG
*size
, LONG
*image
)
226 struct video_renderer
*filter
= impl_from_video_window(iface
);
227 const BITMAPINFOHEADER
*bih
;
231 EnterCriticalSection(&filter
->renderer
.filter
.stream_cs
);
233 bih
= get_bitmap_header(&filter
->renderer
.sink
.pin
.mt
);
234 image_size
= bih
->biWidth
* bih
->biHeight
* bih
->biBitCount
/ 8;
238 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
239 *size
= sizeof(BITMAPINFOHEADER
) + image_size
;
243 if (filter
->renderer
.filter
.state
!= State_Paused
)
245 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
246 return VFW_E_NOT_PAUSED
;
249 if (!filter
->renderer
.current_sample
)
251 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
255 if (*size
< sizeof(BITMAPINFOHEADER
) + image_size
)
257 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
258 return E_OUTOFMEMORY
;
261 memcpy(image
, bih
, sizeof(BITMAPINFOHEADER
));
262 IMediaSample_GetPointer(filter
->renderer
.current_sample
, &sample_data
);
263 memcpy((char *)image
+ sizeof(BITMAPINFOHEADER
), sample_data
, image_size
);
265 LeaveCriticalSection(&filter
->renderer
.filter
.stream_cs
);
269 static const struct video_window_ops window_ops
=
271 .get_default_rect
= video_renderer_get_default_rect
,
272 .get_current_image
= video_renderer_get_current_image
,
275 static HRESULT WINAPI
VideoWindow_get_FullScreenMode(IVideoWindow
*iface
,
276 LONG
*FullScreenMode
)
278 struct video_renderer
*This
= impl_from_IVideoWindow(iface
);
280 TRACE("window %p, fullscreen %p.\n", This
, FullScreenMode
);
285 *FullScreenMode
= This
->FullScreenMode
;
290 static HRESULT WINAPI
VideoWindow_put_FullScreenMode(IVideoWindow
*iface
, LONG fullscreen
)
292 struct video_renderer
*filter
= impl_from_IVideoWindow(iface
);
293 HWND window
= filter
->window
.hwnd
;
295 FIXME("filter %p, fullscreen %ld.\n", filter
, fullscreen
);
299 filter
->saved_style
= GetWindowLongW(window
, GWL_STYLE
);
300 ShowWindow(window
, SW_HIDE
);
301 SetParent(window
, NULL
);
302 SetWindowLongW(window
, GWL_STYLE
, WS_POPUP
);
303 SetWindowPos(window
, HWND_TOP
, 0, 0,
304 GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
), SWP_SHOWWINDOW
);
305 GetWindowRect(window
, &filter
->window
.dst
);
309 ShowWindow(window
, SW_HIDE
);
310 SetParent(window
, filter
->window
.hwndOwner
);
311 SetWindowLongW(window
, GWL_STYLE
, filter
->saved_style
);
312 GetClientRect(window
, &filter
->window
.dst
);
313 SetWindowPos(window
, 0, filter
->window
.dst
.left
, filter
->window
.dst
.top
,
314 filter
->window
.dst
.right
, filter
->window
.dst
.bottom
, SWP_NOZORDER
| SWP_SHOWWINDOW
);
316 filter
->FullScreenMode
= fullscreen
;
321 static const IVideoWindowVtbl IVideoWindow_VTable
=
323 BaseControlWindowImpl_QueryInterface
,
324 BaseControlWindowImpl_AddRef
,
325 BaseControlWindowImpl_Release
,
326 BaseControlWindowImpl_GetTypeInfoCount
,
327 BaseControlWindowImpl_GetTypeInfo
,
328 BaseControlWindowImpl_GetIDsOfNames
,
329 BaseControlWindowImpl_Invoke
,
330 BaseControlWindowImpl_put_Caption
,
331 BaseControlWindowImpl_get_Caption
,
332 BaseControlWindowImpl_put_WindowStyle
,
333 BaseControlWindowImpl_get_WindowStyle
,
334 BaseControlWindowImpl_put_WindowStyleEx
,
335 BaseControlWindowImpl_get_WindowStyleEx
,
336 BaseControlWindowImpl_put_AutoShow
,
337 BaseControlWindowImpl_get_AutoShow
,
338 BaseControlWindowImpl_put_WindowState
,
339 BaseControlWindowImpl_get_WindowState
,
340 BaseControlWindowImpl_put_BackgroundPalette
,
341 BaseControlWindowImpl_get_BackgroundPalette
,
342 BaseControlWindowImpl_put_Visible
,
343 BaseControlWindowImpl_get_Visible
,
344 BaseControlWindowImpl_put_Left
,
345 BaseControlWindowImpl_get_Left
,
346 BaseControlWindowImpl_put_Width
,
347 BaseControlWindowImpl_get_Width
,
348 BaseControlWindowImpl_put_Top
,
349 BaseControlWindowImpl_get_Top
,
350 BaseControlWindowImpl_put_Height
,
351 BaseControlWindowImpl_get_Height
,
352 BaseControlWindowImpl_put_Owner
,
353 BaseControlWindowImpl_get_Owner
,
354 BaseControlWindowImpl_put_MessageDrain
,
355 BaseControlWindowImpl_get_MessageDrain
,
356 BaseControlWindowImpl_get_BorderColor
,
357 BaseControlWindowImpl_put_BorderColor
,
358 VideoWindow_get_FullScreenMode
,
359 VideoWindow_put_FullScreenMode
,
360 BaseControlWindowImpl_SetWindowForeground
,
361 BaseControlWindowImpl_NotifyOwnerMessage
,
362 BaseControlWindowImpl_SetWindowPosition
,
363 BaseControlWindowImpl_GetWindowPosition
,
364 BaseControlWindowImpl_GetMinIdealImageSize
,
365 BaseControlWindowImpl_GetMaxIdealImageSize
,
366 BaseControlWindowImpl_GetRestorePosition
,
367 BaseControlWindowImpl_HideCursor
,
368 BaseControlWindowImpl_IsCursorHidden
371 static inline struct video_renderer
*impl_from_IOverlay(IOverlay
*iface
)
373 return CONTAINING_RECORD(iface
, struct video_renderer
, IOverlay_iface
);
376 static HRESULT WINAPI
overlay_QueryInterface(IOverlay
*iface
, REFIID iid
, void **out
)
378 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
379 return IPin_QueryInterface(&filter
->renderer
.sink
.pin
.IPin_iface
, iid
, out
);
382 static ULONG WINAPI
overlay_AddRef(IOverlay
*iface
)
384 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
385 return IPin_AddRef(&filter
->renderer
.sink
.pin
.IPin_iface
);
388 static ULONG WINAPI
overlay_Release(IOverlay
*iface
)
390 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
391 return IPin_Release(&filter
->renderer
.sink
.pin
.IPin_iface
);
394 static HRESULT WINAPI
overlay_GetPalette(IOverlay
*iface
, DWORD
*count
, PALETTEENTRY
**palette
)
396 FIXME("iface %p, count %p, palette %p, stub!\n", iface
, count
, palette
);
400 static HRESULT WINAPI
overlay_SetPalette(IOverlay
*iface
, DWORD count
, PALETTEENTRY
*palette
)
402 FIXME("iface %p, count %lu, palette %p, stub!\n", iface
, count
, palette
);
406 static HRESULT WINAPI
overlay_GetDefaultColorKey(IOverlay
*iface
, COLORKEY
*key
)
408 FIXME("iface %p, key %p, stub!\n", iface
, key
);
412 static HRESULT WINAPI
overlay_GetColorKey(IOverlay
*iface
, COLORKEY
*key
)
414 FIXME("iface %p, key %p, stub!\n", iface
, key
);
418 static HRESULT WINAPI
overlay_SetColorKey(IOverlay
*iface
, COLORKEY
*key
)
420 FIXME("iface %p, key %p, stub!\n", iface
, key
);
424 static HRESULT WINAPI
overlay_GetWindowHandle(IOverlay
*iface
, HWND
*window
)
426 struct video_renderer
*filter
= impl_from_IOverlay(iface
);
428 TRACE("filter %p, window %p.\n", filter
, window
);
430 *window
= filter
->window
.hwnd
;
434 static HRESULT WINAPI
overlay_GetClipList(IOverlay
*iface
, RECT
*source
, RECT
*dest
, RGNDATA
**region
)
436 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface
, source
, dest
, region
);
440 static HRESULT WINAPI
overlay_GetVideoPosition(IOverlay
*iface
, RECT
*source
, RECT
*dest
)
442 FIXME("iface %p, source %p, dest %p, stub!\n", iface
, source
, dest
);
446 static HRESULT WINAPI
overlay_Advise(IOverlay
*iface
, IOverlayNotify
*sink
, DWORD flags
)
448 FIXME("iface %p, sink %p, flags %#lx, stub!\n", iface
, sink
, flags
);
452 static HRESULT WINAPI
overlay_Unadvise(IOverlay
*iface
)
454 FIXME("iface %p, stub!\n", iface
);
458 static const IOverlayVtbl overlay_vtbl
=
460 overlay_QueryInterface
,
465 overlay_GetDefaultColorKey
,
468 overlay_GetWindowHandle
,
470 overlay_GetVideoPosition
,
475 HRESULT
video_renderer_create(IUnknown
*outer
, IUnknown
**out
)
477 struct video_renderer
*object
;
480 if (!(object
= calloc(1, sizeof(*object
))))
481 return E_OUTOFMEMORY
;
483 strmbase_renderer_init(&object
->renderer
, outer
, &CLSID_VideoRenderer
, L
"In", &renderer_ops
);
484 wcscpy(object
->renderer
.sink
.pin
.name
, L
"Input");
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
);