From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_encoder.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index 2cb73ca89db..1e70a38c7a4 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -56,7 +56,8 @@ static inline struct video_encoder *impl_from_IMFTransform(IMFTransform *iface) return CONTAINING_RECORD(iface, struct video_encoder, IMFTransform_iface); }
-static HRESULT create_input_type(struct video_encoder *encoder, const GUID *subtype, IMFMediaType **out) +static HRESULT video_encoder_create_input_type(struct video_encoder *encoder, + const GUID *subtype, IMFMediaType **out) { IMFVideoMediaType *input_type; UINT64 ratio; @@ -239,7 +240,7 @@ static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD if (index >= encoder->input_type_count) return MF_E_NO_MORE_TYPES;
- return create_input_type(encoder, encoder->input_types[index], type); + return video_encoder_create_input_type(encoder, encoder->input_types[index], type); }
static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, @@ -293,7 +294,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM if (i == encoder->input_type_count) return MF_E_INVALIDMEDIATYPE;
- if (FAILED(hr = create_input_type(encoder, &subtype, &good_input_type))) + if (FAILED(hr = video_encoder_create_input_type(encoder, &subtype, &good_input_type))) return hr; hr = IMFMediaType_Compare(good_input_type, (IMFAttributes *)type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_encoder.c | 43 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-)
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index 1e70a38c7a4..0a56f1b1789 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -96,6 +96,24 @@ done: return hr; }
+static void video_encoder_clear_input_type(struct video_encoder *encoder) +{ + if (encoder->input_type) + { + IMFMediaType_Release(encoder->input_type); + encoder->input_type = NULL; + } +} + +static void video_encoder_clear_output_type(struct video_encoder *encoder) +{ + if (encoder->output_type) + { + IMFMediaType_Release(encoder->input_type); + encoder->output_type = NULL; + } +} + static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) { struct video_encoder *encoder = impl_from_IMFTransform(iface); @@ -269,12 +287,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM
if (!type) { - if (encoder->input_type) - { - IMFMediaType_Release(encoder->input_type); - encoder->input_type = NULL; - } - + video_encoder_clear_input_type(encoder); return S_OK; }
@@ -305,8 +318,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK;
- if (encoder->input_type) - IMFMediaType_Release(encoder->input_type); + video_encoder_clear_input_type(encoder); IMFMediaType_AddRef((encoder->input_type = type));
return S_OK; @@ -324,16 +336,8 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
if (!type) { - if (encoder->input_type) - { - IMFMediaType_Release(encoder->input_type); - encoder->input_type = NULL; - } - if (encoder->output_type) - { - IMFMediaType_Release(encoder->output_type); - encoder->output_type = NULL; - } + video_encoder_clear_input_type(encoder); + video_encoder_clear_output_type(encoder); return S_OK; }
@@ -361,8 +365,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF || FAILED(IMFMediaType_GetUINT32(type, &MF_MT_INTERLACE_MODE, &uint32_value))) return MF_E_INVALIDMEDIATYPE;
- if (encoder->output_type) - IMFMediaType_Release(encoder->output_type); + video_encoder_clear_output_type(encoder); IMFMediaType_AddRef((encoder->output_type = type));
/* FIXME: Add MF_MT_MPEG_SEQUENCE_HEADER attribute. */
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_encoder.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index 0a56f1b1789..b1e51016dd5 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -365,6 +365,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF || FAILED(IMFMediaType_GetUINT32(type, &MF_MT_INTERLACE_MODE, &uint32_value))) return MF_E_INVALIDMEDIATYPE;
+ video_encoder_clear_input_type(encoder); video_encoder_clear_output_type(encoder); IMFMediaType_AddRef((encoder->output_type = type));
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_encoder.c | 36 +++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index b1e51016dd5..62603bddeba 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -49,6 +49,10 @@ struct video_encoder MFT_OUTPUT_STREAM_INFO output_info;
IMFAttributes *attributes; + + wg_transform_t wg_transform; + struct wg_transform_attrs wg_transform_attrs; + struct wg_sample_queue *wg_sample_queue; };
static inline struct video_encoder *impl_from_IMFTransform(IMFTransform *iface) @@ -114,6 +118,21 @@ static void video_encoder_clear_output_type(struct video_encoder *encoder) } }
+static HRESULT video_encoder_create_wg_transform(struct video_encoder *encoder) +{ + return wg_transform_create_mf(encoder->input_type, encoder->output_type, + &encoder->wg_transform_attrs, &encoder->wg_transform); +} + +static void video_encoder_destroy_wg_transform(struct video_encoder *encoder) +{ + if (encoder->wg_transform) + { + wg_transform_destroy(encoder->wg_transform); + encoder->wg_transform = 0; + } +} + static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) { struct video_encoder *encoder = impl_from_IMFTransform(iface); @@ -157,6 +176,9 @@ static ULONG WINAPI transform_Release(IMFTransform *iface) if (encoder->output_type) IMFMediaType_Release(encoder->output_type); IMFAttributes_Release(encoder->attributes); + if (encoder->wg_transform) + wg_transform_destroy(encoder->wg_transform); + wg_sample_queue_destroy(encoder->wg_sample_queue); free(encoder); }
@@ -288,6 +310,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM if (!type) { video_encoder_clear_input_type(encoder); + video_encoder_destroy_wg_transform(encoder); return S_OK; }
@@ -319,9 +342,13 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM return S_OK;
video_encoder_clear_input_type(encoder); + video_encoder_destroy_wg_transform(encoder); IMFMediaType_AddRef((encoder->input_type = type));
- return S_OK; + if (FAILED(hr = video_encoder_create_wg_transform(encoder))) + video_encoder_clear_input_type(encoder); + + return hr; }
static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) @@ -338,6 +365,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF { video_encoder_clear_input_type(encoder); video_encoder_clear_output_type(encoder); + video_encoder_destroy_wg_transform(encoder); return S_OK; }
@@ -367,6 +395,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
video_encoder_clear_input_type(encoder); video_encoder_clear_output_type(encoder); + video_encoder_destroy_wg_transform(encoder); IMFMediaType_AddRef((encoder->output_type = type));
/* FIXME: Add MF_MT_MPEG_SEQUENCE_HEADER attribute. */ @@ -497,11 +526,16 @@ static HRESULT video_encoder_create(const GUID *const *input_types, UINT input_t encoder->output_types = output_types; encoder->output_type_count = output_type_count;
+ encoder->wg_transform_attrs.input_queue_length = 15; + if (FAILED(hr = MFCreateAttributes(&encoder->attributes, 16))) goto failed; if (FAILED(hr = IMFAttributes_SetUINT32(encoder->attributes, &MFT_ENCODER_SUPPORTS_CONFIG_EVENT, TRUE))) goto failed;
+ if (FAILED(hr = wg_sample_queue_create(&encoder->wg_sample_queue))) + goto failed; + *out = encoder; TRACE("Created video encoder %p\n", encoder); return S_OK;
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_encoder.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index 62603bddeba..1e6780a141f 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -468,8 +468,14 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { - FIXME("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags); - return E_NOTIMPL; + struct video_encoder *encoder = impl_from_IMFTransform(iface); + + TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags); + + if (!encoder->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + return wg_transform_push_mf(encoder->wg_transform, sample, encoder->wg_sample_queue); }
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_encoder.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c index 1e6780a141f..f78c9216b33 100644 --- a/dlls/winegstreamer/video_encoder.c +++ b/dlls/winegstreamer/video_encoder.c @@ -462,8 +462,22 @@ static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFM
static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) { - FIXME("iface %p, message %#x, param %Ix.\n", iface, message, param); - return E_NOTIMPL; + struct video_encoder *encoder = impl_from_IMFTransform(iface); + + TRACE("iface %p, message %#x, param %Ix.\n", iface, message, param); + + switch (message) + { + case MFT_MESSAGE_COMMAND_DRAIN: + return wg_transform_drain(encoder->wg_transform); + + case MFT_MESSAGE_COMMAND_FLUSH: + return wg_transform_flush(encoder->wg_transform); + + default: + FIXME("Ignoring message %#x.\n", message); + return S_OK; + } }
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
Rémi Bernon (@rbernon) commented about dlls/winegstreamer/video_encoder.c:
}
+static void video_encoder_clear_input_type(struct video_encoder *encoder) +{
- if (encoder->input_type)
- {
IMFMediaType_Release(encoder->input_type);
encoder->input_type = NULL;
- }
+}
+static void video_encoder_clear_output_type(struct video_encoder *encoder) +{
- if (encoder->output_type)
- {
IMFMediaType_Release(encoder->input_type);
You're releasing the wrong one here.
I'm not entirely sure these helpers are useful, they only save a couple of lines and add an indirection. It breaks a common code pattern that's otherwise used in all the other transform implementations.
Rémi Bernon (@rbernon) commented about dlls/winegstreamer/video_encoder.c:
}
+static HRESULT video_encoder_create_wg_transform(struct video_encoder *encoder) +{
- return wg_transform_create_mf(encoder->input_type, encoder->output_type,
&encoder->wg_transform_attrs, &encoder->wg_transform);
+}
+static void video_encoder_destroy_wg_transform(struct video_encoder *encoder) +{
- if (encoder->wg_transform)
- {
wg_transform_destroy(encoder->wg_transform);
encoder->wg_transform = 0;
- }
+}
Similarly here, I think it would be better for a potential future refactoring to keep the same code pattern and use a similar `try_create_wg_transform` helper as the other transform implementations.
Fwiw I've got the wg_transform changes that I wanted merged now and happy to consider changes to enable encoder support there. Maybe it would be good to have them in this MR that tries to instantiate a transform (which will otherwise currently fail)?
On Thu Jul 4 07:51:53 2024 +0000, Rémi Bernon wrote:
Fwiw I've got the wg_transform changes that I wanted merged now and happy to consider changes to enable encoder support there. Maybe it would be good to have them in this MR that tries to instantiate a transform (which will otherwise currently fail)?
OK, sounds good to me. I'll add the encoder support to wg_transform backend in this MR.
On Thu Jul 4 07:51:53 2024 +0000, Ziqing Hui wrote:
OK, sounds good to me. I'll add the encoder support to wg_transform backend in this MR.
I changed my plan, when I was doing the wg_transform backend work, I think it would be better to keep this MR frontend only and open a new MR for backend. So that it will looks clear for me when I was trying to cherry-pick the changes to Proton in the future.
Also, the backend changes have several commits, adding them to this MR will make this MR large. So I preffer to use a seperate MR.