And use it for decoder transform input types.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391 Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This uses a separate struct for encoded formats, as I believe it was suggested at some point (or I may be mistaken), but I'm not sure it's best. If we intend to support encoders or converters in the wg_transform the formats would need to be swapped, and in which case using the same struct may be cleaner.
In that case, maybe using a separate major type for encoded formats, or a separate major type for each encoded format would be better.
dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/mfplat.c | 84 ++++++++++++++++++++++++++++++++ dlls/winegstreamer/unixlib.h | 25 ++++++++++ dlls/winegstreamer/wma_decoder.c | 12 +++++ 4 files changed, 122 insertions(+)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index df82b229143..cec52e976ec 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -117,6 +117,7 @@ extern HRESULT mfplat_DllRegisterServer(void) DECLSPEC_HIDDEN;
IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format) DECLSPEC_HIDDEN; void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) DECLSPEC_HIDDEN; +void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_format *format) 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 a111bbe196d..61c7fe28a63 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -760,3 +760,87 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) else FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type)); } + +static void mf_media_type_to_wg_encoded_format_wma(IMFMediaType *type, struct wg_encoded_format *format, + UINT32 version) +{ + UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len; + BYTE codec_data[64]; + + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate))) + { + FIXME("Sample rate is not set.\n"); + return; + } + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels))) + { + FIXME("Channel count is not set.\n"); + return; + } + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align))) + { + FIXME("Block alignment is not set.\n"); + return; + } + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth))) + { + FIXME("Depth is not set.\n"); + return; + } + if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, codec_data, sizeof(codec_data), &codec_data_len))) + { + FIXME("Codec data is not set.\n"); + return; + } + if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second))) + { + FIXME("Bitrate is not set.\n"); + bytes_per_second = 0; + } + + format->encoded_type = WG_ENCODED_TYPE_WMA; + format->u.xwma.version = version; + format->u.xwma.bitrate = bytes_per_second * 8; + format->u.xwma.rate = rate; + format->u.xwma.depth = depth; + format->u.xwma.channels = channels; + format->u.xwma.block_align = block_align; + format->u.xwma.codec_data_len = codec_data_len; + memcpy(format->u.xwma.codec_data, codec_data, codec_data_len); +} + +void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_format *format) +{ + GUID major_type, subtype; + + memset(format, 0, sizeof(*format)); + + if (FAILED(IMFMediaType_GetMajorType(type, &major_type))) + { + FIXME("Major type is not set.\n"); + return; + } + if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) + { + FIXME("Subtype is not set.\n"); + return; + } + + if (IsEqualGUID(&major_type, &MFMediaType_Audio)) + { + if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1)) + mf_media_type_to_wg_encoded_format_wma(type, format, 1); + else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8)) + mf_media_type_to_wg_encoded_format_wma(type, format, 2); + else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9)) + mf_media_type_to_wg_encoded_format_wma(type, format, 3); + else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless)) + mf_media_type_to_wg_encoded_format_wma(type, format, 4); + else + FIXME("Unimplemented audio subtype %s.\n", debugstr_guid(&subtype)); + } + else + { + FIXME("Unimplemented major type %s.\n", debugstr_guid(&major_type)); + } +} diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index c8b98da3a64..ea46de4cce1 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -91,6 +91,31 @@ struct wg_format } u; };
+struct wg_encoded_format +{ + enum wg_encoded_type + { + WG_ENCODED_TYPE_UNKNOWN, + WG_ENCODED_TYPE_WMA, + WG_ENCODED_TYPE_XMA, + } encoded_type; + + union + { + struct + { + uint32_t version; + uint32_t bitrate; + uint32_t rate; + uint32_t depth; + uint32_t channels; + uint32_t block_align; + uint32_t codec_data_len; + unsigned char codec_data[64]; + } xwma; + } u; +}; + enum wg_parser_event_type { WG_PARSER_EVENT_NONE = 0, diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 3b051230a9e..b037795fc78 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -64,8 +64,20 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
static HRESULT try_create_wg_transform(struct wma_decoder *decoder) { + struct wg_encoded_format input_format; + struct wg_format output_format; + if (decoder->wg_transform) wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = NULL; + + mf_media_type_to_wg_encoded_format(decoder->input_type, &input_format); + if (input_format.encoded_type == WG_ENCODED_TYPE_UNKNOWN) + return MF_E_INVALIDMEDIATYPE; + + mf_media_type_to_wg_format(decoder->output_type, &output_format); + if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return MF_E_INVALIDMEDIATYPE;
decoder->wg_transform = wg_transform_create(); if (decoder->wg_transform)