Signed-off-by: Derek Lesho dlesho@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; }
Signed-off-by: Derek Lesho dlesho@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;
On 12/2/20 1:54 PM, Derek Lesho wrote:
Signed-off-by: Derek Lesho dlesho@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;
Signed-off-by: Derek Lesho dlesho@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 { }
On 12/2/20 1:54 PM, Derek Lesho wrote:
Signed-off-by: Derek Lesho dlesho@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 { }
On 12/2/20 3:45 PM, Zebediah Figura (she/her) wrote:
+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).
You may have missed my response: https://source.winehq.org/patches/data/196951
On 12/2/20 2:52 PM, Derek Lesho wrote:
On 12/2/20 3:45 PM, Zebediah Figura (she/her) wrote:
+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).
You may have missed my response: https://source.winehq.org/patches/data/196951
Sorry, my fault, I did miss that response somehow.
Signed-off-by: Derek Lesho dlesho@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,
Signed-off-by: Derek Lesho dlesho@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)
Signed-off-by: Derek Lesho dlesho@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)
Signed-off-by: Derek Lesho dlesho@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; }
On 12/2/20 1:54 PM, Derek Lesho wrote:
Signed-off-by: Derek Lesho dlesho@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;
}
Signed-off-by: Derek Lesho dlesho@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)
Signed-off-by: Derek Lesho dlesho@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; +}
Signed-off-by: Derek Lesho dlesho@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)
Signed-off-by: Derek Lesho dlesho@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)))
Signed-off-by: Derek Lesho dlesho@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)
On 12/2/20 1:54 PM, Derek Lesho wrote:
Signed-off-by: Derek Lesho dlesho@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...
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.
On 12/2/20 2:49 PM, Derek Lesho wrote:
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?
Those statements shouldn't be present in this patch, no.
- 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.
I don't think there's any point; I haven't seen any plugins that care about a "bitrate" member for PCM audio.