-- v3: winegstreamer: Implement stubs for h264 encoder. mf/tests: Add tests for H264 encoder types.
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 111 +++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 25 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 6aff6838a80..f982f9071a8 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -694,8 +694,9 @@ static void check_mft_set_input_type_required_(int line, IMFTransform *transform ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref); }
-#define check_mft_set_input_type(a, b) check_mft_set_input_type_(__LINE__, a, b, FALSE) -static void check_mft_set_input_type_(int line, IMFTransform *transform, const struct attribute_desc *attributes, BOOL todo) +#define check_mft_set_input_type(a, b, c) check_mft_set_input_type_(__LINE__, a, b, c, FALSE) +static void check_mft_set_input_type_(int line, IMFTransform *transform, const struct attribute_desc *attributes, + HRESULT expect_hr, BOOL todo) { IMFMediaType *media_type; HRESULT hr; @@ -705,10 +706,10 @@ static void check_mft_set_input_type_(int line, IMFTransform *transform, const s init_media_type(media_type, attributes, -1);
hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY); - ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr); + ok_(__FILE__, line)(hr == expect_hr, "SetInputType returned %#lx.\n", hr); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); todo_wine_if(todo) - ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr); + ok_(__FILE__, line)(hr == expect_hr, "SetInputType returned %#lx.\n", hr);
IMFMediaType_Release(media_type); } @@ -2154,7 +2155,7 @@ static void test_aac_encoder(void) check_mft_get_output_current_type(transform, expect_output_type_desc);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_input_stream_info(transform, S_OK, &input_info); @@ -2412,7 +2413,7 @@ static void test_aac_decoder_subtype(const struct attribute_desc *input_type_des check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type(transform, input_type_desc);
/* check new output media types */ @@ -2920,7 +2921,7 @@ static void test_wma_encoder(void) check_mft_get_output_current_type(transform, expect_output_type_desc);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_input_stream_info(transform, S_OK, &input_info); @@ -3235,7 +3236,7 @@ static void test_wma_decoder(void) check_mft_get_output_current_type_(__LINE__, transform, NULL, TRUE, FALSE);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, TRUE, FALSE);
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL); @@ -3809,6 +3810,32 @@ static void test_h264_encoder(void) {.subtype = &MFVideoFormat_H264}, }, }; + static const media_type_desc default_outputs[] = + { + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264), + }, + }; + static const media_type_desc default_inputs[] = + { + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), + }, + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), + }, + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), + }, + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), + }, + }; static const struct attribute_desc expect_transform_attributes[] = { ATTR_UINT32(MFT_ENCODER_SUPPORTS_CONFIG_EVENT, 1), @@ -3854,9 +3881,11 @@ static void test_h264_encoder(void) static const MFT_OUTPUT_STREAM_INFO expect_output_info = {.cbSize = 0x8000}; MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_H264}; MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12}; + IMFMediaType *media_type; IMFTransform *transform; HRESULT hr; ULONG ret; + DWORD i;
hr = CoInitialize(NULL); ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr); @@ -3885,17 +3914,49 @@ static void test_h264_encoder(void) check_mft_get_input_stream_info(transform, S_OK, NULL); check_mft_get_output_stream_info(transform, S_OK, NULL);
+ /* No input type is available before an output type is set. */ + hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &media_type); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputAvailableType returned %#lx\n", hr); + check_mft_set_input_type(transform, input_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET); + check_mft_get_input_current_type(transform, NULL); + + /* Check available output types. */ + i = -1; + while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type))) + { + winetest_push_context("out %lu", i); + ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr); + check_media_type(media_type, default_outputs[i], -1); + ret = IMFMediaType_Release(media_type); + ok(ret == 0, "Release returned %lu\n", ret); + winetest_pop_context(); + } + ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx.\n", hr); + ok(i == ARRAY_SIZE(default_outputs), "%lu output media types.\n", i); + check_mft_set_output_type_required(transform, output_type_desc); check_mft_set_output_type(transform, output_type_desc, S_OK); + check_mft_get_output_current_type(transform, expect_output_type_desc); + check_mft_get_output_stream_info(transform, S_OK, &expect_output_info); + + /* Input types can now be enumerated. */ + i = -1; + while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type))) + { + winetest_push_context("out %lu", i); + ok(hr == S_OK, "IMFTransform_GetInputAvailableType returned %#lx\n", hr); + check_media_type(media_type, default_inputs[i], -1); + ret = IMFMediaType_Release(media_type); + ok(ret == 0, "Release returned %lu\n", ret); + winetest_pop_context(); + } + ok(hr == MF_E_NO_MORE_TYPES, "IMFTransform_GetInputAvailableType returned %#lx\n", hr); + ok(i == ARRAY_SIZE(default_inputs), "%lu input media types\n", i);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type(transform, expect_input_type_desc); - - check_mft_get_output_current_type(transform, expect_output_type_desc); - check_mft_get_input_stream_info(transform, S_OK, NULL); - check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
ret = IMFTransform_Release(transform); ok(ret == 0, "Release returned %lu\n", ret); @@ -4294,7 +4355,7 @@ static void test_h264_decoder(void) ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
check_mft_get_input_stream_info(transform, S_OK, &input_info); @@ -4971,7 +5032,7 @@ static void test_audio_convert(void) check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL); @@ -5446,7 +5507,7 @@ static void test_wmv_encoder(void) check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
check_mft_set_output_type_required(transform, output_type_desc); @@ -6034,7 +6095,7 @@ static void test_wmv_decoder(void) check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
i = -1; @@ -7159,7 +7220,7 @@ static void test_color_convert(void) ok(i == 20, "%lu input media types\n", i);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
for (i = 0; i < ARRAY_SIZE(color_conversion_tests); i++) @@ -7939,7 +8000,7 @@ static void test_video_processor(void) ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
/* MFVideoFormat_ABGR32 isn't supported by the video processor in non-D3D mode */ - check_mft_set_input_type(transform, nv12_default_stride); + check_mft_set_input_type(transform, nv12_default_stride, S_OK);
hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type); ok(hr == S_OK, "got %#lx\n", hr); @@ -7961,7 +8022,7 @@ static void test_video_processor(void) winetest_push_context("transform #%lu", i);
check_mft_set_input_type_required(transform, test->input_type_desc); - check_mft_set_input_type(transform, test->input_type_desc); + check_mft_set_input_type(transform, test->input_type_desc, S_OK); check_mft_get_input_current_type(transform, test->input_type_desc);
if (i >= 15) @@ -8111,13 +8172,13 @@ skip_test: &IID_IMFTransform, (void **)&transform); ok(hr == S_OK, "got hr %#lx\n", hr);
- check_mft_set_input_type(transform, nv12_no_aperture); + check_mft_set_input_type(transform, nv12_no_aperture, S_OK); check_mft_get_input_current_type(transform, nv12_no_aperture);
check_mft_set_output_type(transform, rgb32_no_aperture, S_OK); check_mft_get_output_current_type(transform, rgb32_no_aperture);
- check_mft_set_input_type_(__LINE__, transform, nv12_with_aperture, TRUE); + check_mft_set_input_type_(__LINE__, transform, nv12_with_aperture, S_OK, TRUE); check_mft_get_input_current_type_(__LINE__, transform, nv12_with_aperture, TRUE, FALSE);
/* output type is the same as before */ @@ -8376,7 +8437,7 @@ static void test_mp3_decoder(void) check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc); - check_mft_set_input_type(transform, input_type_desc); + check_mft_set_input_type(transform, input_type_desc, S_OK); check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL); @@ -9427,7 +9488,7 @@ static void test_video_processor_with_dxgi_manager(void)
/* check RGB32 output aperture cropping with D3D buffers */
- check_mft_set_input_type(transform, nv12_with_aperture); + check_mft_set_input_type(transform, nv12_with_aperture, S_OK); check_mft_set_output_type_(__LINE__, transform, rgb32_no_aperture, S_OK, TRUE);
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len); @@ -9495,7 +9556,7 @@ static void test_video_processor_with_dxgi_manager(void) skip_rgb32: /* check ABGR32 output with D3D buffers */
- check_mft_set_input_type(transform, nv12_with_aperture); + check_mft_set_input_type(transform, nv12_with_aperture, S_OK); check_mft_set_output_type_(__LINE__, transform, abgr32_no_aperture, S_OK, TRUE);
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 3 + dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/gst_private.h | 2 + dlls/winegstreamer/mfplat.c | 23 ++ dlls/winegstreamer/video_encoder.c | 338 +++++++++++++++++++ dlls/winegstreamer/winegstreamer_classes.idl | 6 + include/wmcodecdsp.idl | 6 + 7 files changed, 379 insertions(+) create mode 100644 dlls/winegstreamer/video_encoder.c
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index f982f9071a8..262e3bc4726 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -3903,7 +3903,10 @@ static void test_h264_encoder(void) check_mft_get_info(class_id, &expect_mft_info);
hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform); + todo_wine ok(hr == S_OK, "CoCreateInstance returned %#lx.\n", hr); + if (hr != S_OK) + goto failed;
check_interface(transform, &IID_IMFTransform, TRUE); check_interface(transform, &IID_IMediaObject, FALSE); diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index e33aa6c4d18..83093620af4 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -19,6 +19,7 @@ SOURCES = \ rsrc.rc \ unixlib.c \ video_decoder.c \ + video_encoder.c \ video_processor.c \ wg_allocator.c \ wg_format.c \ diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index ba9064bc467..bc798db5980 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -167,6 +167,8 @@ HRESULT aac_decoder_create(REFIID riid, void **ret); HRESULT h264_decoder_create(REFIID riid, void **ret); HRESULT video_processor_create(REFIID riid, void **ret);
+HRESULT h264_encoder_create(REFIID riid, void **ret); + extern const GUID MFAudioFormat_RAW_AAC;
#endif /* __GST_PRIVATE_INCLUDED__ */ diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 5775e8552db..dd326232b55 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -133,6 +133,7 @@ class_objects[] = { &CLSID_GStreamerByteStreamHandler, &gstreamer_byte_stream_handler_create }, { &CLSID_MSAACDecMFT, &aac_decoder_create }, { &CLSID_MSH264DecoderMFT, &h264_decoder_create }, + { &CLSID_MSH264EncoderMFT, &h264_encoder_create }, };
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) @@ -208,6 +209,18 @@ HRESULT mfplat_DllRegisterServer(void) {MFMediaType_Video, MFVideoFormat_YUY2}, };
+ MFT_REGISTER_TYPE_INFO h264_encoder_input_types[] = + { + {MFMediaType_Video, MFVideoFormat_IYUV}, + {MFMediaType_Video, MFVideoFormat_YV12}, + {MFMediaType_Video, MFVideoFormat_NV12}, + {MFMediaType_Video, MFVideoFormat_YUY2}, + }; + MFT_REGISTER_TYPE_INFO h264_encoder_output_types[] = + { + {MFMediaType_Video, MFVideoFormat_H264}, + }; + MFT_REGISTER_TYPE_INFO video_processor_input_types[] = { {MFMediaType_Video, MFVideoFormat_IYUV}, @@ -371,6 +384,16 @@ HRESULT mfplat_DllRegisterServer(void) ARRAY_SIZE(h264_decoder_output_types), h264_decoder_output_types, }, + { + CLSID_MSH264EncoderMFT, + MFT_CATEGORY_VIDEO_ENCODER, + L"H264 Encoder MFT", + MFT_ENUM_FLAG_SYNCMFT, + ARRAY_SIZE(h264_encoder_input_types), + h264_encoder_input_types, + ARRAY_SIZE(h264_encoder_output_types), + h264_encoder_output_types, + }, { CLSID_WMVDecoderMFT, MFT_CATEGORY_VIDEO_DECODER, diff --git a/dlls/winegstreamer/video_encoder.c b/dlls/winegstreamer/video_encoder.c new file mode 100644 index 00000000000..beb74003d64 --- /dev/null +++ b/dlls/winegstreamer/video_encoder.c @@ -0,0 +1,338 @@ +/* Generic Video Encoder Transform + * + * Copyright 2024 Ziqing Hui for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "gst_private.h" + +#include "mfapi.h" +#include "mferror.h" +#include "mfobjects.h" +#include "mftransform.h" +#include "mediaerr.h" +#include "wmcodecdsp.h" + +#include "wine/debug.h" + +#include "initguid.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); +WINE_DECLARE_DEBUG_CHANNEL(winediag); + +struct video_encoder +{ + IMFTransform IMFTransform_iface; + LONG refcount; + + IMFAttributes *attributes; +}; + +static inline struct video_encoder *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct video_encoder, IMFTransform_iface); +} + +static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + struct video_encoder *encoder = impl_from_IMFTransform(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IMFTransform) || IsEqualGUID(iid, &IID_IUnknown)) + *out = &encoder->IMFTransform_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI transform_AddRef(IMFTransform *iface) +{ + struct video_encoder *encoder = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&encoder->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", encoder, refcount); + + return refcount; +} + +static ULONG WINAPI transform_Release(IMFTransform *iface) +{ + struct video_encoder *encoder = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&encoder->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", encoder, refcount); + + if (!refcount) + { + IMFAttributes_Release(encoder->attributes); + free(encoder); + } + + return refcount; +} + +static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n", + iface, input_minimum, input_maximum, output_minimum, output_maximum); + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + return S_OK; +} + +static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs); + *inputs = *outputs = 1; + return S_OK; +} + +static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface, + input_size, inputs, output_size, outputs); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + FIXME("iface %p, id %#lx, info %p.\n", iface, id, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) +{ + FIXME("iface %p, id %#lx, info %p.\n", iface, id, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + struct video_encoder *encoder = impl_from_IMFTransform(iface); + + TRACE("iface %p, attributes %p.\n", iface, attributes); + + if (!attributes) + return E_POINTER; + + IMFAttributes_AddRef((*attributes = encoder->attributes)); + return S_OK; +} + +static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + FIXME("iface %p, id %#lx, attributes %p.\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + FIXME("iface %p, id %#lx, attributes %p.\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + FIXME("iface %p, id %#lx.\n", iface, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + FIXME("iface %p, streams %lu, ids %p.\n", iface, streams, ids); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, + DWORD index, IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + FIXME("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + FIXME("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, type %p\n", iface, id, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, type %p\n", iface, id, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + FIXME("iface %p, id %#lx, flags %p.\n", iface, id, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + FIXME("iface %p, flags %p stub!\n", iface, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + FIXME("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event); + return E_NOTIMPL; +} + +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; +} + +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; +} + +static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) +{ + FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); + return E_NOTIMPL; +} + +static const IMFTransformVtbl transform_vtbl = +{ + transform_QueryInterface, + transform_AddRef, + transform_Release, + transform_GetStreamLimits, + transform_GetStreamCount, + transform_GetStreamIDs, + transform_GetInputStreamInfo, + transform_GetOutputStreamInfo, + transform_GetAttributes, + transform_GetInputStreamAttributes, + transform_GetOutputStreamAttributes, + transform_DeleteInputStream, + transform_AddInputStreams, + transform_GetInputAvailableType, + transform_GetOutputAvailableType, + transform_SetInputType, + transform_SetOutputType, + transform_GetInputCurrentType, + transform_GetOutputCurrentType, + transform_GetInputStatus, + transform_GetOutputStatus, + transform_SetOutputBounds, + transform_ProcessEvent, + transform_ProcessMessage, + transform_ProcessInput, + transform_ProcessOutput, +}; + +static HRESULT video_encoder_create(struct video_encoder **out) +{ + struct video_encoder *encoder; + HRESULT hr; + + if (!(encoder = calloc(1, sizeof(*encoder)))) + return E_OUTOFMEMORY; + + encoder->IMFTransform_iface.lpVtbl = &transform_vtbl; + encoder->refcount = 1; + + if (FAILED(hr = MFCreateAttributes(&encoder->attributes, 16))) + goto failed; + if (FAILED(hr = IMFAttributes_SetUINT32(encoder->attributes, &MFT_ENCODER_SUPPORTS_CONFIG_EVENT, TRUE))) + goto failed; + + *out = encoder; + TRACE("Created video encoder %p\n", encoder); + return S_OK; + +failed: + if (encoder->attributes) + IMFAttributes_Release(encoder->attributes); + free(encoder); + return hr; +} + +HRESULT h264_encoder_create(REFIID riid, void **out) +{ + const MFVIDEOFORMAT input_format = + { + .dwSize = sizeof(MFVIDEOFORMAT), + .videoInfo = {.dwWidth = 1920, .dwHeight = 1080}, + .guidFormat = MFVideoFormat_NV12, + }; + const MFVIDEOFORMAT output_format = + { + .dwSize = sizeof(MFVIDEOFORMAT), + .videoInfo = {.dwWidth = 1920, .dwHeight = 1080}, + .guidFormat = MFVideoFormat_H264, + }; + struct video_encoder *encoder; + HRESULT hr; + + TRACE("riid %s, out %p.\n", debugstr_guid(riid), out); + + if (FAILED(hr = check_video_transform_support(&input_format, &output_format))) + { + ERR_(winediag)("GStreamer doesn't support H.264 encoding, please install appropriate plugins\n"); + return hr; + } + + if (FAILED(hr = video_encoder_create(&encoder))) + return hr; + + TRACE("Created h264 encoder transform %p.\n", &encoder->IMFTransform_iface); + + hr = IMFTransform_QueryInterface(&encoder->IMFTransform_iface, riid, out); + IMFTransform_Release(&encoder->IMFTransform_iface); + return hr; +} diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index bb727ca8645..41ec2d26123 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -107,6 +107,12 @@ coclass CWMVDecMediaObject {} ] coclass CMSH264DecoderMFT {}
+[ + threading(both), + uuid(6ca50344-051a-4ded-9779-a43305165e35) +] +coclass CMSH264EncoderMFT {} + [ threading(both), uuid(f447b69e-1884-4a7e-8055-346f74d6edb3) diff --git a/include/wmcodecdsp.idl b/include/wmcodecdsp.idl index a6f350ea2fc..9982b6e6b8a 100644 --- a/include/wmcodecdsp.idl +++ b/include/wmcodecdsp.idl @@ -52,6 +52,12 @@ coclass CResamplerMediaObject {} ] coclass CMSH264DecoderMFT {}
+[ + threading(both), + uuid(6ca50344-051a-4ded-9779-a43305165e35) +] +coclass CMSH264EncoderMFT {} + [ uuid(2d709e52-123f-49b5-9cbc-9af5cde28fb9) ]
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146428
Your paranoid android.
=== debian11 (build log) ===
0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0124:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins
=== debian11b (build log) ===
0120:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins 0240:err:winediag:h264_encoder_create GStreamer doesn't support H.264 encoding, please install appropriate plugins
Can we add an encoder element without changing all this code? It doesn't look like you need all the complicated converter sequence, maybe only a videoconvert (do you even need one?).
Yeah, in general the idea that we'd want the same sequence for decoding and encoding is probably wrong. E.g. for decoding we may want deinterlace, but we certainly don't want that for encoding. It's probably better to handle them separately.
Yeah, we should have different elements for encoder and decoder.
This merge request was approved by Rémi Bernon.