From 2a57854c6a32dee57904b87c73982d12daca656d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Fri, 12 Aug 2022 09:52:53 +0200 Subject: [PATCH] winegstreamer: Register AAC decoder MFT stub. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 --- MAINTAINERS | 1 + dlls/mf/tests/transform.c | 9 + dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/aac_decoder.c | 276 +++++++++++++++++++ dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/mfplat.c | 24 ++ dlls/winegstreamer/winegstreamer_classes.idl | 6 + 7 files changed, 318 insertions(+) create mode 100644 dlls/winegstreamer/aac_decoder.c diff --git a/MAINTAINERS b/MAINTAINERS index 4f0cd37ad5d..73c2a486a91 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -207,6 +207,7 @@ M: Rémi Bernon P: Nikolay Sivov P: Zebediah Figura F: dlls/mf/tests/transform.c +F: dlls/winegstreamer/aac_decoder.c F: dlls/winegstreamer/color_convert.c F: dlls/winegstreamer/h264_decoder.c F: dlls/winegstreamer/resampler.c diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index e66baa6e7c9..5ee181e5b0f 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -327,6 +327,7 @@ static void check_mft_get_attributes(IMFTransform *transform, const struct attri ULONG ref; hr = IMFTransform_GetAttributes(transform, &attributes); + todo_wine_if(expect_transform_attributes && hr == E_NOTIMPL) ok(hr == (expect_transform_attributes ? S_OK : E_NOTIMPL), "GetAttributes returned %#lx\n", hr); if (hr == S_OK) { @@ -1940,10 +1941,13 @@ static void test_aac_decoder(void) check_mft_optional_methods(transform, 1); check_mft_get_attributes(transform, expect_transform_attributes, FALSE); + todo_wine check_mft_get_input_stream_info(transform, S_OK, &input_info); + todo_wine check_mft_get_output_stream_info(transform, S_OK, &output_info); hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type); + todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr); i = -1; @@ -1957,10 +1961,14 @@ static void test_aac_decoder(void) ok(ret <= 1, "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 == ARRAY_SIZE(expect_available_inputs) || broken(i == 2) /* w7 */ || broken(i == 4) /* w8 */, "%lu input media types\n", i); + if (hr == E_NOTIMPL) + goto skip_tests; /* setting output media type first doesn't work */ check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET); @@ -2053,6 +2061,7 @@ static void test_aac_decoder(void) ret = IMFSample_Release(input_sample); ok(ret == 0, "Release returned %lu\n", ret); +skip_tests: ret = IMFTransform_Release(transform); ok(ret == 0, "Release returned %lu\n", ret); diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 2245500f0c3..abb11591996 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -7,6 +7,7 @@ UNIX_CFLAGS = $(GSTREAMER_CFLAGS) UNIX_LIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS) C_SRCS = \ + aac_decoder.c \ color_convert.c \ h264_decoder.c \ main.c \ diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c new file mode 100644 index 00000000000..5573166b2db --- /dev/null +++ b/dlls/winegstreamer/aac_decoder.c @@ -0,0 +1,276 @@ +/* AAC Decoder Transform + * + * 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); + +struct aac_decoder +{ + IMFTransform IMFTransform_iface; + LONG refcount; +}; + +static struct aac_decoder *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct aac_decoder, IMFTransform_iface); +} + +static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + struct aac_decoder *decoder = impl_from_IMFTransform(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IMFTransform)) + *out = &decoder->IMFTransform_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI transform_AddRef(IMFTransform *iface) +{ + struct aac_decoder *decoder = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&decoder->refcount); + TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); + return refcount; +} + +static ULONG WINAPI transform_Release(IMFTransform *iface) +{ + struct aac_decoder *decoder = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&decoder->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); + + if (!refcount) + free(decoder); + + return refcount; +} + +static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n", + iface, input_minimum, input_maximum, output_minimum, output_maximum); + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + return S_OK; +} + +static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs); + *inputs = *outputs = 1; + return S_OK; +} + +static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface, + input_size, inputs, output_size, outputs); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + FIXME("iface %p, id %#lx, info %p 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) +{ + TRACE("iface %p, attributes %p.\n", iface, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + TRACE("iface %p, id %#lx.\n", iface, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + TRACE("iface %p, streams %lu, ids %p.\n", iface, streams, ids); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + FIXME("iface %p, id %#lx, index %#lx, type %p 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 %#lx, 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) +{ + TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event); + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + FIXME("iface %p, message %#x, param %p stub!\n", iface, message, (void *)param); + 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; +} + +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, +}; + +HRESULT aac_decoder_create(REFIID riid, void **ret) +{ + struct aac_decoder *decoder; + + TRACE("riid %s, ret %p.\n", debugstr_guid(riid), ret); + + if (!(decoder = calloc(1, sizeof(*decoder)))) + return E_OUTOFMEMORY; + + decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; + decoder->refcount = 1; + + *ret = &decoder->IMFTransform_iface; + TRACE("Created decoder %p\n", *ret); + return S_OK; +} diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 0206e9bc0c0..c38aaaef6d2 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -140,6 +140,7 @@ HRESULT wg_transform_read_quartz(struct wg_transform *transform, struct wg_sampl HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj); +HRESULT aac_decoder_create(REFIID riid, void **ret); HRESULT h264_decoder_create(REFIID riid, void **ret); HRESULT video_processor_create(REFIID riid, void **ret); diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 7e83d570f06..997521768a6 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -36,6 +36,7 @@ DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20 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); +DEFINE_MEDIATYPE_GUID(MFAudioFormat_RAW_AAC,WAVE_FORMAT_RAW_AAC1); struct class_factory { @@ -124,6 +125,7 @@ class_objects[] = { { &CLSID_VideoProcessorMFT, &video_processor_create }, { &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create }, + { &CLSID_MSAACDecMFT, &aac_decoder_create }, { &CLSID_MSH264DecoderMFT, &h264_decoder_create }, }; @@ -161,6 +163,18 @@ HRESULT mfplat_DllRegisterServer(void) {MFMediaType_Audio, MFAudioFormat_Float}, }; + MFT_REGISTER_TYPE_INFO aac_decoder_input_types[] = + { + {MFMediaType_Audio, MFAudioFormat_AAC}, + {MFMediaType_Audio, MFAudioFormat_RAW_AAC}, + {MFMediaType_Audio, MFAudioFormat_ADTS}, + }; + MFT_REGISTER_TYPE_INFO aac_decoder_output_types[] = + { + {MFMediaType_Audio, MFAudioFormat_Float}, + {MFMediaType_Audio, MFAudioFormat_PCM}, + }; + MFT_REGISTER_TYPE_INFO wma_decoder_input_types[] = { {MFMediaType_Audio, MEDIASUBTYPE_MSAUDIO1}, @@ -294,6 +308,16 @@ HRESULT mfplat_DllRegisterServer(void) } mfts[] = { + { + CLSID_MSAACDecMFT, + MFT_CATEGORY_AUDIO_DECODER, + L"Microsoft AAC Audio Decoder MFT", + MFT_ENUM_FLAG_SYNCMFT, + ARRAY_SIZE(aac_decoder_input_types), + aac_decoder_input_types, + ARRAY_SIZE(aac_decoder_output_types), + aac_decoder_output_types, + }, { CLSID_WMADecMediaObject, MFT_CATEGORY_AUDIO_DECODER, diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index c95f4135835..0bb88d9cd08 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -75,6 +75,12 @@ coclass GStreamerByteStreamHandler {} ] coclass CWMADecMediaObject {}; +[ + threading(both), + uuid(32d186a7-218f-4c75-8876-dd77273a8999) +] +coclass CMSAACDecMFT {} + [ threading(both), uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)