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 --- dlls/winegstreamer/mfplat.c | 109 +++++++++++++++++++++++------ dlls/winegstreamer/quartz_parser.c | 8 +++ dlls/winegstreamer/unixlib.h | 12 ++++ dlls/winegstreamer/wg_format.c | 7 ++ dlls/winegstreamer/wm_reader.c | 8 +++ dlls/winegstreamer/wma_decoder.c | 18 +++++ 6 files changed, 141 insertions(+), 21 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index a111bbe196d..9b3fc429d32 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -635,6 +635,10 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format) case WG_MAJOR_TYPE_UNKNOWN: return NULL;
+ case WG_MAJOR_TYPE_WMA: + FIXME("WMA format not implemented!\n"); + return NULL; + case WG_MAJOR_TYPE_AUDIO: return mf_media_type_from_wg_format_audio(format);
@@ -646,17 +650,11 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format) return NULL; }
-static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_format *format) +static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *subtype, struct wg_format *format) { UINT32 rate, channels, channel_mask, depth; unsigned int i; - GUID subtype;
- if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) - { - FIXME("Subtype is not set.\n"); - return; - } if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate))) { FIXME("Sample rate is not set.\n"); @@ -692,26 +690,20 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_forma
for (i = 0; i < ARRAY_SIZE(audio_formats); ++i) { - if (IsEqualGUID(&subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth) + if (IsEqualGUID(subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth) { format->u.audio.format = audio_formats[i].format; return; } } - FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(&subtype), depth); + FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth); }
-static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_format *format) +static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *subtype, struct wg_format *format) { UINT64 frame_rate, frame_size; unsigned int i; - GUID subtype;
- if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) - { - FIXME("Subtype is not set.\n"); - return; - } if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) { FIXME("Frame size is not set.\n"); @@ -732,18 +724,80 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_forma
for (i = 0; i < ARRAY_SIZE(video_formats); ++i) { - if (IsEqualGUID(&subtype, video_formats[i].subtype)) + if (IsEqualGUID(subtype, video_formats[i].subtype)) { format->u.video.format = video_formats[i].format; return; } } - FIXME("Unrecognized video subtype %s.\n", debugstr_guid(&subtype)); + FIXME("Unrecognized video subtype %s.\n", debugstr_guid(subtype)); +} + +static void mf_media_type_to_wg_format_wma(IMFMediaType *type, const GUID *subtype, struct wg_format *format) +{ + UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len; + BYTE codec_data[64]; + UINT32 version; + + 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; + } + + if (IsEqualGUID(subtype, &MEDIASUBTYPE_MSAUDIO1)) + version = 1; + else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV8)) + version = 2; + else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV9)) + version = 3; + else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudio_Lossless)) + version = 4; + else + { + assert(0); + return; + } + + format->major_type = WG_MAJOR_TYPE_WMA; + format->u.wma.version = version; + format->u.wma.bitrate = bytes_per_second * 8; + format->u.wma.rate = rate; + format->u.wma.depth = depth; + format->u.wma.channels = channels; + format->u.wma.block_align = block_align; + format->u.wma.codec_data_len = codec_data_len; + memcpy(format->u.wma.codec_data, codec_data, codec_data_len); }
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) { - GUID major_type; + GUID major_type, subtype;
memset(format, 0, sizeof(*format));
@@ -752,11 +806,24 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) 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)) - mf_media_type_to_wg_format_audio(type, format); + { + if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1) || + IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8) || + IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) || + IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless)) + mf_media_type_to_wg_format_wma(type, &subtype, format); + else + mf_media_type_to_wg_format_audio(type, &subtype, format); + } else if (IsEqualGUID(&major_type, &MFMediaType_Video)) - mf_media_type_to_wg_format_video(type, format); + mf_media_type_to_wg_format_video(type, &subtype, format); else FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type)); } diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 45313ebda27..e06c55ccfe0 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -319,6 +319,10 @@ unsigned int wg_format_get_max_size(const struct wg_format *format) break; }
+ case WG_MAJOR_TYPE_WMA: + FIXME("WMA format not implemented!\n"); + return 0; + case WG_MAJOR_TYPE_UNKNOWN: FIXME("Cannot guess maximum sample size for unknown format.\n"); return 0; @@ -413,6 +417,10 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool case WG_MAJOR_TYPE_UNKNOWN: return false;
+ case WG_MAJOR_TYPE_WMA: + FIXME("WMA format not implemented!\n"); + return false; + case WG_MAJOR_TYPE_AUDIO: return amt_from_wg_format_audio(mt, format);
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 82bb534b938..45ec606fc6a 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -37,6 +37,7 @@ struct wg_format WG_MAJOR_TYPE_UNKNOWN, WG_MAJOR_TYPE_VIDEO, WG_MAJOR_TYPE_AUDIO, + WG_MAJOR_TYPE_WMA, } major_type;
union @@ -88,6 +89,17 @@ struct wg_format uint32_t channel_mask; /* In WinMM format. */ uint32_t rate; } audio; + 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]; + } wma; } u; };
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 8952acc1c2e..8f771bb8abd 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -400,6 +400,9 @@ GstCaps *wg_format_to_caps(const struct wg_format *format) { case WG_MAJOR_TYPE_UNKNOWN: return NULL; + case WG_MAJOR_TYPE_WMA: + GST_FIXME("WMA format not implemented!\n"); + return NULL; case WG_MAJOR_TYPE_AUDIO: return wg_format_to_caps_audio(format); case WG_MAJOR_TYPE_VIDEO: @@ -419,6 +422,10 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) case WG_MAJOR_TYPE_UNKNOWN: return false;
+ case WG_MAJOR_TYPE_WMA: + GST_FIXME("WMA format not implemented!\n"); + return false; + case WG_MAJOR_TYPE_AUDIO: return a->u.audio.format == b->u.audio.format && a->u.audio.channels == b->u.audio.channels diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index d40afb66afd..01518c6b9a8 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1687,6 +1687,9 @@ HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output *count = ARRAY_SIZE(video_formats); break;
+ case WG_MAJOR_TYPE_WMA: + FIXME("WMA format not implemented!\n"); + /* fallthrough */ case WG_MAJOR_TYPE_AUDIO: case WG_MAJOR_TYPE_UNKNOWN: *count = 1; @@ -1733,6 +1736,9 @@ HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output, format.u.audio.format = WG_AUDIO_FORMAT_S16LE; break;
+ case WG_MAJOR_TYPE_WMA: + FIXME("WMA format not implemented!\n"); + break; case WG_MAJOR_TYPE_UNKNOWN: break; } @@ -1808,6 +1814,8 @@ static const char *get_major_type_string(enum wg_major_type type) return "video"; case WG_MAJOR_TYPE_UNKNOWN: return "unknown"; + case WG_MAJOR_TYPE_WMA: + return "wma"; } assert(0); return NULL; diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 78316059052..31f735a5b1d 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -60,6 +60,21 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface) return CONTAINING_RECORD(iface, struct wma_decoder, IUnknown_inner); }
+static HRESULT try_create_wg_transform(struct wma_decoder *decoder) +{ + struct wg_format input_format, output_format; + + mf_media_type_to_wg_format(decoder->input_type, &input_format); + if (input_format.major_type == WG_MAJOR_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; + + return S_OK; +} + static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) { struct wma_decoder *decoder = impl_from_IUnknown(iface); @@ -438,6 +453,9 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->output_type))) goto failed;
+ if (FAILED(hr = try_create_wg_transform(decoder))) + goto failed; + return S_OK;
failed: