Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
Re: [PATCH v3 0/6] MR302: winegstreamer: Some wg_transform H264 fixes for Mortal Kombat 11 and Yakuza 4.
by Rémi Bernon
v3: Fix Win7 test failures in PATCH 5.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/302#note_2576
June 23, 2022
[PATCH v3 6/6] winegstreamer: Use an atomic queue for wg_transform input buffers.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
And push them one by one until an output buffer is generated, to avoid
generating multiple output buffers without a backing wg_sample.
This makes zero-copy more efficient for games which queue multiple input
buffers before checking output, such as Yakuza 4.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/wg_transform.c | 40 +++++++++++++++----------------
1 file changed, 19 insertions(+), 21 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index b90fde70519..73bec6d35e4 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -51,10 +51,10 @@ struct wg_transform
GstPad *my_src, *my_sink;
GstPad *their_sink, *their_src;
GstSegment segment;
- GstBufferList *input;
guint input_max_length;
guint output_plane_align;
struct wg_sample *output_wg_sample;
+ GstAtomicQueue *input_queue;
GstAtomicQueue *output_queue;
GstSample *output_sample;
bool output_caps_changed;
@@ -240,9 +240,11 @@ NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
GstSample *sample;
+ GstBuffer *buffer;
- if (transform->input)
- gst_buffer_list_unref(transform->input);
+ while ((buffer = gst_atomic_queue_pop(transform->input_queue)))
+ gst_buffer_unref(buffer);
+ gst_atomic_queue_unref(transform->input_queue);
gst_element_set_state(transform->container, GST_STATE_NULL);
@@ -371,7 +373,7 @@ NTSTATUS wg_transform_create(void *args)
return STATUS_NO_MEMORY;
if (!(transform->container = gst_bin_new("wg_transform")))
goto out;
- if (!(transform->input = gst_buffer_list_new()))
+ if (!(transform->input_queue = gst_atomic_queue_new(8)))
goto out;
if (!(transform->output_queue = gst_atomic_queue_new(8)))
goto out;
@@ -538,8 +540,8 @@ out:
wg_allocator_destroy(transform->allocator);
if (transform->output_queue)
gst_atomic_queue_unref(transform->output_queue);
- if (transform->input)
- gst_buffer_list_unref(transform->input);
+ if (transform->input_queue)
+ gst_atomic_queue_unref(transform->input_queue);
if (transform->container)
{
gst_element_set_state(transform->container, GST_STATE_NULL);
@@ -610,7 +612,7 @@ NTSTATUS wg_transform_push_data(void *args)
GstBuffer *buffer;
guint length;
- length = gst_buffer_list_length(transform->input);
+ length = gst_atomic_queue_length(transform->input_queue);
if (length >= transform->input_max_length)
{
GST_INFO("Refusing %u bytes, %u buffers already queued", sample->size, length);
@@ -636,7 +638,7 @@ NTSTATUS wg_transform_push_data(void *args)
GST_BUFFER_DURATION(buffer) = sample->duration * 100;
if (!(sample->flags & WG_SAMPLE_FLAG_SYNC_POINT))
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
- gst_buffer_list_insert(transform->input, -1, buffer);
+ gst_atomic_queue_push(transform->input_queue, buffer);
params->result = S_OK;
return STATUS_SUCCESS;
@@ -791,9 +793,8 @@ NTSTATUS wg_transform_read_data(void *args)
struct wg_transform *transform = params->transform;
struct wg_sample *sample = params->sample;
struct wg_format *format = params->format;
+ GstBuffer *output_buffer, *input_buffer;
GstFlowReturn ret = GST_FLOW_OK;
- GstBuffer *output_buffer;
- GstBufferList *input;
GstCaps *output_caps;
bool discard_data;
NTSTATUS status;
@@ -802,17 +803,14 @@ NTSTATUS wg_transform_read_data(void *args)
InterlockedIncrement(&sample->refcount);
InterlockedExchangePointer((void **)&transform->output_wg_sample, sample);
- if (!gst_buffer_list_length(transform->input))
- GST_DEBUG("Not input buffer queued");
- else if ((input = gst_buffer_list_new()))
+ while (!transform->output_sample && ret == GST_FLOW_OK)
{
- ret = gst_pad_push_list(transform->my_src, transform->input);
- transform->input = input;
- }
- else
- {
- GST_ERROR("Failed to allocate new input queue");
- ret = GST_FLOW_ERROR;
+ if ((input_buffer = gst_atomic_queue_pop(transform->input_queue)))
+ ret = gst_pad_push(transform->my_src, input_buffer);
+ transform->output_sample = gst_atomic_queue_pop(transform->output_queue);
+
+ if (!input_buffer)
+ break;
}
/* Remove the sample so transform_request_sample cannot use it */
@@ -826,7 +824,7 @@ NTSTATUS wg_transform_read_data(void *args)
return STATUS_UNSUCCESSFUL;
}
- if (!transform->output_sample && !(transform->output_sample = gst_atomic_queue_pop(transform->output_queue)))
+ if (!transform->output_sample)
{
sample->size = 0;
params->result = MF_E_TRANSFORM_NEED_MORE_INPUT;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
[PATCH v3 5/6] winegstreamer: Check H264 ProcessOutput sample against actual image size.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Instead of maximum output sample size returned from GetOutputStreamInfo.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 114 ++++++------------------------
dlls/winegstreamer/h264_decoder.c | 14 ++--
2 files changed, 32 insertions(+), 96 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 7b598ba7dac..5108d2b2523 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6675,8 +6675,6 @@ static void test_h264_decoder(void)
},
};
static const DWORD input_width = 120, input_height = 248;
- static const DWORD align_input_width = (input_width + 15) & ~15;
- static const DWORD align_input_height = (input_height + 15) & ~15;
const media_type_desc default_outputs[] =
{
{
@@ -6688,6 +6686,9 @@ static void test_h264_decoder(void)
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
+ /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
@@ -6698,6 +6699,9 @@ static void test_h264_decoder(void)
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
+ /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
@@ -6708,6 +6712,9 @@ static void test_h264_decoder(void)
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
+ /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
@@ -6718,6 +6725,9 @@ static void test_h264_decoder(void)
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
+ /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
@@ -6728,57 +6738,9 @@ static void test_h264_decoder(void)
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
- },
- };
- const media_type_desc default_outputs_extra[] =
- {
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
- ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
- ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
- ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
- ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
- },
- {
ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
- ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
- },
- };
- const media_type_desc default_outputs_win7[] =
- {
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
- },
- {
- ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 2),
+ /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
},
};
const struct attribute_desc input_type_desc[] =
@@ -6807,18 +6769,6 @@ static void test_h264_decoder(void)
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
{0},
};
- const struct attribute_desc output_type_desc_win7[] =
- {
- ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
- ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
- ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
- ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
- ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
- ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * align_input_height * 3 / 2),
- ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
- {0},
- };
static const struct attribute_desc new_output_type_desc[] =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
@@ -6828,15 +6778,6 @@ static void test_h264_decoder(void)
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
{0},
};
- static const struct attribute_desc new_output_type_desc_win7[] =
- {
- ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
- ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
- ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
- ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
- ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
- {0},
- };
static const MFVideoArea actual_aperture = {.Area={82,84}};
static const DWORD actual_width = 96, actual_height = 96;
const media_type_desc actual_outputs[] =
@@ -6928,7 +6869,6 @@ static void test_h264_decoder(void)
IMFMediaType *media_type;
LONGLONG time, duration;
IMFTransform *transform;
- BOOL is_win7 = FALSE;
ULONG i, ret, flags;
HANDLE output_file;
IMFSample *sample;
@@ -7033,9 +6973,7 @@ static void test_h264_decoder(void)
ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
todo_wine
- ok(output_info.cbSize == input_width * input_height * 2
- || broken(output_info.cbSize == align_input_width * align_input_height * 2) /* Win7 */,
- "got cbSize %#lx\n", output_info.cbSize);
+ ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
/* output types can now be enumerated (though they are actually the same for all input types) */
@@ -7046,9 +6984,6 @@ static void test_h264_decoder(void)
winetest_push_context("out %lu", i);
ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
check_media_type(media_type, default_outputs[i], -1);
- hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL);
- is_win7 = broken(FAILED(hr));
- check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1);
ret = IMFMediaType_Release(media_type);
ok(ret == 0, "Release returned %lu\n", ret);
winetest_pop_context();
@@ -7076,8 +7011,8 @@ static void test_h264_decoder(void)
init_media_type(media_type, minimal_output_type_desc, i + 1);
}
hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
- ok(hr == (is_win7 ? MF_E_INVALIDMEDIATYPE : S_OK), "SetOutputType returned %#lx.\n", hr);
- init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
+ ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
+ init_media_type(media_type, output_type_desc, -1);
hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
ret = IMFMediaType_Release(media_type);
@@ -7085,7 +7020,7 @@ static void test_h264_decoder(void)
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
- check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
+ check_media_type(media_type, output_type_desc, -1);
ret = IMFMediaType_Release(media_type);
ok(ret == 0, "Release returned %lu\n", ret);
@@ -7097,7 +7032,6 @@ static void test_h264_decoder(void)
winetest_push_context("out %lu", i);
ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
check_media_type(media_type, default_outputs[i], -1);
- check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1);
ret = IMFMediaType_Release(media_type);
ok(ret == 0, "Release returned %lu\n", ret);
winetest_pop_context();
@@ -7121,9 +7055,7 @@ static void test_h264_decoder(void)
ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
todo_wine
- ok(output_info.cbSize == input_width * input_height * 2
- || broken(output_info.cbSize == align_input_width * align_input_height * 2) /* Win7 */,
- "got cbSize %#lx\n", output_info.cbSize);
+ ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
input_count = output_count = 0xdeadbeef;
@@ -7234,7 +7166,7 @@ static void test_h264_decoder(void)
/* current output type is still the one we selected */
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
- check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
+ check_media_type(media_type, output_type_desc, -1);
hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
ret = IMFMediaType_Release(media_type);
@@ -7254,7 +7186,7 @@ static void test_h264_decoder(void)
status = 0;
memset(&output, 0, sizeof(output));
- output.pSample = create_sample(NULL, actual_width * actual_height * 2);
+ output.pSample = create_sample(NULL, actual_width * actual_height * 3 / 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
@@ -7318,10 +7250,10 @@ static void test_h264_decoder(void)
/* we can change it, but only with the correct frame size */
hr = MFCreateMediaType(&media_type);
ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
- init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
+ init_media_type(media_type, output_type_desc, -1);
hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
- init_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1);
+ init_media_type(media_type, new_output_type_desc, -1);
hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
ret = IMFMediaType_Release(media_type);
@@ -7329,7 +7261,7 @@ static void test_h264_decoder(void)
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
- check_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1);
+ check_media_type(media_type, new_output_type_desc, -1);
hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
ret = IMFMediaType_Release(media_type);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 2ece7dee5b1..561a3c1578c 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -581,10 +581,11 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
- MFT_OUTPUT_STREAM_INFO info;
struct wg_sample *wg_sample;
struct wg_format wg_format;
+ UINT32 sample_size;
UINT64 frame_rate;
+ GUID subtype;
HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
@@ -592,9 +593,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
if (count != 1)
return E_INVALIDARG;
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
- return hr;
-
if (!decoder->wg_transform)
return MF_E_TRANSFORM_TYPE_NOT_SET;
@@ -602,10 +600,16 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
samples[0].dwStatus = 0;
if (!samples[0].pSample) return E_INVALIDARG;
+ if (FAILED(hr = IMFMediaType_GetGUID(decoder->output_type, &MF_MT_SUBTYPE, &subtype)))
+ return hr;
+ if (FAILED(hr = MFCalculateImageSize(&subtype, decoder->wg_format.u.video.width,
+ decoder->wg_format.u.video.height, &sample_size)))
+ return hr;
+
if (FAILED(hr = wg_sample_create_mf(samples[0].pSample, &wg_sample)))
return hr;
- if (wg_sample->max_size < info.cbSize)
+ if (wg_sample->max_size < sample_size)
{
wg_sample_release(wg_sample);
return MF_E_BUFFERTOOSMALL;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
[PATCH v3 4/6] winegstreamer: Use H264 input media type frame size when specified.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Updating the internal stream format frame size accordingly.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 87 +++++++++++++++++--------------
dlls/winegstreamer/h264_decoder.c | 7 +++
2 files changed, 55 insertions(+), 39 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index afe85ddbf3c..7b598ba7dac 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6674,14 +6674,17 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
},
};
- static const media_type_desc default_outputs[] =
+ static const DWORD input_width = 120, input_height = 248;
+ static const DWORD align_input_width = (input_width + 15) & ~15;
+ static const DWORD align_input_height = (input_height + 15) & ~15;
+ const media_type_desc default_outputs[] =
{
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
- ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
+ ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
@@ -6691,7 +6694,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
- ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
+ ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
@@ -6701,7 +6704,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
- ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
+ ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
@@ -6711,7 +6714,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
- ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
+ ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
@@ -6721,97 +6724,98 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
- ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
+ ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
},
};
- static const media_type_desc default_outputs_extra[] =
+ const media_type_desc default_outputs_extra[] =
{
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4147200),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
},
};
- static const media_type_desc default_outputs_win7[] =
+ const media_type_desc default_outputs_win7[] =
{
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2),
},
{
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4177920),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 2),
},
};
- static const struct attribute_desc input_type_desc[] =
+ const struct attribute_desc input_type_desc[] =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
{0},
};
- static const struct attribute_desc minimal_output_type_desc[] =
+ const struct attribute_desc minimal_output_type_desc[] =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
{0},
};
- static const struct attribute_desc output_type_desc[] =
+ const struct attribute_desc output_type_desc[] =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1080 * 3 / 2),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
{0},
};
- static const struct attribute_desc output_type_desc_win7[] =
+ const struct attribute_desc output_type_desc_win7[] =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
- ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
+ ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height),
ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
- ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1088 * 3 / 2),
+ ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * align_input_height * 3 / 2),
ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
{0},
};
@@ -7017,6 +7021,9 @@ static void test_h264_decoder(void)
init_media_type(media_type, input_type_desc, 2);
hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
+ init_media_type(media_type, input_type_desc, -1);
+ hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
+ ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
ret = IMFMediaType_Release(media_type);
ok(ret == 1, "Release returned %lu\n", ret);
@@ -7026,7 +7033,8 @@ static void test_h264_decoder(void)
ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
todo_wine
- ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
+ ok(output_info.cbSize == input_width * input_height * 2
+ || broken(output_info.cbSize == align_input_width * align_input_height * 2) /* Win7 */,
"got cbSize %#lx\n", output_info.cbSize);
ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
@@ -7113,7 +7121,8 @@ static void test_h264_decoder(void)
ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
todo_wine
- ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
+ ok(output_info.cbSize == input_width * input_height * 2
+ || broken(output_info.cbSize == align_input_width * align_input_height * 2) /* Win7 */,
"got cbSize %#lx\n", output_info.cbSize);
ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 1a9dcbd561c..2ece7dee5b1 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -401,6 +401,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM
{
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
GUID major, subtype;
+ UINT64 frame_size;
HRESULT hr;
ULONG i;
@@ -429,6 +430,12 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM
IMFMediaType_Release(decoder->input_type);
IMFMediaType_AddRef((decoder->input_type = type));
+ if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
+ {
+ decoder->wg_format.u.video.width = frame_size >> 32;
+ decoder->wg_format.u.video.height = (UINT32)frame_size;
+ }
+
return S_OK;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
[PATCH v3 3/6] winegstreamer: Implement H264 SetOutputType by reconfiguring the pipeline.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 11 ++---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/h264_decoder.c | 23 +++++++++-
dlls/winegstreamer/main.c | 13 ++++++
dlls/winegstreamer/unix_private.h | 1 +
dlls/winegstreamer/unixlib.h | 7 ++++
dlls/winegstreamer/wg_parser.c | 1 +
dlls/winegstreamer/wg_transform.c | 70 +++++++++++++++++++++++++++++++
8 files changed, 119 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 5f26b1a6238..afe85ddbf3c 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -7333,7 +7333,7 @@ static void test_h264_decoder(void)
todo_wine
ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
- if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
+ while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
{
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
@@ -7341,16 +7341,14 @@ static void test_h264_decoder(void)
ok(ret <= 1, "Release returned %lu\n", ret);
sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
+ todo_wine_if(hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
}
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample);
- todo_wine
ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
- todo_wine
ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
hr = IMFSample_GetTotalLength(output.pSample, &length);
ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
@@ -7373,17 +7371,16 @@ static void test_h264_decoder(void)
memset(&output, 0, sizeof(output));
output.pSample = create_sample(NULL, actual_width * actual_height * 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
ok(status == 0, "got status %#lx\n", status);
- if (hr != S_OK) goto skip_i420_tests;
hr = IMFSample_GetSampleTime(output.pSample, &time);
ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
+ todo_wine_if(time == 1334666) /* when VA-API plugin is used */
ok(time - 333666 <= 2, "got time %I64d\n", time);
duration = 0xdeadbeef;
@@ -7419,7 +7416,6 @@ static void test_h264_decoder(void)
check_sample(output.pSample, i420_frame_data, output_file);
-skip_i420_tests:
ret = IMFSample_Release(output.pSample);
ok(ret == 0, "Release returned %lu\n", ret);
@@ -7430,6 +7426,7 @@ skip_i420_tests:
memset(&output, 0, sizeof(output));
output.pSample = create_sample(NULL, actual_width * actual_height * 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
+ todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample);
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 8348d2e8360..14a52df5921 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -102,6 +102,7 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
struct wg_transform *wg_transform_create(const struct wg_format *input_format,
const struct wg_format *output_format);
void wg_transform_destroy(struct wg_transform *transform);
+bool wg_transform_set_format(struct wg_transform *transform, struct wg_format *format);
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 012a7060f29..1a9dcbd561c 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -467,7 +467,28 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
IMFMediaType_Release(decoder->output_type);
IMFMediaType_AddRef((decoder->output_type = type));
- if (FAILED(hr = try_create_wg_transform(decoder)))
+ if (decoder->wg_transform)
+ {
+ struct wg_format output_format;
+ mf_media_type_to_wg_format(decoder->output_type, &output_format);
+
+ /* Don't force any specific size, H264 streams already have the metadata for it
+ * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
+ */
+ output_format.u.video.width = 0;
+ output_format.u.video.height = 0;
+ output_format.u.video.fps_d = 0;
+ output_format.u.video.fps_n = 0;
+
+ if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN
+ || !wg_transform_set_format(decoder->wg_transform, &output_format))
+ {
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = NULL;
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ }
+ else if (FAILED(hr = try_create_wg_transform(decoder)))
{
IMFMediaType_Release(decoder->output_type);
decoder->output_type = NULL;
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index fc7b9d73285..fb2e8865089 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -348,6 +348,19 @@ HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample
return params.result;
}
+bool wg_transform_set_format(struct wg_transform *transform, struct wg_format *format)
+{
+ struct wg_transform_set_format_params params =
+ {
+ .transform = transform,
+ .format = format,
+ };
+
+ TRACE("transform %p, format %p.\n", transform, format);
+
+ return !__wine_unix_call(unix_handle, unix_wg_transform_set_format, ¶ms);
+}
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index e9f472986ae..3a6b162c500 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -34,6 +34,7 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS wg_transform_set_format(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 860a8ab2a52..ed02f025b05 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -263,6 +263,12 @@ struct wg_transform_read_data_params
HRESULT result;
};
+struct wg_transform_set_format_params
+{
+ struct wg_transform *transform;
+ const struct wg_format *format;
+};
+
enum unix_funcs
{
unix_wg_parser_create,
@@ -291,6 +297,7 @@ enum unix_funcs
unix_wg_transform_create,
unix_wg_transform_destroy,
+ unix_wg_transform_set_format,
unix_wg_transform_push_data,
unix_wg_transform_read_data,
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 7d55897aa0a..a4aa945a708 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1625,6 +1625,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create),
X(wg_transform_destroy),
+ X(wg_transform_set_format),
X(wg_transform_push_data),
X(wg_transform_read_data),
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index b0048fad644..b90fde70519 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -173,6 +173,31 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery
g_object_unref(pool);
return true;
}
+
+ case GST_QUERY_CAPS:
+ {
+ GstCaps *caps, *filter, *temp;
+ gchar *str;
+
+ gst_query_parse_caps(query, &filter);
+ caps = gst_caps_ref(transform->output_caps);
+
+ if (filter)
+ {
+ temp = gst_caps_intersect(caps, filter);
+ gst_caps_unref(caps);
+ caps = temp;
+ }
+
+ str = gst_caps_to_string(caps);
+ GST_INFO("Returning caps %s", str);
+ g_free(str);
+
+ gst_query_set_caps_result(query, caps);
+ gst_caps_unref(caps);
+ return true;
+ }
+
default:
GST_WARNING("Ignoring \"%s\" query.", gst_query_type_get_name(query->type));
break;
@@ -525,6 +550,51 @@ out:
return status;
}
+NTSTATUS wg_transform_set_format(void *args)
+{
+ struct wg_transform_set_format_params *params = args;
+ struct wg_transform *transform = params->transform;
+ GstSample *sample;
+ GstEvent *event;
+ GstCaps *caps;
+ gchar *str;
+
+ if (!(caps = wg_format_to_caps(params->format)))
+ {
+ GST_ERROR("Failed to convert format to caps.");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (gst_caps_is_always_compatible(transform->output_caps, caps))
+ {
+ gst_caps_unref(caps);
+ return STATUS_SUCCESS;
+ }
+
+ gst_caps_unref(transform->output_caps);
+ transform->output_caps = caps;
+
+ if (!gst_pad_set_caps(transform->my_sink, caps)
+ || !(event = gst_event_new_reconfigure())
+ || !gst_pad_push_event(transform->my_sink, event))
+ {
+ GST_ERROR("Failed to reconfigure transform.");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ str = gst_caps_to_string(caps);
+ GST_INFO("Configured new caps %s.", str);
+ g_free(str);
+
+ if (transform->output_sample)
+ gst_sample_unref(transform->output_sample);
+ while ((sample = gst_atomic_queue_pop(transform->output_queue)))
+ gst_sample_unref(sample);
+ transform->output_sample = NULL;
+
+ return STATUS_SUCCESS;
+}
+
static void wg_sample_free_notify(void *arg)
{
struct wg_sample *sample = arg;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
[PATCH v3 2/6] winegstreamer: Release wg_transform output sample when too small.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/wg_transform.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index e05432f6ac7..b0048fad644 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -314,10 +314,15 @@ static struct wg_sample *transform_request_sample(gsize size, void *context)
GST_LOG("size %#zx, context %p", size, transform);
- sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL);
- if (!sample || sample->max_size < size)
+ if (!(sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL)))
return NULL;
+ if (sample->max_size < size)
+ {
+ InterlockedDecrement(&sample->refcount);
+ return NULL;
+ }
+
return sample;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
[PATCH v3 1/6] mf/tests: Add todo_wine for newer FFmpeg versions.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 2f3ee3151da..5f26b1a6238 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -5911,7 +5911,7 @@ static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_
if (expect - value + 512 > 1024) break;
}
- todo_wine_if(todo)
+ todo_wine_if(todo && i < length / 2)
ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
@@ -6544,6 +6544,9 @@ static void test_wma_decoder(void)
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
winetest_pop_context();
+
+ /* some FFmpeg version request more input to complete decoding */
+ if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && i == 2) break;
}
todo_wine
ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
[PATCH v3 0/6] MR302: winegstreamer: Some wg_transform H264 fixes for Mortal Kombat 11 and Yakuza 4.
by Rémi Bernon
--
v3: winegstreamer: Use an atomic queue for wg_transform input buffers.
winegstreamer: Check H264 ProcessOutput sample against actual image size.
winegstreamer: Use H264 input media type frame size when specified.
winegstreamer: Implement H264 SetOutputType by reconfiguring the pipeline.
winegstreamer: Release wg_transform output sample when too small.
mf/tests: Add todo_wine for newer FFmpeg versions.
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 23, 2022
Re: [PATCH v2 0/1] MR296: nsiproxy.sys: Add static ARP entries which are always present on Windows.
by Paul Gofman (@gofman)
v2:
- use decimals for specifying ipv4 addresses;
- added comment to commit message;
- test all the parameters in uphlpapi tests (and remove nsi/tests change);
- use nsi_enumerate_all() instead of if_nameindex();
- use static array for added addresses and introduce IPV4_ADDR() macro instead of using inet_addr();
- handle the case when some of the static ARP entires are already present from host data.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/296#note_2574
June 23, 2022
[PATCH v2 1/1] nsiproxy.sys: Add static ARP entries which are always present on Windows.
by Paul Gofman
From: Paul Gofman <pgofman(a)codeweavers.com>
Some apps (Roon or SCP: Secret Laboratory are examples) depend on ARP
table always containing some entries if there is a network adapter present.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53175
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/iphlpapi/tests/iphlpapi.c | 52 ++++++++++++++++++-
dlls/nsiproxy.sys/ip.c | 86 +++++++++++++++++++++++++++++++-
dlls/nsiproxy.sys/unix_private.h | 6 +++
3 files changed, 142 insertions(+), 2 deletions(-)
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index 84d5143ba8e..1a0cb76bcf5 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -120,6 +120,11 @@ static const char *ntoa6( IN6_ADDR *ip )
return buffers[i];
}
+static DWORD ipv4_addr( BYTE b1, BYTE b2, BYTE b3, BYTE b4 )
+{
+ return htonl( (b1 << 24) | (b2 << 16) | (b3 << 8) | b4 );
+}
+
/*
still-to-be-tested 98-only functions:
GetUniDirectionalAdapterInfo
@@ -369,10 +374,16 @@ static void testGetIpForwardTable(void)
static void testGetIpNetTable(void)
{
- DWORD apiReturn;
+ DWORD apiReturn, ret, prev_idx;
+ BOOL igmp3_found, ssdp_found;
+ DWORD igmp3_addr, ssdp_addr;
+ MIB_IPNET_TABLE2 *table2;
ULONG dwSize = 0;
unsigned int i;
+ igmp3_addr = ipv4_addr( 224, 0, 0, 22 );
+ ssdp_addr = ipv4_addr( 239, 255, 255, 250 );
+
apiReturn = GetIpNetTable(NULL, NULL, FALSE);
if (apiReturn == ERROR_NOT_SUPPORTED) {
skip("GetIpNetTable is not supported\n");
@@ -406,6 +417,45 @@ static void testGetIpNetTable(void)
ok(ntohl(buf->table[i].dwAddr) <= ntohl(buf->table[i + 1].dwAddr),
"Entries are not sorted by address, i %u.\n", i );
}
+
+ igmp3_found = ssdp_found = FALSE;
+ prev_idx = ~0ul;
+ for (i = 0; i < buf->dwNumEntries; ++i)
+ {
+ if (buf->table[i].dwIndex != prev_idx)
+ {
+ if (prev_idx != ~0ul)
+ {
+ ok( igmp3_found, "%s not found, iface index %lu.\n", ntoa( igmp3_addr ), prev_idx);
+ ok( ssdp_found || broken(!ssdp_found) /* 239.255.255.250 is always present since Win10 */,
+ "%s not found.\n", ntoa( ssdp_addr ));
+ }
+ prev_idx = buf->table[i].dwIndex;
+ igmp3_found = ssdp_found = FALSE;
+ }
+ if (buf->table[i].dwAddr == igmp3_addr)
+ igmp3_found = TRUE;
+ else if (buf->table[i].dwAddr == ssdp_addr)
+ ssdp_found = TRUE;
+ }
+ ok( igmp3_found, "%s not found.\n", ntoa( igmp3_addr ));
+ ok( ssdp_found || broken(!ssdp_found) /* 239.255.255.250 is always present since Win10 */,
+ "%s not found.\n", ntoa( ssdp_addr ));
+
+ ret = GetIpNetTable2( AF_INET, &table2 );
+ ok( !ret, "got ret %lu.\n", ret );
+ for (i = 0; i < table2->NumEntries; ++i)
+ {
+ MIB_IPNET_ROW2 *row = &table2->Table[i];
+ if (row->Address.Ipv4.sin_addr.s_addr == igmp3_addr
+ || row->Address.Ipv4.sin_addr.s_addr == ssdp_addr)
+ {
+ ok( row->State == NlnsPermanent, "got state %d.\n", row->State );
+ ok( !row->IsRouter, "IsRouter is set.\n" );
+ ok( !row->IsUnreachable, "IsUnreachable is set.\n" );
+ }
+ }
+ FreeMibTable( table2 );
}
if (apiReturn == NO_ERROR && winetest_debug > 1)
diff --git a/dlls/nsiproxy.sys/ip.c b/dlls/nsiproxy.sys/ip.c
index 79f3bd80bfe..13e1f3c4623 100644
--- a/dlls/nsiproxy.sys/ip.c
+++ b/dlls/nsiproxy.sys/ip.c
@@ -1000,18 +1000,67 @@ static void ipv4_neighbour_fill_entry( struct ipv4_neighbour_data *entry, struct
}
}
+/* ARP entries for these multicast addresses are always present on Windows for each interface. */
+static DWORD ipv4_multicast_addresses[] =
+{
+ IPV4_ADDR(224, 0, 0, 22),
+ IPV4_ADDR(239, 255, 255, 250),
+};
+
+static void update_static_address_found( DWORD address, UINT if_index, struct nsi_ndis_ifinfo_static *iface,
+ unsigned int iface_count )
+{
+ unsigned int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(ipv4_multicast_addresses); ++i)
+ if (ipv4_multicast_addresses[i] == address) break;
+
+ if (i == ARRAY_SIZE(ipv4_multicast_addresses)) return;
+
+ for (j = 0; j < iface_count; ++j)
+ {
+ if (iface[j].if_index == if_index)
+ {
+ iface[j].unk |= 1 << i;
+ return;
+ }
+ }
+}
+
static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, void *rw_data, UINT rw_size,
void *dynamic_data, UINT dynamic_size,
void *static_data, UINT static_size, UINT_PTR *count )
{
- UINT num = 0;
+ UINT num = 0, iface_count;
NTSTATUS status = STATUS_SUCCESS;
BOOL want_data = key_size || rw_size || dynamic_size || static_size;
+ struct nsi_ndis_ifinfo_static *iface_static;
struct ipv4_neighbour_data entry;
+ unsigned int i, j;
TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data, key_size, rw_data, rw_size,
dynamic_data, dynamic_size, static_data, static_size, count );
+ iface_count = 0;
+ if ((status = nsi_enumerate_all( 1, 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0, &iface_count )))
+ return status;
+
+ if (!(iface_static = malloc( iface_count * sizeof(*iface_static) )))
+ return STATUS_NO_MEMORY;
+
+ if ((status = nsi_enumerate_all( 1, 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, NULL, 0, NULL, 0,
+ NULL, 0, iface_static, sizeof(*iface_static), &iface_count ))
+ && status != STATUS_BUFFER_OVERFLOW)
+ {
+ free( iface_static );
+ return status;
+ }
+
+ /* Use unk field to indicate whether we found mandatory multicast addresses in the host ARP table. */
+ for (i = 0; i < iface_count; ++i)
+ iface_static[i].unk = 0;
+
#ifdef __linux__
{
char buf[512], *ptr, *s;
@@ -1059,6 +1108,8 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
if (!convert_unix_name_to_luid( ptr, &entry.luid )) continue;
if (!convert_luid_to_index( &entry.luid, &entry.if_index )) continue;
+ update_static_address_found( entry.addr.s_addr, entry.if_index, iface_static, iface_count );
+
if (num < *count)
{
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
@@ -1119,6 +1170,8 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
#endif
entry.is_unreachable = 0; /* FIXME */
+ update_static_address_found( entry.addr.s_addr, entry.if_index, iface_static, iface_count );
+
if (num < *count)
{
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
@@ -1136,9 +1189,40 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
}
#else
FIXME( "not implemented\n" );
+ free( iface_static );
return STATUS_NOT_IMPLEMENTED;
#endif
+ if (!want_data || num <= *count)
+ {
+ /* Certain ipv4 multicast addresses are always present on Windows for each interface.
+ * Add those if they weren't added already. */
+ memset( &entry, 0, sizeof(entry) );
+ entry.state = NlnsPermanent;
+ for (i = 0; i < iface_count; ++i)
+ {
+ entry.if_index = iface_static[i].if_index;
+ convert_index_to_luid( entry.if_index, &entry.luid );
+ for (j = 0; j < ARRAY_SIZE(ipv4_multicast_addresses); ++j)
+ {
+ if (iface_static[i].unk & (1 << i)) continue;
+ if (num <= *count)
+ {
+ entry.addr.s_addr = ipv4_multicast_addresses[j];
+ ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
+
+ if (key_data) key_data = (BYTE *)key_data + key_size;
+ if (rw_data) rw_data = (BYTE *)rw_data + rw_size;
+ if (dynamic_data) dynamic_data = (BYTE *)dynamic_data + dynamic_size;
+ if (static_data) static_data = (BYTE *)static_data + static_size;
+ }
+ ++num;
+ }
+ }
+ }
+
+ free( iface_static );
+
if (!want_data || num <= *count) *count = num;
else status = STATUS_BUFFER_OVERFLOW;
diff --git a/dlls/nsiproxy.sys/unix_private.h b/dlls/nsiproxy.sys/unix_private.h
index 8ab56f6d9a3..84fea0c42d2 100644
--- a/dlls/nsiproxy.sys/unix_private.h
+++ b/dlls/nsiproxy.sys/unix_private.h
@@ -18,6 +18,12 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#ifdef WORDS_BIGENDIAN
+#define IPV4_ADDR(b1, b2, b3, b4) (((unsigned int)b1 << 24) | (b2 << 16) | (b3 << 8) | b4)
+#else
+#define IPV4_ADDR(b1, b2, b3, b4) (((unsigned int)b4 << 24) | (b3 << 16) | (b2 << 8) | b1)
+#endif
+
NTSTATUS nsi_enumerate_all_ex( struct nsi_enumerate_all_ex *params ) DECLSPEC_HIDDEN;
NTSTATUS nsi_get_all_parameters_ex( struct nsi_get_all_parameters_ex *params ) DECLSPEC_HIDDEN;
NTSTATUS nsi_get_parameter_ex( struct nsi_get_parameter_ex *params ) DECLSPEC_HIDDEN;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/296
June 23, 2022