Along with !4449, this fixes WMV videos in microkiri (https://bugs.winehq.org/show_bug.cgi?id=9127#c102) and Wagamama High Spec Trial Edition (https://wagahigh.com/download_trial.php#normal ; ダウンロード means download).
-- v5: winegstreamer/tests: Test IMediaObject_GetOutputSizeInfo. winegstreamer: Implement DMO interface for WMA decoder. winegstreamer: Switch WMA decoder to use wg_format internally. winegstreamer: Implement WMA <-> AMT conversion. winegstreamer: Add wg_format_from_caps_audio_wma function.
From: Alfred Agrell floating@muncher.se
--- dlls/winegstreamer/wg_format.c | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+)
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 7d4bc7a5f8c..67dee1a58db 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -201,6 +201,70 @@ static void wg_format_from_caps_audio_mpeg1(struct wg_format *format, const GstC format->u.audio_mpeg1.rate = rate; }
+static void wg_format_from_caps_audio_wma(struct wg_format *format, const GstCaps *caps) +{ + const GstStructure *structure = gst_caps_get_structure(caps, 0); + gint version, bitrate, rate, depth, channels, block_align; + const GValue *codec_data_value; + GstBuffer *codec_data; + GstMapInfo map; + + if (!gst_structure_get_int(structure, "wmaversion", &version)) + { + GST_WARNING("Missing "wmaversion" value in %" GST_PTR_FORMAT ".", caps); + return; + } + if (!gst_structure_get_int(structure, "bitrate", &bitrate)) + { + GST_WARNING("Missing "bitrate" value in %" GST_PTR_FORMAT ".", caps); + return; + } + if (!gst_structure_get_int(structure, "rate", &rate)) + { + GST_WARNING("Missing "rate" value in %" GST_PTR_FORMAT ".", caps); + return; + } + if (!gst_structure_get_int(structure, "depth", &depth)) + { + GST_WARNING("Missing "depth" value in %" GST_PTR_FORMAT ".", caps); + return; + } + if (!gst_structure_get_int(structure, "channels", &channels)) + { + GST_WARNING("Missing "channels" value in %" GST_PTR_FORMAT ".", caps); + return; + } + if (!gst_structure_get_int(structure, "block_align", &block_align)) + { + GST_WARNING("Missing "block_align" value in %" GST_PTR_FORMAT ".", caps); + return; + } + if (!(codec_data_value = gst_structure_get_value(structure, "codec_data")) + || !(codec_data = gst_value_get_buffer(codec_data_value))) + { + GST_WARNING("Missing "codec_data" value in %" GST_PTR_FORMAT ".", caps); + return; + } + + format->major_type = WG_MAJOR_TYPE_AUDIO_WMA; + format->u.audio_wma.version = version; + format->u.audio_wma.bitrate = bitrate; + format->u.audio_wma.rate = rate; + format->u.audio_wma.depth = depth; + format->u.audio_wma.channels = channels; + format->u.audio_wma.block_align = block_align; + + gst_buffer_map(codec_data, &map, GST_MAP_READ); + if (map.size <= sizeof(format->u.audio_wma.codec_data)) + { + format->u.audio_wma.codec_data_len = map.size; + memcpy(format->u.audio_wma.codec_data, map.data, map.size); + } + else + GST_WARNING("Too big codec_data value (%u) in %" GST_PTR_FORMAT ".", (unsigned)map.size, caps); + gst_buffer_unmap(codec_data, &map); +} + static void wg_format_from_caps_video_cinepak(struct wg_format *format, const GstCaps *caps) { const GstStructure *structure = gst_caps_get_structure(caps, 0); @@ -336,6 +400,10 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) { wg_format_from_caps_audio_mpeg1(format, caps); } + else if (!strcmp(name, "audio/x-wma")) + { + wg_format_from_caps_audio_wma(format, caps); + } else if (!strcmp(name, "video/x-cinepak")) { wg_format_from_caps_video_cinepak(format, caps);
From: Alfred Agrell floating@muncher.se
--- dlls/winegstreamer/quartz_parser.c | 127 ++++++++++++++++++++++++++++- dlls/wmvcore/tests/wmvcore.c | 11 ++- 2 files changed, 130 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 0670fbd5181..596f7a5011a 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -278,6 +278,68 @@ static bool amt_from_wg_format_audio_mpeg1(AM_MEDIA_TYPE *mt, const struct wg_fo return false; }
+static bool amt_from_wg_format_audio_wma(AM_MEDIA_TYPE *mt, const struct wg_format *format) +{ + DWORD codec_data_len, size; + WAVEFORMATEX *wave_format; + const GUID *subtype; + WORD fmt_tag; + + mt->majortype = MEDIATYPE_Audio; + mt->formattype = FORMAT_WaveFormatEx; + + switch (format->u.audio_wma.version) + { + case 1: + subtype = &MEDIASUBTYPE_MSAUDIO1; + codec_data_len = MSAUDIO1_WFX_EXTRA_BYTES; + fmt_tag = WAVE_FORMAT_MSAUDIO1; + break; + case 2: + subtype = &MEDIASUBTYPE_WMAUDIO2; + codec_data_len = WMAUDIO2_WFX_EXTRA_BYTES; + fmt_tag = WAVE_FORMAT_WMAUDIO2; + break; + case 3: + subtype = &MEDIASUBTYPE_WMAUDIO3; + codec_data_len = WMAUDIO3_WFX_EXTRA_BYTES; + fmt_tag = WAVE_FORMAT_WMAUDIO3; + break; + case 4: + subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS; + codec_data_len = 18; + fmt_tag = WAVE_FORMAT_WMAUDIO_LOSSLESS; + break; + default: + assert(false); + return false; + } + + size = sizeof(WAVEFORMATEX) + codec_data_len; + if (!(wave_format = CoTaskMemAlloc(size))) + return false; + memset(wave_format, 0, size); + + mt->subtype = *subtype; + mt->bFixedSizeSamples = TRUE; + mt->lSampleSize = format->u.audio_wma.block_align; + mt->cbFormat = size; + mt->pbFormat = (BYTE *)wave_format; + wave_format->wFormatTag = fmt_tag; + wave_format->nChannels = format->u.audio_wma.channels; + wave_format->nSamplesPerSec = format->u.audio_wma.rate; + wave_format->nAvgBytesPerSec = format->u.audio_wma.bitrate / 8; + wave_format->nBlockAlign = format->u.audio_wma.block_align; + wave_format->wBitsPerSample = format->u.audio_wma.depth; + wave_format->cbSize = codec_data_len; + + if (format->u.audio_wma.codec_data_len == codec_data_len) + memcpy(wave_format+1, format->u.audio_wma.codec_data, format->u.audio_wma.codec_data_len); + else + FIXME("Unexpected codec_data length; got %u, expected %lu\n", format->u.audio_wma.codec_data_len, codec_data_len); + return true; +} + #define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
static unsigned int wg_format_get_max_size_video_raw(enum wg_video_format format, unsigned int width, unsigned int height) @@ -384,8 +446,13 @@ unsigned int wg_format_get_max_size(const struct wg_format *format) } break;
- case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_AUDIO_WMA: + /* Estimated max size of a compressed audio frame. + * There's no way to no way to know the real upper bound, + * so let's just use one second of decompressed size and hope it works. */ + return format->u.audio_wma.rate * format->u.audio_wma.channels * format->u.audio_wma.depth / 8; + + case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_VIDEO_H264: case WG_MAJOR_TYPE_VIDEO_WMV: case WG_MAJOR_TYPE_VIDEO_INDEO: @@ -643,7 +710,6 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool switch (format->major_type) { case WG_MAJOR_TYPE_AUDIO_MPEG4: - case WG_MAJOR_TYPE_AUDIO_WMA: case WG_MAJOR_TYPE_VIDEO_H264: case WG_MAJOR_TYPE_VIDEO_INDEO: FIXME("Format %u not implemented!\n", format->major_type); @@ -657,6 +723,9 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool case WG_MAJOR_TYPE_AUDIO_MPEG1: return amt_from_wg_format_audio_mpeg1(mt, format);
+ case WG_MAJOR_TYPE_AUDIO_WMA: + return amt_from_wg_format_audio_wma(mt, format); + case WG_MAJOR_TYPE_VIDEO: return amt_from_wg_format_video(mt, format, wm);
@@ -787,6 +856,55 @@ static bool amt_to_wg_format_audio_mpeg1_layer3(const AM_MEDIA_TYPE *mt, struct return true; }
+static bool amt_to_wg_format_audio_wma(const AM_MEDIA_TYPE *mt, struct wg_format *format) +{ + const WAVEFORMATEX *audio_format = (const WAVEFORMATEX *)mt->pbFormat; + + if (!IsEqualGUID(&mt->formattype, &FORMAT_WaveFormatEx)) + { + FIXME("Unknown format type %s.\n", debugstr_guid(&mt->formattype)); + return false; + } + if (mt->cbFormat < sizeof(*audio_format) || !mt->pbFormat) + { + ERR("Unexpected format size %lu.\n", mt->cbFormat); + return false; + } + + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MSAUDIO1)) + format->u.audio_wma.version = 1; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO2)) + format->u.audio_wma.version = 2; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO3)) + format->u.audio_wma.version = 3; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO_LOSSLESS)) + format->u.audio_wma.version = 4; + else + assert(false); + format->major_type = WG_MAJOR_TYPE_AUDIO_WMA; + format->u.audio_wma.bitrate = audio_format->nAvgBytesPerSec * 8; + format->u.audio_wma.rate = audio_format->nSamplesPerSec; + format->u.audio_wma.depth = audio_format->wBitsPerSample; + format->u.audio_wma.channels = audio_format->nChannels; + format->u.audio_wma.block_align = audio_format->nBlockAlign; + + format->u.audio_wma.codec_data_len = 0; + if (format->u.audio_wma.version == 1) + format->u.audio_wma.codec_data_len = 4; + if (format->u.audio_wma.version == 2) + format->u.audio_wma.codec_data_len = 10; + if (format->u.audio_wma.version == 3) + format->u.audio_wma.codec_data_len = 18; + if (format->u.audio_wma.version == 4) + format->u.audio_wma.codec_data_len = 18; + if (mt->cbFormat >= sizeof(WAVEFORMATEX) + format->u.audio_wma.codec_data_len) + memcpy(format->u.audio_wma.codec_data, audio_format+1, format->u.audio_wma.codec_data_len); + else + FIXME("Too small format block, can't copy codec data\n"); + + return true; +} + static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *format) { static const struct @@ -932,6 +1050,11 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format) return amt_to_wg_format_audio_mpeg1(mt, format); if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MP3)) return amt_to_wg_format_audio_mpeg1_layer3(mt, format); + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MSAUDIO1) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO2) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO3) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO_LOSSLESS)) + return amt_to_wg_format_audio_wma(mt, format); return amt_to_wg_format_audio(mt, format); }
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index f40ae37c0ce..1741299e654 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -1455,7 +1455,7 @@ static void check_audio_type(const WM_MEDIA_TYPE *mt) }
static void test_stream_media_props(IWMStreamConfig *config, - const GUID *majortype, const GUID *subtype, const GUID *formattype, BOOL todo_subtype) + const GUID *majortype, const GUID *subtype, const GUID *formattype) { char mt_buffer[2000]; WM_MEDIA_TYPE *mt = (WM_MEDIA_TYPE *)mt_buffer; @@ -1484,7 +1484,6 @@ static void test_stream_media_props(IWMStreamConfig *config, ok(size == sizeof(WM_MEDIA_TYPE) + mt->cbFormat, "got %lu.\n", size); ok(IsEqualGUID(&mt->majortype, majortype), "Expected major type %s, got %s.\n", debugstr_guid(majortype), debugstr_guid(&mt->majortype)); - todo_wine_if(todo_subtype) ok(IsEqualGUID(&mt->subtype, subtype), "Expected sub type %s, got %s.\n", debugstr_guid(subtype), debugstr_guid(&mt->subtype)); ok(IsEqualGUID(&mt->formattype, formattype), "Expected format type %s, got %s.\n", @@ -1546,9 +1545,9 @@ static void test_sync_reader_types(void) ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) - test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE); + test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx); else - test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE); + test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo);
ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %ld.\n", ref); @@ -3425,9 +3424,9 @@ static void test_async_reader_types(void) ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) - test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE); + test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx); else - test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE); + test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo);
ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %ld.\n", ref);
On Tue Nov 21 19:58:28 2023 +0000, Zebediah Figura wrote:
We explicitly check this in the caller, so you could even get rid of the else.
The WMV converters have similar else clauses, I'd prefer something there. But yeah, no need for something that big.
On Tue Nov 21 19:58:30 2023 +0000, Zebediah Figura wrote:
We should validate cbFormat before doing this.
Sure, can do
From: Alfred Agrell floating@muncher.se
--- dlls/mf/tests/transform.c | 1 + dlls/winegstreamer/wma_decoder.c | 101 ++++++++++++------------------- 2 files changed, 40 insertions(+), 62 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 3f5524784cc..56103c25d09 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -3042,6 +3042,7 @@ static void test_wma_decoder(void) ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE), ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003), /* not required by SetInputType, but needed for the transform to work */ + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16), {0}, }; static const struct attribute_desc output_type_desc[] = diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index d1082fe327a..64c9a1881f2 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -52,10 +52,11 @@ struct wma_decoder IUnknown *outer; LONG refcount;
- IMFMediaType *input_type; - MFT_INPUT_STREAM_INFO input_info; - IMFMediaType *output_type; - MFT_OUTPUT_STREAM_INFO output_info; + struct wg_format input_format; + struct wg_format output_format; + + DWORD input_buf_size; + DWORD output_buf_size;
wg_transform_t wg_transform; struct wg_sample_queue *wg_sample_queue; @@ -68,22 +69,19 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
static HRESULT try_create_wg_transform(struct wma_decoder *decoder) { - struct wg_format input_format, output_format; struct wg_transform_attrs attrs = {0};
if (decoder->wg_transform) wg_transform_destroy(decoder->wg_transform); decoder->wg_transform = 0;
- mf_media_type_to_wg_format(decoder->input_type, &input_format); - if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (decoder->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) + if (decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE;
- if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format, &attrs))) + if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) return E_FAIL;
return S_OK; @@ -135,10 +133,6 @@ static ULONG WINAPI unknown_Release(IUnknown *iface) { if (decoder->wg_transform) wg_transform_destroy(decoder->wg_transform); - if (decoder->input_type) - IMFMediaType_Release(decoder->input_type); - if (decoder->output_type) - IMFMediaType_Release(decoder->output_type);
wg_sample_queue_destroy(decoder->wg_sample_queue); free(decoder); @@ -207,13 +201,18 @@ static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id
TRACE("iface %p, id %lu, info %p.\n", iface, id, info);
- if (!decoder->input_type || !decoder->output_type) + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN + || decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) { memset(info, 0, sizeof(*info)); return MF_E_TRANSFORM_TYPE_NOT_SET; }
- *info = decoder->input_info; + info->hnsMaxLatency = 0; + info->dwFlags = 0; + info->cbSize = decoder->input_buf_size; + info->cbMaxLookahead = 0; + info->cbAlignment = 1; return S_OK; }
@@ -223,13 +222,14 @@ static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD i
TRACE("iface %p, id %lu, info %p.\n", iface, id, info);
- if (!decoder->input_type || !decoder->output_type) + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN + || decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) { memset(info, 0, sizeof(*info)); return MF_E_TRANSFORM_TYPE_NOT_SET; }
- *info = decoder->output_info; + *info = (MFT_OUTPUT_STREAM_INFO){ 0, decoder->output_buf_size, 1 }; return S_OK; }
@@ -273,7 +273,7 @@ static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - UINT32 channel_count, sample_size, sample_rate, block_alignment; + UINT32 sample_size, block_alignment; struct wma_decoder *decoder = impl_from_IMFTransform(iface); IMFMediaType *media_type; const GUID *output_type; @@ -281,7 +281,7 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR
TRACE("iface %p, id %lu, index %lu, type %p.\n", iface, id, index, type);
- if (!decoder->input_type) + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_TRANSFORM_TYPE_NOT_SET;
*type = NULL; @@ -309,23 +309,24 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR goto done; }
- if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, sample_size))) + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, + sample_size))) goto done;
- if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count))) - goto done; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, channel_count))) + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, + decoder->input_format.u.audio_wma.channels))) goto done;
- if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &sample_rate))) - goto done; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, sample_rate))) + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, + decoder->input_format.u.audio_wma.rate))) goto done;
- block_alignment = sample_size * channel_count / 8; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, block_alignment))) + block_alignment = sample_size * decoder->input_format.u.audio_wma.channels / 8; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, + block_alignment))) goto done; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, sample_rate * block_alignment))) + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, + decoder->input_format.u.audio_wma.rate * block_alignment))) goto done;
if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1))) @@ -381,23 +382,9 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK;
- if (!decoder->input_type && FAILED(hr = MFCreateMediaType(&decoder->input_type))) - return hr; - - if (decoder->output_type) - { - IMFMediaType_Release(decoder->output_type); - decoder->output_type = NULL; - } - - if (SUCCEEDED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->input_type))) - decoder->input_info.cbSize = block_alignment; - else - { - IMFMediaType_Release(decoder->input_type); - decoder->input_info.cbSize = 0; - decoder->input_type = NULL; - } + mf_media_type_to_wg_format(type, &decoder->input_format); + decoder->input_buf_size = block_alignment; + decoder->output_format.major_type = WG_MAJOR_TYPE_UNKNOWN;
return hr; } @@ -413,7 +400,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
TRACE("iface %p, id %lu, type %p, flags %#lx.\n", iface, id, type, flags);
- if (!decoder->input_type) + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_TRANSFORM_TYPE_NOT_SET;
if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) || @@ -456,25 +443,18 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK;
- if (FAILED(IMFMediaType_SetUINT32(decoder->input_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, sample_size))) - return MF_E_INVALIDMEDIATYPE; - - if (!decoder->output_type && FAILED(hr = MFCreateMediaType(&decoder->output_type))) - return hr; + decoder->input_format.u.audio_wma.depth = sample_size;
- if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->output_type))) - goto failed; + mf_media_type_to_wg_format(type, &decoder->output_format); + decoder->output_buf_size = 1024 * block_alignment * channel_count;
if (FAILED(hr = try_create_wg_transform(decoder))) goto failed;
- decoder->output_info.cbSize = 1024 * block_alignment * channel_count; return S_OK;
failed: - IMFMediaType_Release(decoder->output_type); - decoder->output_info.cbSize = 0; - decoder->output_type = NULL; + decoder->output_format.major_type = WG_MAJOR_TYPE_UNKNOWN; return hr; }
@@ -881,9 +861,6 @@ HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out) decoder->refcount = 1; decoder->outer = outer ? outer : &decoder->IUnknown_inner;
- decoder->input_info.cbAlignment = 1; - decoder->output_info.cbAlignment = 1; - *out = &decoder->IUnknown_inner; TRACE("Created decoder %p\n", *out); return S_OK;
From: Alfred Agrell floating@muncher.se
--- dlls/mf/tests/transform.c | 34 +---- dlls/winegstreamer/wma_decoder.c | 240 ++++++++++++++++++++++++++++--- 2 files changed, 224 insertions(+), 50 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 56103c25d09..8374d12cd65 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -1384,7 +1384,9 @@ static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DM "Got unexpected formattype %s.\n", debugstr_guid(&media_type->formattype)); ok_(__FILE__, line)(media_type->pUnk == NULL, "Got unexpected pUnk %p.\n", media_type->pUnk); - todo_wine_if(expected->cbFormat && expected->cbFormat != sizeof(VIDEOINFOHEADER)) + todo_wine_if(expected->cbFormat + && expected->cbFormat != sizeof(VIDEOINFOHEADER) + && IsEqualGUID(&expected->majortype, &MEDIATYPE_Video)) check_member_(__FILE__, line, *media_type, *expected, "%lu", cbFormat);
if (expected->pbFormat) @@ -3384,8 +3386,6 @@ static void test_wma_decoder_dmo_input_type(void) bad_input_type = (void *)buffer_bad;
/* Test GetInputType. */ - todo_wine - { count = ARRAY_SIZE(expected_input_types); hr = IMediaObject_GetInputType(dmo, 1, 0, NULL); ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr); @@ -3401,7 +3401,6 @@ static void test_wma_decoder_dmo_input_type(void) ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr); hr = IMediaObject_GetInputType(dmo, 0, count - 1, NULL); ok(hr == S_OK, "GetInputType returned %#lx.\n", hr); - }
i = -1; while (SUCCEEDED(hr = IMediaObject_GetInputType(dmo, 0, ++i, &type))) @@ -3411,17 +3410,13 @@ static void test_wma_decoder_dmo_input_type(void) MoFreeMediaType(&type); winetest_pop_context(); } - todo_wine ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr); - todo_wine ok(i == count, "%lu types.\n", i);
/* Test SetInputType. */ init_dmo_media_type_audio(good_input_type, &MEDIASUBTYPE_WMAUDIO2, 2, 22050, 32); memset(bad_input_type, 0, sizeof(buffer_bad));
- todo_wine - { hr = IMediaObject_SetInputType(dmo, 1, NULL, 0); ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_SetInputType(dmo, 1, bad_input_type, 0); @@ -3477,11 +3472,9 @@ static void test_wma_decoder_dmo_input_type(void) ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_SetInputType(dmo, 0, good_input_type, 0x4); ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr); - }
/* Test GetInputCurrentType. */ hr = IMediaObject_SetInputType(dmo, 0, NULL, DMO_SET_TYPEF_CLEAR); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetInputCurrentType(dmo, 1, NULL); todo_wine @@ -3497,7 +3490,6 @@ static void test_wma_decoder_dmo_input_type(void) ok(hr == DMO_E_TYPE_NOT_SET, "GetInputCurrentType returned %#lx.\n", hr);
hr = IMediaObject_SetInputType(dmo, 0, good_input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetInputCurrentType(dmo, 1, NULL); todo_wine @@ -3567,18 +3559,13 @@ static void test_wma_decoder_dmo_output_type(void)
/* Test GetOutputType. */ hr = IMediaObject_GetOutputType(dmo, 1, 0, NULL); - todo_wine ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputType(dmo, 0, 0, NULL); - todo_wine ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned %#lx.\n", hr);
hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
- todo_wine - { count = 1; hr = IMediaObject_GetOutputType(dmo, 1, 0, NULL); ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr); @@ -3594,7 +3581,6 @@ static void test_wma_decoder_dmo_output_type(void) ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputType(dmo, 0, count - 1, NULL); ok(hr == S_OK, "GetOutputType returned %#lx.\n", hr); - }
i = -1; while (SUCCEEDED(hr = IMediaObject_GetOutputType(dmo, 0, ++i, &type))) @@ -3604,17 +3590,12 @@ static void test_wma_decoder_dmo_output_type(void) MoFreeMediaType(&type); winetest_pop_context(); } - todo_wine ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr); - todo_wine ok(i == count, "%lu types.\n", i);
/* Test SetOutputType. */ hr = IMediaObject_SetInputType(dmo, 0, NULL, DMO_SET_TYPEF_CLEAR); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); - todo_wine - { hr = IMediaObject_SetOutputType(dmo, 1, NULL, 0); ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 1, good_output_type, 0); @@ -3635,14 +3616,10 @@ static void test_wma_decoder_dmo_output_type(void) ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 0, good_output_type, 0x4); ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr); - }
hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
- todo_wine - { hr = IMediaObject_SetOutputType(dmo, 1, NULL, 0); ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 1, bad_output_type, 0); @@ -3698,11 +3675,9 @@ static void test_wma_decoder_dmo_output_type(void) ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 0, good_output_type, 0x4); ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr); - }
/* Test GetOutputCurrentType. */ hr = IMediaObject_SetOutputType(dmo, 0, NULL, DMO_SET_TYPEF_CLEAR); - todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); todo_wine { @@ -3717,7 +3692,6 @@ static void test_wma_decoder_dmo_output_type(void) }
hr = IMediaObject_SetOutputType(dmo, 0, good_output_type, 0); - todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); todo_wine { @@ -3740,7 +3714,6 @@ static void test_wma_decoder_dmo_output_type(void) todo_wine ok(hr == S_OK, "GetInputCurrentType returned %#lx.\n", hr); hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputCurrentType(dmo, 0, &type); todo_wine @@ -3748,7 +3721,6 @@ static void test_wma_decoder_dmo_output_type(void)
init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate * 2, 32); hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputCurrentType(dmo, 0, &type); todo_wine diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 64c9a1881f2..91a49e029fa 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -24,6 +24,7 @@ #include "mfobjects.h" #include "mftransform.h" #include "wmcodecdsp.h" +#include "mediaerr.h"
#include "wine/debug.h"
@@ -630,29 +631,182 @@ static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWOR static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type) { - FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); - return E_NOTIMPL; + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= ARRAY_SIZE(wma_decoder_input_types)) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Audio; + type->subtype = *wma_decoder_input_types[type_index]; + type->bFixedSizeSamples = FALSE; + type->bTemporalCompression = TRUE; + type->lSampleSize = 0; + + return S_OK; }
static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type) { - FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + WAVEFORMATEX *wfx; + + TRACE("iface %p, index %lu, type_index %lu, type %p\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= 1) + return DMO_E_NO_MORE_ITEMS; + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return DMO_E_TYPE_NOT_SET; + if (!type) + return S_OK; + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Audio; + type->subtype = MEDIASUBTYPE_PCM; + type->formattype = FORMAT_WaveFormatEx; + type->bFixedSizeSamples = FALSE; + type->bTemporalCompression = TRUE; + type->lSampleSize = 0; + + type->cbFormat = sizeof(WAVEFORMATEX); + type->pbFormat = CoTaskMemAlloc(type->cbFormat); + memset(type->pbFormat, 0, type->cbFormat); + + wfx = (WAVEFORMATEX *)type->pbFormat; + wfx->wFormatTag = WAVE_FORMAT_PCM; + wfx->nChannels = decoder->input_format.u.audio_wma.channels; + wfx->nSamplesPerSec = decoder->input_format.u.audio_wma.rate; + wfx->wBitsPerSample = decoder->input_format.u.audio_wma.depth; + wfx->nAvgBytesPerSec = wfx->nChannels * wfx->nSamplesPerSec * wfx->wBitsPerSample / 8; + wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; + + return S_OK; }
static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags) { - FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + struct wg_format wg_format; + unsigned int i; + + TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (flags & DMO_SET_TYPEF_CLEAR) + { + if (flags != DMO_SET_TYPEF_CLEAR) + return E_INVALIDARG; + memset(&decoder->input_format, 0, sizeof(decoder->input_format)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + if (!type) + return E_POINTER; + if (flags & ~DMO_SET_TYPEF_TEST_ONLY) + return E_INVALIDARG; + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < ARRAY_SIZE(wma_decoder_input_types); ++i) + if (IsEqualGUID(&type->subtype, wma_decoder_input_types[i])) + break; + if (i == ARRAY_SIZE(wma_decoder_input_types)) + return DMO_E_TYPE_NOT_ACCEPTED; + + if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + return DMO_E_TYPE_NOT_ACCEPTED; + assert(wg_format.major_type == WG_MAJOR_TYPE_AUDIO_WMA); + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + decoder->input_format = wg_format; + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + + return S_OK; }
static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags) { - FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + struct wg_transform_attrs attrs = {0}; + struct wg_format wg_format; + unsigned int i; + + TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (flags & DMO_SET_TYPEF_CLEAR) + { + if (flags != DMO_SET_TYPEF_CLEAR) + return E_INVALIDARG; + memset(&decoder->output_format, 0, sizeof(decoder->output_format)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + if (!type) + return E_POINTER; + if (flags & ~DMO_SET_TYPEF_TEST_ONLY) + return E_INVALIDARG; + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < ARRAY_SIZE(wma_decoder_output_types); ++i) + if (IsEqualGUID(&type->subtype, wma_decoder_output_types[i])) + break; + if (i == ARRAY_SIZE(wma_decoder_output_types)) + return DMO_E_TYPE_NOT_ACCEPTED; + + + if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + return DMO_E_TYPE_NOT_ACCEPTED; + assert(wg_format.major_type == WG_MAJOR_TYPE_AUDIO); + + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return DMO_E_TYPE_NOT_SET; + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + decoder->output_format = wg_format; + + /* Set up wg_transform. */ + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) + return E_FAIL; + + return S_OK; }
static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) @@ -677,8 +831,21 @@ static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD i
static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) { - FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment); + + if (!size || !alignment) + return E_POINTER; + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return DMO_E_TYPE_NOT_SET; + + *size = 8192; + *alignment = 1; + + return S_OK; }
static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) @@ -695,14 +862,27 @@ static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD
static HRESULT WINAPI media_object_Flush(IMediaObject *iface) { - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + if (FAILED(hr = wg_transform_flush(decoder->wg_transform))) + return hr; + + wg_sample_queue_flush(decoder->wg_sample_queue, TRUE); + + return S_OK; }
static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) { - FIXME("iface %p, index %lu stub!\n", iface, index); - return E_NOTIMPL; + TRACE("iface %p, index %lu.\n", iface, index); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + return S_OK; }
static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) @@ -726,16 +906,38 @@ static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD ind static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) { - FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface, - index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface, + index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + return wg_transform_push_dmo(decoder->wg_transform, buffer, flags, timestamp, timelength, decoder->wg_sample_queue); }
static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) { - FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface, flags, count, buffers, status); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + hr = wg_transform_read_dmo(decoder->wg_transform, buffers); + + if (SUCCEEDED(hr)) + { + /* WMA Lossless emits anything from 0 to 12 packets of output for each packet of input */ + buffers[0].dwStatus |= DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE; + wg_sample_queue_flush(decoder->wg_sample_queue, false); + } + + return hr; }
static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock)
From: Alfred Agrell floating@muncher.se
--- dlls/mf/tests/transform.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 8374d12cd65..ea78f14b581 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -3533,7 +3533,7 @@ static void test_wma_decoder_dmo_output_type(void)
char buffer_good_output[1024], buffer_bad_output[1024], buffer_input[1024]; DMO_MEDIA_TYPE *good_output_type, *bad_output_type, *input_type, type; - DWORD count, i, ret; + DWORD count, i, ret, size, alignment; IMediaObject *dmo; HRESULT hr;
@@ -3710,6 +3710,20 @@ static void test_wma_decoder_dmo_output_type(void) MoFreeMediaType(&type); }
+ /* Test GetOutputSizeInfo. */ + hr = IMediaObject_GetOutputSizeInfo(dmo, 1, NULL, NULL); + ok(hr == E_POINTER, "GetOutputSizeInfo returned %#lx.\n", hr); + hr = IMediaObject_GetOutputSizeInfo(dmo, 0, NULL, NULL); + ok(hr == E_POINTER, "GetOutputSizeInfo returned %#lx.\n", hr); + hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, NULL); + ok(hr == E_POINTER, "GetOutputSizeInfo returned %#lx.\n", hr); + hr = IMediaObject_GetOutputSizeInfo(dmo, 0, NULL, &alignment); + ok(hr == E_POINTER, "GetOutputSizeInfo returned %#lx.\n", hr); + hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment); + ok(hr == S_OK, "GetOutputSizeInfo returned %#lx.\n", hr); + ok(size == 8192, "Unexpected size %lu.\n", size); + ok(alignment == 1, "Unexpected alignment %lu.\n", alignment); + hr = IMediaObject_GetInputCurrentType(dmo, 0, input_type); todo_wine ok(hr == S_OK, "GetInputCurrentType returned %#lx.\n", hr);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=140119
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w7u_adm (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w7u_el (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0. 0a5c:transform: unhandled exception c0000005 at 009E45C2
=== w8 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w8adm (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w864 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064v1507 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064v1809 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064_tsign (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w10pro64 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w10pro64_en_AE_u8 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w11pro64 (32 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w7pro64 (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w864 (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064v1507 (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064v1809 (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064_2qxl (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064_adm (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w1064_tsign (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w10pro64 (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w10pro64_ar (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w10pro64_ja (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w10pro64_zh_CN (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== w11pro64_amd (64 bit report) ===
mf: transform.c:734: Test failed: wmadec: got result 0.
=== debian11 (32 bit report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit ar:MA report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit de report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit fr report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit he:IL report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit hi:IN report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit ja:JP report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11 (32 bit zh:CN report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11b (32 bit WoW report) ===
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
=== debian11b (64 bit WoW report) ===
dinput: device8.c:2238: Test failed: 0x700: got key_state[0] 0
mf: transform.c:1403: Test failed: wmadec: type 0: Got nAvgBytesPerSec 176400, expected 88200. transform.c:1403: Test failed: wmadec: type 0: Got nBlockAlign 8, expected 4. transform.c:1403: Test failed: wmadec: type 0: Got wBitsPerSample 32, expected 16.
On Tue Nov 21 21:53:51 2023 +0000, Alfred Agrell wrote:
We could, but that should be discussed among all Wine maintainers, and a MR is a quite poor place for that.
Well, Wine hasn't really ever had formal requirements in terms of compiler or feature support; we just use whatever compilers support (tempered also by aesthetic preference). Hence often new language features get added simply by showing up in one patch and waiting for someone to complain.
On Tue Nov 21 21:53:53 2023 +0000, Alfred Agrell wrote:
Hard to know if there are more samples to process, other than by simply always saying there's more and occasionally returning "sorry, I've got nothing after all". The first input packet returns zero output packets, so the DMO wrapper has to be prepared for unexpected emptiness anyways; might as well reuse that codepath. This code is in the WMA decoder specifically.
This is true. Given GStreamer's asynchronous nature this may arguably even be the best solution. We can assume that the GStreamer element is going to be synchronous, which is often the case, but not always...
It does make me nervous to return DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE and then have a following call to ProcessOutput() fail, though. But I doubt there's a better alternative.
On Tue Nov 21 21:53:53 2023 +0000, Alfred Agrell wrote:
Yes, it would. I created a comprehensive test for WMV1+WMA1 media types in !4449 using test.wmv, but as I said at https://gitlab.winehq.org/wine/wine/-/merge_requests/4450#note_53102, I don't have access to other suitable test files; if you do, upload em somewhere and I'll add them.
ffmpeg can do wmav2 at least, but other than that, I guess it'd be necessary to use Microsoft's encoders.
Having at least one test is probably good enough, though I would never object to more.
Testbot is reporting failures on Windows and Wine:
On Tue Nov 21 22:26:01 2023 +0000, Zebediah Figura wrote:
This is true. Given GStreamer's asynchronous nature this may arguably even be the best solution. We can assume that the GStreamer element is going to be synchronous, which is often the case, but not always... It does make me nervous to return DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE and then have a following call to ProcessOutput() fail, though. But I doubt there's a better alternative.
Yeah, this looks comparable to mpegpsdemux output to me; whatever it gives to the mpegvideoparse element has nothing to do with the frame boundaries. Especially considering all input packets are 13375 bytes - 13375 bytes of losslessly compressed input means variable amount of output.
I could check if the queue is empty and return a flag based on that, but that'd be a chunk of WMA-specific code in shared regions, it would have zero test coverage unless I include that 80MB Wagamama WMV somewhere, and it would solve a problem that affects exactly nothing in practice.
Yeah, the current solution is still the best option I can think of.
(But yes, still not good.)
On Tue Nov 21 23:47:37 2023 +0000, Zebediah Figura wrote:
Testbot is reporting failures on Windows and Wine: https://testbot.winehq.org/JobDetails.pl?Key=140119
Hard to see with all the false positives floating around; good catch. I should've guessed that adding that depth parameter would have some side effects.
Fixed the 734 failure. 1403 doesn't reproduce for me, and the symptoms suggest uninitialized memory or something; I hope it's the same root cause as 734.