I don't think this will cause any conflicts with the other MR, as long as the `wg_sample` API doesn't change.
-- v2: winegstreamer: Implement ColorConvertDMO transform. winegstreamer: Register stub ColorConvertDMO transform. winegstreamer: Remove unnecessary WineAudioConverter transform. winegstreamer: Implement ResamplerMediaObject transform. winegstreamer: Register stub ResamplerMediaObject transform.
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 42 +- dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/main.c | 13 + dlls/winegstreamer/mfplat.c | 20 +- dlls/winegstreamer/resampler.c | 606 +++++++++++++++++++ dlls/winegstreamer/winegstreamer_classes.idl | 6 + 7 files changed, 681 insertions(+), 8 deletions(-) create mode 100644 dlls/winegstreamer/resampler.c
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 13f0e38b0b8..990b29302de 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -254,9 +254,7 @@ static BOOL create_transform(GUID category, MFT_REGISTER_TYPE_INFO *input_type, if (IsEqualGUID(expect_class_id, class_ids + i)) break; } - todo_wine_if(IsEqualGUID(class_ids, &CLSID_WINEAudioConverter)) ok(i < count, "failed to find %s transform\n", debugstr_w(expect_name)); - if (i == count) return FALSE; *class_id = class_ids[i]; CoTaskMemFree(class_ids); ok(IsEqualGUID(class_id, expect_class_id), "got class id %s\n", debugstr_guid(class_id)); @@ -7566,15 +7564,16 @@ static void test_audio_convert(void) check_interface(transform, &IID_IMFTransform, TRUE); check_interface(transform, &IID_IMediaObject, TRUE); check_interface(transform, &IID_IPropertyStore, TRUE); - todo_wine check_interface(transform, &IID_IPropertyBag, TRUE); /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
/* check default media types */
hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
i = -1; @@ -7587,7 +7586,9 @@ static void test_audio_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } + todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr); + todo_wine ok(i == 4, "%lu output media types\n", i);
i = -1; @@ -7602,7 +7603,9 @@ static void test_audio_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } + todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr); + todo_wine ok(i == 2, "%lu input media types\n", i);
/* setting output media type first doesn't work */ @@ -7611,6 +7614,7 @@ static void test_audio_convert(void) ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); init_media_type(media_type, output_type_desc, -1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret); @@ -7620,25 +7624,31 @@ static void test_audio_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 1); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 2); for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i) { hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, i + 1); } hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
/* check new output media types */ @@ -7653,7 +7663,9 @@ static void test_audio_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } + todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr); + todo_wine ok(i == 4, "%lu output media types\n", i);
/* check required output media type attributes */ @@ -7661,36 +7673,50 @@ static void test_audio_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 2); for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i) { hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, i + 1); } hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
memset(&input_info, 0xcd, sizeof(input_info)); hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + todo_wine ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr); + todo_wine ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); + todo_wine ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags); + todo_wine ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize); + todo_wine ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead); + todo_wine ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
memset(&output_info, 0xcd, sizeof(output_info)); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + todo_wine ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); + todo_wine ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags); + todo_wine ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize); + todo_wine ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA); @@ -7705,10 +7731,13 @@ static void test_audio_convert(void) hr = IMFSample_SetSampleDuration(sample, 10000000); ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0); + todo_wine ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); IMFSample_Release(sample);
@@ -7764,9 +7793,12 @@ static void test_audio_convert(void) }
hr = IMFSample_GetSampleTime(sample, &time); + todo_wine ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); + todo_wine_if(i != 0) ok(time == i * 928798, "got time %I64d\n", time); hr = IMFSample_GetSampleDuration(sample, &duration); + todo_wine ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr); todo_wine ok(duration == 897506, "got duration %I64d\n", duration); @@ -7774,6 +7806,7 @@ static void test_audio_convert(void) ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); todo_wine ok(length == 15832, "got length %lu\n", length); + todo_wine ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len); check_sample_pcm16(sample, audioconv_data, output_file, FALSE); audioconv_data_len -= length; @@ -7788,6 +7821,7 @@ static void test_audio_convert(void) todo_wine ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */, "got dwStatus %#lx\n", output.dwStatus); + todo_wine ok(status == 0, "got status %#lx\n", status);
if (hr == S_OK) @@ -7819,9 +7853,11 @@ static void test_audio_convert(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); + todo_wine ok(status == 0, "got status %#lx\n", status); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 6e3517dcb36..f365608ed6a 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -14,6 +14,7 @@ C_SRCS = \ mfplat.c \ quartz_parser.c \ quartz_transform.c \ + resampler.c \ wg_allocator.c \ wg_format.c \ wg_parser.c \ diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index e1abe7018da..c539084fa89 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -111,6 +111,7 @@ HRESULT mpeg_audio_codec_create(IUnknown *outer, IUnknown **out); HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out); HRESULT wave_parser_create(IUnknown *outer, IUnknown **out); HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out); +HRESULT resampler_create(IUnknown *outer, IUnknown **out);
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm); bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 5075b3118cd..fedf4e48538 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -437,6 +437,7 @@ static struct class_factory mpeg_audio_codec_cf = {{&class_factory_vtbl}, mpeg_a static struct class_factory mpeg_splitter_cf = {{&class_factory_vtbl}, mpeg_splitter_create}; static struct class_factory wave_parser_cf = {{&class_factory_vtbl}, wave_parser_create}; static struct class_factory wma_decoder_cf = {{&class_factory_vtbl}, wma_decoder_create}; +static struct class_factory resampler_cf = {{&class_factory_vtbl}, resampler_create};
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) { @@ -463,6 +464,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) factory = &wave_parser_cf; else if (IsEqualGUID(clsid, &CLSID_WMADecMediaObject)) factory = &wma_decoder_cf; + else if (IsEqualGUID(clsid, &CLSID_CResamplerMediaObject)) + factory = &resampler_cf; else { FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); @@ -657,6 +660,11 @@ static const REGFILTER2 reg_decodebin_parser =
HRESULT WINAPI DllRegisterServer(void) { + DMO_PARTIAL_MEDIATYPE audio_convert_types[2] = + { + {.type = MEDIATYPE_Audio, .subtype = MEDIASUBTYPE_PCM}, + {.type = MEDIATYPE_Audio, .subtype = MEDIASUBTYPE_IEEE_FLOAT}, + }; DMO_PARTIAL_MEDIATYPE wma_decoder_output[2] = { {.type = MEDIATYPE_Audio, .subtype = MEDIASUBTYPE_PCM}, @@ -696,6 +704,9 @@ HRESULT WINAPI DllRegisterServer(void) if (FAILED(hr = DMORegister(L"WMA Decoder DMO", &CLSID_WMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER, 0, ARRAY_SIZE(wma_decoder_input), wma_decoder_input, ARRAY_SIZE(wma_decoder_output), wma_decoder_output))) return hr; + if (FAILED(hr = DMORegister(L"Resampler DMO", &CLSID_CResamplerMediaObject, &DMOCATEGORY_AUDIO_EFFECT, + 0, ARRAY_SIZE(audio_convert_types), audio_convert_types, ARRAY_SIZE(audio_convert_types), audio_convert_types))) + return hr;
return mfplat_DllRegisterServer(); } @@ -722,6 +733,8 @@ HRESULT WINAPI DllUnregisterServer(void)
IFilterMapper2_Release(mapper);
+ if (FAILED(hr = DMOUnregister(&CLSID_CResamplerMediaObject, &DMOCATEGORY_AUDIO_EFFECT))) + return hr; if (FAILED(hr = DMOUnregister(&CLSID_WMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER))) return hr;
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index c5ca4b15c0f..ee0a5d25056 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -440,7 +440,7 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
HRESULT mfplat_DllRegisterServer(void) { - MFT_REGISTER_TYPE_INFO audio_converter_supported_types[] = + MFT_REGISTER_TYPE_INFO resampler_types[] = { {MFMediaType_Audio, MFAudioFormat_PCM}, {MFMediaType_Audio, MFAudioFormat_Float}, @@ -541,10 +541,10 @@ HRESULT mfplat_DllRegisterServer(void) MFT_CATEGORY_AUDIO_EFFECT, L"Audio Converter", MFT_ENUM_FLAG_SYNCMFT, - ARRAY_SIZE(audio_converter_supported_types), - audio_converter_supported_types, - ARRAY_SIZE(audio_converter_supported_types), - audio_converter_supported_types, + ARRAY_SIZE(resampler_types), + resampler_types, + ARRAY_SIZE(resampler_types), + resampler_types, }, { CLSID_WMADecMediaObject, @@ -576,6 +576,16 @@ HRESULT mfplat_DllRegisterServer(void) ARRAY_SIZE(video_processor_output_types), video_processor_output_types, }, + { + CLSID_CResamplerMediaObject, + MFT_CATEGORY_AUDIO_EFFECT, + L"Resampler MFT", + MFT_ENUM_FLAG_SYNCMFT, + ARRAY_SIZE(resampler_types), + resampler_types, + ARRAY_SIZE(resampler_types), + resampler_types, + }, };
unsigned int i; diff --git a/dlls/winegstreamer/resampler.c b/dlls/winegstreamer/resampler.c new file mode 100644 index 00000000000..554c76d6085 --- /dev/null +++ b/dlls/winegstreamer/resampler.c @@ -0,0 +1,606 @@ +/* Copyright 2022 Rémi Bernon 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 "wmcodecdsp.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); +WINE_DECLARE_DEBUG_CHANNEL(winediag); + +struct resampler +{ + IUnknown IUnknown_inner; + IMFTransform IMFTransform_iface; + IMediaObject IMediaObject_iface; + IPropertyBag IPropertyBag_iface; + IPropertyStore IPropertyStore_iface; + IUnknown *outer; + LONG refcount; +}; + +static inline struct resampler *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct resampler, IUnknown_inner); +} + +static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + struct resampler *impl = impl_from_IUnknown(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown)) + *out = &impl->IUnknown_inner; + else if (IsEqualGUID(iid, &IID_IMFTransform)) + *out = &impl->IMFTransform_iface; + else if (IsEqualGUID(iid, &IID_IMediaObject)) + *out = &impl->IMediaObject_iface; + else if (IsEqualIID(iid, &IID_IPropertyBag)) + *out = &impl->IPropertyBag_iface; + else if (IsEqualIID(iid, &IID_IPropertyStore)) + *out = &impl->IPropertyStore_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 unknown_AddRef(IUnknown *iface) +{ + struct resampler *impl = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&impl->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI unknown_Release(IUnknown *iface) +{ + struct resampler *impl = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&impl->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + free(impl); + + return refcount; +} + +static const IUnknownVtbl unknown_vtbl = +{ + unknown_QueryInterface, + unknown_AddRef, + unknown_Release, +}; + +static struct resampler *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct resampler, IMFTransform_iface); +} + +static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); +} + +static ULONG WINAPI transform_AddRef(IMFTransform *iface) +{ + return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); +} + +static ULONG WINAPI transform_Release(IMFTransform *iface) +{ + return IUnknown_Release(impl_from_IMFTransform(iface)->outer); +} + +static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n", + iface, input_minimum, input_maximum, output_minimum, output_maximum); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs); + return E_NOTIMPL; +} + +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 stub!\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 stub!\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 stub!\n", iface, id, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + FIXME("iface %p, attributes %p stub!\n", iface, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + FIXME("iface %p, id %#lx, attributes %p stub!\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 stub!\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + FIXME("iface %p, id %#lx stub!\n", iface, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + FIXME("iface %p, streams %lu, ids %p stub!\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 %lu, type %p stub!\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 %lu, type %p stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 %p stub!\n", iface, message, (void *)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 stub!\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 stub!\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 inline struct resampler *impl_from_IMediaObject(IMediaObject *iface) +{ + return CONTAINING_RECORD(iface, struct resampler, IMediaObject_iface); +} + +static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj) +{ + return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj); +} + +static ULONG WINAPI media_object_AddRef(IMediaObject *iface) +{ + return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer); +} + +static ULONG WINAPI media_object_Release(IMediaObject *iface) +{ + return IUnknown_Release(impl_from_IMediaObject(iface)->outer); +} + +static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) +{ + FIXME("iface %p, input %p, output %p stub!\n", iface, input, output); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, + DWORD *lookahead, DWORD *alignment) +{ + FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size, + lookahead, alignment); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) +{ + FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) +{ + FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency) +{ + FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Flush(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) +{ + FIXME("iface %p, index %lu stub!\n", iface, index); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, + IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) +{ + FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface, + index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, + DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) +{ + FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock) +{ + FIXME("iface %p, lock %ld stub!\n", iface, lock); + return E_NOTIMPL; +} + +static const IMediaObjectVtbl media_object_vtbl = +{ + media_object_QueryInterface, + media_object_AddRef, + media_object_Release, + media_object_GetStreamCount, + media_object_GetInputStreamInfo, + media_object_GetOutputStreamInfo, + media_object_GetInputType, + media_object_GetOutputType, + media_object_SetInputType, + media_object_SetOutputType, + media_object_GetInputCurrentType, + media_object_GetOutputCurrentType, + media_object_GetInputSizeInfo, + media_object_GetOutputSizeInfo, + media_object_GetInputMaxLatency, + media_object_SetInputMaxLatency, + media_object_Flush, + media_object_Discontinuity, + media_object_AllocateStreamingResources, + media_object_FreeStreamingResources, + media_object_GetInputStatus, + media_object_ProcessInput, + media_object_ProcessOutput, + media_object_Lock, +}; + +static inline struct resampler *impl_from_IPropertyBag(IPropertyBag *iface) +{ + return CONTAINING_RECORD(iface, struct resampler, IPropertyBag_iface); +} + +static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out); +} + +static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer); +} + +static ULONG WINAPI property_bag_Release(IPropertyBag *iface) +{ + return IUnknown_Release(impl_from_IPropertyBag(iface)->outer); +} + +static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value, + IErrorLog *error_log) +{ + FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value) +{ + FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value); + return S_OK; +} + +static const IPropertyBagVtbl property_bag_vtbl = +{ + property_bag_QueryInterface, + property_bag_AddRef, + property_bag_Release, + property_bag_Read, + property_bag_Write, +}; + +static inline struct resampler *impl_from_IPropertyStore(IPropertyStore *iface) +{ + return CONTAINING_RECORD(iface, struct resampler, IPropertyStore_iface); +} + +static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out); +} + +static ULONG WINAPI property_store_AddRef(IPropertyStore *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer); +} + +static ULONG WINAPI property_store_Release(IPropertyStore *iface) +{ + return IUnknown_Release(impl_from_IPropertyStore(iface)->outer); +} + +static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count) +{ + FIXME("iface %p, count %p stub!\n", iface, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key) +{ + FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_Commit(IPropertyStore *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static const IPropertyStoreVtbl property_store_vtbl = +{ + property_store_QueryInterface, + property_store_AddRef, + property_store_Release, + property_store_GetCount, + property_store_GetAt, + property_store_GetValue, + property_store_SetValue, + property_store_Commit, +}; + +HRESULT resampler_create(IUnknown *outer, IUnknown **out) +{ + struct resampler *impl; + + TRACE("outer %p, out %p.\n", outer, out); + + if (!(impl = calloc(1, sizeof(*impl)))) + return E_OUTOFMEMORY; + + impl->IUnknown_inner.lpVtbl = &unknown_vtbl; + impl->IMFTransform_iface.lpVtbl = &transform_vtbl; + impl->IMediaObject_iface.lpVtbl = &media_object_vtbl; + impl->IPropertyBag_iface.lpVtbl = &property_bag_vtbl; + impl->IPropertyStore_iface.lpVtbl = &property_store_vtbl; + impl->refcount = 1; + impl->outer = outer ? outer : &impl->IUnknown_inner; + + *out = &impl->IUnknown_inner; + TRACE("Created %p\n", *out); + return S_OK; +} diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index 037f0573b34..77a9f801fa3 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -86,3 +86,9 @@ coclass CWMADecMediaObject {}; uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d) ] coclass CMSH264DecoderMFT {} + +[ + threading(both), + uuid(f447b69e-1884-4a7e-8055-346f74d6edb3) +] +coclass CResamplerMediaObject {}
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.
1 TestBot errors prevented a full analysis of your patch. If the test caused the operating system (e.g. Windows) to crash or reboot you will probably have to modify it to avoid that. Other issues should be reported to the TestBot administrators.
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=117130
Your paranoid android.
=== build (build log) ===
WineRunBuild.pl:error: An error occurred while waiting for the build to complete: the 2826 process does not exist or is not a child process WineRunBuild.pl:error: BotError: The test VM has crashed, rebooted or lost connectivity (or the TestAgent server died)
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 full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117130
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/mf/tests/mf.c:254 error: patch failed: dlls/winegstreamer/Makefile.in:14 error: patch failed: dlls/winegstreamer/gst_private.h:111 error: patch failed: dlls/winegstreamer/main.c:437 error: patch failed: dlls/winegstreamer/mfplat.c:440 error: patch failed: dlls/winegstreamer/winegstreamer_classes.idl:86 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/mf/tests/mf.c:254 error: patch failed: dlls/winegstreamer/Makefile.in:14 error: patch failed: dlls/winegstreamer/gst_private.h:111 error: patch failed: dlls/winegstreamer/main.c:437 error: patch failed: dlls/winegstreamer/mfplat.c:440 error: patch failed: dlls/winegstreamer/winegstreamer_classes.idl:86 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/mf/tests/mf.c:254 error: patch failed: dlls/winegstreamer/Makefile.in:14 error: patch failed: dlls/winegstreamer/gst_private.h:111 error: patch failed: dlls/winegstreamer/main.c:437 error: patch failed: dlls/winegstreamer/mfplat.c:440 error: patch failed: dlls/winegstreamer/winegstreamer_classes.idl:86 Task: Patch failed to apply
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 39 --- dlls/winegstreamer/resampler.c | 402 ++++++++++++++++++++++++++++-- dlls/winegstreamer/wg_transform.c | 1 + 3 files changed, 376 insertions(+), 66 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 990b29302de..11261342d35 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7570,10 +7570,8 @@ static void test_audio_convert(void) /* check default media types */
hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
i = -1; @@ -7586,9 +7584,7 @@ static void test_audio_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr); - todo_wine ok(i == 4, "%lu output media types\n", i);
i = -1; @@ -7603,9 +7599,7 @@ static void test_audio_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr); - todo_wine ok(i == 2, "%lu input media types\n", i);
/* setting output media type first doesn't work */ @@ -7614,7 +7608,6 @@ static void test_audio_convert(void) ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); init_media_type(media_type, output_type_desc, -1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret); @@ -7624,31 +7617,25 @@ static void test_audio_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 1); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 2); for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i) { hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, i + 1); } hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
/* check new output media types */ @@ -7663,9 +7650,7 @@ static void test_audio_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr); - todo_wine ok(i == 4, "%lu output media types\n", i);
/* check required output media type attributes */ @@ -7673,50 +7658,36 @@ static void test_audio_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 2); for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i) { hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, i + 1); } hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
memset(&input_info, 0xcd, sizeof(input_info)); hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); - todo_wine ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr); - todo_wine ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); - todo_wine ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags); - todo_wine ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize); - todo_wine ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead); - todo_wine ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
memset(&output_info, 0xcd, sizeof(output_info)); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); - todo_wine ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); - todo_wine ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags); - todo_wine ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize); - todo_wine ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA); @@ -7731,13 +7702,10 @@ static void test_audio_convert(void) hr = IMFSample_SetSampleDuration(sample, 10000000); ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0); - todo_wine ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); IMFSample_Release(sample);
@@ -7793,12 +7761,9 @@ static void test_audio_convert(void) }
hr = IMFSample_GetSampleTime(sample, &time); - todo_wine ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); - todo_wine_if(i != 0) ok(time == i * 928798, "got time %I64d\n", time); hr = IMFSample_GetSampleDuration(sample, &duration); - todo_wine ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr); todo_wine ok(duration == 897506, "got duration %I64d\n", duration); @@ -7806,7 +7771,6 @@ static void test_audio_convert(void) ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); todo_wine ok(length == 15832, "got length %lu\n", length); - todo_wine ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len); check_sample_pcm16(sample, audioconv_data, output_file, FALSE); audioconv_data_len -= length; @@ -7821,7 +7785,6 @@ static void test_audio_convert(void) todo_wine ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status);
if (hr == S_OK) @@ -7853,11 +7816,9 @@ static void test_audio_convert(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); diff --git a/dlls/winegstreamer/resampler.c b/dlls/winegstreamer/resampler.c index 554c76d6085..ea000e3b96f 100644 --- a/dlls/winegstreamer/resampler.c +++ b/dlls/winegstreamer/resampler.c @@ -28,6 +28,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DECLARE_DEBUG_CHANNEL(winediag);
+static const GUID *audio_formats[] = +{ + &MFAudioFormat_Float, + &MFAudioFormat_PCM, +}; + struct resampler { IUnknown IUnknown_inner; @@ -37,8 +43,35 @@ struct resampler IPropertyStore IPropertyStore_iface; IUnknown *outer; LONG refcount; + IMFMediaType *input_type; + IMFMediaType *output_type; + + struct wg_transform *wg_transform; + struct wg_sample_queue *wg_sample_queue; };
+static HRESULT try_create_wg_transform(struct resampler *impl) +{ + struct wg_format input_format, output_format; + + if (impl->wg_transform) + wg_transform_destroy(impl->wg_transform); + impl->wg_transform = NULL; + + mf_media_type_to_wg_format(impl->input_type, &input_format); + if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return MF_E_INVALIDMEDIATYPE; + + mf_media_type_to_wg_format(impl->output_type, &output_format); + if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return MF_E_INVALIDMEDIATYPE; + + if (!(impl->wg_transform = wg_transform_create(&input_format, &output_format))) + return E_FAIL; + + return S_OK; +} + static inline struct resampler *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct resampler, IUnknown_inner); @@ -89,7 +122,17 @@ static ULONG WINAPI unknown_Release(IUnknown *iface) TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
if (!refcount) + { + if (impl->wg_transform) + wg_transform_destroy(impl->wg_transform); + if (impl->input_type) + IMFMediaType_Release(impl->input_type); + if (impl->output_type) + IMFMediaType_Release(impl->output_type); + + wg_sample_queue_destroy(impl->wg_sample_queue); free(impl); + }
return refcount; } @@ -124,15 +167,17 @@ static ULONG WINAPI transform_Release(IMFTransform *iface) static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) { - FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n", + 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); - return E_NOTIMPL; + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + return S_OK; }
static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) { - FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs); - return E_NOTIMPL; + 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, @@ -145,14 +190,46 @@ static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_si
static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) { - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + UINT32 block_alignment; + HRESULT hr; + + TRACE("iface %p, id %#lx, info %p.\n", iface, id, info); + + if (!impl->input_type || !impl->output_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = IMFMediaType_GetUINT32(impl->input_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment))) + return hr; + + info->dwFlags = 0; + info->cbSize = block_alignment; + info->cbAlignment = 1; + info->hnsMaxLatency = 0; + info->cbMaxLookahead = 0; + + return S_OK; }
static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) { - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + UINT32 block_alignment; + HRESULT hr; + + TRACE("iface %p, id %#lx, info %p.\n", iface, id, info); + + if (!impl->input_type || !impl->output_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = IMFMediaType_GetUINT32(impl->output_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment))) + return hr; + + info->dwFlags = 0; + info->cbSize = block_alignment; + info->cbAlignment = 1; + + return S_OK; }
static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) @@ -185,42 +262,214 @@ static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD strea return E_NOTIMPL; }
+static HRESULT get_available_media_type(DWORD index, IMFMediaType **type, BOOL output) +{ + UINT32 sample_size, sample_rate = 48000, block_alignment, channel_count = 2; + IMFMediaType *media_type; + const GUID *subtype; + HRESULT hr; + + if (FAILED(hr = MFCreateMediaType(&media_type))) + return hr; + + *type = NULL; + + if (index >= (output ? 2 : 1) * ARRAY_SIZE(audio_formats)) + return MF_E_NO_MORE_TYPES; + subtype = audio_formats[index % ARRAY_SIZE(audio_formats)]; + + if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio))) + goto done; + if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1))) + goto done; + if (index < ARRAY_SIZE(audio_formats)) + goto done; + + if (IsEqualGUID(subtype, &MFAudioFormat_Float)) + sample_size = 32; + else if (IsEqualGUID(subtype, &MFAudioFormat_PCM)) + sample_size = 16; + else + { + FIXME("Subtype %s not implemented!\n", debugstr_guid(subtype)); + hr = E_NOTIMPL; + goto done; + } + + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, sample_size))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, channel_count))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, sample_rate))) + goto done; + + block_alignment = sample_size * channel_count / 8; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, block_alignment))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, sample_rate * block_alignment))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1))) + goto done; + +done: + if (SUCCEEDED(hr)) + IMFMediaType_AddRef((*type = media_type)); + + IMFMediaType_Release(media_type); + return hr; +} + static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; + TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type); + return get_available_media_type(index, type, FALSE); }
static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; + TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type); + return get_available_media_type(index, type, TRUE); +} + +static HRESULT check_media_type(IMFMediaType *type) +{ + MF_ATTRIBUTE_TYPE item_type; + GUID major, subtype; + HRESULT hr; + ULONG i; + + if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) || + FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) + return MF_E_ATTRIBUTENOTFOUND; + + if (!IsEqualGUID(&major, &MFMediaType_Audio)) + return MF_E_INVALIDMEDIATYPE; + + for (i = 0; i < ARRAY_SIZE(audio_formats); ++i) + if (IsEqualGUID(&subtype, audio_formats[i])) + break; + if (i == ARRAY_SIZE(audio_formats)) + return MF_E_INVALIDMEDIATYPE; + + if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &item_type)) || + item_type != MF_ATTRIBUTE_UINT32) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &item_type)) || + item_type != MF_ATTRIBUTE_UINT32) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_NUM_CHANNELS, &item_type)) || + item_type != MF_ATTRIBUTE_UINT32) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &item_type)) || + item_type != MF_ATTRIBUTE_UINT32) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &item_type)) || + item_type != MF_ATTRIBUTE_UINT32) + return MF_E_INVALIDMEDIATYPE; + + return S_OK; }
static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags); + + if (FAILED(hr = check_media_type(type))) + return hr; + + if (!impl->input_type && FAILED(hr = MFCreateMediaType(&impl->input_type))) + return hr; + + if (impl->output_type) + { + IMFMediaType_Release(impl->output_type); + impl->output_type = NULL; + } + + if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->input_type))) + { + IMFMediaType_Release(impl->input_type); + impl->input_type = NULL; + } + + return hr; }
static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags); + + if (!impl->input_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = check_media_type(type))) + return hr; + + if (!impl->output_type && FAILED(hr = MFCreateMediaType(&impl->output_type))) + return hr; + + if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->output_type))) + goto failed; + + if (FAILED(hr = try_create_wg_transform(impl))) + goto failed; + + return hr; + +failed: + IMFMediaType_Release(impl->output_type); + impl->output_type = NULL; + return hr; }
static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + IMFMediaType *ret; + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p.\n", iface, id, type); + + if (id != 0) + return MF_E_INVALIDSTREAMNUMBER; + + if (!impl->input_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(&ret))) + return hr; + + return IMFMediaType_CopyAllItems(impl->input_type, (IMFAttributes *)ret); }
static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + IMFMediaType *ret; + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p.\n", iface, id, type); + + if (id != 0) + return MF_E_INVALIDSTREAMNUMBER; + + if (!impl->output_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(&ret))) + return hr; + + return IMFMediaType_CopyAllItems(impl->output_type, (IMFAttributes *)ret); }
static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) @@ -250,20 +499,81 @@ 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 %p stub!\n", iface, message, (void *)param); - return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { - FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + struct wg_sample *wg_sample; + HRESULT hr; + + TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags); + + if (!impl->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = wg_sample_create_mf(sample, &wg_sample))) + return hr; + + return wg_transform_push_mf(impl->wg_transform, wg_sample, + impl->wg_sample_queue); }
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 stub!\n", iface, flags, count, samples, status); - return E_NOTIMPL; + struct resampler *impl = impl_from_IMFTransform(iface); + MFT_OUTPUT_STREAM_INFO info; + struct wg_sample *wg_sample; + HRESULT hr; + + TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); + + if (count > 1) + return E_INVALIDARG; + + if (!impl->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) + return hr; + + *status = 0; + samples[0].dwStatus = 0; + if (!samples[0].pSample) + { + samples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE; + return MF_E_TRANSFORM_NEED_MORE_INPUT; + } + + if (FAILED(hr = wg_sample_create_mf(samples[0].pSample, &wg_sample))) + return hr; + + wg_sample->size = 0; + if (wg_sample->max_size < info.cbSize) + { + wg_sample_release(wg_sample); + return MF_E_BUFFERTOOSMALL; + } + + if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, wg_sample, NULL))) + { + if (wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE) + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE; + wg_sample_queue_flush(impl->wg_sample_queue, false); + } + + wg_sample_release(wg_sample); + + if (hr == MF_E_TRANSFORM_STREAM_CHANGE) + { + FIXME("Unexpected stream format change!\n"); + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + } + + return hr; }
static const IMFTransformVtbl transform_vtbl = @@ -318,8 +628,9 @@ static ULONG WINAPI media_object_Release(IMediaObject *iface)
static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) { - FIXME("iface %p, input %p, output %p stub!\n", iface, input, output); - return E_NOTIMPL; + FIXME("iface %p, input %p, output %p semi-stub!\n", iface, input, output); + *input = *output = 1; + return S_OK; }
static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) @@ -585,13 +896,50 @@ static const IPropertyStoreVtbl property_store_vtbl =
HRESULT resampler_create(IUnknown *outer, IUnknown **out) { + static const struct wg_format input_format = + { + .major_type = WG_MAJOR_TYPE_AUDIO, + .u.audio = + { + .format = WG_AUDIO_FORMAT_S16LE, + .channel_mask = 1, + .channels = 1, + .rate = 44100, + }, + }; + static const struct wg_format output_format = + { + .major_type = WG_MAJOR_TYPE_AUDIO, + .u.audio = + { + .format = WG_AUDIO_FORMAT_F32LE, + .channel_mask = 1, + .channels = 1, + .rate = 44100, + }, + }; + struct wg_transform *transform; struct resampler *impl; + HRESULT hr;
TRACE("outer %p, out %p.\n", outer, out);
+ if (!(transform = wg_transform_create(&input_format, &output_format))) + { + ERR_(winediag)("GStreamer doesn't support audio resampling, please install appropriate plugins.\n"); + return E_FAIL; + } + wg_transform_destroy(transform); + if (!(impl = calloc(1, sizeof(*impl)))) return E_OUTOFMEMORY;
+ if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue))) + { + free(impl); + return hr; + } + impl->IUnknown_inner.lpVtbl = &unknown_vtbl; impl->IMFTransform_iface.lpVtbl = &transform_vtbl; impl->IMediaObject_iface.lpVtbl = &media_object_vtbl; diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index b5517f24515..46725712aca 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -406,6 +406,7 @@ NTSTATUS wg_transform_create(void *args) break;
case WG_MAJOR_TYPE_AUDIO: + break; case WG_MAJOR_TYPE_VIDEO: case WG_MAJOR_TYPE_UNKNOWN: GST_FIXME("Format %u not implemented!", input_format.major_type);
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.
1 TestBot errors prevented a full analysis of your patch. If the test caused the operating system (e.g. Windows) to crash or reboot you will probably have to modify it to avoid that. Other issues should be reported to the TestBot administrators.
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=117131
Your paranoid android.
=== build (build log) ===
WineRunBuild.pl:error: Could not copy the patch to the VM: network read timed out (sendfile/connect:AgentVersion.h:0/9) WineRunBuild.pl:error: BotError: The test VM has crashed, rebooted or lost connectivity (or the TestAgent server died)
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39787 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39769 bytes)
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 full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117131
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/mf/tests/mf.c:254 error: patch failed: dlls/winegstreamer/Makefile.in:14 error: patch failed: dlls/winegstreamer/gst_private.h:111 error: patch failed: dlls/winegstreamer/main.c:437 error: patch failed: dlls/winegstreamer/mfplat.c:440 error: patch failed: dlls/winegstreamer/winegstreamer_classes.idl:86 error: patch failed: dlls/mf/tests/mf.c:7570 error: patch failed: dlls/winegstreamer/resampler.c:28 error: patch failed: dlls/winegstreamer/wg_transform.c:406 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/mf/tests/mf.c:254 error: patch failed: dlls/winegstreamer/Makefile.in:14 error: patch failed: dlls/winegstreamer/gst_private.h:111 error: patch failed: dlls/winegstreamer/main.c:437 error: patch failed: dlls/winegstreamer/mfplat.c:440 error: patch failed: dlls/winegstreamer/winegstreamer_classes.idl:86 error: patch failed: dlls/mf/tests/mf.c:7570 error: patch failed: dlls/winegstreamer/resampler.c:28 error: patch failed: dlls/winegstreamer/wg_transform.c:406 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/mf/tests/mf.c:254 error: patch failed: dlls/winegstreamer/Makefile.in:14 error: patch failed: dlls/winegstreamer/gst_private.h:111 error: patch failed: dlls/winegstreamer/main.c:437 error: patch failed: dlls/winegstreamer/mfplat.c:440 error: patch failed: dlls/winegstreamer/winegstreamer_classes.idl:86 error: patch failed: dlls/mf/tests/mf.c:7570 error: patch failed: dlls/winegstreamer/resampler.c:28 error: patch failed: dlls/winegstreamer/wg_transform.c:406 Task: Patch failed to apply
This merge request was approved by Alexandre Julliard.
From: Rémi Bernon rbernon@codeweavers.com
Superseded by the standard ResamplerMediaObject transform.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/Makefile.in | 1 - dlls/winegstreamer/audioconvert.c | 584 ------------------- dlls/winegstreamer/gst_private.h | 1 - dlls/winegstreamer/mfplat.c | 13 - dlls/winegstreamer/winegstreamer_classes.idl | 6 - 5 files changed, 605 deletions(-) delete mode 100644 dlls/winegstreamer/audioconvert.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index f365608ed6a..e7bffa92df0 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -7,7 +7,6 @@ EXTRAINCL = $(GSTREAMER_CFLAGS) EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
C_SRCS = \ - audioconvert.c \ h264_decoder.c \ main.c \ media_source.c \ diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c deleted file mode 100644 index d5723cdf58f..00000000000 --- a/dlls/winegstreamer/audioconvert.c +++ /dev/null @@ -1,584 +0,0 @@ -/* GStreamer Audio Converter - * - * Copyright 2020 Derek Lesho - * - * 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 "ks.h" -#include "ksmedia.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(mfplat); - -struct audio_converter -{ - IMFTransform IMFTransform_iface; - LONG refcount; - IMFMediaType *input_type; - IMFMediaType *output_type; - CRITICAL_SECTION cs; -}; - -static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface) -{ - return CONTAINING_RECORD(iface, struct audio_converter, IMFTransform_iface); -} - -static HRESULT WINAPI audio_converter_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) -{ - TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); - - if (IsEqualIID(riid, &IID_IMFTransform) || - IsEqualIID(riid, &IID_IUnknown)) - { - *obj = iface; - IMFTransform_AddRef(iface); - return S_OK; - } - - WARN("Unsupported %s.\n", debugstr_guid(riid)); - *obj = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI audio_converter_AddRef(IMFTransform *iface) -{ - struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface); - ULONG refcount = InterlockedIncrement(&transform->refcount); - - TRACE("%p, refcount %lu.\n", iface, refcount); - - return refcount; -} - -static ULONG WINAPI audio_converter_Release(IMFTransform *iface) -{ - struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface); - ULONG refcount = InterlockedDecrement(&transform->refcount); - - TRACE("%p, refcount %lu.\n", iface, refcount); - - if (!refcount) - { - transform->cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&transform->cs); - free(transform); - } - - return refcount; -} - -static HRESULT WINAPI audio_converter_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum, - DWORD *output_minimum, DWORD *output_maximum) -{ - TRACE("%p, %p, %p, %p, %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 audio_converter_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) -{ - TRACE("%p, %p, %p.\n", iface, inputs, outputs); - - *inputs = *outputs = 1; - - return S_OK; -} - -static HRESULT WINAPI audio_converter_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, - DWORD output_size, DWORD *outputs) -{ - TRACE("%p, %lu, %p, %lu, %p.\n", iface, input_size, inputs, output_size, outputs); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) -{ - FIXME("%p, %lu, %p.\n", iface, id, info); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) -{ - FIXME("%p. %lu, %p.\n", iface, id, info); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) -{ - FIXME("%p, %p.\n", iface, attributes); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id, - IMFAttributes **attributes) -{ - FIXME("%p, %lu, %p.\n", iface, id, attributes); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, - IMFAttributes **attributes) -{ - FIXME("%p, %lu, %p.\n", iface, id, attributes); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id) -{ - TRACE("%p, %lu.\n", iface, id); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) -{ - TRACE("%p, %lu, %p.\n", iface, streams, ids); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - IMFMediaType *ret; - HRESULT hr; - - TRACE("%p, %lu, %lu, %p.\n", iface, id, index, type); - - if (id != 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (index >= 2) - return MF_E_NO_MORE_TYPES; - - if (FAILED(hr = MFCreateMediaType(&ret))) - return hr; - - if (FAILED(hr = IMFMediaType_SetGUID(ret, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio))) - { - IMFMediaType_Release(ret); - return hr; - } - - if (FAILED(hr = IMFMediaType_SetGUID(ret, &MF_MT_SUBTYPE, index ? &MFAudioFormat_Float : &MFAudioFormat_PCM))) - { - IMFMediaType_Release(ret); - return hr; - } - - *type = ret; - - return S_OK; -} - -static HRESULT WINAPI audio_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - IMFMediaType *output_type; - HRESULT hr; - - static const struct - { - const GUID *subtype; - DWORD depth; - } - formats[] = - { - {&MFAudioFormat_PCM, 16}, - {&MFAudioFormat_PCM, 24}, - {&MFAudioFormat_PCM, 32}, - {&MFAudioFormat_Float, 32}, - }; - - static const DWORD rates[] = {44100, 48000}; - static const DWORD channel_cnts[] = {1, 2, 6}; - const GUID *subtype; - DWORD rate, channels, bps; - - TRACE("%p, %lu, %lu, %p.\n", iface, id, index, type); - - if (id != 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (index >= ARRAY_SIZE(formats) * 2/*rates*/ * 3/*layouts*/) - return MF_E_NO_MORE_TYPES; - - if (FAILED(hr = MFCreateMediaType(&output_type))) - return hr; - - subtype = formats[index / 6].subtype; - bps = formats[index / 6].depth; - rate = rates[index % 2]; - channels = channel_cnts[(index / 2) % 3]; - - if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio))) - goto fail; - if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_SUBTYPE, subtype))) - goto fail; - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, rate))) - goto fail; - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_NUM_CHANNELS, channels))) - goto fail; - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, bps))) - goto fail; - - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, channels * bps / 8))) - goto fail; - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, rate * channels * bps / 8))) - goto fail; - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_CHANNEL_MASK, - channels == 1 ? KSAUDIO_SPEAKER_MONO : - channels == 2 ? KSAUDIO_SPEAKER_STEREO : - /*channels == 6*/ KSAUDIO_SPEAKER_5POINT1))) - goto fail; - if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE))) - goto fail; - - *type = output_type; - - return S_OK; -fail: - IMFMediaType_Release(output_type); - return hr; -} - -static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - GUID major_type, subtype; - UINT32 unused; - HRESULT hr; - - struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface); - - TRACE("%p, %lu, %p, %#lx.\n", iface, id, type, flags); - - if (id != 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!type) - { - if (flags & MFT_SET_TYPE_TEST_ONLY) - return S_OK; - - EnterCriticalSection(&converter->cs); - - if (converter->input_type) - { - IMFMediaType_Release(converter->input_type); - converter->input_type = NULL; - } - - LeaveCriticalSection(&converter->cs); - - return S_OK; - } - - if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type))) - return MF_E_INVALIDTYPE; - if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) - return MF_E_INVALIDTYPE; - if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &unused))) - return MF_E_INVALIDTYPE; - if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &unused))) - return MF_E_INVALIDTYPE; - if (IsEqualGUID(&subtype, &MFAudioFormat_PCM) && FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &unused))) - return MF_E_INVALIDTYPE; - - if (!(IsEqualGUID(&major_type, &MFMediaType_Audio))) - return MF_E_INVALIDTYPE; - - if (!IsEqualGUID(&subtype, &MFAudioFormat_PCM) && !IsEqualGUID(&subtype, &MFAudioFormat_Float)) - return MF_E_INVALIDTYPE; - - if (flags & MFT_SET_TYPE_TEST_ONLY) - return S_OK; - - EnterCriticalSection(&converter->cs); - - hr = S_OK; - - if (!converter->input_type) - hr = MFCreateMediaType(&converter->input_type); - - if (SUCCEEDED(hr)) - hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type); - - if (FAILED(hr)) - { - IMFMediaType_Release(converter->input_type); - converter->input_type = NULL; - } - - LeaveCriticalSection(&converter->cs); - - return hr; -} - -static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface); - GUID major_type, subtype; - UINT32 unused; - HRESULT hr; - - TRACE("%p, %lu, %p, %#lx.\n", iface, id, type, flags); - - if (id != 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!converter->input_type) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (!type) - { - if (flags & MFT_SET_TYPE_TEST_ONLY) - return S_OK; - - EnterCriticalSection(&converter->cs); - - if (converter->output_type) - { - IMFMediaType_Release(converter->output_type); - converter->output_type = NULL; - } - - LeaveCriticalSection(&converter->cs); - - return S_OK; - } - - if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type))) - return MF_E_INVALIDTYPE; - if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) - return MF_E_INVALIDTYPE; - if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &unused))) - return MF_E_INVALIDTYPE; - if (IsEqualGUID(&subtype, &MFAudioFormat_PCM) && FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &unused))) - return MF_E_INVALIDTYPE; - if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &unused))) - return MF_E_INVALIDTYPE; - - if (!(IsEqualGUID(&major_type, &MFMediaType_Audio))) - return MF_E_INVALIDTYPE; - - if (!IsEqualGUID(&subtype, &MFAudioFormat_PCM) && !IsEqualGUID(&subtype, &MFAudioFormat_Float)) - return MF_E_INVALIDTYPE; - - if (flags & MFT_SET_TYPE_TEST_ONLY) - return S_OK; - - EnterCriticalSection(&converter->cs); - - hr = S_OK; - - if (!converter->output_type) - hr = MFCreateMediaType(&converter->output_type); - - if (SUCCEEDED(hr)) - hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type); - - if (FAILED(hr)) - { - IMFMediaType_Release(converter->output_type); - converter->output_type = NULL; - } - - LeaveCriticalSection(&converter->cs); - - return hr; -} - -static HRESULT WINAPI audio_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface); - IMFMediaType *ret; - HRESULT hr; - - TRACE("%p, %lu, %p.\n", converter, id, type); - - if (id != 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (FAILED(hr = MFCreateMediaType(&ret))) - return hr; - - EnterCriticalSection(&converter->cs); - - if (converter->input_type) - hr = IMFMediaType_CopyAllItems(converter->input_type, (IMFAttributes *)ret); - else - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - - LeaveCriticalSection(&converter->cs); - - if (SUCCEEDED(hr)) - *type = ret; - else - IMFMediaType_Release(ret); - - return hr; -} - -static HRESULT WINAPI audio_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface); - IMFMediaType *ret; - HRESULT hr; - - TRACE("%p, %lu, %p.\n", converter, id, type); - - if (id != 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (FAILED(hr = MFCreateMediaType(&ret))) - return hr; - - EnterCriticalSection(&converter->cs); - - if (converter->output_type) - hr = IMFMediaType_CopyAllItems(converter->output_type, (IMFAttributes *)ret); - else - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - - LeaveCriticalSection(&converter->cs); - - if (SUCCEEDED(hr)) - *type = ret; - else - IMFMediaType_Release(ret); - - return hr; -} - -static HRESULT WINAPI audio_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) -{ - FIXME("%p, %lu, %p.\n", iface, id, flags); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_GetOutputStatus(IMFTransform *iface, DWORD *flags) -{ - FIXME("%p, %p.\n", iface, flags); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) -{ - FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper)); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) -{ - TRACE("%p, %lu, %p.\n", iface, id, event); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) -{ - TRACE("%p, %u, %Iu.\n", iface, message, param); - - switch(message) - { - case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING: - return S_OK; - default: - FIXME("Unhandled message type %x.\n", message); - return E_NOTIMPL; - } -} - -static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) -{ - FIXME("%p, %lu, %p, %#lx.\n", iface, id, sample, flags); - - return E_NOTIMPL; -} - -static HRESULT WINAPI audio_converter_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, - MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) -{ - FIXME("%p, %#lx, %lu, %p, %p.\n", iface, flags, count, samples, status); - - return E_NOTIMPL; -} - -static const IMFTransformVtbl audio_converter_vtbl = -{ - audio_converter_QueryInterface, - audio_converter_AddRef, - audio_converter_Release, - audio_converter_GetStreamLimits, - audio_converter_GetStreamCount, - audio_converter_GetStreamIDs, - audio_converter_GetInputStreamInfo, - audio_converter_GetOutputStreamInfo, - audio_converter_GetAttributes, - audio_converter_GetInputStreamAttributes, - audio_converter_GetOutputStreamAttributes, - audio_converter_DeleteInputStream, - audio_converter_AddInputStreams, - audio_converter_GetInputAvailableType, - audio_converter_GetOutputAvailableType, - audio_converter_SetInputType, - audio_converter_SetOutputType, - audio_converter_GetInputCurrentType, - audio_converter_GetOutputCurrentType, - audio_converter_GetInputStatus, - audio_converter_GetOutputStatus, - audio_converter_SetOutputBounds, - audio_converter_ProcessEvent, - audio_converter_ProcessMessage, - audio_converter_ProcessInput, - audio_converter_ProcessOutput, -}; - -HRESULT audio_converter_create(REFIID riid, void **ret) -{ - struct audio_converter *object; - - TRACE("%s %p\n", debugstr_guid(riid), ret); - - if (!(object = calloc(1, sizeof(*object)))) - return E_OUTOFMEMORY; - - object->IMFTransform_iface.lpVtbl = &audio_converter_vtbl; - object->refcount = 1; - - InitializeCriticalSection(&object->cs); - object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_converter_lock"); - - *ret = &object->IMFTransform_iface; - return S_OK; -} diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index c539084fa89..065849e9a8c 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -139,7 +139,6 @@ HRESULT wg_transform_read_quartz(struct wg_transform *transform, struct wg_sampl HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
HRESULT h264_decoder_create(REFIID riid, void **ret); -HRESULT audio_converter_create(REFIID riid, void **ret);
struct wm_stream { diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index ee0a5d25056..779387009c2 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -397,8 +397,6 @@ failed:
static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
-static const GUID CLSID_WINEAudioConverter = {0x6a170414,0xaad9,0x4693,{0xb8,0x06,0x3a,0x0c,0x47,0xc5,0x70,0xd6}}; - static const struct class_object { const GUID *clsid; @@ -408,7 +406,6 @@ class_objects[] = { { &CLSID_VideoProcessorMFT, &video_processor_create }, { &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create }, - { &CLSID_WINEAudioConverter, &audio_converter_create }, { &CLSID_MSH264DecoderMFT, &h264_decoder_create }, };
@@ -536,16 +533,6 @@ HRESULT mfplat_DllRegisterServer(void) } mfts[] = { - { - CLSID_WINEAudioConverter, - MFT_CATEGORY_AUDIO_EFFECT, - L"Audio Converter", - MFT_ENUM_FLAG_SYNCMFT, - ARRAY_SIZE(resampler_types), - resampler_types, - ARRAY_SIZE(resampler_types), - resampler_types, - }, { CLSID_WMADecMediaObject, MFT_CATEGORY_AUDIO_DECODER, diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index 77a9f801fa3..bed1fc5281a 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -69,12 +69,6 @@ coclass VideoProcessorMFT {} ] coclass GStreamerByteStreamHandler {}
-[ - threading(both), - uuid(6a170414-aad9-4693-b806-3a0c47c570d6) -] -coclass WINEAudioConverter { } - [ threading(both), uuid(2eeb4adf-4578-4d10-bca7-bb955f56320a)
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 42 +- dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/color_convert.c | 606 +++++++++++++++++++ dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/main.c | 50 ++ dlls/winegstreamer/mfplat.c | 60 ++ dlls/winegstreamer/winegstreamer_classes.idl | 6 + 7 files changed, 765 insertions(+), 1 deletion(-) create mode 100644 dlls/winegstreamer/color_convert.c
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 11261342d35..329b770b344 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -8020,14 +8020,17 @@ static void test_color_convert(void) check_interface(transform, &IID_IMFTransform, TRUE); check_interface(transform, &IID_IMediaObject, TRUE); check_interface(transform, &IID_IPropertyStore, TRUE); + todo_wine check_interface(transform, &IID_IMFRealTimeClient, TRUE); /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
/* check default media types */
hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
i = -1; @@ -8041,7 +8044,9 @@ static void test_color_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } + todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr); + todo_wine ok(i == 16, "%lu output media types\n", i);
i = -1; @@ -8063,7 +8068,9 @@ static void test_color_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } + todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr); + todo_wine ok(i == 20, "%lu input media types\n", i);
/* check required output media type attributes */ @@ -8071,18 +8078,22 @@ static void test_color_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 2); for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i) { hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, i + 1); } hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret); @@ -8092,36 +8103,50 @@ static void test_color_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 1); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 2); for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i) { hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, i + 1); } hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
memset(&input_info, 0xcd, sizeof(input_info)); hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + todo_wine ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr); + todo_wine ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); + todo_wine ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags); + todo_wine ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize); + todo_wine ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead); + todo_wine ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
memset(&output_info, 0xcd, sizeof(output_info)); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + todo_wine ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); + todo_wine ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags); + todo_wine ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize); + todo_wine ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA); @@ -8136,10 +8161,13 @@ static void test_color_convert(void) hr = IMFSample_SetSampleDuration(sample, 10000000); ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); + todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0); + todo_wine ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr); IMFSample_Release(sample);
@@ -8147,7 +8175,9 @@ static void test_color_convert(void) ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError()); rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource); + todo_wine ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len); + if (rgb32_data_len != output_info.cbSize) output_info.cbSize = actual_width * actual_height * 4;
/* and generate a new one as well in a temporary directory */ GetTempPathW(ARRAY_SIZE(output_path), output_path); @@ -8160,21 +8190,29 @@ static void test_color_convert(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus); + todo_wine ok(status == 0, "got status %#lx\n", status);
hr = IMFSample_GetSampleTime(sample, &time); + todo_wine ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); + todo_wine ok(time == 0, "got time %I64d\n", time); hr = IMFSample_GetSampleDuration(sample, &duration); + todo_wine ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr); + todo_wine ok(duration == 10000000, "got duration %I64d\n", duration); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); + todo_wine ok(length == output_info.cbSize, "got length %lu\n", length); - check_sample_rgb32(sample, rgb32_data, output_file); + if (length == output_info.cbSize) + check_sample_rgb32(sample, rgb32_data, output_file); rgb32_data_len -= output_info.cbSize; rgb32_data += output_info.cbSize;
@@ -8189,9 +8227,11 @@ static void test_color_convert(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); + todo_wine ok(status == 0, "got status %#lx\n", status); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index e7bffa92df0..462b54f2557 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -7,6 +7,7 @@ EXTRAINCL = $(GSTREAMER_CFLAGS) EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
C_SRCS = \ + color_convert.c \ h264_decoder.c \ main.c \ media_source.c \ diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c new file mode 100644 index 00000000000..8e0db4ac61b --- /dev/null +++ b/dlls/winegstreamer/color_convert.c @@ -0,0 +1,606 @@ +/* Copyright 2022 Rémi Bernon 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 "wmcodecdsp.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); +WINE_DECLARE_DEBUG_CHANNEL(winediag); + +struct color_convert +{ + IUnknown IUnknown_inner; + IMFTransform IMFTransform_iface; + IMediaObject IMediaObject_iface; + IPropertyBag IPropertyBag_iface; + IPropertyStore IPropertyStore_iface; + IUnknown *outer; + LONG refcount; +}; + +static inline struct color_convert *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct color_convert, IUnknown_inner); +} + +static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + struct color_convert *impl = impl_from_IUnknown(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown)) + *out = &impl->IUnknown_inner; + else if (IsEqualGUID(iid, &IID_IMFTransform)) + *out = &impl->IMFTransform_iface; + else if (IsEqualGUID(iid, &IID_IMediaObject)) + *out = &impl->IMediaObject_iface; + else if (IsEqualIID(iid, &IID_IPropertyBag)) + *out = &impl->IPropertyBag_iface; + else if (IsEqualIID(iid, &IID_IPropertyStore)) + *out = &impl->IPropertyStore_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 unknown_AddRef(IUnknown *iface) +{ + struct color_convert *impl = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&impl->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI unknown_Release(IUnknown *iface) +{ + struct color_convert *impl = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&impl->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + free(impl); + + return refcount; +} + +static const IUnknownVtbl unknown_vtbl = +{ + unknown_QueryInterface, + unknown_AddRef, + unknown_Release, +}; + +static struct color_convert *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct color_convert, IMFTransform_iface); +} + +static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); +} + +static ULONG WINAPI transform_AddRef(IMFTransform *iface) +{ + return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); +} + +static ULONG WINAPI transform_Release(IMFTransform *iface) +{ + return IUnknown_Release(impl_from_IMFTransform(iface)->outer); +} + +static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n", + iface, input_minimum, input_maximum, output_minimum, output_maximum); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs); + return E_NOTIMPL; +} + +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 stub!\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 stub!\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 stub!\n", iface, id, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + FIXME("iface %p, attributes %p stub!\n", iface, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + FIXME("iface %p, id %#lx, attributes %p stub!\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 stub!\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + FIXME("iface %p, id %#lx stub!\n", iface, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + FIXME("iface %p, streams %lu, ids %p stub!\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 %lu, type %p stub!\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 %lu, type %p stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 stub!\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 inline struct color_convert *impl_from_IMediaObject(IMediaObject *iface) +{ + return CONTAINING_RECORD(iface, struct color_convert, IMediaObject_iface); +} + +static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj) +{ + return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj); +} + +static ULONG WINAPI media_object_AddRef(IMediaObject *iface) +{ + return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer); +} + +static ULONG WINAPI media_object_Release(IMediaObject *iface) +{ + return IUnknown_Release(impl_from_IMediaObject(iface)->outer); +} + +static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) +{ + FIXME("iface %p, input %p, output %p stub!\n", iface, input, output); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, + DWORD *lookahead, DWORD *alignment) +{ + FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size, + lookahead, alignment); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) +{ + FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) +{ + FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency) +{ + FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Flush(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) +{ + FIXME("iface %p, index %lu stub!\n", iface, index); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, + IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) +{ + FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface, + index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, + DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) +{ + FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock) +{ + FIXME("iface %p, lock %ld stub!\n", iface, lock); + return E_NOTIMPL; +} + +static const IMediaObjectVtbl media_object_vtbl = +{ + media_object_QueryInterface, + media_object_AddRef, + media_object_Release, + media_object_GetStreamCount, + media_object_GetInputStreamInfo, + media_object_GetOutputStreamInfo, + media_object_GetInputType, + media_object_GetOutputType, + media_object_SetInputType, + media_object_SetOutputType, + media_object_GetInputCurrentType, + media_object_GetOutputCurrentType, + media_object_GetInputSizeInfo, + media_object_GetOutputSizeInfo, + media_object_GetInputMaxLatency, + media_object_SetInputMaxLatency, + media_object_Flush, + media_object_Discontinuity, + media_object_AllocateStreamingResources, + media_object_FreeStreamingResources, + media_object_GetInputStatus, + media_object_ProcessInput, + media_object_ProcessOutput, + media_object_Lock, +}; + +static inline struct color_convert *impl_from_IPropertyBag(IPropertyBag *iface) +{ + return CONTAINING_RECORD(iface, struct color_convert, IPropertyBag_iface); +} + +static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out); +} + +static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer); +} + +static ULONG WINAPI property_bag_Release(IPropertyBag *iface) +{ + return IUnknown_Release(impl_from_IPropertyBag(iface)->outer); +} + +static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value, + IErrorLog *error_log) +{ + FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value) +{ + FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value); + return S_OK; +} + +static const IPropertyBagVtbl property_bag_vtbl = +{ + property_bag_QueryInterface, + property_bag_AddRef, + property_bag_Release, + property_bag_Read, + property_bag_Write, +}; + +static inline struct color_convert *impl_from_IPropertyStore(IPropertyStore *iface) +{ + return CONTAINING_RECORD(iface, struct color_convert, IPropertyStore_iface); +} + +static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out); +} + +static ULONG WINAPI property_store_AddRef(IPropertyStore *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer); +} + +static ULONG WINAPI property_store_Release(IPropertyStore *iface) +{ + return IUnknown_Release(impl_from_IPropertyStore(iface)->outer); +} + +static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count) +{ + FIXME("iface %p, count %p stub!\n", iface, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key) +{ + FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_Commit(IPropertyStore *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static const IPropertyStoreVtbl property_store_vtbl = +{ + property_store_QueryInterface, + property_store_AddRef, + property_store_Release, + property_store_GetCount, + property_store_GetAt, + property_store_GetValue, + property_store_SetValue, + property_store_Commit, +}; + +HRESULT color_convert_create(IUnknown *outer, IUnknown **out) +{ + struct color_convert *impl; + + TRACE("outer %p, out %p.\n", outer, out); + + if (!(impl = calloc(1, sizeof(*impl)))) + return E_OUTOFMEMORY; + + impl->IUnknown_inner.lpVtbl = &unknown_vtbl; + impl->IMFTransform_iface.lpVtbl = &transform_vtbl; + impl->IMediaObject_iface.lpVtbl = &media_object_vtbl; + impl->IPropertyBag_iface.lpVtbl = &property_bag_vtbl; + impl->IPropertyStore_iface.lpVtbl = &property_store_vtbl; + impl->refcount = 1; + impl->outer = outer ? outer : &impl->IUnknown_inner; + + *out = &impl->IUnknown_inner; + TRACE("Created %p\n", *out); + return S_OK; +} diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 065849e9a8c..8348d2e8360 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -112,6 +112,7 @@ HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out); HRESULT wave_parser_create(IUnknown *outer, IUnknown **out); HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out); HRESULT resampler_create(IUnknown *outer, IUnknown **out); +HRESULT color_convert_create(IUnknown *outer, IUnknown **out);
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm); bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index fedf4e48538..fc7b9d73285 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -438,6 +438,7 @@ static struct class_factory mpeg_splitter_cf = {{&class_factory_vtbl}, mpeg_spli static struct class_factory wave_parser_cf = {{&class_factory_vtbl}, wave_parser_create}; static struct class_factory wma_decoder_cf = {{&class_factory_vtbl}, wma_decoder_create}; static struct class_factory resampler_cf = {{&class_factory_vtbl}, resampler_create}; +static struct class_factory color_convert_cf = {{&class_factory_vtbl}, color_convert_create};
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) { @@ -466,6 +467,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) factory = &wma_decoder_cf; else if (IsEqualGUID(clsid, &CLSID_CResamplerMediaObject)) factory = &resampler_cf; + else if (IsEqualGUID(clsid, &CLSID_CColorConvertDMO)) + factory = &color_convert_cf; else { FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); @@ -677,6 +680,48 @@ HRESULT WINAPI DllRegisterServer(void) {.type = MEDIATYPE_Audio, .subtype = MEDIASUBTYPE_WMAUDIO3}, {.type = MEDIATYPE_Audio, .subtype = MEDIASUBTYPE_WMAUDIO_LOSSLESS}, }; + DMO_PARTIAL_MEDIATYPE color_convert_input[20] = + { + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YV12}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YUY2}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_UYVY}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_AYUV}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_NV12}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB32}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB565}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_I420}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_IYUV}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YVYU}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB24}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB555}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB8}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_V216}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_V410}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_NV11}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_Y41P}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_Y41T}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_Y42T}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YVU9}, + }; + DMO_PARTIAL_MEDIATYPE color_convert_output[16] = + { + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YV12}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YUY2}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_UYVY}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_AYUV}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_NV12}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB32}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB565}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_I420}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_IYUV}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_YVYU}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB24}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB555}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_RGB8}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_V216}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_V410}, + {.type = MEDIATYPE_Video, .subtype = MEDIASUBTYPE_NV11}, + };
IFilterMapper2 *mapper; HRESULT hr; @@ -707,6 +752,9 @@ HRESULT WINAPI DllRegisterServer(void) if (FAILED(hr = DMORegister(L"Resampler DMO", &CLSID_CResamplerMediaObject, &DMOCATEGORY_AUDIO_EFFECT, 0, ARRAY_SIZE(audio_convert_types), audio_convert_types, ARRAY_SIZE(audio_convert_types), audio_convert_types))) return hr; + if (FAILED(hr = DMORegister(L"Color Converter DMO", &CLSID_CColorConvertDMO, &DMOCATEGORY_VIDEO_EFFECT, + 0, ARRAY_SIZE(color_convert_input), color_convert_input, ARRAY_SIZE(color_convert_output), color_convert_output))) + return hr;
return mfplat_DllRegisterServer(); } @@ -733,6 +781,8 @@ HRESULT WINAPI DllUnregisterServer(void)
IFilterMapper2_Release(mapper);
+ if (FAILED(hr = DMOUnregister(&CLSID_CColorConvertDMO, &DMOCATEGORY_VIDEO_EFFECT))) + return hr; if (FAILED(hr = DMOUnregister(&CLSID_CResamplerMediaObject, &DMOCATEGORY_AUDIO_EFFECT))) return hr; if (FAILED(hr = DMOUnregister(&CLSID_WMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER))) diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 779387009c2..33557211243 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -23,6 +23,7 @@ #include "ksmedia.h" #include "wmcodecdsp.h" #include "initguid.h" +#include "d3d9types.h" #include "mfapi.h"
#include "wine/debug.h" @@ -30,6 +31,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+DEFINE_GUID(DMOVideoFormat_RGB32,D3DFMT_X8R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70); +DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70); +DEFINE_GUID(DMOVideoFormat_RGB565,D3DFMT_R5G6B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70); +DEFINE_GUID(DMOVideoFormat_RGB555,D3DFMT_X1R5G5B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70); +DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70); + struct video_processor { IMFTransform IMFTransform_iface; @@ -520,6 +527,49 @@ HRESULT mfplat_DllRegisterServer(void) {MFMediaType_Video, MFVideoFormat_YVYU}, };
+ MFT_REGISTER_TYPE_INFO color_convert_input_types[] = + { + {MFMediaType_Video, MFVideoFormat_YV12}, + {MFMediaType_Video, MFVideoFormat_YUY2}, + {MFMediaType_Video, MFVideoFormat_UYVY}, + {MFMediaType_Video, MFVideoFormat_AYUV}, + {MFMediaType_Video, MFVideoFormat_NV12}, + {MFMediaType_Video, DMOVideoFormat_RGB32}, + {MFMediaType_Video, DMOVideoFormat_RGB565}, + {MFMediaType_Video, MFVideoFormat_I420}, + {MFMediaType_Video, MFVideoFormat_IYUV}, + {MFMediaType_Video, MFVideoFormat_YVYU}, + {MFMediaType_Video, DMOVideoFormat_RGB24}, + {MFMediaType_Video, DMOVideoFormat_RGB555}, + {MFMediaType_Video, DMOVideoFormat_RGB8}, + {MFMediaType_Video, MEDIASUBTYPE_V216}, + {MFMediaType_Video, MEDIASUBTYPE_V410}, + {MFMediaType_Video, MFVideoFormat_NV11}, + {MFMediaType_Video, MFVideoFormat_Y41P}, + {MFMediaType_Video, MFVideoFormat_Y41T}, + {MFMediaType_Video, MFVideoFormat_Y42T}, + {MFMediaType_Video, MFVideoFormat_YVU9}, + }; + MFT_REGISTER_TYPE_INFO color_convert_output_types[] = + { + {MFMediaType_Video, MFVideoFormat_YV12}, + {MFMediaType_Video, MFVideoFormat_YUY2}, + {MFMediaType_Video, MFVideoFormat_UYVY}, + {MFMediaType_Video, MFVideoFormat_AYUV}, + {MFMediaType_Video, MFVideoFormat_NV12}, + {MFMediaType_Video, DMOVideoFormat_RGB32}, + {MFMediaType_Video, DMOVideoFormat_RGB565}, + {MFMediaType_Video, MFVideoFormat_I420}, + {MFMediaType_Video, MFVideoFormat_IYUV}, + {MFMediaType_Video, MFVideoFormat_YVYU}, + {MFMediaType_Video, DMOVideoFormat_RGB24}, + {MFMediaType_Video, DMOVideoFormat_RGB555}, + {MFMediaType_Video, DMOVideoFormat_RGB8}, + {MFMediaType_Video, MEDIASUBTYPE_V216}, + {MFMediaType_Video, MEDIASUBTYPE_V410}, + {MFMediaType_Video, MFVideoFormat_NV11}, + }; + struct mft { GUID clsid; @@ -573,6 +623,16 @@ HRESULT mfplat_DllRegisterServer(void) ARRAY_SIZE(resampler_types), resampler_types, }, + { + CLSID_CColorConvertDMO, + MFT_CATEGORY_VIDEO_EFFECT, + L"Color Converter MFT", + MFT_ENUM_FLAG_SYNCMFT, + ARRAY_SIZE(color_convert_input_types), + color_convert_input_types, + ARRAY_SIZE(color_convert_output_types), + color_convert_output_types, + }, };
unsigned int i; diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index bed1fc5281a..c95f4135835 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -86,3 +86,9 @@ coclass CMSH264DecoderMFT {} uuid(f447b69e-1884-4a7e-8055-346f74d6edb3) ] coclass CResamplerMediaObject {} + +[ + threading(both), + uuid(98230571-0087-4204-b020-3282538e57d3) +] +coclass CColorConvertDMO {}
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=117133
Your paranoid android.
=== w1064v1809 (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== w1064_adm (testbot log) ===
WineRunTask.pl:error: The previous 2 run(s) terminated abnormally
=== w10pro64_zh_CN (testbot log) ===
WineRunTask.pl:error: The previous 2 run(s) terminated abnormally
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39699 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39789 bytes)
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 41 +-- dlls/winegstreamer/color_convert.c | 422 +++++++++++++++++++++++++++-- dlls/winegstreamer/wg_transform.c | 2 +- 3 files changed, 398 insertions(+), 67 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 329b770b344..2f3ee3151da 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -8027,10 +8027,8 @@ static void test_color_convert(void) /* check default media types */
hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
i = -1; @@ -8044,9 +8042,7 @@ static void test_color_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr); - todo_wine ok(i == 16, "%lu output media types\n", i);
i = -1; @@ -8068,9 +8064,7 @@ static void test_color_convert(void) ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); } - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr); - todo_wine ok(i == 20, "%lu input media types\n", i);
/* check required output media type attributes */ @@ -8078,22 +8072,18 @@ static void test_color_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, 2); for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i) { hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr); init_media_type(media_type, output_type_desc, i + 1); } hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret); @@ -8103,50 +8093,36 @@ static void test_color_convert(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 1); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, 2); for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i) { hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr); init_media_type(media_type, input_type_desc, i + 1); } hr = IMFTransform_SetInputType(transform, 0, media_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
memset(&input_info, 0xcd, sizeof(input_info)); hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); - todo_wine ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr); - todo_wine ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); - todo_wine ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags); - todo_wine ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize); - todo_wine ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead); - todo_wine ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
memset(&output_info, 0xcd, sizeof(output_info)); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); - todo_wine ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); - todo_wine ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags); - todo_wine ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize); - todo_wine ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA); @@ -8161,13 +8137,10 @@ static void test_color_convert(void) hr = IMFSample_SetSampleDuration(sample, 10000000); ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0); - todo_wine ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr); IMFSample_Release(sample);
@@ -8175,9 +8148,7 @@ static void test_color_convert(void) ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError()); rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource); - todo_wine ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len); - if (rgb32_data_len != output_info.cbSize) output_info.cbSize = actual_width * actual_height * 4;
/* and generate a new one as well in a temporary directory */ GetTempPathW(ARRAY_SIZE(output_path), output_path); @@ -8190,29 +8161,21 @@ static void test_color_convert(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status);
hr = IMFSample_GetSampleTime(sample, &time); - todo_wine ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); - todo_wine ok(time == 0, "got time %I64d\n", time); hr = IMFSample_GetSampleDuration(sample, &duration); - todo_wine ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr); - todo_wine ok(duration == 10000000, "got duration %I64d\n", duration); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); - todo_wine ok(length == output_info.cbSize, "got length %lu\n", length); - if (length == output_info.cbSize) - check_sample_rgb32(sample, rgb32_data, output_file); + check_sample_rgb32(sample, rgb32_data, output_file); rgb32_data_len -= output_info.cbSize; rgb32_data += output_info.cbSize;
@@ -8227,11 +8190,9 @@ static void test_color_convert(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status); hr = IMFSample_GetTotalLength(sample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index 8e0db4ac61b..66a86aa4602 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -28,6 +28,49 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DECLARE_DEBUG_CHANNEL(winediag);
+static const GUID *const input_types[] = +{ + &MFVideoFormat_YV12, + &MFVideoFormat_YUY2, + &MFVideoFormat_UYVY, + &MFVideoFormat_AYUV, + &MFVideoFormat_NV12, + &MFVideoFormat_RGB32, + &MFVideoFormat_RGB565, + &MFVideoFormat_I420, + &MFVideoFormat_IYUV, + &MFVideoFormat_YVYU, + &MFVideoFormat_RGB24, + &MFVideoFormat_RGB555, + &MEDIASUBTYPE_RGB8, + &MEDIASUBTYPE_V216, + &MEDIASUBTYPE_V410, + &MFVideoFormat_NV11, + &MFVideoFormat_Y41P, + &MFVideoFormat_Y41T, + &MFVideoFormat_Y42T, + &MFVideoFormat_YVU9, +}; +static const GUID *const output_types[] = +{ + &MFVideoFormat_YV12, + &MFVideoFormat_YUY2, + &MFVideoFormat_UYVY, + &MFVideoFormat_AYUV, + &MFVideoFormat_NV12, + &MFVideoFormat_RGB32, + &MFVideoFormat_RGB565, + &MFVideoFormat_I420, + &MFVideoFormat_IYUV, + &MFVideoFormat_YVYU, + &MFVideoFormat_RGB24, + &MFVideoFormat_RGB555, + &MEDIASUBTYPE_RGB8, + &MEDIASUBTYPE_V216, + &MEDIASUBTYPE_V410, + &MFVideoFormat_NV11, +}; + struct color_convert { IUnknown IUnknown_inner; @@ -37,6 +80,11 @@ struct color_convert IPropertyStore IPropertyStore_iface; IUnknown *outer; LONG refcount; + IMFMediaType *input_type; + IMFMediaType *output_type; + + struct wg_transform *wg_transform; + struct wg_sample_queue *wg_sample_queue; };
static inline struct color_convert *impl_from_IUnknown(IUnknown *iface) @@ -44,6 +92,28 @@ static inline struct color_convert *impl_from_IUnknown(IUnknown *iface) return CONTAINING_RECORD(iface, struct color_convert, IUnknown_inner); }
+static HRESULT try_create_wg_transform(struct color_convert *impl) +{ + struct wg_format input_format, output_format; + + if (impl->wg_transform) + wg_transform_destroy(impl->wg_transform); + impl->wg_transform = NULL; + + mf_media_type_to_wg_format(impl->input_type, &input_format); + if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return MF_E_INVALIDMEDIATYPE; + + mf_media_type_to_wg_format(impl->output_type, &output_format); + if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return MF_E_INVALIDMEDIATYPE; + + if (!(impl->wg_transform = wg_transform_create(&input_format, &output_format))) + return E_FAIL; + + return S_OK; +} + static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) { struct color_convert *impl = impl_from_IUnknown(iface); @@ -89,7 +159,17 @@ static ULONG WINAPI unknown_Release(IUnknown *iface) TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
if (!refcount) + { + if (impl->wg_transform) + wg_transform_destroy(impl->wg_transform); + if (impl->input_type) + IMFMediaType_Release(impl->input_type); + if (impl->output_type) + IMFMediaType_Release(impl->output_type); + + wg_sample_queue_destroy(impl->wg_sample_queue); free(impl); + }
return refcount; } @@ -124,15 +204,17 @@ static ULONG WINAPI transform_Release(IMFTransform *iface) static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) { - FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n", + 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); - return E_NOTIMPL; + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + return S_OK; }
static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) { - FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs); - return E_NOTIMPL; + 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, @@ -145,14 +227,56 @@ static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_si
static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) { - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + UINT32 sample_size; + UINT64 framesize; + GUID subtype; + HRESULT hr; + + TRACE("iface %p, id %#lx, info %p.\n", iface, id, info); + + if (!impl->input_type || !impl->output_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (SUCCEEDED(hr = IMFMediaType_GetGUID(impl->input_type, &MF_MT_SUBTYPE, &subtype)) && + SUCCEEDED(hr = IMFMediaType_GetUINT64(impl->input_type, &MF_MT_FRAME_SIZE, &framesize))) + MFCalculateImageSize(&subtype, framesize >> 32, (UINT32)framesize, &sample_size); + else + sample_size = 0; + + info->dwFlags = 0; + info->cbSize = sample_size; + info->cbAlignment = 1; + info->hnsMaxLatency = 0; + info->cbMaxLookahead = 0; + + return S_OK; }
static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) { - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + UINT32 sample_size; + UINT64 framesize; + GUID subtype; + HRESULT hr; + + TRACE("iface %p, id %#lx, info %p.\n", iface, id, info); + + if (!impl->input_type || !impl->output_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (SUCCEEDED(hr = IMFMediaType_GetGUID(impl->output_type, &MF_MT_SUBTYPE, &subtype)) && + SUCCEEDED(hr = IMFMediaType_GetUINT64(impl->output_type, &MF_MT_FRAME_SIZE, &framesize))) + MFCalculateImageSize(&subtype, framesize >> 32, (UINT32)framesize, &sample_size); + else + sample_size = 0; + + info->dwFlags = 0; + info->cbSize = sample_size; + info->cbAlignment = 1; + + return S_OK; }
static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) @@ -164,7 +288,7 @@ static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) { FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes); - return E_NOTIMPL; + return MFCreateAttributes(attributes, 0); }
static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) @@ -188,39 +312,195 @@ static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD strea static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; + IMFMediaType *media_type; + const GUID *subtype; + HRESULT hr; + + TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type); + + *type = NULL; + + if (index >= ARRAY_SIZE(input_types)) + return MF_E_NO_MORE_TYPES; + subtype = input_types[index]; + + if (FAILED(hr = MFCreateMediaType(&media_type))) + return hr; + + if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video))) + goto done; + if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1))) + goto done; + + IMFMediaType_AddRef((*type = media_type)); + +done: + IMFMediaType_Release(media_type); + return hr; }
static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; + IMFMediaType *media_type; + const GUID *subtype; + HRESULT hr; + + TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type); + + *type = NULL; + + if (index >= ARRAY_SIZE(output_types)) + return MF_E_NO_MORE_TYPES; + subtype = output_types[index]; + + if (FAILED(hr = MFCreateMediaType(&media_type))) + return hr; + + if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video))) + goto done; + if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1))) + goto done; + + IMFMediaType_AddRef((*type = media_type)); + +done: + IMFMediaType_Release(media_type); + return hr; }
static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + MF_ATTRIBUTE_TYPE item_type; + GUID major, subtype; + HRESULT hr; + ULONG i; + + TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags); + + if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) || + FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) + return MF_E_ATTRIBUTENOTFOUND; + + if (!IsEqualGUID(&major, &MFMediaType_Video) + || FAILED(IMFMediaType_GetItemType(type, &MF_MT_FRAME_SIZE, &item_type)) + || item_type != MF_ATTRIBUTE_UINT64) + return E_INVALIDARG; + + for (i = 0; i < ARRAY_SIZE(input_types); ++i) + if (IsEqualGUID(&subtype, input_types[i])) + break; + if (i == ARRAY_SIZE(input_types)) + return MF_E_INVALIDMEDIATYPE; + + if (!impl->input_type && FAILED(hr = MFCreateMediaType(&impl->input_type))) + return hr; + + if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->input_type))) + { + IMFMediaType_Release(impl->input_type); + impl->input_type = NULL; + } + + if (impl->output_type && FAILED(hr = try_create_wg_transform(impl))) + { + IMFMediaType_Release(impl->input_type); + impl->input_type = NULL; + } + + return hr; }
static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + MF_ATTRIBUTE_TYPE item_type; + GUID major, subtype; + HRESULT hr; + ULONG i; + + TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags); + + if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) || + FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) + return MF_E_ATTRIBUTENOTFOUND; + + if (!IsEqualGUID(&major, &MFMediaType_Video) + || FAILED(IMFMediaType_GetItemType(type, &MF_MT_FRAME_SIZE, &item_type)) + || item_type != MF_ATTRIBUTE_UINT64) + return E_INVALIDARG; + + for (i = 0; i < ARRAY_SIZE(output_types); ++i) + if (IsEqualGUID(&subtype, output_types[i])) + break; + if (i == ARRAY_SIZE(output_types)) + return MF_E_INVALIDMEDIATYPE; + + if (!impl->output_type && FAILED(hr = MFCreateMediaType(&impl->output_type))) + return hr; + + if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->output_type))) + { + IMFMediaType_Release(impl->output_type); + impl->output_type = NULL; + } + + if (impl->input_type && FAILED(hr = try_create_wg_transform(impl))) + { + IMFMediaType_Release(impl->output_type); + impl->output_type = NULL; + } + + return hr; }
static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + IMFMediaType *ret; + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p.\n", iface, id, type); + + if (id != 0) + return MF_E_INVALIDSTREAMNUMBER; + + if (!impl->input_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(&ret))) + return hr; + + return IMFMediaType_CopyAllItems(impl->input_type, (IMFAttributes *)ret); }
static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + IMFMediaType *ret; + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p.\n", iface, id, type); + + if (id != 0) + return MF_E_INVALIDSTREAMNUMBER; + + if (!impl->output_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(&ret))) + return hr; + + return IMFMediaType_CopyAllItems(impl->output_type, (IMFAttributes *)ret); }
static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) @@ -250,20 +530,75 @@ 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 stub!\n", iface, message, param); - return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { - FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + struct wg_sample *wg_sample; + MFT_INPUT_STREAM_INFO info; + HRESULT hr; + + TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags); + + if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info))) + return hr; + + if (!impl->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = wg_sample_create_mf(sample, &wg_sample))) + return hr; + + return wg_transform_push_mf(impl->wg_transform, wg_sample, + impl->wg_sample_queue); }
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 stub!\n", iface, flags, count, samples, status); - return E_NOTIMPL; + struct color_convert *impl = impl_from_IMFTransform(iface); + MFT_OUTPUT_STREAM_INFO info; + struct wg_sample *wg_sample; + HRESULT hr; + + TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); + + if (count != 1) + return E_INVALIDARG; + + if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) + return hr; + + if (!impl->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + *status = 0; + samples[0].dwStatus = 0; + if (!samples[0].pSample) return E_INVALIDARG; + + if (FAILED(hr = wg_sample_create_mf(samples[0].pSample, &wg_sample))) + return hr; + + if (wg_sample->max_size < info.cbSize) + { + wg_sample_release(wg_sample); + return MF_E_BUFFERTOOSMALL; + } + + if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, wg_sample, NULL))) + wg_sample_queue_flush(impl->wg_sample_queue, false); + wg_sample_release(wg_sample); + + if (hr == MF_E_TRANSFORM_STREAM_CHANGE) + { + FIXME("Unexpected stream format change!\n"); + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + } + + return hr; }
static const IMFTransformVtbl transform_vtbl = @@ -585,13 +920,48 @@ static const IPropertyStoreVtbl property_store_vtbl =
HRESULT color_convert_create(IUnknown *outer, IUnknown **out) { + static const struct wg_format input_format = + { + .major_type = WG_MAJOR_TYPE_VIDEO, + .u.video = + { + .format = WG_VIDEO_FORMAT_I420, + .width = 1920, + .height = 1080, + }, + }; + static const struct wg_format output_format = + { + .major_type = WG_MAJOR_TYPE_VIDEO, + .u.video = + { + .format = WG_VIDEO_FORMAT_NV12, + .width = 1920, + .height = 1080, + }, + }; + struct wg_transform *transform; struct color_convert *impl; + HRESULT hr;
TRACE("outer %p, out %p.\n", outer, out);
+ if (!(transform = wg_transform_create(&input_format, &output_format))) + { + ERR_(winediag)("GStreamer doesn't support video conversion, please install appropriate plugins.\n"); + return E_FAIL; + } + wg_transform_destroy(transform); + if (!(impl = calloc(1, sizeof(*impl)))) return E_OUTOFMEMORY;
+ if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue))) + { + free(impl); + return hr; + } + impl->IUnknown_inner.lpVtbl = &unknown_vtbl; impl->IMFTransform_iface.lpVtbl = &transform_vtbl; impl->IMediaObject_iface.lpVtbl = &media_object_vtbl; diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 46725712aca..e05432f6ac7 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -406,8 +406,8 @@ NTSTATUS wg_transform_create(void *args) break;
case WG_MAJOR_TYPE_AUDIO: - break; case WG_MAJOR_TYPE_VIDEO: + break; case WG_MAJOR_TYPE_UNKNOWN: GST_FIXME("Format %u not implemented!", input_format.major_type); gst_caps_unref(raw_caps);
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=117134
Your paranoid android.
=== w7u_2qxl (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== w1064v1809 (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== w10pro64_zh_CN (testbot log) ===
WineRunTask.pl:error: The previous 2 run(s) terminated abnormally
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39779 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39711 bytes)