widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / quartz / videorenderer.c
blob1a59a9b52135989d102948871147d8a374138ee6
1 /*
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 #include "uuids.h"
24 #include "vfwmsgs.h"
25 #include "amvideo.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "dshow.h"
29 #include "evcode.h"
30 #include "strmif.h"
31 #include "ddraw.h"
32 #include "dvdmedia.h"
34 #include <assert.h>
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
39 struct video_renderer
41 struct strmbase_renderer renderer;
42 struct video_window window;
44 IOverlay IOverlay_iface;
46 LONG VideoWidth;
47 LONG VideoHeight;
48 LONG FullScreenMode;
50 DWORD saved_style;
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;
72 else
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;
87 HRESULT hr;
88 HDC dc;
90 TRACE("filter %p, sample %p.\n", filter, pSample);
92 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
93 if (FAILED(hr))
95 ERR("Cannot get pointer to sample data (%x)\n", hr);
96 return 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);
105 return S_OK;
108 static HRESULT video_renderer_query_accept(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
110 if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video))
111 return S_FALSE;
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))
117 return S_FALSE;
119 if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
120 && !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
121 return S_FALSE;
123 return S_OK;
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);
132 free(filter);
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;
145 else
146 return E_NOINTERFACE;
148 IUnknown_AddRef((IUnknown *)*out);
149 return S_OK;
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;
158 else
159 return E_NOINTERFACE;
161 IUnknown_AddRef((IUnknown *)*out);
162 return S_OK;
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)
172 /* Black it out */
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;
188 RECT rect;
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);
201 return S_OK;
204 static RECT video_renderer_get_default_rect(struct video_window *iface)
206 struct video_renderer *This = impl_from_video_window(iface);
207 static RECT defRect;
209 SetRect(&defRect, 0, 0, This->VideoWidth, This->VideoHeight);
211 return defRect;
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;
230 size_t image_size;
231 BYTE *sample_data;
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;
238 if (!image)
240 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
241 *size = sizeof(BITMAPINFOHEADER) + image_size;
242 return S_OK;
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);
254 return E_UNEXPECTED;
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);
268 return S_OK;
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);
284 if (!FullScreenMode)
285 return E_POINTER;
287 *FullScreenMode = This->FullScreenMode;
289 return S_OK;
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);
299 if (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);
309 else
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;
320 return S_OK;
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);
399 return E_NOTIMPL;
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);
405 return E_NOTIMPL;
408 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
410 FIXME("iface %p, key %p, stub!\n", iface, key);
411 return E_NOTIMPL;
414 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
416 FIXME("iface %p, key %p, stub!\n", iface, key);
417 return E_NOTIMPL;
420 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
422 FIXME("iface %p, key %p, stub!\n", iface, key);
423 return E_NOTIMPL;
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;
433 return S_OK;
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);
439 return E_NOTIMPL;
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);
445 return E_NOTIMPL;
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);
451 return E_NOTIMPL;
454 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
456 FIXME("iface %p, stub!\n", iface);
457 return E_NOTIMPL;
460 static const IOverlayVtbl overlay_vtbl =
462 overlay_QueryInterface,
463 overlay_AddRef,
464 overlay_Release,
465 overlay_GetPalette,
466 overlay_SetPalette,
467 overlay_GetDefaultColorKey,
468 overlay_GetColorKey,
469 overlay_SetColorKey,
470 overlay_GetWindowHandle,
471 overlay_GetClipList,
472 overlay_GetVideoPosition,
473 overlay_Advise,
474 overlay_Unadvise,
477 HRESULT video_renderer_create(IUnknown *outer, IUnknown **out)
479 struct video_renderer *object;
480 HRESULT hr;
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);
495 free(object);
496 return hr;
499 TRACE("Created video renderer %p.\n", object);
500 *out = &object->renderer.filter.IUnknown_inner;
501 return S_OK;
504 HRESULT video_renderer_default_create(IUnknown *outer, IUnknown **out)
506 HRESULT hr;
508 if (SUCCEEDED(hr = vmr7_create(outer, out)))
509 return hr;
511 return video_renderer_create(outer, out);