-- v4: winegstreamer: Output compressed samples from the media source. winegstreamer: Stop on unparsed H.264 in autoplug-continue. winegstreamer: Explicitly append an H.264 parser for H.264.
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/winegstreamer/wg_parser.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index e806298fb57..639d5356b4a 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -957,6 +957,23 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser if (!link_src_to_element(pad, first) || !link_element_to_sink(last, stream->my_sink)) return false; } + else if (!strcmp(name, "video/x-h264")) + { + GstCaps *parsed_caps; + + /* Windows needs stream-format=byte-stream. + * decodebin will autoplug a h264parse if we stop on parsed=true, + * but it's not enough, because that h264parse will already have its + * caps set (to stream-format=avc), and we can't link it to our pad. */ + parsed_caps = gst_caps_copy(caps); + gst_caps_set_simple(parsed_caps, "parsed", G_TYPE_BOOLEAN, true, NULL); + if (!(element = find_element(GST_ELEMENT_FACTORY_TYPE_PARSER, caps, parsed_caps)) + || !append_element(parser->container, element, &first, &last)) + return false; + + if (!link_src_to_element(pad, first) || !link_element_to_sink(last, stream->my_sink)) + return false; + } else { return link_src_to_sink(pad, stream->my_sink);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/winegstreamer/wg_parser.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 639d5356b4a..f0cdfd47e65 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -133,10 +133,16 @@ static struct wg_parser_stream *get_stream(wg_parser_stream_t stream)
static bool caps_is_compressed(GstCaps *caps) { + const GstStructure *structure = gst_caps_get_structure(caps, 0); struct wg_format format;
- if (!caps) - return false; + /* H.264 not in byte-stream format cannot be used by Windows. + * wg_format_from_caps() rejects this accordingly, but we still want to + * stop here, and force h264parse to convert to byte-stream for us. + * Therefore explicitly accept it here. */ + if (!strcmp(gst_structure_get_name(structure), "video/x-h264")) + return true; + wg_format_from_caps(&format, caps);
return format.major_type != WG_MAJOR_TYPE_UNKNOWN @@ -526,7 +532,7 @@ static bool parser_no_more_pads(struct wg_parser *parser)
static gboolean autoplug_continue_cb(GstElement * decodebin, GstPad *pad, GstCaps * caps, gpointer user) { - return !caps_is_compressed(caps); + return caps && !caps_is_compressed(caps); }
static GstAutoplugSelectResult autoplug_select_cb(GstElement *bin, GstPad *pad,
From: Elizabeth Figura zfigura@codeweavers.com
Several games depend directly or indirectly on this behaviour, including Onimusha: Warlords and Call of Cthulhu. --- dlls/mfplat/tests/mfplat.c | 48 +++++++++++++++---------------- dlls/mfreadwrite/tests/mfplat.c | 6 ++-- dlls/winegstreamer/media_source.c | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 1cdbb6f48ff..a66467d6dfd 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -1090,13 +1090,13 @@ static void test_compressed_media_types(IMFSourceResolver *resolver) L"video/mp4", { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), - ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .todo_value = TRUE), - ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_MPEG2Video, .todo = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264), + ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_MPEG2Video), ATTR_RATIO(MF_MT_FRAME_SIZE, 320, 240), ATTR_RATIO(MF_MT_FRAME_RATE, 30, 1), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1, .todo = TRUE), - ATTR_UINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_High, .todo = TRUE), - ATTR_UINT32(MF_MT_MPEG2_LEVEL, eAVEncH264VLevel2, .todo = TRUE), + ATTR_UINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_High), + ATTR_UINT32(MF_MT_MPEG2_LEVEL, eAVEncH264VLevel2), }, }, { @@ -1104,19 +1104,19 @@ static void test_compressed_media_types(IMFSourceResolver *resolver) L"video/mp4", { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), - ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .todo_value = TRUE), - ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx, .todo = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC), + ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), - ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .todo_value = TRUE), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16), ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), - ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 9180, .todo_value = TRUE), - ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 9180, .todo = TRUE), + ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1), ATTR_UINT32(MF_MT_AVG_BITRATE, 73440, .todo = TRUE), - ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0), ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0, .todo = TRUE), - ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), - ATTR_BLOB(MF_MT_USER_DATA, aac_data, sizeof(aac_data), .todo = TRUE), + ATTR_BLOB(MF_MT_USER_DATA, aac_data, sizeof(aac_data)), }, }, { @@ -1124,7 +1124,7 @@ static void test_compressed_media_types(IMFSourceResolver *resolver) L"video/x-ms-wmv", { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), - ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .todo_value = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1), ATTR_RATIO(MF_MT_FRAME_SIZE, 320, 240), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1, .todo = TRUE), }, @@ -1134,13 +1134,13 @@ static void test_compressed_media_types(IMFSourceResolver *resolver) L"video/x-ms-wmv", { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), - ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .todo_value = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), - ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000, .todo_value = TRUE), - ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1, .todo = TRUE), - ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 743, .todo_value = TRUE), - ATTR_BLOB(MF_MT_USER_DATA, wma2_data, sizeof(wma2_data), .todo = TRUE), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000), + ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 743), + ATTR_BLOB(MF_MT_USER_DATA, wma2_data, sizeof(wma2_data)), }, }, { @@ -1148,12 +1148,12 @@ static void test_compressed_media_types(IMFSourceResolver *resolver) L"video/mp4", { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), - ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3, .todo_value = TRUE), - ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx, .todo = TRUE), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3), + ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), - ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), - ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1, .todo = TRUE), - ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .todo = TRUE), + ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1), + ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), }, }, @@ -1229,7 +1229,7 @@ static void test_compressed_media_types(IMFSourceResolver *resolver)
hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(count == 1, "Got type count %lu.\n", count); + todo_wine_if (i == 5) ok(count == 1, "Got type count %lu.\n", count);
IMFMediaTypeHandler_Release(handler); IMFStreamDescriptor_Release(sd); diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 2946425e494..6409d4c9a93 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -942,7 +942,7 @@ static void test_source_reader(const char *filename, bool video)
hr = IMFMediaType_GetGUID(mediatype, &MF_MT_SUBTYPE, &subtype); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&subtype, &MFVideoFormat_H264), "Got subtype %s.\n", debugstr_guid(&subtype)); + ok(IsEqualGUID(&subtype, &MFVideoFormat_H264), "Got subtype %s.\n", debugstr_guid(&subtype));
hr = IMFMediaType_GetUINT64(mediatype, &MF_MT_FRAME_SIZE, &framesize); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -950,7 +950,7 @@ static void test_source_reader(const char *filename, bool video) (unsigned int)(framesize >> 32), (unsigned int)framesize);
hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_DEFAULT_STRIDE, &stride); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
IMFMediaType_Release(mediatype);
@@ -1002,7 +1002,7 @@ static void test_source_reader(const char *filename, bool video)
hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_DEFAULT_STRIDE, &stride); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(stride == 160 * 4, "Got stride %u.\n", stride); + ok(stride == 160 * 4, "Got stride %u.\n", stride);
IMFMediaType_Release(mediatype); } diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index ab842b3e438..155d4ba0479 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -1743,7 +1743,7 @@ static HRESULT media_source_create(struct object_context *context, IMFMediaSourc if (FAILED(hr = MFAllocateWorkQueue(&object->async_commands_queue))) goto fail;
- if (!(parser = wg_parser_create(FALSE))) + if (!(parser = wg_parser_create(true))) { hr = E_OUTOFMEMORY; goto fail;