Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
December 2020
- 68 participants
- 931 messages
Re: [PATCH v3 07/12] winegstreamer: Implement ::SetInputType for audio conversion transform.
by Zebediah Figura (she/her)
On 12/2/20 1:54 PM, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
> ---
> v3: Factor out update_pipeline_state.
> ---
> dlls/winegstreamer/audioconvert.c | 70 ++++++++++++++++++++++++++++++-
> 1 file changed, 68 insertions(+), 2 deletions(-)
>
> diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
> index 1174f9df0db..82756281aa9 100644
> --- a/dlls/winegstreamer/audioconvert.c
> +++ b/dlls/winegstreamer/audioconvert.c
> @@ -1,4 +1,5 @@
> #include "config.h"
> +#include <gst/gst.h>
>
> #include "gst_private.h"
>
> @@ -17,6 +18,8 @@ struct audio_converter
> {
> IMFTransform IMFTransform_iface;
> LONG refcount;
> + IMFMediaType *input_type;
> + CRITICAL_SECTION cs;
> };
>
> static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
> @@ -60,6 +63,7 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
>
> if (!refcount)
> {
> + DeleteCriticalSection(&transform->cs);
> heap_free(transform);
> }
>
You also need to reset the CS debug info to 0 before destroying it.
> @@ -251,9 +255,68 @@ fail:
>
> static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
> {
> - FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
> + GstCaps *input_caps;
> + HRESULT hr;
>
> - return E_NOTIMPL;
> + struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
> +
> + TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
> +
> + if (id != 0)
> + return MF_E_INVALIDSTREAMNUMBER;
> +
> + if (type)
> + {
> + GUID major_type, subtype;
> + DWORD unused;
> +
> + 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 (!(input_caps = caps_from_mf_media_type(type)))
> + return MF_E_INVALIDTYPE;
> +
> + gst_caps_unref(input_caps);
> + }
> +
> + if (flags & MFT_SET_TYPE_TEST_ONLY)
> + return S_OK;
> +
> + EnterCriticalSection(&converter->cs);
> +
> + hr = S_OK;
> +
> + if (type)
> + {
> + if (!converter->input_type)
> + hr = MFCreateMediaType(&converter->input_type);
> +
> + if (SUCCEEDED(hr))
> + hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
> + }
> + if (converter->input_type && (!type || FAILED(hr)))
This condition feels more than a little confusing; I don't think it's
worth it just to save a couple lines.
> + {
> + 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)
> @@ -376,6 +439,9 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
> 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;
> }
>
Dec. 2, 2020
Re: [PATCH v3 01/12] winegstreamer: Utilize gst_audio_info_to_caps for media type translation.
by Derek Lesho
On 12/2/20 3:39 PM, Zebediah Figura (she/her) wrote:
> "rate" and "channels" are already set by gst_audio_info_to_caps().
Yeah, the reason I have them here is that future patches I have convert
from compressed audio types, which I don't think can use
gst_audio_info_to_caps, so I reset it after the subtype specific section
of the function. Should I remove this until those patches?
>
>
>> - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
>> - {
>> + if (channel_mask != -1)
>> gst_caps_set_simple(output, "channel-mask", GST_TYPE_BITMASK, (guint64) channel_mask, NULL);
>> - }
>> -
>> - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate)))
>> - {
>> + if (bitrate != -1)
>> gst_caps_set_simple(output, "bitrate", G_TYPE_INT, bitrate, NULL);
>> - }
>>
>> return output;
>> }
>>
> I only just now notice this, but MF_MT_AVG_BITRATE is a video type
> attribute, not an audio type attribute; I suspect it should be removed
> from this function...
Good catch, if you think I should keep rate and channels manually set, I
guess I would just use MF_MT_AUDIO_AVG_BYTES_PER_SECOND instead. If
not, I'll just remove this one too.
Dec. 2, 2020
Re: [PATCH v3 03/12] winegstreamer: Introduce audio conversion transform.
by Zebediah Figura (she/her)
On 12/2/20 1:54 PM, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
> ---
> v3: Split up patch.
> ---
> dlls/winegstreamer/Makefile.in | 1 +
> dlls/winegstreamer/audioconvert.c | 285 +++++++++++++++++++
> dlls/winegstreamer/gst_private.h | 2 +
> dlls/winegstreamer/mfplat.c | 28 +-
> dlls/winegstreamer/winegstreamer_classes.idl | 6 +
> 5 files changed, 320 insertions(+), 2 deletions(-)
> create mode 100644 dlls/winegstreamer/audioconvert.c
>
> diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
> index e578d194f7f..0b3229160b9 100644
> --- a/dlls/winegstreamer/Makefile.in
> +++ b/dlls/winegstreamer/Makefile.in
> @@ -6,6 +6,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
> PARENTSRC = ../strmbase
>
> C_SRCS = \
> + audioconvert.c \
> filter.c \
> gst_cbs.c \
> gstdemux.c \
> diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
> new file mode 100644
> index 00000000000..35b984618de
> --- /dev/null
> +++ b/dlls/winegstreamer/audioconvert.c
> @@ -0,0 +1,285 @@
> +#include "config.h"
> +
> +#include "gst_private.h"
> +
> +#include "mfapi.h"
> +#include "mferror.h"
> +#include "mfidl.h"
> +#include "ks.h"
> +#include "ksmedia.h"
> +
> +#include "wine/debug.h"
> +#include "wine/heap.h"
> +
> +WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
> +
> +struct audio_converter
> +{
> + IMFTransform IMFTransform_iface;
> + LONG refcount;
> +};
> +
> +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 %u.\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 %u.\n", iface, refcount);
> +
> + if (!refcount)
> + {
> + heap_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 %u %p %u %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 %u %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 %u %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, %u, %p.\n", iface, id, attributes);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
> + IMFAttributes **attributes)
> +{
> + FIXME("%p, %u, %p.\n", iface, id, attributes);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
> +{
> + TRACE("%p, %u.\n", iface, id);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
> +{
> + TRACE("%p, %u, %p.\n", iface, streams, ids);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
> + IMFMediaType **type)
> +{
> + FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
> + IMFMediaType **type)
> +{
> + FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
> +{
> + FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
> +{
> + FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
> +{
> + FIXME("%p, %u, %p.\n", iface, id, type);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
> +{
> + FIXME("%p, %u, %p.\n", iface, id, type);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
> +{
> + FIXME("%p, %u, %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, %u, %p.\n", iface, id, event);
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
> +{
> + FIXME("%p, %u.\n", iface, message);
"param" isn't traced here; I'm not sure if that was intentional.
> +
> + return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
> +{
> + FIXME("%p, %u, %p, %#x.\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, %#x, %u, %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 = heap_alloc_zero(sizeof(*object))))
> + return E_OUTOFMEMORY;
> +
> + object->IMFTransform_iface.lpVtbl = &audio_converter_vtbl;
> + object->refcount = 1;
> +
> + *ret = &object->IMFTransform_iface;
> + return S_OK;
> +}
> diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
> index 9752b242ad6..9518f721504 100644
> --- a/dlls/winegstreamer/gst_private.h
> +++ b/dlls/winegstreamer/gst_private.h
> @@ -85,4 +85,6 @@ IMFSample *mf_sample_from_gst_buffer(GstBuffer *in) DECLSPEC_HIDDEN;
>
> HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
>
> +HRESULT audio_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
> +
> #endif /* __GST_PRIVATE_INCLUDED__ */
> diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
> index 9d5a7e0427e..833cd202a64 100644
> --- a/dlls/winegstreamer/mfplat.c
> +++ b/dlls/winegstreamer/mfplat.c
> @@ -405,6 +405,8 @@ 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}};
> +
This comment seems to have been overlooked from the last revision:
Why not CLSID_CResamplerMediaObject? In fact, we already have one
application that needs it (bug 47781).
> static const struct class_object
> {
> const GUID *clsid;
> @@ -414,6 +416,7 @@ class_objects[] =
> {
> { &CLSID_VideoProcessorMFT, &video_processor_create },
> { &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
> + { &CLSID_WINEAudioConverter, &audio_converter_create },
> };
>
> HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
> @@ -442,6 +445,13 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
> return CLASS_E_CLASSNOTAVAILABLE;
> }
>
> +static WCHAR audio_converterW[] = {'A','u','d','i','o',' ','C','o','n','v','e','r','t','e','r',0};
> +static const GUID *audio_converter_supported_types[] =
> +{
> + &MFAudioFormat_PCM,
> + &MFAudioFormat_Float,
> +};
> +
> static const struct mft
> {
> const GUID *clsid;
> @@ -455,13 +465,27 @@ static const struct mft
> const GUID **output_types;
> IMFAttributes *attributes;
> }
> -mfts[] = {};
> +mfts[] =
> +{
> + {
> + &CLSID_WINEAudioConverter,
> + &MFT_CATEGORY_AUDIO_EFFECT,
> + audio_converterW,
> + MFT_ENUM_FLAG_SYNCMFT,
> + &MFMediaType_Audio,
> + ARRAY_SIZE(audio_converter_supported_types),
> + audio_converter_supported_types,
> + ARRAY_SIZE(audio_converter_supported_types),
> + audio_converter_supported_types,
> + NULL
> + },
> +};
>
> HRESULT mfplat_DllRegisterServer(void)
> {
> unsigned int i, j;
> HRESULT hr;
> - MFT_REGISTER_TYPE_INFO input_types[1], output_types[1];
> + MFT_REGISTER_TYPE_INFO input_types[2], output_types[2];
>
> for (i = 0; i < ARRAY_SIZE(mfts); i++)
> {
> diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
> index 1dc4ba9a10b..cf1fc69f38a 100644
> --- a/dlls/winegstreamer/winegstreamer_classes.idl
> +++ b/dlls/winegstreamer/winegstreamer_classes.idl
> @@ -61,3 +61,9 @@ coclass VideoProcessorMFT {}
> uuid(317df618-5e5a-468a-9f15-d827a9a08162)
> ]
> coclass GStreamerByteStreamHandler {}
> +
> +[
> + threading(both),
> + uuid(6a170414-aad9-4693-b806-3a0c47c570d6)
> +]
> +coclass WINEAudioConverter { }
>
Dec. 2, 2020
Re: [PATCH v3 02/12] winegstreamer: Add MFT registration helper for gstreamer-backed MFTs.
by Zebediah Figura (she/her)
On 12/2/20 1:54 PM, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
> ---
> dlls/winegstreamer/gst_private.h | 1 +
> dlls/winegstreamer/main.c | 3 +-
> dlls/winegstreamer/mfplat.c | 48 ++++++++++++++++++++++++++++++++
> 3 files changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
> index 28e424439d8..9752b242ad6 100644
> --- a/dlls/winegstreamer/gst_private.h
> +++ b/dlls/winegstreamer/gst_private.h
> @@ -76,6 +76,7 @@ BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
> void start_dispatch_thread(void) DECLSPEC_HIDDEN;
>
> extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
> +extern HRESULT mfplat_DllRegisterServer(void) DECLSPEC_HIDDEN;
>
> HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
> IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
> diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
> index 4ca371d58bd..385c5550235 100644
> --- a/dlls/winegstreamer/main.c
> +++ b/dlls/winegstreamer/main.c
> @@ -368,7 +368,8 @@ HRESULT WINAPI DllRegisterServer(void)
> IFilterMapper2_RegisterFilter(mapper, &CLSID_WAVEParser, wave_parserW, NULL, NULL, NULL, ®_wave_parser);
>
> IFilterMapper2_Release(mapper);
> - return S_OK;
> +
> + return mfplat_DllRegisterServer();
> }
>
> HRESULT WINAPI DllUnregisterServer(void)
> diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
> index c5b133c824e..9d5a7e0427e 100644
> --- a/dlls/winegstreamer/mfplat.c
> +++ b/dlls/winegstreamer/mfplat.c
> @@ -442,6 +442,54 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
> return CLASS_E_CLASSNOTAVAILABLE;
> }
>
> +static const struct mft
> +{
> + const GUID *clsid;
> + const GUID *category;
> + LPWSTR name;
> + const UINT32 flags;
> + const GUID *major_type;
> + const UINT32 input_types_count;
> + const GUID **input_types;
> + const UINT32 output_types_count;
> + const GUID **output_types;
> + IMFAttributes *attributes;
> +}
> +mfts[] = {};
I'm not sure if declaring an empty array like this is valid, and I had
in mind moving the entire registration to this patch. Note that your
patch 3/12 isn't dead code without it, as you're still able to create
the object through CoCreateInstance() directly.
> +
> +HRESULT mfplat_DllRegisterServer(void)
> +{
> + unsigned int i, j;
> + HRESULT hr;
> + MFT_REGISTER_TYPE_INFO input_types[1], output_types[1];
> +
> + for (i = 0; i < ARRAY_SIZE(mfts); i++)
> + {
> + const struct mft *cur = &mfts[i];
> +
> + for (j = 0; j < cur->input_types_count; j++)
> + {
> + input_types[j].guidMajorType = *(cur->major_type);
> + input_types[j].guidSubtype = *(cur->input_types[j]);
> + }
> + for (j = 0; j < cur->output_types_count; j++)
> + {
> + output_types[j].guidMajorType = *(cur->major_type);
> + output_types[j].guidSubtype = *(cur->output_types[j]);
> + }
> +
> + hr = MFTRegister(*(cur->clsid), *(cur->category), cur->name, cur->flags, cur->input_types_count,
> + input_types, cur->output_types_count, output_types, cur->attributes);
> +
> + if (FAILED(hr))
> + {
> + FIXME("Failed to register MFT, hr %#x\n", hr);
> + return hr;
> + }
> + }
> + return S_OK;
> +}
> +
> static const struct
> {
> const GUID *subtype;
>
Dec. 2, 2020
Re: [PATCH v3 01/12] winegstreamer: Utilize gst_audio_info_to_caps for media type translation.
by Zebediah Figura (she/her)
On 12/2/20 1:54 PM, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
> ---
> dlls/winegstreamer/mfplat.c | 44 +++++++++++++++----------------------
> 1 file changed, 18 insertions(+), 26 deletions(-)
>
> diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
> index 3d224a5accc..c5b133c824e 100644
> --- a/dlls/winegstreamer/mfplat.c
> +++ b/dlls/winegstreamer/mfplat.c
> @@ -669,31 +669,32 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
> }
> else if (IsEqualGUID(&major_type, &MFMediaType_Audio))
> {
> - DWORD rate, channels, channel_mask, bitrate;
> + DWORD rate = -1, channels = -1, channel_mask = -1, bitrate = -1;
> +
> + IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
> + IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
> + IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask);
> + IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate);
>
> if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
> {
> - output = gst_caps_new_empty_simple("audio/x-raw");
> + GstAudioInfo float_info;
>
> - gst_caps_set_simple(output, "format", G_TYPE_STRING, "F32LE", NULL);
> - gst_caps_set_simple(output, "layout", G_TYPE_STRING, "interleaved", NULL);
> + gst_audio_info_set_format(&float_info, GST_AUDIO_FORMAT_F32LE, rate, channels, NULL);
> + output = gst_audio_info_to_caps(&float_info);
> }
> else if (IsEqualGUID(&subtype, &MFAudioFormat_PCM))
> {
> + GstAudioFormat pcm_format;
> + GstAudioInfo pcm_info;
> DWORD bits_per_sample;
>
> if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample)))
> {
> - char format[6];
> - char type;
> -
> - type = bits_per_sample > 8 ? 'S' : 'U';
> -
> - output = gst_caps_new_empty_simple("audio/x-raw");
> -
> - sprintf(format, "%c%u%s", type, bits_per_sample, bits_per_sample > 8 ? "LE" : "");
> + pcm_format = gst_audio_format_build_integer(bits_per_sample > 8, G_LITTLE_ENDIAN, bits_per_sample, bits_per_sample);
>
> - gst_caps_set_simple(output, "format", G_TYPE_STRING, format, NULL);
> + gst_audio_info_set_format(&pcm_info, pcm_format, rate, channels, NULL);
> + output = gst_audio_info_to_caps(&pcm_info);
> }
> else
> {
> @@ -707,23 +708,14 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
> return NULL;
> }
>
> - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
> - {
> + if (rate != -1)
> gst_caps_set_simple(output, "rate", G_TYPE_INT, rate, NULL);
> - }
> - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
> - {
> + if (channels != -1)
> gst_caps_set_simple(output, "channels", G_TYPE_INT, channels, NULL);
> - }
"rate" and "channels" are already set by gst_audio_info_to_caps().
> - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
> - {
> + if (channel_mask != -1)
> gst_caps_set_simple(output, "channel-mask", GST_TYPE_BITMASK, (guint64) channel_mask, NULL);
> - }
> -
> - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate)))
> - {
> + if (bitrate != -1)
> gst_caps_set_simple(output, "bitrate", G_TYPE_INT, bitrate, NULL);
> - }
>
> return output;
> }
>
I only just now notice this, but MF_MT_AVG_BITRATE is a video type
attribute, not an audio type attribute; I suspect it should be removed
from this function...
Dec. 2, 2020
[PATCH] configure: Don't prepend folder name for SDL.h.
by Gijs Vermeulen
From: Dean M Greer <gcenx83(a)gmail.com>
This fixes pkgconfig SDL2 detection when SDL2 is installed in a non-standard location.
Signed-off-by: Dean M Greer <gcenx83(a)gmail.com>
Signed-off-by: Gijs Vermeulen <gijsvrm(a)gmail.com>
---
configure.ac | 2 +-
dlls/winebus.sys/bus_sdl.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index e823543f1cd..168df52f791 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1712,7 +1712,7 @@ dnl **** Check for libSDL2 ****
if test "x$with_sdl" != "xno"
then
WINE_PACKAGE_FLAGS(SDL2,[sdl2],[-lSDL2],,,
- [AC_CHECK_HEADERS([SDL2/SDL.h],
+ [AC_CHECK_HEADERS([SDL.h],
[WINE_CHECK_SONAME(SDL2,SDL_Init,,,[$SDL2_LIBS],[[libSDL2-2.0*]])])])
fi
WINE_NOTICE_WITH(sdl,[test "x$ac_cv_lib_soname_SDL2" = "x"],
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 19c6f23e071..06fdaa4dc62 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -28,7 +28,7 @@
# include <unistd.h>
#endif
#ifdef HAVE_SDL2_SDL_H
-# include <SDL2/SDL.h>
+# include <SDL.h>
#endif
#define NONAMELESSUNION
--
2.29.2
Dec. 2, 2020
[PATCH v3 12/12] Implement Get(Input/Output)CurrentType functions for audio converter transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/audioconvert.c | 52 ++++++++++++++++++++++++++++---
1 file changed, 48 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index f156c06e413..82e23eeb4ef 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -447,16 +447,60 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
static HRESULT WINAPI audio_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
- FIXME("%p, %u, %p.\n", iface, id, type);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+ IMFMediaType *ret;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %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;
+
+ return hr;
}
static HRESULT WINAPI audio_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
- FIXME("%p, %u, %p.\n", iface, id, type);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+ IMFMediaType *ret;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %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;
+
+ return hr;
}
static HRESULT WINAPI audio_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
--
2.29.2
Dec. 2, 2020
[PATCH v3 11/12] winegstreamer: Implement Get*Attributes functions for audio converter transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/audioconvert.c | 36 +++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 5b8df79a647..f156c06e413 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -18,6 +18,8 @@ struct audio_converter
{
IMFTransform IMFTransform_iface;
LONG refcount;
+ IMFAttributes *attributes;
+ IMFAttributes *output_attributes;
IMFMediaType *input_type;
IMFMediaType *output_type;
CRITICAL_SECTION cs;
@@ -67,6 +69,10 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
if (!refcount)
{
DeleteCriticalSection(&transform->cs);
+ if (transform->attributes)
+ IMFAttributes_Release(transform->attributes);
+ if (transform->output_attributes)
+ IMFAttributes_Release(transform->output_attributes);
gst_object_unref(transform->container);
heap_free(transform);
}
@@ -138,9 +144,14 @@ static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, D
static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
{
- FIXME("%p, %p.\n", iface, attributes);
+ struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, attributes);
+
+ *attributes = transform->attributes;
+ IMFAttributes_AddRef(*attributes);
+
+ return S_OK;
}
static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
@@ -154,9 +165,14 @@ static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *ifa
static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
IMFAttributes **attributes)
{
- FIXME("%p, %u, %p.\n", iface, id, attributes);
+ struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p, %u, %p.\n", iface, id, attributes);
+
+ *attributes = transform->output_attributes;
+ IMFAttributes_AddRef(*attributes);
+
+ return S_OK;
}
static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
@@ -629,6 +645,18 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
InitializeCriticalSection(&object->cs);
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_converter_lock");
+ if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
+ {
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return hr;
+ }
+
+ if (FAILED(hr = MFCreateAttributes(&object->output_attributes, 0)))
+ {
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return hr;
+ }
+
object->container = gst_bin_new(NULL);
if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
--
2.29.2
Dec. 2, 2020
[PATCH v3 10/12] winegstreamer: Implement ::Get(Input/Output)StreamInfo for audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/audioconvert.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 0ae522d07d1..5b8df79a647 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -103,16 +103,37 @@ static HRESULT WINAPI audio_converter_GetStreamIDs(IMFTransform *iface, DWORD in
static HRESULT WINAPI audio_converter_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
{
- FIXME("%p %u %p.\n", iface, id, info);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p %u %p\n", converter, id, info);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ info->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_DOES_NOT_ADDREF;
+ info->cbMaxLookahead = 0;
+ info->cbAlignment = 0;
+ info->hnsMaxLatency = 0;
+ return S_OK;
}
static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
- FIXME("%p %u %p.\n", iface, id, info);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+ MFT_OUTPUT_STREAM_INFO stream_info = {};
- return E_NOTIMPL;
+ TRACE("%p %u %p\n", converter, id, info);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ stream_info.dwFlags = MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
+ stream_info.cbSize = 0;
+ stream_info.cbAlignment = 0;
+
+ *info = stream_info;
+
+ return S_OK;
}
static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
--
2.29.2
Dec. 2, 2020
[PATCH v3 09/12] winegstreamer: Implement ::Process(Input/Output) for audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Simplify parameter validation in ::ProcessOutput.
---
dlls/winegstreamer/audioconvert.c | 174 ++++++++++++++++++++++++++++--
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/mfplat.c | 69 ++++++++++++
3 files changed, 238 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 365c86fb11b..0ae522d07d1 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -21,6 +21,8 @@ struct audio_converter
IMFMediaType *input_type;
IMFMediaType *output_type;
CRITICAL_SECTION cs;
+ BOOL inflight;
+ GstElement *container, *appsrc, *audioconvert, *resampler, *appsink;
};
static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
@@ -65,6 +67,7 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
if (!refcount)
{
DeleteCriticalSection(&transform->cs);
+ gst_object_unref(transform->container);
heap_free(transform);
}
@@ -291,7 +294,8 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
if (!(input_caps = caps_from_mf_media_type(type)))
return MF_E_INVALIDTYPE;
- gst_caps_unref(input_caps);
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ gst_caps_unref(input_caps);
}
if (flags & MFT_SET_TYPE_TEST_ONLY)
@@ -300,6 +304,7 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
EnterCriticalSection(&converter->cs);
hr = S_OK;
+ gst_element_set_state(converter->container, GST_STATE_READY);
if (type)
{
@@ -308,6 +313,9 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
if (SUCCEEDED(hr))
hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
+
+ g_object_set(converter->appsrc, "caps", input_caps, NULL);
+ gst_caps_unref(input_caps);
}
if (converter->input_type && (!type || FAILED(hr)))
{
@@ -315,6 +323,9 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
converter->input_type = NULL;
}
+ if (converter->input_type && converter->output_type)
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -360,7 +371,8 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
if (!(output_caps = caps_from_mf_media_type(type)))
return MF_E_INVALIDTYPE;
- gst_caps_unref(output_caps);
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ gst_caps_unref(output_caps);
}
if (flags & MFT_SET_TYPE_TEST_ONLY)
@@ -369,6 +381,7 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
EnterCriticalSection(&converter->cs);
hr = S_OK;
+ gst_element_set_state(converter->container, GST_STATE_READY);
if (type)
{
@@ -377,6 +390,9 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
if (SUCCEEDED(hr))
hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type);
+
+ g_object_set(converter->appsink, "caps", output_caps, NULL);
+ gst_caps_unref(output_caps);
}
if (converter->output_type && (!type || FAILED(hr)))
{
@@ -384,6 +400,9 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
converter->output_type = NULL;
}
+ if (converter->input_type && converter->output_type)
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -447,17 +466,100 @@ static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_ME
static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+ GstBuffer *gst_buffer;
+ int ret;
- return E_NOTIMPL;
+ TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+
+ if (flags)
+ WARN("Unsupported flags %#x\n", flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!converter->input_type || !converter->output_type)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (converter->inflight)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_NOTACCEPTING;
+ }
+
+ if (!(gst_buffer = gst_buffer_from_mf_sample(sample)))
+ {
+ LeaveCriticalSection(&converter->cs);
+ return E_FAIL;
+ }
+
+ g_signal_emit_by_name(converter->appsrc, "push-buffer", gst_buffer, &ret);
+ gst_buffer_unref(gst_buffer);
+ if (ret != GST_FLOW_OK)
+ {
+ ERR("Couldn't push buffer ret = %d (%s)\n", ret, gst_flow_get_name(ret));
+ LeaveCriticalSection(&converter->cs);
+ return E_FAIL;
+ }
+
+ converter->inflight = TRUE;
+ LeaveCriticalSection(&converter->cs);
+
+ return S_OK;
}
static HRESULT WINAPI audio_converter_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
- FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+ GstSample *sample;
- return E_NOTIMPL;
+ TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+
+ if (flags)
+ WARN("Unsupported flags %#x\n", flags);
+
+ if (!count)
+ return S_OK;
+
+ if (count != 1)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (samples[0].dwStreamID != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!converter->input_type || !converter->output_type)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (!converter->inflight)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
+ g_signal_emit_by_name(converter->appsink, "pull-sample", &sample);
+
+ converter->inflight = FALSE;
+
+ samples[0].pSample = mf_sample_from_gst_buffer(gst_sample_get_buffer(sample));
+ gst_sample_unref(sample);
+ samples[0].dwStatus = S_OK;
+ samples[0].pEvents = NULL;
+ *status = 0;
+
+ LeaveCriticalSection(&converter->cs);
+
+ return S_OK;
}
static const IMFTransformVtbl audio_converter_vtbl =
@@ -493,6 +595,7 @@ static const IMFTransformVtbl audio_converter_vtbl =
HRESULT audio_converter_create(REFIID riid, void **ret)
{
struct audio_converter *object;
+ HRESULT hr;
TRACE("%s %p\n", debugstr_guid(riid), ret);
@@ -505,6 +608,65 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
InitializeCriticalSection(&object->cs);
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_converter_lock");
+ object->container = gst_bin_new(NULL);
+
+ if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
+ {
+ ERR("Failed to create appsrc, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->appsrc);
+
+ if (!(object->audioconvert = gst_element_factory_make("audioconvert", NULL)))
+ {
+ ERR("Failed to create audioconvert, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->audioconvert);
+
+ if (!(object->resampler = gst_element_factory_make("audioresample", NULL)))
+ {
+ ERR("Failed to create audioresample, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->resampler);
+
+ if (!(object->appsink = gst_element_factory_make("appsink", NULL)))
+ {
+ ERR("Failed to create appsink, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->appsink);
+
+ if (!(gst_element_link(object->appsrc, object->audioconvert)))
+ {
+ ERR("Failed to link appsrc to audioconvert\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
+ if (!(gst_element_link(object->audioconvert, object->resampler)))
+ {
+ ERR("Failed to link audioconvert to resampler\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
+ if (!(gst_element_link(object->resampler, object->appsink)))
+ {
+ ERR("Failed to link resampler to appsink\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
*ret = &object->IMFTransform_iface;
return S_OK;
}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 9518f721504..14b6a011ac2 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -82,6 +82,7 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HI
IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
GstCaps *caps_from_mf_media_type(IMFMediaType *type) DECLSPEC_HIDDEN;
IMFSample *mf_sample_from_gst_buffer(GstBuffer *in) DECLSPEC_HIDDEN;
+GstBuffer *gst_buffer_from_mf_sample(IMFSample *in) DECLSPEC_HIDDEN;
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 833cd202a64..95f38c71b53 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -864,3 +864,72 @@ done:
return out;
}
+
+GstBuffer* gst_buffer_from_mf_sample(IMFSample *mf_sample)
+{
+ GstBuffer *out = gst_buffer_new();
+ IMFMediaBuffer *mf_buffer = NULL;
+ LONGLONG duration, time;
+ DWORD buffer_count;
+ unsigned int i;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFSample_GetSampleDuration(mf_sample, &duration)))
+ goto fail;
+
+ if (FAILED(hr = IMFSample_GetSampleTime(mf_sample, &time)))
+ goto fail;
+
+ GST_BUFFER_DURATION(out) = duration;
+ GST_BUFFER_PTS(out) = time * 100;
+
+ if (FAILED(hr = IMFSample_GetBufferCount(mf_sample, &buffer_count)))
+ goto fail;
+
+ for (i = 0; i < buffer_count; i++)
+ {
+ DWORD buffer_size;
+ GstMapInfo map_info;
+ GstMemory *memory;
+ BYTE *buf_data;
+
+ if (FAILED(hr = IMFSample_GetBufferByIndex(mf_sample, i, &mf_buffer)))
+ goto fail;
+
+ if (FAILED(hr = IMFMediaBuffer_GetCurrentLength(mf_buffer, &buffer_size)))
+ goto fail;
+
+ memory = gst_allocator_alloc(NULL, buffer_size, NULL);
+ gst_memory_resize(memory, 0, buffer_size);
+
+ if (!(gst_memory_map(memory, &map_info, GST_MAP_WRITE)))
+ {
+ hr = E_FAIL;
+ goto fail;
+ }
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(mf_buffer, &buf_data, NULL, NULL)))
+ goto fail;
+
+ memcpy(map_info.data, buf_data, buffer_size);
+
+ if (FAILED(hr = IMFMediaBuffer_Unlock(mf_buffer)))
+ goto fail;
+
+ gst_memory_unmap(memory, &map_info);
+
+ gst_buffer_append_memory(out, memory);
+
+ IMFMediaBuffer_Release(mf_buffer);
+ mf_buffer = NULL;
+ }
+
+ return out;
+
+fail:
+ ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
+ if (mf_buffer)
+ IMFMediaBuffer_Release(mf_buffer);
+ gst_buffer_unref(out);
+ return NULL;
+}
--
2.29.2
Dec. 2, 2020
[PATCH v3 08/12] winegstreamer: Implement ::SetOutputType for audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/audioconvert.c | 67 ++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 82756281aa9..365c86fb11b 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -19,6 +19,7 @@ struct audio_converter
IMFTransform IMFTransform_iface;
LONG refcount;
IMFMediaType *input_type;
+ IMFMediaType *output_type;
CRITICAL_SECTION cs;
};
@@ -321,9 +322,71 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+ GUID major_type, subtype;
+ GstCaps *output_caps;
+ DWORD unused;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %p, %#x.\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)
+ {
+ /* validate the type */
+
+ 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 (!(output_caps = caps_from_mf_media_type(type)))
+ return MF_E_INVALIDTYPE;
+
+ gst_caps_unref(output_caps);
+ }
+
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&converter->cs);
+
+ hr = S_OK;
+
+ if (type)
+ {
+ if (!converter->output_type)
+ hr = MFCreateMediaType(&converter->output_type);
+
+ if (SUCCEEDED(hr))
+ hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type);
+ }
+ if (converter->output_type && (!type || 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)
--
2.29.2
Dec. 2, 2020
[PATCH v3 07/12] winegstreamer: Implement ::SetInputType for audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Factor out update_pipeline_state.
---
dlls/winegstreamer/audioconvert.c | 70 ++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 1174f9df0db..82756281aa9 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -1,4 +1,5 @@
#include "config.h"
+#include <gst/gst.h>
#include "gst_private.h"
@@ -17,6 +18,8 @@ struct audio_converter
{
IMFTransform IMFTransform_iface;
LONG refcount;
+ IMFMediaType *input_type;
+ CRITICAL_SECTION cs;
};
static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
@@ -60,6 +63,7 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
if (!refcount)
{
+ DeleteCriticalSection(&transform->cs);
heap_free(transform);
}
@@ -251,9 +255,68 @@ fail:
static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+ GstCaps *input_caps;
+ HRESULT hr;
- return E_NOTIMPL;
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (type)
+ {
+ GUID major_type, subtype;
+ DWORD unused;
+
+ 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 (!(input_caps = caps_from_mf_media_type(type)))
+ return MF_E_INVALIDTYPE;
+
+ gst_caps_unref(input_caps);
+ }
+
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&converter->cs);
+
+ hr = S_OK;
+
+ if (type)
+ {
+ if (!converter->input_type)
+ hr = MFCreateMediaType(&converter->input_type);
+
+ if (SUCCEEDED(hr))
+ hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
+ }
+ if (converter->input_type && (!type || 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)
@@ -376,6 +439,9 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
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;
}
--
2.29.2
Dec. 2, 2020
[PATCH v3 06/12] winegstreamer: Implement ::ProcessMessage for audio conversion MFT.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/audioconvert.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index f28ddd70cda..1174f9df0db 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -307,9 +307,16 @@ static HRESULT WINAPI audio_converter_ProcessEvent(IMFTransform *iface, DWORD id
static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
{
- FIXME("%p, %u.\n", iface, message);
+ TRACE("%p, %u.\n", iface, message);
- return E_NOTIMPL;
+ switch(message)
+ {
+ case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
+ 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)
--
2.29.2
Dec. 2, 2020
[PATCH v3 05/12] winegstreamer: Implement ::GetOutputAvailableType for audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Simplify logic.
---
dlls/winegstreamer/audioconvert.c | 67 ++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 9d7e9da9d3a..f28ddd70cda 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -181,9 +181,72 @@ static HRESULT WINAPI audio_converter_GetInputAvailableType(IMFTransform *iface,
static HRESULT WINAPI audio_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ IMFMediaType *output_type;
+ HRESULT hr;
- return E_NOTIMPL;
+ 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, %u, %u, %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)
--
2.29.2
Dec. 2, 2020
[PATCH v3 04/12] winegstreamer: Implement ::GetInputAvailableType for audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Discard usage of raw_types.
---
dlls/winegstreamer/audioconvert.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 35b984618de..9d7e9da9d3a 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -147,9 +147,35 @@ static HRESULT WINAPI audio_converter_AddInputStreams(IMFTransform *iface, DWORD
static HRESULT WINAPI audio_converter_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ IMFMediaType *ret;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %u, %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,
--
2.29.2
Dec. 2, 2020
[PATCH v3 03/12] winegstreamer: Introduce audio conversion transform.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Split up patch.
---
dlls/winegstreamer/Makefile.in | 1 +
dlls/winegstreamer/audioconvert.c | 285 +++++++++++++++++++
dlls/winegstreamer/gst_private.h | 2 +
dlls/winegstreamer/mfplat.c | 28 +-
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
5 files changed, 320 insertions(+), 2 deletions(-)
create mode 100644 dlls/winegstreamer/audioconvert.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index e578d194f7f..0b3229160b9 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -6,6 +6,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
PARENTSRC = ../strmbase
C_SRCS = \
+ audioconvert.c \
filter.c \
gst_cbs.c \
gstdemux.c \
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
new file mode 100644
index 00000000000..35b984618de
--- /dev/null
+++ b/dlls/winegstreamer/audioconvert.c
@@ -0,0 +1,285 @@
+#include "config.h"
+
+#include "gst_private.h"
+
+#include "mfapi.h"
+#include "mferror.h"
+#include "mfidl.h"
+#include "ks.h"
+#include "ksmedia.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct audio_converter
+{
+ IMFTransform IMFTransform_iface;
+ LONG refcount;
+};
+
+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 %u.\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 %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ heap_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 %u %p %u %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 %u %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 %u %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, %u, %p.\n", iface, id, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("%p, %u, %p.\n", iface, id, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
+{
+ TRACE("%p, %u.\n", iface, id);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
+{
+ TRACE("%p, %u, %p.\n", iface, streams, ids);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
+ IMFMediaType **type)
+{
+ FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
+ IMFMediaType **type)
+{
+ FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
+{
+ FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
+{
+ FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("%p, %u, %p.\n", iface, id, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("%p, %u, %p.\n", iface, id, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
+{
+ FIXME("%p, %u, %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, %u, %p.\n", iface, id, event);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
+{
+ FIXME("%p, %u.\n", iface, message);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
+{
+ FIXME("%p, %u, %p, %#x.\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, %#x, %u, %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 = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->IMFTransform_iface.lpVtbl = &audio_converter_vtbl;
+ object->refcount = 1;
+
+ *ret = &object->IMFTransform_iface;
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 9752b242ad6..9518f721504 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -85,4 +85,6 @@ IMFSample *mf_sample_from_gst_buffer(GstBuffer *in) DECLSPEC_HIDDEN;
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
+HRESULT audio_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
+
#endif /* __GST_PRIVATE_INCLUDED__ */
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 9d5a7e0427e..833cd202a64 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -405,6 +405,8 @@ 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;
@@ -414,6 +416,7 @@ class_objects[] =
{
{ &CLSID_VideoProcessorMFT, &video_processor_create },
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
+ { &CLSID_WINEAudioConverter, &audio_converter_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
@@ -442,6 +445,13 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
return CLASS_E_CLASSNOTAVAILABLE;
}
+static WCHAR audio_converterW[] = {'A','u','d','i','o',' ','C','o','n','v','e','r','t','e','r',0};
+static const GUID *audio_converter_supported_types[] =
+{
+ &MFAudioFormat_PCM,
+ &MFAudioFormat_Float,
+};
+
static const struct mft
{
const GUID *clsid;
@@ -455,13 +465,27 @@ static const struct mft
const GUID **output_types;
IMFAttributes *attributes;
}
-mfts[] = {};
+mfts[] =
+{
+ {
+ &CLSID_WINEAudioConverter,
+ &MFT_CATEGORY_AUDIO_EFFECT,
+ audio_converterW,
+ MFT_ENUM_FLAG_SYNCMFT,
+ &MFMediaType_Audio,
+ ARRAY_SIZE(audio_converter_supported_types),
+ audio_converter_supported_types,
+ ARRAY_SIZE(audio_converter_supported_types),
+ audio_converter_supported_types,
+ NULL
+ },
+};
HRESULT mfplat_DllRegisterServer(void)
{
unsigned int i, j;
HRESULT hr;
- MFT_REGISTER_TYPE_INFO input_types[1], output_types[1];
+ MFT_REGISTER_TYPE_INFO input_types[2], output_types[2];
for (i = 0; i < ARRAY_SIZE(mfts); i++)
{
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
index 1dc4ba9a10b..cf1fc69f38a 100644
--- a/dlls/winegstreamer/winegstreamer_classes.idl
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
@@ -61,3 +61,9 @@ coclass VideoProcessorMFT {}
uuid(317df618-5e5a-468a-9f15-d827a9a08162)
]
coclass GStreamerByteStreamHandler {}
+
+[
+ threading(both),
+ uuid(6a170414-aad9-4693-b806-3a0c47c570d6)
+]
+coclass WINEAudioConverter { }
--
2.29.2
Dec. 2, 2020
[PATCH v3 02/12] winegstreamer: Add MFT registration helper for gstreamer-backed MFTs.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/main.c | 3 +-
dlls/winegstreamer/mfplat.c | 48 ++++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 28e424439d8..9752b242ad6 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -76,6 +76,7 @@ BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
void start_dispatch_thread(void) DECLSPEC_HIDDEN;
extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
+extern HRESULT mfplat_DllRegisterServer(void) DECLSPEC_HIDDEN;
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 4ca371d58bd..385c5550235 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -368,7 +368,8 @@ HRESULT WINAPI DllRegisterServer(void)
IFilterMapper2_RegisterFilter(mapper, &CLSID_WAVEParser, wave_parserW, NULL, NULL, NULL, ®_wave_parser);
IFilterMapper2_Release(mapper);
- return S_OK;
+
+ return mfplat_DllRegisterServer();
}
HRESULT WINAPI DllUnregisterServer(void)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index c5b133c824e..9d5a7e0427e 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -442,6 +442,54 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
return CLASS_E_CLASSNOTAVAILABLE;
}
+static const struct mft
+{
+ const GUID *clsid;
+ const GUID *category;
+ LPWSTR name;
+ const UINT32 flags;
+ const GUID *major_type;
+ const UINT32 input_types_count;
+ const GUID **input_types;
+ const UINT32 output_types_count;
+ const GUID **output_types;
+ IMFAttributes *attributes;
+}
+mfts[] = {};
+
+HRESULT mfplat_DllRegisterServer(void)
+{
+ unsigned int i, j;
+ HRESULT hr;
+ MFT_REGISTER_TYPE_INFO input_types[1], output_types[1];
+
+ for (i = 0; i < ARRAY_SIZE(mfts); i++)
+ {
+ const struct mft *cur = &mfts[i];
+
+ for (j = 0; j < cur->input_types_count; j++)
+ {
+ input_types[j].guidMajorType = *(cur->major_type);
+ input_types[j].guidSubtype = *(cur->input_types[j]);
+ }
+ for (j = 0; j < cur->output_types_count; j++)
+ {
+ output_types[j].guidMajorType = *(cur->major_type);
+ output_types[j].guidSubtype = *(cur->output_types[j]);
+ }
+
+ hr = MFTRegister(*(cur->clsid), *(cur->category), cur->name, cur->flags, cur->input_types_count,
+ input_types, cur->output_types_count, output_types, cur->attributes);
+
+ if (FAILED(hr))
+ {
+ FIXME("Failed to register MFT, hr %#x\n", hr);
+ return hr;
+ }
+ }
+ return S_OK;
+}
+
static const struct
{
const GUID *subtype;
--
2.29.2
Dec. 2, 2020
[PATCH v3 01/12] winegstreamer: Utilize gst_audio_info_to_caps for media type translation.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/mfplat.c | 44 +++++++++++++++----------------------
1 file changed, 18 insertions(+), 26 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 3d224a5accc..c5b133c824e 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -669,31 +669,32 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
}
else if (IsEqualGUID(&major_type, &MFMediaType_Audio))
{
- DWORD rate, channels, channel_mask, bitrate;
+ DWORD rate = -1, channels = -1, channel_mask = -1, bitrate = -1;
+
+ IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
+ IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
+ IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask);
+ IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate);
if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
{
- output = gst_caps_new_empty_simple("audio/x-raw");
+ GstAudioInfo float_info;
- gst_caps_set_simple(output, "format", G_TYPE_STRING, "F32LE", NULL);
- gst_caps_set_simple(output, "layout", G_TYPE_STRING, "interleaved", NULL);
+ gst_audio_info_set_format(&float_info, GST_AUDIO_FORMAT_F32LE, rate, channels, NULL);
+ output = gst_audio_info_to_caps(&float_info);
}
else if (IsEqualGUID(&subtype, &MFAudioFormat_PCM))
{
+ GstAudioFormat pcm_format;
+ GstAudioInfo pcm_info;
DWORD bits_per_sample;
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample)))
{
- char format[6];
- char type;
-
- type = bits_per_sample > 8 ? 'S' : 'U';
-
- output = gst_caps_new_empty_simple("audio/x-raw");
-
- sprintf(format, "%c%u%s", type, bits_per_sample, bits_per_sample > 8 ? "LE" : "");
+ pcm_format = gst_audio_format_build_integer(bits_per_sample > 8, G_LITTLE_ENDIAN, bits_per_sample, bits_per_sample);
- gst_caps_set_simple(output, "format", G_TYPE_STRING, format, NULL);
+ gst_audio_info_set_format(&pcm_info, pcm_format, rate, channels, NULL);
+ output = gst_audio_info_to_caps(&pcm_info);
}
else
{
@@ -707,23 +708,14 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
return NULL;
}
- if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
- {
+ if (rate != -1)
gst_caps_set_simple(output, "rate", G_TYPE_INT, rate, NULL);
- }
- if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
- {
+ if (channels != -1)
gst_caps_set_simple(output, "channels", G_TYPE_INT, channels, NULL);
- }
- if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
- {
+ if (channel_mask != -1)
gst_caps_set_simple(output, "channel-mask", GST_TYPE_BITMASK, (guint64) channel_mask, NULL);
- }
-
- if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate)))
- {
+ if (bitrate != -1)
gst_caps_set_simple(output, "bitrate", G_TYPE_INT, bitrate, NULL);
- }
return output;
}
--
2.29.2
Dec. 2, 2020
Re: [PATCH] mf/sar: Only require MF_MEDIATYPE_EQUAL_FORMAT_DATA in IsMediaTypeSupported.
by Derek Lesho
On 12/2/20 2:20 PM, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
> ---
> dlls/mf/sar.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
> index e318576e80e..20bb052cb7a 100644
> --- a/dlls/mf/sar.c
> +++ b/dlls/mf/sar.c
> @@ -1482,6 +1482,9 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_IsMediaTypeSupported(IM
> hr = IMFMediaType_IsEqual(renderer->media_type, in_type, &flags);
> LeaveCriticalSection(&renderer->cs);
>
> + if (flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA)
> + hr = S_OK;
> +
> return hr != S_OK ? MF_E_INVALIDMEDIATYPE : hr;
> }
>
Please reject, looks like this was already fixed by Nikolay yesterday,
sorry.
Dec. 2, 2020
Re: [PATCH] server: Fix handling of STATUS_ALERTED in get_next_console_request.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=82981
Your paranoid android.
=== w2008s64 (64 bit report) ===
kernel32:
console.c:3175: Test failed: expected INVALID_FILE_SIZE, got 0x1000
Dec. 2, 2020
[PATCH] mf/sar: Only require MF_MEDIATYPE_EQUAL_FORMAT_DATA in IsMediaTypeSupported.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/mf/sar.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
index e318576e80e..20bb052cb7a 100644
--- a/dlls/mf/sar.c
+++ b/dlls/mf/sar.c
@@ -1482,6 +1482,9 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_IsMediaTypeSupported(IM
hr = IMFMediaType_IsEqual(renderer->media_type, in_type, &flags);
LeaveCriticalSection(&renderer->cs);
+ if (flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA)
+ hr = S_OK;
+
return hr != S_OK ? MF_E_INVALIDMEDIATYPE : hr;
}
--
2.29.2
Dec. 2, 2020
[PATCH] server: Fix handling of STATUS_ALERTED in get_next_console_request.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/kernel32/tests/console.c | 14 ++++++++++++++
server/console.c | 2 +-
2 files changed, 15 insertions(+), 1 deletion(-)
Dec. 2, 2020
Re: [PATCH 1/2] jscript: Use wide-char string literals.
by Jacek Caban
Hi Jeff,
For some reason, the patch status page shows Testbot status OK, while
tests failed.
On 01.12.2020 23:02, Jeff Smith wrote:
> @@ -510,8 +508,8 @@ static HRESULT str_to_number(jsstr_t *str, double *ret)
> ptr++;
> }
>
> - if(!wcsncmp(ptr, infinityW, ARRAY_SIZE(infinityW))) {
> - ptr += ARRAY_SIZE(infinityW);
> + if(!wcscmp(ptr, L"Infinity")) {
> + ptr += lstrlenW(L"Infinity");
> while(*ptr && iswspace(*ptr))
> ptr++;
There is a reason wcsncmp is used in current code: we want to check only
a prefix of ptr. Also lstrlenW() has runtime cost, which should be
avoided in places like this. ARRAY_SIZE()-1 will give you that in
compile time. The same applies to other places.
Thanks,
Jacek
Dec. 2, 2020
[tools] testbot: Tweak the VMs default status and snapshot name.
by Francois Gouget
These are only relevant when creating a new VM so provide more
appropriate defaults. In particular new VMs are normally off and the
TestBot deals with powering them up and setting up the live snapshot.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/VMs.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/testbot/lib/WineTestBot/VMs.pm b/testbot/lib/WineTestBot/VMs.pm
index 6dd1ff2bb1..53f43948bc 100644
--- a/testbot/lib/WineTestBot/VMs.pm
+++ b/testbot/lib/WineTestBot/VMs.pm
@@ -170,8 +170,8 @@ sub InitializeNew($$)
{
my ($self, $Collection) = @_;
- $self->Status("idle");
- $self->IdleSnapshot("wtb");
+ $self->Status("off");
+ $self->IdleSnapshot("base-live");
$self->SUPER::InitializeNew($Collection);
}
--
2.20.1
Dec. 2, 2020
Re: [PATCH v2 1/4] winegstreamer: Introduce audio conversion transform.
by Derek Lesho
On 12/2/20 12:55 PM, Zebediah Figura (she/her) wrote:
> On 12/2/20 11:26 AM, Derek Lesho wrote:
>> On 12/2/20 12:25 PM, Zebediah Figura (she/her) wrote:
>>
>>> On 12/2/20 11:15 AM, Derek Lesho wrote:
>>>> On 12/2/20 12:07 PM, Zebediah Figura (she/her) wrote:
>>>>> Performance isn't really the concern—it's more code, and you really
>>>>> should be handling allocation failure.
>>>>>
>>>>> Another solution could be to just use a fixed-size stack buffer.
>>>> Okay, I guess I'll do that. There's no limit to how many types you can
>>>> register for the MFT so I'll just make a max of 100 for both input and
>>>> output (so ~3.2kb of stack space).
>>> I think there's no need for that; just allocate as much stack space as
>>> you actually need.
>> That varies on a per MFT registration basis, some MFTs require more
>> registration structs than others, since they have more input/output
>> types. Unless you're suggesting I use a VLA?
> No, simply use the maximum array size that any individual transform needs.
Not looking forward to the bugs that show up from somebody adding more
entries to the supported types list and not increasing the array size
just so we can avoid two heap_allocs, but ok.
Dec. 2, 2020