[PATCH v2 6/6] winegstreamer: Expose output media type attributes from the stream format.
Rémi Bernon
wine at gitlab.winehq.org
Fri May 13 04:48:34 CDT 2022
From: Rémi Bernon <rbernon at 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 at codeweavers.com>
---
dlls/mf/tests/mf.c | 17 ++++------
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/h264_decoder.c | 53 +++++++++++++++++--------------
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 | 16 ++++++++++
8 files changed, 75 insertions(+), 34 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 291c9d0a175..9a9e201bf87 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6801,7 +6801,7 @@ static void test_h264_decoder(void)
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, 60000, 1000, .todo_value = TRUE),
+ ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
@@ -6815,7 +6815,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
- ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000, .todo_value = TRUE),
+ ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
@@ -6829,7 +6829,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
- ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000, .todo_value = TRUE),
+ ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
@@ -6843,7 +6843,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
- ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000, .todo_value = TRUE),
+ ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
@@ -6857,7 +6857,7 @@ static void test_h264_decoder(void)
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
- ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000, .todo_value = TRUE),
+ ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2, .todo_value = TRUE),
ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2, .todo_value = TRUE),
@@ -7166,7 +7166,6 @@ static void test_h264_decoder(void)
hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
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 == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
@@ -7208,14 +7207,12 @@ 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_nv12_tests;
hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
@@ -7232,9 +7229,7 @@ static void test_h264_decoder(void)
time = 0xdeadbeef;
hr = IMFSample_GetSampleTime(output.pSample, &time);
- todo_wine
ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
- todo_wine
ok(time == 0, "got time %I64d\n", time);
/* doesn't matter what frame rate we've selected, duration is defined by the stream */
@@ -7249,7 +7244,9 @@ static void test_h264_decoder(void)
ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
ok(hr == S_OK, "Lock returned %#lx\n", hr);
+ todo_wine
ok(length == nv12_frame_len, "got length %lu\n", length);
+ if (length != nv12_frame_len) goto skip_nv12_tests;
for (i = 0; i < actual_aperture.Area.cy; ++i)
{
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 2a4b16079c1..55b2adc7e08 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -98,6 +98,7 @@ struct wg_transform *wg_transform_create(const struct wg_format *input_format,
void wg_transform_destroy(struct wg_transform *transform);
HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample *sample);
HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample);
+void wg_transform_get_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 ea80956b038..1b0061f4b4e 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -50,6 +50,7 @@ struct h264_decoder
IMFMediaType *input_type;
IMFMediaType *output_type;
+ struct wg_format format;
struct wg_transform *wg_transform;
};
@@ -89,8 +90,10 @@ static HRESULT try_create_wg_transform(struct h264_decoder *decoder)
return S_OK;
}
-static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *default_type)
+static HRESULT fill_output_media_type(struct h264_decoder *decoder, IMFMediaType *media_type)
{
+ IMFMediaType *default_type = decoder->output_type;
+ struct wg_format *format = &decoder->format;
UINT32 value, width, height;
UINT64 ratio;
GUID subtype;
@@ -101,8 +104,7 @@ static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *de
if (FAILED(hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &ratio)))
{
- if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_SIZE, &ratio)))
- ratio = (UINT64)1920 << 32 | 1080;
+ ratio = (UINT64)format->u.video.width << 32 | format->u.video.height;
if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ratio)))
return hr;
}
@@ -111,24 +113,21 @@ static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *de
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FRAME_RATE, NULL)))
{
- if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_RATE, &ratio)))
- ratio = (UINT64)30000 << 32 | 1001;
+ ratio = (UINT64)format->u.video.fps_n << 32 | format->u.video.fps_d;
if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, ratio)))
return hr;
}
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_PIXEL_ASPECT_RATIO, NULL)))
{
- if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_PIXEL_ASPECT_RATIO, &ratio)))
- ratio = (UINT64)1 << 32 | 1;
+ ratio = (UINT64)1 << 32 | 1; /* FIXME: read it from format */
if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, ratio)))
return hr;
}
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_SAMPLE_SIZE, NULL)))
{
- if ((!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_SAMPLE_SIZE, &value))) &&
- FAILED(hr = MFCalculateImageSize(&subtype, width, height, &value)))
+ if (FAILED(hr = MFCalculateImageSize(&subtype, width, height, &value)))
return hr;
if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, value)))
return hr;
@@ -136,8 +135,7 @@ static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *de
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_DEFAULT_STRIDE, NULL)))
{
- if ((!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_DEFAULT_STRIDE, &value))) &&
- FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG *)&value)))
+ if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG *)&value)))
return hr;
if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_DEFAULT_STRIDE, value)))
return hr;
@@ -272,23 +270,15 @@ static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id
static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
- UINT32 sample_size;
- UINT64 frame_size;
+ UINT32 actual_width, actual_height;
TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
- if (!decoder->output_type)
- sample_size = 1920 * 1088 * 2;
- else if (FAILED(IMFMediaType_GetUINT32(decoder->output_type, &MF_MT_SAMPLE_SIZE, &sample_size)))
- {
- if (FAILED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_SIZE, &frame_size)))
- sample_size = 1920 * 1088 * 2;
- else
- sample_size = (frame_size >> 32) * (UINT32)frame_size * 2;
- }
+ actual_width = (decoder->format.u.video.width + 15) & ~15;
+ actual_height = (decoder->format.u.video.height + 15) & ~15;
info->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
- info->cbSize = sample_size;
+ info->cbSize = actual_width * actual_height * 2;
info->cbAlignment = 0;
return S_OK;
@@ -378,7 +368,7 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR
if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, output_type)))
goto done;
- hr = fill_output_media_type(media_type, NULL);
+ hr = fill_output_media_type(decoder, media_type);
done:
if (SUCCEEDED(hr))
@@ -543,6 +533,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
MFT_OUTPUT_STREAM_INFO info;
struct wg_sample *wg_sample;
+ UINT64 frame_rate;
HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
@@ -572,6 +563,15 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
{
+ wg_transform_get_format(decoder->wg_transform, &decoder->format);
+
+ /* keep the frame rate that was requested, GStreamer doesn't provide any */
+ if (SUCCEEDED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_RATE, &frame_rate)))
+ {
+ decoder->format.u.video.fps_n = frame_rate >> 32;
+ decoder->format.u.video.fps_d = (UINT32)frame_rate;
+ }
+
samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
*status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
}
@@ -639,6 +639,11 @@ HRESULT h264_decoder_create(REFIID riid, void **ret)
decoder->IMFTransform_iface.lpVtbl = &transform_vtbl;
decoder->refcount = 1;
+ decoder->format.u.video.format = WG_VIDEO_FORMAT_UNKNOWN;
+ decoder->format.u.video.width = 1920;
+ decoder->format.u.video.height = 1080;
+ decoder->format.u.video.fps_n = 30000;
+ decoder->format.u.video.fps_d = 1001;
*ret = &decoder->IMFTransform_iface;
TRACE("Created decoder %p\n", *ret);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index c3adbb82d61..3afc279a86f 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -346,6 +346,19 @@ HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample
return params.result;
}
+void wg_transform_get_format(struct wg_transform *transform, struct wg_format *format)
+{
+ struct wg_transform_get_format_params params =
+ {
+ .transform = transform,
+ .format = format,
+ };
+
+ TRACE("transform %p, format %p.\n", transform, format);
+
+ __wine_unix_call(unix_handle, unix_wg_transform_get_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 7bce8263aaf..eeeda671ad8 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -36,5 +36,6 @@ extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS wg_transform_get_format(void *args) DECLSPEC_HIDDEN;
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 5911278530d..029d6992342 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -260,6 +260,12 @@ struct wg_transform_read_data_params
HRESULT result;
};
+struct wg_transform_get_format_params
+{
+ struct wg_transform *transform;
+ struct wg_format *format;
+};
+
enum unix_funcs
{
unix_wg_parser_create,
@@ -291,6 +297,7 @@ enum unix_funcs
unix_wg_transform_push_data,
unix_wg_transform_read_data,
+ unix_wg_transform_get_format,
};
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 7d55897aa0a..c6382adcb65 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1628,4 +1628,5 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_push_data),
X(wg_transform_read_data),
+ X(wg_transform_get_format),
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 9edcd72754f..ff8de777232 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -537,3 +537,19 @@ NTSTATUS wg_transform_read_data(void *args)
params->result = S_OK;
return STATUS_SUCCESS;
}
+
+NTSTATUS wg_transform_get_format(void *args)
+{
+ struct wg_transform_get_format_params *params = args;
+ struct wg_transform *transform = params->transform;
+ GstCaps *output_caps;
+
+ if (!transform->output_sample)
+ return STATUS_UNSUCCESSFUL;
+
+ output_caps = gst_sample_get_caps(transform->output_sample);
+
+ wg_format_from_caps(params->format, output_caps);
+
+ return STATUS_SUCCESS;
+}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/61
More information about the wine-devel
mailing list