[PATCH 0/2] MR7563: mf/tests: Tests timestamp values on output samples from the H.264 and WMV MFT decoders.
These tests serve to illustrate the output sample time and duration values from their respective native MFT video decoders with respect to the following circumstances: 1. When no frame rate nor input sample timestamps are provided; 2. When a frame rate is provided but there are no sample timestamps; and 3. When a frame rate is provided, but the input sample timestamps disagree with this value It also highlights the gap in our implementation. However, I don't believe this can be fixed without first confirming the correct output from our IMFMediaStream implementations. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7563
From: Brendan McGrath <bmcgrath(a)codeweavers.com> --- dlls/mf/tests/transform.c | 300 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 439d8ee9d54..4589d91eef4 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -5075,6 +5075,305 @@ failed: CoUninitialize(); } +static void test_h264_decoder_timestamps(void) +{ + struct timestamps + { + LONGLONG time; + LONGLONG duration; + }; + + static const DWORD actual_width = 96, actual_height = 96; + + const GUID *const class_id = &CLSID_MSH264DecoderMFT; + const struct attribute_desc input_type_nofps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height), + {0}, + }; + const struct attribute_desc output_type_nofps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE), + {0}, + }; + + const struct attribute_desc input_type_24fps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height), + ATTR_RATIO(MF_MT_FRAME_RATE, 24, 1), + {0}, + }; + const struct attribute_desc output_type_24fps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 24, 1), + {0}, + }; + static const struct timestamps exp_nofps[] = + { + { 0 , 333667 }, + { 333667, 333667 }, + { 667334, 333667 }, + { 1001001, 333667 }, + { 1334668, 333667 }, + { 1668335, 333667 }, + { 2002002, 333667 }, + { 2335669, 333667 }, + { 2669336, 333667 }, + { 3003003, 333667 }, + }; + static const struct timestamps exp_24fps[] = + { + { 0, 416667 }, + { 416667, 416667 }, + { 833334, 416667 }, + { 1250001, 416667 }, + { 1666668, 416667 }, + { 2083335, 416667 }, + { 2500002, 416667 }, + { 2916669, 416667 }, + { 3333336, 416667 }, + { 3750003, 416667 }, + }; + static const struct timestamps input_sample_ts[] = + { + { 666666, 166667 }, + { 2333332, 166667 }, + { 2666666, 166667 }, + { 1333332, 166667 }, + { 999999, 166666 }, + { 833333, 166666 }, + { 1166665, 166667 }, + { 1999999, 166667 }, + { 1666666, 166666 }, + { 1499999, 166667 }, + { 1833332, 166667 }, + { 2833333, 166666 }, + { 2499999, 166667 }, + { 2166666, 166666 }, + { 3333332, 166667 }, + { 2999999, 166666 }, + { 3166665, 166667 }, + { 3999999, 166667 }, + { 3666666, 166666 }, + { 3499999, 166667 }, + { 3833332, 166667 }, + { 4666666, 166667 }, + { 4333332, 166667 }, + { 4166666, 166666 }, + { 4499999, 166667 }, + { 5333332, 166667 }, + { 4999999, 166666 }, + { 4833333, 166666 }, + { 5166665, 166667 }, + { 5999999, 166667 }, + { 5666666, 166666 }, + { 5499999, 166667 }, + { 5833332, 166667 }, + { 6666666, 166667 }, + }; + static const struct timestamps exp_sample_ts[] = + { + { 666666, 166667 }, + { 833333, 166666 }, + { 999999, 166666 }, + { 1166665, 166667 }, + { 1333332, 166667 }, + { 1499999, 166667 }, + { 1666666, 166666 }, + { 1833332, 166667 }, + { 1999999, 166667 }, + { 2166666, 166666 }, + }; + + IMFSample *input_sample, *output_sample; + const BYTE *h264_encoded_data; + ULONG h264_encoded_data_len; + IMFTransform *transform; + LONGLONG duration, time; + DWORD output_status; + ULONG i, j, ret; + HRESULT hr; + + hr = CoInitialize(NULL); + ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr); + + winetest_push_context("h264dec timestamps"); + + /* Test when no framerate is provided and samples contain no timestamps */ + if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform))) + goto failed; + + load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len); + + check_mft_set_input_type(transform, input_type_nofps_desc, S_OK); + check_mft_set_output_type(transform, output_type_nofps_desc, S_OK); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + ok(hr == S_OK, "Got %#lx\n", hr); + + output_sample = create_sample(NULL, actual_width * actual_height * 2); + for (i = 0; i < ARRAYSIZE(exp_nofps);) + { + winetest_push_context("output %ld", i); + hr = check_mft_process_output(transform, output_sample, &output_status); + ok(hr == S_OK || hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); + if (hr == S_OK) + { + hr = IMFSample_GetSampleTime(output_sample, &time); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine_if(i) + ok(time == exp_nofps[i].time, "got time %I64d, expected %I64d\n", time, exp_nofps[i].time); + hr = IMFSample_GetSampleDuration(output_sample, &duration); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine + ok(duration == exp_nofps[i].duration, "got duration %I64d, expected %I64d\n", duration, exp_nofps[i].duration); + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + output_sample = create_sample(NULL, actual_width * actual_height * 2); + i++; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + { + input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); + ret = IMFSample_Release(input_sample); + ok(ret <= 1, "Release returned %lu\n", ret); + } + winetest_pop_context(); + } + + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMFTransform_Release(transform); + ok(ret == 0, "Release returned %lu\n", ret); + + /* Test when 24fps framerate is provided and samples contain no timestamps */ + hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Got %#lx\n", hr); + + load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len); + + check_mft_set_input_type(transform, input_type_24fps_desc, S_OK); + check_mft_set_output_type(transform, output_type_24fps_desc, S_OK); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + ok(hr == S_OK, "Got %#lx\n", hr); + + output_sample = create_sample(NULL, actual_width * actual_height * 2); + for (i = 0; i < ARRAYSIZE(exp_24fps);) + { + winetest_push_context("output %ld", i); + hr = check_mft_process_output(transform, output_sample, &output_status); + ok(hr == S_OK || hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); + if (hr == S_OK) + { + hr = IMFSample_GetSampleTime(output_sample, &time); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine_if(i) + ok(time == exp_24fps[i].time, "got time %I64d, expected %I64d\n", time, exp_24fps[i].time); + hr = IMFSample_GetSampleDuration(output_sample, &duration); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine + ok(duration == exp_24fps[i].duration, "got duration %I64d, expected %I64d\n", duration, exp_24fps[i].duration); + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + output_sample = create_sample(NULL, actual_width * actual_height * 2); + i++; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + { + input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); + ret = IMFSample_Release(input_sample); + ok(ret <= 1, "Release returned %lu\n", ret); + } + winetest_pop_context(); + } + + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMFTransform_Release(transform); + ok(ret == 0, "Release returned %lu\n", ret); + + /* Test when supplied sample timestamps disagree with MT_MF_FRAME_RATE */ + hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Got %#lx\n", hr); + + load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len); + + check_mft_set_input_type(transform, input_type_24fps_desc, S_OK); + check_mft_set_output_type(transform, output_type_24fps_desc, S_OK); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + ok(hr == S_OK, "Got %#lx\n", hr); + + j = 0; + output_sample = create_sample(NULL, actual_width * actual_height * 2); + for (i = 0; i < ARRAYSIZE(exp_sample_ts);) + { + winetest_push_context("output %ld", i); + hr = check_mft_process_output(transform, output_sample, &output_status); + ok(hr == S_OK || hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); + if (hr == S_OK) + { + hr = IMFSample_GetSampleTime(output_sample, &time); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine_if(i) + ok(time == exp_sample_ts[i].time, "got time %I64d, expected %I64d\n", time, exp_sample_ts[i].time); + hr = IMFSample_GetSampleDuration(output_sample, &duration); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine + ok(duration == exp_sample_ts[i].duration, "got duration %I64d, expected %I64d\n", duration, exp_sample_ts[i].duration); + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + output_sample = create_sample(NULL, actual_width * actual_height * 2); + i++; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && j < ARRAYSIZE(input_sample_ts)) + { + input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); + hr = IMFSample_SetSampleTime(input_sample, input_sample_ts[j].time); + ok(hr == S_OK, "Got %#lx\n", hr); + hr = IMFSample_SetSampleDuration(input_sample, input_sample_ts[j].duration); + ok(hr == S_OK, "Got %#lx\n", hr); + j++; + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); + ret = IMFSample_Release(input_sample); + ok(ret <= 1, "Release returned %lu\n", ret); + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && j == ARRAYSIZE(input_sample_ts)) + { + ok(0, "no more input to provide\n"); + i = ARRAYSIZE(exp_sample_ts); + } + winetest_pop_context(); + } + + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMFTransform_Release(transform); + ok(ret == 0, "Release returned %lu\n", ret); + +failed: + winetest_pop_context(); + CoUninitialize(); +} + static void test_h264_decoder_concat_streams(void) { const struct buffer_desc output_buffer_desc[] = @@ -10444,6 +10743,7 @@ START_TEST(transform) test_wma_decoder_dmo_output_type(); test_h264_encoder(); test_h264_decoder(); + test_h264_decoder_timestamps(); test_wmv_encoder(); test_wmv_decoder(); test_wmv_decoder_dmo_input_type(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7563
From: Brendan McGrath <bmcgrath(a)codeweavers.com> --- dlls/mf/tests/transform.c | 306 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 4589d91eef4..4f496b8c9cc 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -7051,6 +7051,311 @@ failed: CoUninitialize(); } +static void test_wmv_decoder_timestamps(void) +{ + struct timestamps + { + LONGLONG time; + LONGLONG duration; + }; + + static const DWORD actual_width = 96, actual_height = 96; + + const GUID *const class_id = &CLSID_CWMVDecMediaObject; + const struct attribute_desc input_type_nofps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE, .todo = TRUE), + {0}, + }; + const struct attribute_desc output_type_nofps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE), + {0}, + }; + + const struct attribute_desc input_type_24fps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE, .todo = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 24, 1,), + {0}, + }; + const struct attribute_desc output_type_24fps_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 24, 1,), + {0}, + }; + static const struct timestamps exp_nofps[] = + { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; + static const struct timestamps exp_24fps[] = + { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; + static const struct timestamps input_sample_ts[] = + { + { 666666, 166667 }, + { 833333, 166666 }, + { 999999, 166666 }, + { 1166665, 166667 }, + { 1333332, 166667 }, + { 1499999, 166667 }, + { 1666666, 166666 }, + { 1833332, 166667 }, + { 1999999, 166667 }, + { 2166666, 166666 }, + { 2333332, 166667 }, + { 2499999, 166667 }, + { 2666666, 166667 }, + { 2833333, 166666 }, + { 2999999, 166666 }, + { 3166665, 166667 }, + { 3333332, 166667 }, + { 3499999, 166667 }, + { 3666666, 166666 }, + { 3833332, 166667 }, + { 3999999, 166667 }, + }; + static const struct timestamps exp_sample_ts[] = + { + { 666666, 166667 }, + { 833333, 166666 }, + { 999999, 166666 }, + { 1166665, 166667 }, + { 1333332, 166667 }, + { 1499999, 166667 }, + { 1666666, 166666 }, + { 1833332, 166667 }, + { 1999999, 166667 }, + { 2166666, 166666 }, + }; + + IMFSample *input_sample, *output_sample; + const BYTE *wmvenc_data; + ULONG wmvenc_data_len; + IMFTransform *transform; + LONGLONG duration, time; + DWORD output_status; + ULONG i, j, ret; + HRESULT hr; + + hr = CoInitialize(NULL); + ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr); + + winetest_push_context("wmvdec timestamps"); + + /* Test when no framerate is provided and samples contain no timestamps */ + if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform))) + goto failed; + + load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len); + + check_mft_set_input_type(transform, input_type_nofps_desc, S_OK); + check_mft_set_output_type(transform, output_type_nofps_desc, S_OK); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + ok(hr == S_OK, "Got %#lx\n", hr); + + output_sample = create_sample(NULL, actual_width * actual_height * 2); + for (i = 0; i < ARRAYSIZE(exp_nofps);) + { + winetest_push_context("output %ld", i); + hr = check_mft_process_output(transform, output_sample, &output_status); + ok(hr == S_OK || hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); + if (hr == S_OK) + { + hr = IMFSample_GetSampleTime(output_sample, &time); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine_if(i) + ok(time == exp_nofps[i].time, "got time %I64d, expected %I64d\n", time, exp_nofps[i].time); + hr = IMFSample_GetSampleDuration(output_sample, &duration); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine + ok(duration == exp_nofps[i].duration, "got duration %I64d, expected %I64d\n", duration, exp_nofps[i].duration); + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + output_sample = create_sample(NULL, actual_width * actual_height * 2); + i++; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && wmvenc_data_len) + { + input_sample = create_sample(wmvenc_data + sizeof(DWORD), *(DWORD *)wmvenc_data); + wmvenc_data_len -= *(DWORD *)wmvenc_data + sizeof(DWORD); + wmvenc_data += *(DWORD *)wmvenc_data + sizeof(DWORD); + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); + ret = IMFSample_Release(input_sample); + ok(ret <= 1, "Release returned %lu\n", ret); + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && !wmvenc_data_len) + { + todo_wine + ok(0, "no more input to provide\n"); + i = ARRAYSIZE(exp_nofps); + } + winetest_pop_context(); + } + + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMFTransform_Release(transform); + ok(ret == 0, "Release returned %lu\n", ret); + + /* Test when 24fps framerate is provided and samples contain no timestamps */ + hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Got %#lx\n", hr); + + load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len); + + check_mft_set_input_type(transform, input_type_24fps_desc, S_OK); + check_mft_set_output_type(transform, output_type_24fps_desc, S_OK); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + ok(hr == S_OK, "Got %#lx\n", hr); + + output_sample = create_sample(NULL, actual_width * actual_height * 2); + for (i = 0; i < ARRAYSIZE(exp_24fps);) + { + winetest_push_context("output %ld", i); + hr = check_mft_process_output(transform, output_sample, &output_status); + ok(hr == S_OK || hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); + if (hr == S_OK) + { + hr = IMFSample_GetSampleTime(output_sample, &time); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine_if(i) + ok(time == exp_24fps[i].time, "got time %I64d, expected %I64d\n", time, exp_24fps[i].time); + hr = IMFSample_GetSampleDuration(output_sample, &duration); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine + ok(duration == exp_24fps[i].duration, "got duration %I64d, expected %I64d\n", duration, exp_24fps[i].duration); + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + output_sample = create_sample(NULL, actual_width * actual_height * 2); + i++; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && wmvenc_data_len) + { + input_sample = create_sample(wmvenc_data + sizeof(DWORD), *(DWORD *)wmvenc_data); + wmvenc_data_len -= *(DWORD *)wmvenc_data + sizeof(DWORD); + wmvenc_data += *(DWORD *)wmvenc_data + sizeof(DWORD); + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); + ret = IMFSample_Release(input_sample); + ok(ret <= 1, "Release returned %lu\n", ret); + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && !wmvenc_data_len) + { + todo_wine + ok(0, "no more input to provide\n"); + i = ARRAYSIZE(exp_nofps); + } + winetest_pop_context(); + } + + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMFTransform_Release(transform); + ok(ret == 0, "Release returned %lu\n", ret); + + /* Test when provided sample timestamps disagree with MT_MF_FRAME_RATE */ + hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Got %#lx\n", hr); + + load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len); + + check_mft_set_input_type(transform, input_type_24fps_desc, S_OK); + check_mft_set_output_type(transform, output_type_24fps_desc, S_OK); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + ok(hr == S_OK, "Got %#lx\n", hr); + + j = 0; + output_sample = create_sample(NULL, actual_width * actual_height * 2); + for (i = 0; i < ARRAYSIZE(exp_sample_ts);) + { + winetest_push_context("output %ld", i); + hr = check_mft_process_output(transform, output_sample, &output_status); + ok(hr == S_OK || hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); + if (hr == S_OK) + { + hr = IMFSample_GetSampleTime(output_sample, &time); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine_if(i) + ok(time == exp_sample_ts[i].time, "got time %I64d, expected %I64d\n", time, exp_sample_ts[i].time); + hr = IMFSample_GetSampleDuration(output_sample, &duration); + ok(hr == S_OK, "Got %#lx\n", hr); + todo_wine + ok(duration == exp_sample_ts[i].duration, "got duration %I64d, expected %I64d\n", duration, exp_sample_ts[i].duration); + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + output_sample = create_sample(NULL, actual_width * actual_height * 2); + i++; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && j < ARRAYSIZE(input_sample_ts)) + { + input_sample = create_sample(wmvenc_data + sizeof(DWORD), *(DWORD *)wmvenc_data); + wmvenc_data_len -= *(DWORD *)wmvenc_data + sizeof(DWORD); + wmvenc_data += *(DWORD *)wmvenc_data + sizeof(DWORD); + hr = IMFSample_SetSampleTime(input_sample, input_sample_ts[j].time); + ok(hr == S_OK, "Got %#lx\n", hr); + hr = IMFSample_SetSampleDuration(input_sample, input_sample_ts[j].duration); + ok(hr == S_OK, "Got %#lx\n", hr); + j++; + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); + ret = IMFSample_Release(input_sample); + ok(ret <= 1, "Release returned %lu\n", ret); + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && j == ARRAYSIZE(input_sample_ts)) + { + todo_wine + ok(0, "no more input to provide\n"); + i = ARRAYSIZE(exp_sample_ts); + } + winetest_pop_context(); + } + + ret = IMFSample_Release(output_sample); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMFTransform_Release(transform); + ok(ret == 0, "Release returned %lu\n", ret); + +failed: + winetest_pop_context(); + CoUninitialize(); +} + static void test_wmv_decoder_dmo_input_type(void) { const GUID *input_subtypes[] = @@ -10746,6 +11051,7 @@ START_TEST(transform) test_h264_decoder_timestamps(); test_wmv_encoder(); test_wmv_decoder(); + test_wmv_decoder_timestamps(); test_wmv_decoder_dmo_input_type(); test_wmv_decoder_dmo_output_type(); test_wmv_decoder_dmo_get_size_info(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7563
participants (2)
-
Brendan McGrath -
Brendan McGrath (@redmcg)