evr/mixer: Keep per-stream output rectangles.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
adc4dd674a
commit
0b8b00216f
|
@ -41,6 +41,7 @@ struct input_stream
|
|||
unsigned int id;
|
||||
IMFAttributes *attributes;
|
||||
IMFVideoMediaType *media_type;
|
||||
MFVideoNormalizedRect rect;
|
||||
};
|
||||
|
||||
struct output_stream
|
||||
|
@ -145,15 +146,18 @@ static int video_mixer_compare_input_id(const void *a, const void *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct input_stream * video_mixer_get_input(const struct video_mixer *mixer, unsigned int id)
|
||||
static HRESULT video_mixer_get_input(const struct video_mixer *mixer, unsigned int id, struct input_stream **stream)
|
||||
{
|
||||
return bsearch(&id, mixer->inputs, mixer->input_count, sizeof(*mixer->inputs), video_mixer_compare_input_id);
|
||||
*stream = bsearch(&id, mixer->inputs, mixer->input_count, sizeof(*mixer->inputs), video_mixer_compare_input_id);
|
||||
return *stream ? S_OK : MF_E_INVALIDSTREAMNUMBER;
|
||||
}
|
||||
|
||||
static void video_mixer_init_input(struct input_stream *stream)
|
||||
{
|
||||
if (SUCCEEDED(MFCreateAttributes(&stream->attributes, 1)))
|
||||
IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, 1);
|
||||
stream->rect.left = stream->rect.top = 0.0f;
|
||||
stream->rect.right = stream->rect.bottom = 1.0f;
|
||||
}
|
||||
|
||||
static void video_mixer_clear_types(struct video_mixer *mixer)
|
||||
|
@ -352,19 +356,19 @@ static HRESULT WINAPI video_mixer_transform_GetInputStreamInfo(IMFTransform *ifa
|
|||
{
|
||||
struct video_mixer *mixer = impl_from_IMFTransform(iface);
|
||||
struct input_stream *input;
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p, %u, %p.\n", iface, id, info);
|
||||
|
||||
EnterCriticalSection(&mixer->cs);
|
||||
if (!(input = video_mixer_get_input(mixer, id)))
|
||||
hr = MF_E_INVALIDSTREAMNUMBER;
|
||||
else
|
||||
|
||||
if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
if (id)
|
||||
info->dwFlags |= MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&mixer->cs);
|
||||
|
||||
return hr;
|
||||
|
@ -402,15 +406,13 @@ static HRESULT WINAPI video_mixer_transform_GetInputStreamAttributes(IMFTransfor
|
|||
{
|
||||
struct video_mixer *mixer = impl_from_IMFTransform(iface);
|
||||
struct input_stream *input;
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p, %u, %p.\n", iface, id, attributes);
|
||||
|
||||
EnterCriticalSection(&mixer->cs);
|
||||
|
||||
if (!(input = video_mixer_get_input(mixer, id)))
|
||||
hr = MF_E_INVALIDSTREAMNUMBER;
|
||||
else
|
||||
if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
|
||||
{
|
||||
*attributes = input->attributes;
|
||||
if (*attributes)
|
||||
|
@ -434,17 +436,18 @@ static HRESULT WINAPI video_mixer_transform_DeleteInputStream(IMFTransform *ifac
|
|||
{
|
||||
struct video_mixer *mixer = impl_from_IMFTransform(iface);
|
||||
struct input_stream *input;
|
||||
HRESULT hr = S_OK;
|
||||
unsigned int idx;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p, %u.\n", iface, id);
|
||||
|
||||
if (!id)
|
||||
return MF_E_INVALIDSTREAMNUMBER;
|
||||
|
||||
EnterCriticalSection(&mixer->cs);
|
||||
|
||||
/* Can't delete reference stream. */
|
||||
if (!id || !(input = video_mixer_get_input(mixer, id)))
|
||||
hr = MF_E_INVALIDSTREAMNUMBER;
|
||||
else
|
||||
if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
|
||||
{
|
||||
mixer->input_count--;
|
||||
idx = input - mixer->inputs;
|
||||
|
@ -736,13 +739,13 @@ static HRESULT WINAPI video_mixer_transform_GetInputCurrentType(IMFTransform *if
|
|||
{
|
||||
struct video_mixer *mixer = impl_from_IMFTransform(iface);
|
||||
struct input_stream *stream;
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p, %u, %p.\n", iface, id, type);
|
||||
|
||||
EnterCriticalSection(&mixer->cs);
|
||||
|
||||
if ((stream = video_mixer_get_input(mixer, id)))
|
||||
if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
|
||||
{
|
||||
if (!stream->media_type)
|
||||
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
|
@ -752,8 +755,6 @@ static HRESULT WINAPI video_mixer_transform_GetInputCurrentType(IMFTransform *if
|
|||
IMFMediaType_AddRef(*type);
|
||||
}
|
||||
}
|
||||
else
|
||||
hr = MF_E_INVALIDSTREAMNUMBER;
|
||||
|
||||
LeaveCriticalSection(&mixer->cs);
|
||||
|
||||
|
@ -1029,20 +1030,54 @@ static HRESULT WINAPI video_mixer_control_GetStreamZOrder(IMFVideoMixerControl2
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD stream_id,
|
||||
static HRESULT WINAPI video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD id,
|
||||
const MFVideoNormalizedRect *rect)
|
||||
{
|
||||
FIXME("%p, %u, %p.\n", iface, stream_id, rect);
|
||||
struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
|
||||
struct input_stream *stream;
|
||||
HRESULT hr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p, %u, %p.\n", iface, id, rect);
|
||||
|
||||
if (!rect)
|
||||
return E_POINTER;
|
||||
|
||||
if (rect->left > rect->right || rect->top > rect->bottom ||
|
||||
rect->left < 0.0f || rect->top < 0.0f || rect->right > 1.0f || rect->bottom > 1.0f)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&mixer->cs);
|
||||
|
||||
if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
|
||||
stream->rect = *rect;
|
||||
|
||||
LeaveCriticalSection(&mixer->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD stream_id,
|
||||
static HRESULT WINAPI video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD id,
|
||||
MFVideoNormalizedRect *rect)
|
||||
{
|
||||
FIXME("%p, %u, %p.\n", iface, stream_id, rect);
|
||||
struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
|
||||
struct input_stream *stream;
|
||||
HRESULT hr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p, %u, %p.\n", iface, id, rect);
|
||||
|
||||
if (!rect)
|
||||
return E_POINTER;
|
||||
|
||||
EnterCriticalSection(&mixer->cs);
|
||||
|
||||
if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
|
||||
*rect = stream->rect;
|
||||
|
||||
LeaveCriticalSection(&mixer->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD flags)
|
||||
|
|
|
@ -33,6 +33,14 @@ static const WCHAR sink_id[] = {'E','V','R',' ','I','n','p','u','t','0',0};
|
|||
|
||||
static HRESULT (WINAPI *pMFCreateVideoMediaTypeFromSubtype)(const GUID *subtype, IMFVideoMediaType **video_type);
|
||||
|
||||
static void set_rect(MFVideoNormalizedRect *rect, float left, float top, float right, float bottom)
|
||||
{
|
||||
rect->left = left;
|
||||
rect->top = top;
|
||||
rect->right = right;
|
||||
rect->bottom = bottom;
|
||||
}
|
||||
|
||||
static HWND create_window(void)
|
||||
{
|
||||
RECT r = {0, 0, 640, 480};
|
||||
|
@ -1483,38 +1491,24 @@ static void test_presenter_video_position(void)
|
|||
ok(dst_rect.left == 0 && dst_rect.right == 10 && dst_rect.top == 0 && dst_rect.bottom == 10,
|
||||
"Unexpected destination rectangle %s.\n", wine_dbgstr_rect(&dst_rect));
|
||||
|
||||
src_rect.left = src_rect.top = 0.0f;
|
||||
src_rect.right = 2.0f;
|
||||
src_rect.bottom = 1.0f;
|
||||
set_rect(&src_rect, 0.0f, 0.0f, 2.0f, 1.0f);
|
||||
hr = IMFVideoDisplayControl_SetVideoPosition(display_control, &src_rect, NULL);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
src_rect.left = -0.1f;
|
||||
src_rect.top = 0.0f;
|
||||
src_rect.right = 0.9f;
|
||||
src_rect.bottom = 1.0f;
|
||||
set_rect(&src_rect, -0.1f, 0.0f, 0.9f, 1.0f);
|
||||
hr = IMFVideoDisplayControl_SetVideoPosition(display_control, &src_rect, NULL);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Flipped source rectangle. */
|
||||
src_rect.left = 0.5f;
|
||||
src_rect.top = 0.0f;
|
||||
src_rect.right = 0.4f;
|
||||
src_rect.bottom = 1.0f;
|
||||
set_rect(&src_rect, 0.5f, 0.0f, 0.4f, 1.0f);
|
||||
hr = IMFVideoDisplayControl_SetVideoPosition(display_control, &src_rect, NULL);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
src_rect.left = 0.0f;
|
||||
src_rect.top = 0.5f;
|
||||
src_rect.right = 0.4f;
|
||||
src_rect.bottom = 0.1f;
|
||||
set_rect(&src_rect, 0.0f, 0.5f, 0.4f, 0.1f);
|
||||
hr = IMFVideoDisplayControl_SetVideoPosition(display_control, &src_rect, NULL);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
src_rect.left = 0.1f;
|
||||
src_rect.top = 0.2f;
|
||||
src_rect.right = 0.8f;
|
||||
src_rect.bottom = 0.9f;
|
||||
set_rect(&src_rect, 0.1f, 0.2f, 0.8f, 0.9f);
|
||||
hr = IMFVideoDisplayControl_SetVideoPosition(display_control, &src_rect, NULL);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
|
@ -1559,6 +1553,122 @@ static void test_presenter_video_position(void)
|
|||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
static void test_presenter_native_video_size(void)
|
||||
{
|
||||
IMFTopologyServiceLookupClient *lookup_client;
|
||||
IMFVideoDisplayControl *display_control;
|
||||
IMFVideoPresenter *presenter;
|
||||
struct test_host host;
|
||||
IMFTransform *mixer;
|
||||
SIZE size, ratio;
|
||||
HRESULT hr;
|
||||
|
||||
hr = MFCreateVideoMixer(NULL, &IID_IDirect3DDevice9, &IID_IMFTransform, (void **)&mixer);
|
||||
ok(hr == S_OK, "Failed to create a mixer, hr %#x.\n", hr);
|
||||
|
||||
hr = MFCreateVideoPresenter(NULL, &IID_IDirect3DDevice9, &IID_IMFVideoPresenter, (void **)&presenter);
|
||||
ok(hr == S_OK, "Failed to create default presenter, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFVideoDisplayControl, (void **)&display_control);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, NULL, NULL);
|
||||
todo_wine
|
||||
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
memset(&size, 0xcc, sizeof(size));
|
||||
hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, NULL);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(size.cx == 0 && size.cy == 0, "Unexpected size.\n");
|
||||
}
|
||||
memset(&ratio, 0xcc, sizeof(ratio));
|
||||
hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, NULL, &ratio);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(ratio.cx == 0 && ratio.cy == 0, "Unexpected ratio.\n");
|
||||
}
|
||||
hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
init_test_host(&host, mixer, presenter);
|
||||
|
||||
hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client, &host.IMFTopologyServiceLookup_iface);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, &ratio);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(size.cx == 0 && size.cy == 0, "Unexpected size.\n");
|
||||
ok(ratio.cx == 0 && ratio.cy == 0, "Unexpected ratio.\n");
|
||||
}
|
||||
IMFVideoDisplayControl_Release(display_control);
|
||||
IMFVideoPresenter_Release(presenter);
|
||||
IMFTransform_Release(mixer);
|
||||
}
|
||||
|
||||
static void test_mixer_output_rectangle(void)
|
||||
{
|
||||
IMFVideoMixerControl *mixer_control;
|
||||
MFVideoNormalizedRect rect;
|
||||
IMFTransform *mixer;
|
||||
HRESULT hr;
|
||||
|
||||
hr = MFCreateVideoMixer(NULL, &IID_IDirect3DDevice9, &IID_IMFTransform, (void **)&mixer);
|
||||
ok(hr == S_OK, "Failed to create a mixer, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFTransform_QueryInterface(mixer, &IID_IMFVideoMixerControl, (void **)&mixer_control);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoMixerControl_GetStreamOutputRect(mixer_control, 0, NULL);
|
||||
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
hr = IMFVideoMixerControl_GetStreamOutputRect(mixer_control, 0, &rect);
|
||||
ok(hr == S_OK, "Failed to get output rect, hr %#x.\n", hr);
|
||||
ok(rect.left == 0.0f && rect.top == 0.0f && rect.right == 1.0f && rect.bottom == 1.0f,
|
||||
"Unexpected rectangle.\n");
|
||||
|
||||
hr = IMFVideoMixerControl_GetStreamOutputRect(mixer_control, 1, &rect);
|
||||
ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoMixerControl_GetStreamOutputRect(mixer_control, 1, NULL);
|
||||
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 1, &rect);
|
||||
ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 1, NULL);
|
||||
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Wrong bounds. */
|
||||
set_rect(&rect, 0.0f, 0.0f, 1.1f, 1.0f);
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 0, &rect);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
set_rect(&rect, -0.1f, 0.0f, 0.5f, 1.0f);
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 0, &rect);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Flipped. */
|
||||
set_rect(&rect, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 0, &rect);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
set_rect(&rect, 0.0f, 1.0f, 1.0f, 0.5f);
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 0, &rect);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFVideoMixerControl_SetStreamOutputRect(mixer_control, 0, NULL);
|
||||
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
IMFVideoMixerControl_Release(mixer_control);
|
||||
IMFTransform_Release(mixer);
|
||||
}
|
||||
|
||||
START_TEST(evr)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
|
@ -1577,6 +1687,8 @@ START_TEST(evr)
|
|||
test_MFCreateVideoMixerAndPresenter();
|
||||
test_MFCreateVideoSampleAllocator();
|
||||
test_presenter_video_position();
|
||||
test_presenter_native_video_size();
|
||||
test_mixer_output_rectangle();
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue