742 lines
24 KiB
C
742 lines
24 KiB
C
/*
|
|
* Video Renderer (Fullscreen and Windowed using Direct Draw)
|
|
*
|
|
* Copyright 2004 Christian Costa
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "quartz_private.h"
|
|
|
|
#include "uuids.h"
|
|
#include "vfwmsgs.h"
|
|
#include "amvideo.h"
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "dshow.h"
|
|
#include "evcode.h"
|
|
#include "strmif.h"
|
|
#include "ddraw.h"
|
|
#include "dvdmedia.h"
|
|
|
|
#include <assert.h>
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
|
|
|
struct video_renderer
|
|
{
|
|
struct strmbase_renderer renderer;
|
|
struct video_window baseControlWindow;
|
|
BaseControlVideo baseControlVideo;
|
|
|
|
IOverlay IOverlay_iface;
|
|
|
|
BOOL init;
|
|
|
|
RECT SourceRect;
|
|
RECT DestRect;
|
|
RECT WindowPos;
|
|
LONG VideoWidth;
|
|
LONG VideoHeight;
|
|
LONG FullScreenMode;
|
|
|
|
DWORD saved_style;
|
|
|
|
HANDLE run_event;
|
|
IMediaSample *current_sample;
|
|
};
|
|
|
|
static inline struct video_renderer *impl_from_video_window(struct video_window *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct video_renderer, baseControlWindow);
|
|
}
|
|
|
|
static inline struct video_renderer *impl_from_strmbase_renderer(struct strmbase_renderer *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct video_renderer, renderer);
|
|
}
|
|
|
|
static inline struct video_renderer *impl_from_IVideoWindow(IVideoWindow *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct video_renderer, baseControlWindow.IVideoWindow_iface);
|
|
}
|
|
|
|
static inline struct video_renderer *impl_from_BaseControlVideo(BaseControlVideo *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct video_renderer, baseControlVideo);
|
|
}
|
|
|
|
static void VideoRenderer_AutoShowWindow(struct video_renderer *This)
|
|
{
|
|
if (!This->init && (!This->WindowPos.right || !This->WindowPos.top))
|
|
{
|
|
DWORD style = GetWindowLongW(This->baseControlWindow.hwnd, GWL_STYLE);
|
|
DWORD style_ex = GetWindowLongW(This->baseControlWindow.hwnd, GWL_EXSTYLE);
|
|
|
|
if (!This->WindowPos.right)
|
|
{
|
|
if (This->DestRect.right)
|
|
{
|
|
This->WindowPos.left = This->DestRect.left;
|
|
This->WindowPos.right = This->DestRect.right;
|
|
}
|
|
else
|
|
{
|
|
This->WindowPos.left = This->SourceRect.left;
|
|
This->WindowPos.right = This->SourceRect.right;
|
|
}
|
|
}
|
|
if (!This->WindowPos.bottom)
|
|
{
|
|
if (This->DestRect.bottom)
|
|
{
|
|
This->WindowPos.top = This->DestRect.top;
|
|
This->WindowPos.bottom = This->DestRect.bottom;
|
|
}
|
|
else
|
|
{
|
|
This->WindowPos.top = This->SourceRect.top;
|
|
This->WindowPos.bottom = This->SourceRect.bottom;
|
|
}
|
|
}
|
|
|
|
AdjustWindowRectEx(&This->WindowPos, style, FALSE, style_ex);
|
|
|
|
TRACE("WindowPos: %s\n", wine_dbgstr_rect(&This->WindowPos));
|
|
SetWindowPos(This->baseControlWindow.hwnd, NULL,
|
|
This->WindowPos.left,
|
|
This->WindowPos.top,
|
|
This->WindowPos.right - This->WindowPos.left,
|
|
This->WindowPos.bottom - This->WindowPos.top,
|
|
SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
|
|
|
|
GetClientRect(This->baseControlWindow.hwnd, &This->DestRect);
|
|
}
|
|
else if (!This->init)
|
|
This->DestRect = This->WindowPos;
|
|
This->init = TRUE;
|
|
if (This->baseControlWindow.AutoShow)
|
|
ShowWindow(This->baseControlWindow.hwnd, SW_SHOW);
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_ShouldDrawSampleNow(struct strmbase_renderer *filter,
|
|
IMediaSample *pSample, REFERENCE_TIME *start, REFERENCE_TIME *end)
|
|
{
|
|
/* Preroll means the sample isn't shown, this is used for key frames and things like that */
|
|
if (IMediaSample_IsPreroll(pSample) == S_OK)
|
|
return E_FAIL;
|
|
return S_FALSE;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_DoRenderSample(struct strmbase_renderer *iface, IMediaSample *pSample)
|
|
{
|
|
struct video_renderer *filter = impl_from_strmbase_renderer(iface);
|
|
const AM_MEDIA_TYPE *mt = &filter->renderer.sink.pin.mt;
|
|
LPBYTE pbSrcStream = NULL;
|
|
BITMAPINFOHEADER *bih;
|
|
HRESULT hr;
|
|
HDC dc;
|
|
|
|
TRACE("filter %p, sample %p.\n", filter, pSample);
|
|
|
|
hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
|
|
if (FAILED(hr))
|
|
{
|
|
ERR("Cannot get pointer to sample data (%x)\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
|
|
bih = &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
|
|
else
|
|
bih = &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
|
|
|
|
dc = GetDC(filter->baseControlWindow.hwnd);
|
|
StretchDIBits(dc, filter->DestRect.left, filter->DestRect.top,
|
|
filter->DestRect.right - filter->DestRect.left,
|
|
filter->DestRect.bottom - filter->DestRect.top,
|
|
filter->SourceRect.left, filter->SourceRect.top,
|
|
filter->SourceRect.right - filter->SourceRect.left,
|
|
filter->SourceRect.bottom - filter->SourceRect.top,
|
|
pbSrcStream, (BITMAPINFO *)bih, DIB_RGB_COLORS, SRCCOPY);
|
|
ReleaseDC(filter->baseControlWindow.hwnd, dc);
|
|
|
|
if (filter->renderer.filter.state == State_Paused)
|
|
{
|
|
const HANDLE events[2] = {filter->run_event, filter->renderer.flush_event};
|
|
|
|
filter->current_sample = pSample;
|
|
|
|
LeaveCriticalSection(&filter->renderer.csRenderLock);
|
|
WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
|
EnterCriticalSection(&filter->renderer.csRenderLock);
|
|
|
|
filter->current_sample = NULL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_CheckMediaType(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *pmt)
|
|
{
|
|
struct video_renderer *This = impl_from_strmbase_renderer(iface);
|
|
|
|
if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
|
|
return S_FALSE;
|
|
|
|
if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
|
|
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
|
|
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
|
|
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
|
|
{
|
|
LONG height;
|
|
|
|
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
|
|
{
|
|
VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
|
|
This->SourceRect.left = 0;
|
|
This->SourceRect.top = 0;
|
|
This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
|
|
height = format->bmiHeader.biHeight;
|
|
if (height < 0)
|
|
This->SourceRect.bottom = This->VideoHeight = -height;
|
|
else
|
|
This->SourceRect.bottom = This->VideoHeight = height;
|
|
}
|
|
else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
|
|
{
|
|
VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat;
|
|
|
|
This->SourceRect.left = 0;
|
|
This->SourceRect.top = 0;
|
|
This->SourceRect.right = This->VideoWidth = format2->bmiHeader.biWidth;
|
|
height = format2->bmiHeader.biHeight;
|
|
if (height < 0)
|
|
This->SourceRect.bottom = This->VideoHeight = -height;
|
|
else
|
|
This->SourceRect.bottom = This->VideoHeight = height;
|
|
}
|
|
else
|
|
{
|
|
WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
|
|
return S_FALSE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
static void video_renderer_destroy(struct strmbase_renderer *iface)
|
|
{
|
|
struct video_renderer *filter = impl_from_strmbase_renderer(iface);
|
|
|
|
video_window_cleanup(&filter->baseControlWindow);
|
|
CloseHandle(filter->run_event);
|
|
strmbase_renderer_cleanup(&filter->renderer);
|
|
free(filter);
|
|
|
|
InterlockedDecrement(&object_locks);
|
|
}
|
|
|
|
static HRESULT video_renderer_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
|
|
{
|
|
struct video_renderer *filter = impl_from_strmbase_renderer(iface);
|
|
|
|
if (IsEqualGUID(iid, &IID_IBasicVideo))
|
|
*out = &filter->baseControlVideo.IBasicVideo_iface;
|
|
else if (IsEqualGUID(iid, &IID_IVideoWindow))
|
|
*out = &filter->baseControlWindow.IVideoWindow_iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUnknown_AddRef((IUnknown *)*out);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT video_renderer_pin_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
|
|
{
|
|
struct video_renderer *filter = impl_from_strmbase_renderer(iface);
|
|
|
|
if (IsEqualGUID(iid, &IID_IOverlay))
|
|
*out = &filter->IOverlay_iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUnknown_AddRef((IUnknown *)*out);
|
|
return S_OK;
|
|
}
|
|
|
|
static void video_renderer_start_stream(struct strmbase_renderer *iface)
|
|
{
|
|
struct video_renderer *filter = impl_from_strmbase_renderer(iface);
|
|
|
|
SetEvent(filter->run_event);
|
|
}
|
|
|
|
static void video_renderer_stop_stream(struct strmbase_renderer *iface)
|
|
{
|
|
struct video_renderer *This = impl_from_strmbase_renderer(iface);
|
|
|
|
TRACE("(%p)->()\n", This);
|
|
|
|
if (This->baseControlWindow.AutoShow)
|
|
/* Black it out */
|
|
RedrawWindow(This->baseControlWindow.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
|
|
|
|
ResetEvent(This->run_event);
|
|
}
|
|
|
|
static void video_renderer_init_stream(struct strmbase_renderer *iface)
|
|
{
|
|
struct video_renderer *filter = impl_from_strmbase_renderer(iface);
|
|
|
|
VideoRenderer_AutoShowWindow(filter);
|
|
}
|
|
|
|
static RECT video_renderer_get_default_rect(struct video_window *iface)
|
|
{
|
|
struct video_renderer *This = impl_from_video_window(iface);
|
|
static RECT defRect;
|
|
|
|
SetRect(&defRect, 0, 0, This->VideoWidth, This->VideoHeight);
|
|
|
|
return defRect;
|
|
}
|
|
|
|
static BOOL video_renderer_resize(struct video_window *iface, LONG Width, LONG Height)
|
|
{
|
|
struct video_renderer *This = impl_from_video_window(iface);
|
|
|
|
TRACE("WM_SIZE %d %d\n", Width, Height);
|
|
GetClientRect(iface->hwnd, &This->DestRect);
|
|
TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
|
|
This->DestRect.left,
|
|
This->DestRect.top,
|
|
This->DestRect.right - This->DestRect.left,
|
|
This->DestRect.bottom - This->DestRect.top);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static const struct strmbase_renderer_ops renderer_ops =
|
|
{
|
|
.pfnCheckMediaType = VideoRenderer_CheckMediaType,
|
|
.pfnDoRenderSample = VideoRenderer_DoRenderSample,
|
|
.renderer_init_stream = video_renderer_init_stream,
|
|
.renderer_start_stream = video_renderer_start_stream,
|
|
.renderer_stop_stream = video_renderer_stop_stream,
|
|
.pfnShouldDrawSampleNow = VideoRenderer_ShouldDrawSampleNow,
|
|
.renderer_destroy = video_renderer_destroy,
|
|
.renderer_query_interface = video_renderer_query_interface,
|
|
.renderer_pin_query_interface = video_renderer_pin_query_interface,
|
|
};
|
|
|
|
static const struct video_window_ops window_ops =
|
|
{
|
|
.get_default_rect = video_renderer_get_default_rect,
|
|
.resize = video_renderer_resize,
|
|
};
|
|
|
|
static HRESULT WINAPI VideoRenderer_GetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
CopyRect(pSourceRect,&This->SourceRect);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_GetStaticImage(BaseControlVideo *iface, LONG *size, LONG *image)
|
|
{
|
|
struct video_renderer *filter = impl_from_BaseControlVideo(iface);
|
|
const AM_MEDIA_TYPE *mt = &filter->renderer.sink.pin.mt;
|
|
const BITMAPINFOHEADER *bih;
|
|
size_t image_size;
|
|
BYTE *sample_data;
|
|
|
|
TRACE("filter %p, size %p, image %p.\n", filter, size, image);
|
|
|
|
EnterCriticalSection(&filter->renderer.csRenderLock);
|
|
|
|
if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
|
|
bih = &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
|
|
else /* if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2)) */
|
|
bih = &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
|
|
image_size = bih->biWidth * bih->biHeight * bih->biBitCount / 8;
|
|
|
|
if (!image)
|
|
{
|
|
LeaveCriticalSection(&filter->renderer.csRenderLock);
|
|
*size = sizeof(BITMAPINFOHEADER) + image_size;
|
|
return S_OK;
|
|
}
|
|
|
|
if (filter->renderer.filter.state != State_Paused)
|
|
{
|
|
LeaveCriticalSection(&filter->renderer.csRenderLock);
|
|
return VFW_E_NOT_PAUSED;
|
|
}
|
|
|
|
if (!filter->current_sample)
|
|
{
|
|
LeaveCriticalSection(&filter->renderer.csRenderLock);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (*size < sizeof(BITMAPINFOHEADER) + image_size)
|
|
{
|
|
LeaveCriticalSection(&filter->renderer.csRenderLock);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
memcpy(image, bih, sizeof(BITMAPINFOHEADER));
|
|
IMediaSample_GetPointer(filter->current_sample, &sample_data);
|
|
memcpy((char *)image + sizeof(BITMAPINFOHEADER), sample_data, image_size);
|
|
|
|
LeaveCriticalSection(&filter->renderer.csRenderLock);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_GetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
CopyRect(pTargetRect,&This->DestRect);
|
|
return S_OK;
|
|
}
|
|
|
|
static VIDEOINFOHEADER* WINAPI VideoRenderer_GetVideoFormat(BaseControlVideo* iface)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
AM_MEDIA_TYPE *pmt;
|
|
|
|
TRACE("(%p/%p)\n", This, iface);
|
|
|
|
pmt = &This->renderer.sink.pin.mt;
|
|
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
|
|
return (VIDEOINFOHEADER*)pmt->pbFormat;
|
|
} else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
|
|
static VIDEOINFOHEADER vih;
|
|
VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
|
|
memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
|
|
memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
|
|
return &vih;
|
|
} else {
|
|
ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_IsDefaultSourceRect(BaseControlVideo* iface)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
FIXME("(%p/%p)->(): stub !!!\n", This, iface);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_IsDefaultTargetRect(BaseControlVideo* iface)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
FIXME("(%p/%p)->(): stub !!!\n", This, iface);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_SetDefaultSourceRect(BaseControlVideo* iface)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
|
|
SetRect(&This->SourceRect, 0, 0, This->VideoWidth, This->VideoHeight);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_SetDefaultTargetRect(BaseControlVideo* iface)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
RECT rect;
|
|
|
|
if (!GetClientRect(This->baseControlWindow.hwnd, &rect))
|
|
return E_FAIL;
|
|
|
|
SetRect(&This->DestRect, 0, 0, rect.right, rect.bottom);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_SetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
CopyRect(&This->SourceRect,pSourceRect);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoRenderer_SetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
|
|
{
|
|
struct video_renderer *This = impl_from_BaseControlVideo(iface);
|
|
CopyRect(&This->DestRect,pTargetRect);
|
|
return S_OK;
|
|
}
|
|
|
|
static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
|
|
VideoRenderer_GetSourceRect,
|
|
VideoRenderer_GetStaticImage,
|
|
VideoRenderer_GetTargetRect,
|
|
VideoRenderer_GetVideoFormat,
|
|
VideoRenderer_IsDefaultSourceRect,
|
|
VideoRenderer_IsDefaultTargetRect,
|
|
VideoRenderer_SetDefaultSourceRect,
|
|
VideoRenderer_SetDefaultTargetRect,
|
|
VideoRenderer_SetSourceRect,
|
|
VideoRenderer_SetTargetRect
|
|
};
|
|
|
|
static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
|
|
LONG *FullScreenMode)
|
|
{
|
|
struct video_renderer *This = impl_from_IVideoWindow(iface);
|
|
|
|
TRACE("(%p/%p)->(%p): %d\n", This, iface, FullScreenMode, This->FullScreenMode);
|
|
|
|
if (!FullScreenMode)
|
|
return E_POINTER;
|
|
|
|
*FullScreenMode = This->FullScreenMode;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG fullscreen)
|
|
{
|
|
struct video_renderer *filter = impl_from_IVideoWindow(iface);
|
|
|
|
FIXME("filter %p, fullscreen %d.\n", filter, fullscreen);
|
|
|
|
if (fullscreen)
|
|
{
|
|
filter->saved_style = GetWindowLongW(filter->baseControlWindow.hwnd, GWL_STYLE);
|
|
ShowWindow(filter->baseControlWindow.hwnd, SW_HIDE);
|
|
SetParent(filter->baseControlWindow.hwnd, NULL);
|
|
SetWindowLongW(filter->baseControlWindow.hwnd, GWL_STYLE, WS_POPUP);
|
|
SetWindowPos(filter->baseControlWindow.hwnd, HWND_TOP, 0, 0,
|
|
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW);
|
|
GetWindowRect(filter->baseControlWindow.hwnd, &filter->DestRect);
|
|
filter->WindowPos = filter->DestRect;
|
|
}
|
|
else
|
|
{
|
|
ShowWindow(filter->baseControlWindow.hwnd, SW_HIDE);
|
|
SetParent(filter->baseControlWindow.hwnd, filter->baseControlWindow.hwndOwner);
|
|
SetWindowLongW(filter->baseControlWindow.hwnd, GWL_STYLE, filter->saved_style);
|
|
GetClientRect(filter->baseControlWindow.hwnd, &filter->DestRect);
|
|
SetWindowPos(filter->baseControlWindow.hwnd, 0, filter->DestRect.left, filter->DestRect.top,
|
|
filter->DestRect.right, filter->DestRect.bottom, SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
filter->WindowPos = filter->DestRect;
|
|
}
|
|
filter->FullScreenMode = fullscreen;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IVideoWindowVtbl IVideoWindow_VTable =
|
|
{
|
|
BaseControlWindowImpl_QueryInterface,
|
|
BaseControlWindowImpl_AddRef,
|
|
BaseControlWindowImpl_Release,
|
|
BaseControlWindowImpl_GetTypeInfoCount,
|
|
BaseControlWindowImpl_GetTypeInfo,
|
|
BaseControlWindowImpl_GetIDsOfNames,
|
|
BaseControlWindowImpl_Invoke,
|
|
BaseControlWindowImpl_put_Caption,
|
|
BaseControlWindowImpl_get_Caption,
|
|
BaseControlWindowImpl_put_WindowStyle,
|
|
BaseControlWindowImpl_get_WindowStyle,
|
|
BaseControlWindowImpl_put_WindowStyleEx,
|
|
BaseControlWindowImpl_get_WindowStyleEx,
|
|
BaseControlWindowImpl_put_AutoShow,
|
|
BaseControlWindowImpl_get_AutoShow,
|
|
BaseControlWindowImpl_put_WindowState,
|
|
BaseControlWindowImpl_get_WindowState,
|
|
BaseControlWindowImpl_put_BackgroundPalette,
|
|
BaseControlWindowImpl_get_BackgroundPalette,
|
|
BaseControlWindowImpl_put_Visible,
|
|
BaseControlWindowImpl_get_Visible,
|
|
BaseControlWindowImpl_put_Left,
|
|
BaseControlWindowImpl_get_Left,
|
|
BaseControlWindowImpl_put_Width,
|
|
BaseControlWindowImpl_get_Width,
|
|
BaseControlWindowImpl_put_Top,
|
|
BaseControlWindowImpl_get_Top,
|
|
BaseControlWindowImpl_put_Height,
|
|
BaseControlWindowImpl_get_Height,
|
|
BaseControlWindowImpl_put_Owner,
|
|
BaseControlWindowImpl_get_Owner,
|
|
BaseControlWindowImpl_put_MessageDrain,
|
|
BaseControlWindowImpl_get_MessageDrain,
|
|
BaseControlWindowImpl_get_BorderColor,
|
|
BaseControlWindowImpl_put_BorderColor,
|
|
VideoWindow_get_FullScreenMode,
|
|
VideoWindow_put_FullScreenMode,
|
|
BaseControlWindowImpl_SetWindowForeground,
|
|
BaseControlWindowImpl_NotifyOwnerMessage,
|
|
BaseControlWindowImpl_SetWindowPosition,
|
|
BaseControlWindowImpl_GetWindowPosition,
|
|
BaseControlWindowImpl_GetMinIdealImageSize,
|
|
BaseControlWindowImpl_GetMaxIdealImageSize,
|
|
BaseControlWindowImpl_GetRestorePosition,
|
|
BaseControlWindowImpl_HideCursor,
|
|
BaseControlWindowImpl_IsCursorHidden
|
|
};
|
|
|
|
static inline struct video_renderer *impl_from_IOverlay(IOverlay *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct video_renderer, IOverlay_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
|
|
{
|
|
struct video_renderer *filter = impl_from_IOverlay(iface);
|
|
return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
|
|
}
|
|
|
|
static ULONG WINAPI overlay_AddRef(IOverlay *iface)
|
|
{
|
|
struct video_renderer *filter = impl_from_IOverlay(iface);
|
|
return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
|
|
}
|
|
|
|
static ULONG WINAPI overlay_Release(IOverlay *iface)
|
|
{
|
|
struct video_renderer *filter = impl_from_IOverlay(iface);
|
|
return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
|
|
{
|
|
FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
|
|
{
|
|
FIXME("iface %p, count %u, palette %p, stub!\n", iface, count, palette);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
|
|
{
|
|
FIXME("iface %p, key %p, stub!\n", iface, key);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
|
|
{
|
|
FIXME("iface %p, key %p, stub!\n", iface, key);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
|
|
{
|
|
FIXME("iface %p, key %p, stub!\n", iface, key);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
|
|
{
|
|
struct video_renderer *filter = impl_from_IOverlay(iface);
|
|
|
|
TRACE("filter %p, window %p.\n", filter, window);
|
|
|
|
*window = filter->baseControlWindow.hwnd;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
|
|
{
|
|
FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
|
|
{
|
|
FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
|
|
{
|
|
FIXME("iface %p, sink %p, flags %#x, stub!\n", iface, sink, flags);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
|
|
{
|
|
FIXME("iface %p, stub!\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IOverlayVtbl overlay_vtbl =
|
|
{
|
|
overlay_QueryInterface,
|
|
overlay_AddRef,
|
|
overlay_Release,
|
|
overlay_GetPalette,
|
|
overlay_SetPalette,
|
|
overlay_GetDefaultColorKey,
|
|
overlay_GetColorKey,
|
|
overlay_SetColorKey,
|
|
overlay_GetWindowHandle,
|
|
overlay_GetClipList,
|
|
overlay_GetVideoPosition,
|
|
overlay_Advise,
|
|
overlay_Unadvise,
|
|
};
|
|
|
|
HRESULT video_renderer_create(IUnknown *outer, IUnknown **out)
|
|
{
|
|
struct video_renderer *object;
|
|
HRESULT hr;
|
|
|
|
if (!(object = calloc(1, sizeof(*object))))
|
|
return E_OUTOFMEMORY;
|
|
|
|
strmbase_renderer_init(&object->renderer, outer, &CLSID_VideoRenderer, L"In", &renderer_ops);
|
|
object->IOverlay_iface.lpVtbl = &overlay_vtbl;
|
|
|
|
video_window_init(&object->baseControlWindow, &IVideoWindow_VTable,
|
|
&object->renderer.filter, &object->renderer.sink.pin, &window_ops);
|
|
basic_video_init(&object->baseControlVideo, &object->renderer.filter,
|
|
&object->renderer.sink.pin, &renderer_BaseControlVideoFuncTable);
|
|
|
|
if (FAILED(hr = video_window_create_window(&object->baseControlWindow)))
|
|
{
|
|
video_window_cleanup(&object->baseControlWindow);
|
|
strmbase_renderer_cleanup(&object->renderer);
|
|
free(object);
|
|
return hr;
|
|
}
|
|
|
|
object->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
|
|
|
TRACE("Created video renderer %p.\n", object);
|
|
*out = &object->renderer.filter.IUnknown_inner;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT video_renderer_default_create(IUnknown *outer, IUnknown **out)
|
|
{
|
|
/* TODO: Attempt to use the VMR-7 renderer instead when possible */
|
|
return video_renderer_create(outer, out);
|
|
}
|