Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/tests/mf.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index d304a62f08a..c38c817eb4b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3921,6 +3921,108 @@ static void test_sample_copier(void) IMFTransform_Release(copier); }
+static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer, + IMFMediaBuffer *output_buffer) +{ + IMFSample *input_sample, *output_sample; + MFT_OUTPUT_DATA_BUFFER buffer; + DWORD status; + HRESULT hr; + + hr = MFCreateSample(&input_sample); + ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr); + + hr = MFCreateSample(&output_sample); + ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr); + + hr = IMFSample_AddBuffer(input_sample, input_buffer); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFSample_AddBuffer(output_sample, output_buffer); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0); + ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr); + + status = 0; + memset(&buffer, 0, sizeof(buffer)); + buffer.pSample = output_sample; + hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status); + ok(hr == S_OK, "Failed to get output, hr %#x.\n", hr); + + IMFSample_Release(input_sample); + IMFSample_Release(output_sample); +} + +static void test_sample_copier_output_processing(void) +{ + IMFMediaBuffer *input_buffer, *output_buffer; + MFT_OUTPUT_STREAM_INFO output_info; + IMFMediaType *mediatype; + IMFTransform *copier; + DWORD max_length; + HRESULT hr; + BYTE *ptr; + + hr = MFCreateSampleCopierMFT(&copier); + ok(hr == S_OK, "Failed to create sample copier, hr %#x.\n", hr); + + /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */ + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFTransform_SetInputType(copier, 0, mediatype, 0); + ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr); + + hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0); + ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr); + + /* Source and destination are linear buffers, destination is twice as large. */ + hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info); + ok(hr == S_OK, "Failed to get output info, hr %#x.\n", hr); + + hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer); + ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + memset(ptr, 0xcc, max_length); + hr = IMFMediaBuffer_Unlock(output_buffer); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer); + ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + memset(ptr, 0xaa, max_length); + hr = IMFMediaBuffer_Unlock(input_buffer); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + sample_copier_process(copier, input_buffer, output_buffer); + + hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n"); + + hr = IMFMediaBuffer_Unlock(output_buffer); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IMFMediaType_Release(mediatype); + IMFTransform_Release(copier); +} + static void test_MFGetTopoNodeCurrentType(void) { IMFMediaType *media_type, *media_type2; @@ -4020,5 +4122,6 @@ START_TEST(mf) test_MFGetSupportedMimeTypes(); test_MFGetSupportedSchemes(); test_sample_copier(); + test_sample_copier_output_processing(); test_MFGetTopoNodeCurrentType(); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index f5bbfffc4a5..486958f5f79 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -350,7 +350,7 @@ static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFS { WARN("No sample timestamp, hr %#x.\n", hr); } - else if (stream->parent->state == EVR_STATE_RUNNING) + else if (stream->parent->state == EVR_STATE_RUNNING || stream->flags & EVR_STREAM_PREROLLING) { if (SUCCEEDED(IMFTransform_ProcessInput(stream->parent->mixer, stream->id, sample, 0))) IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_PROCESSINPUTNOTIFY, 0);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 16 ++++++++++++---- dlls/evr/tests/evr.c | 21 ++++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 20b5e3b2bba..a60da623f64 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -653,7 +653,8 @@ static int rt_formats_sort_compare(const void *left, const void *right) }
static HRESULT video_mixer_collect_output_types(struct video_mixer *mixer, const DXVA2_VideoDesc *video_desc, - IDirectXVideoProcessorService *service, unsigned int device_count, const GUID *devices, unsigned int flags) + IMFMediaType *media_type, IDirectXVideoProcessorService *service, unsigned int device_count, + const GUID *devices, unsigned int flags) { unsigned int i, j, format_count, count; struct rt_format *rt_formats = NULL, *ptr; @@ -706,9 +707,16 @@ static HRESULT video_mixer_collect_output_types(struct video_mixer *mixer, const { for (i = 0; i < count; ++i) { + IMFMediaType *rt_media_type; + subtype.Data1 = rt_formats[i].format; mixer->output.rt_formats[i] = rt_formats[i]; - MFCreateVideoMediaTypeFromSubtype(&subtype, (IMFVideoMediaType **)&mixer->output.rt_formats[i].media_type); + + MFCreateMediaType(&rt_media_type); + IMFMediaType_CopyAllItems(media_type, (IMFAttributes *)rt_media_type); + IMFMediaType_SetGUID(rt_media_type, &MF_MT_SUBTYPE, &subtype); + + mixer->output.rt_formats[i].media_type = rt_media_type; } mixer->output.rt_formats_count = count; } @@ -785,8 +793,8 @@ static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DW if (SUCCEEDED(hr = IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service, &video_desc, &count, &guids))) { - if (SUCCEEDED(hr = video_mixer_collect_output_types(mixer, &video_desc, service, count, - guids, flags)) && !(flags & MFT_SET_TYPE_TEST_ONLY)) + if (SUCCEEDED(hr = video_mixer_collect_output_types(mixer, &video_desc, media_type, + service, count, guids, flags)) && !(flags & MFT_SET_TYPE_TEST_ONLY)) { if (mixer->inputs[0].media_type) IMFMediaType_Release(mixer->inputs[0].media_type); diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index a711be7ad21..a1d7b7109d9 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -915,11 +915,11 @@ static void test_default_mixer_type_negotiation(void) IDirect3DDevice9 *device; IMFMediaType *video_type; IMFTransform *transform; + DWORD index, count; GUID guid, *guids; IDirect3D9 *d3d; IUnknown *unk; HWND window; - DWORD count; HRESULT hr; UINT token;
@@ -1013,6 +1013,25 @@ static void test_default_mixer_type_negotiation(void) IMFMediaType_Release(media_type); IMFMediaType_Release(media_type2);
+ /* Check attributes on available output types. */ + index = 0; + while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, index++, &media_type))) + { + UINT64 frame_size; + GUID subtype; + UINT32 value; + + hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &subtype); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFMediaType_GetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, &value); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IMFMediaType_Release(media_type); + } + ok(index > 1, "Unexpected number of available types.\n"); + hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoProcessor, (void **)&processor); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index a60da623f64..bbaf68ab870 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -1163,6 +1163,65 @@ static HRESULT video_mixer_get_d3d_device(struct video_mixer *mixer, IDirect3DDe return hr; }
+static void video_mixer_scale_rect(RECT *rect, unsigned int width, unsigned int height, + const MFVideoNormalizedRect *scale) +{ + if (rect->left == 0.0f && rect->top == 0.0f && rect->right == 1.0f && rect->bottom == 1.0f) + { + SetRect(rect, 0, 0, width, height); + } + else + { + rect->left = width * scale->left; + rect->right = width * scale->right; + rect->top = height * scale->top; + rect->bottom = height * scale->bottom; + } +} + +static void video_mixer_render(struct video_mixer *mixer, IDirect3DSurface9 *rt) +{ + DXVA2_VideoSample samples[1] = { 0 }; + DXVA2_VideoProcessBltParams params = { 0 }; + MFVideoNormalizedRect zoom_rect; + struct input_stream *stream; + IDirect3DSurface9 *surface; + D3DSURFACE_DESC desc; + HRESULT hr; + + IDirect3DSurface9_GetDesc(rt, &desc); + + if (FAILED(IMFAttributes_GetBlob(mixer->attributes, &VIDEO_ZOOM_RECT, (UINT8 *)&zoom_rect, + sizeof(zoom_rect), NULL))) + { + zoom_rect.left = zoom_rect.top = 0.0f; + zoom_rect.right = zoom_rect.bottom = 1.0f; + } + + video_mixer_scale_rect(¶ms.TargetRect, desc.Width, desc.Height, &zoom_rect); + + /* FIXME: for now only handle reference stream. */ + + video_mixer_get_input(mixer, 0, &stream); + + if (FAILED(hr = video_mixer_get_sample_surface(stream->sample, &surface))) + { + WARN("Failed to get source surface, hr %#x.\n", hr); + return; + } + + IDirect3DSurface9_GetDesc(surface, &desc); + + samples[0].SrcSurface = surface; + SetRect(&samples[0].SrcRect, 0, 0, desc.Width, desc.Height); + video_mixer_scale_rect(&samples[0].DstRect, desc.Width, desc.Height, &stream->rect); + + if (FAILED(hr = IDirectXVideoProcessor_VideoProcessBlt(mixer->processor, rt, ¶ms, samples, 1, NULL))) + WARN("Failed to process samples, hr %#x.\n", hr); + + IDirect3DSurface9_Release(surface); +} + static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status) { @@ -1197,13 +1256,15 @@ static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, D } }
- /* FIXME: for now discard input */ + if (SUCCEEDED(hr)) + video_mixer_render(mixer, surface);
if (SUCCEEDED(hr)) { for (i = 0; i < mixer->input_count; ++i) { - IMFSample_Release(mixer->inputs[i].sample); + if (mixer->inputs[i].sample) + IMFSample_Release(mixer->inputs[i].sample); mixer->inputs[i].sample = NULL; video_mixer_request_sample(mixer, i); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/presenter.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index 1b98e63a49a..335e5df2459 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -1207,13 +1207,18 @@ HRESULT evr_presenter_create(IUnknown *outer, void **out) InitializeCriticalSection(&object->cs);
if (FAILED(hr = DXVA2CreateDirect3DDeviceManager9(&object->reset_token, &object->device_manager))) - IUnknown_Release(&object->IUnknown_inner); + goto failed;
if (FAILED(hr = video_presenter_init_d3d(object))) - IUnknown_Release(&object->IUnknown_inner); + goto failed;
- if (SUCCEEDED(hr)) - *out = &object->IUnknown_inner; + *out = &object->IUnknown_inner; + + return S_OK; + +failed: + + IUnknown_Release(&object->IUnknown_inner);
return hr; }