From: Anton Baskanov baskanov@gmail.com
Fixes in-game video playback in Earth 2150. --- dlls/quartz/tests/mpegsplit.c | 4 +- dlls/winegstreamer/quartz_parser.c | 77 ++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 12 deletions(-)
diff --git a/dlls/quartz/tests/mpegsplit.c b/dlls/quartz/tests/mpegsplit.c index ea9eb7e87c6..dca22f73a63 100644 --- a/dlls/quartz/tests/mpegsplit.c +++ b/dlls/quartz/tests/mpegsplit.c @@ -510,7 +510,7 @@ static void test_find_pin(void)
hr = IBaseFilter_FindPin(filter, L"Audio", &pin); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(pin == pin2, "Expected pin %p, got %p.\n", pin2, pin); + ok(pin == pin2, "Expected pin %p, got %p.\n", pin2, pin); IPin_Release(pin); IPin_Release(pin2);
@@ -519,7 +519,7 @@ static void test_find_pin(void)
hr = IBaseFilter_FindPin(filter, L"Video", &pin); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(pin == pin2, "Expected pin %p, got %p.\n", pin2, pin); + ok(pin == pin2, "Expected pin %p, got %p.\n", pin2, pin); IPin_Release(pin); IPin_Release(pin2);
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index c41b0dca0f6..63322bec324 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -73,7 +73,7 @@ struct parser
HANDLE read_thread;
- BOOL (*init_gst)(struct parser *filter); + BOOL (*init_gst)(struct parser *filter, const AM_MEDIA_TYPE *mt); HRESULT (*source_query_accept)(struct parser_source *pin, const AM_MEDIA_TYPE *mt); HRESULT (*source_get_media_type)(struct parser_source *pin, unsigned int index, AM_MEDIA_TYPE *mt); }; @@ -1517,7 +1517,7 @@ static HRESULT parser_sink_connect(struct strmbase_sink *iface, IPin *peer, cons if (FAILED(hr = wg_parser_connect(filter->wg_parser, file_size))) goto err;
- if (!filter->init_gst(filter)) + if (!filter->init_gst(filter, pmt)) { hr = E_FAIL; goto err; @@ -1556,7 +1556,7 @@ static const struct strmbase_sink_ops sink_ops = .sink_disconnect = parser_sink_disconnect, };
-static BOOL decodebin_parser_filter_init_gst(struct parser *filter) +static BOOL decodebin_parser_filter_init_gst(struct parser *filter, const AM_MEDIA_TYPE *mt) { wg_parser_t parser = filter->wg_parser; unsigned int i, stream_count; @@ -2198,7 +2198,7 @@ static const struct strmbase_sink_ops wave_parser_sink_ops = .sink_disconnect = parser_sink_disconnect, };
-static BOOL wave_parser_filter_init_gst(struct parser *filter) +static BOOL wave_parser_filter_init_gst(struct parser *filter, const AM_MEDIA_TYPE *mt) { if (!create_pin(filter, wg_parser_get_stream(filter->wg_parser, 0), L"output")) return FALSE; @@ -2267,7 +2267,7 @@ static const struct strmbase_sink_ops avi_splitter_sink_ops = .sink_disconnect = parser_sink_disconnect, };
-static BOOL avi_splitter_filter_init_gst(struct parser *filter) +static BOOL avi_splitter_filter_init_gst(struct parser *filter, const AM_MEDIA_TYPE *mt) { wg_parser_t parser = filter->wg_parser; uint32_t i, stream_count; @@ -2350,9 +2350,51 @@ static const struct strmbase_sink_ops mpeg_splitter_sink_ops = .sink_disconnect = parser_sink_disconnect, };
-static BOOL mpeg_splitter_filter_init_gst(struct parser *filter) +static BOOL mpeg_splitter_is_audio_stream_first(struct parser *filter, const AM_MEDIA_TYPE *mt) +{ + DWORD max_stream_count; + DWORD header_length; + BYTE buffer[2]; + DWORD i; + + if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Stream) + || !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1System)) + return FALSE; + + if (FAILED(IAsyncReader_SyncRead(filter->reader, 16, 2, buffer))) + return FALSE; + + header_length = MAKEWORD(buffer[1], buffer[0]); + if (header_length < 6) + return FALSE; + max_stream_count = (header_length - 6) / 3; + + for (i = 0; i < max_stream_count; ++i) + { + BYTE stream_id; + + if (FAILED(IAsyncReader_SyncRead(filter->reader, 24 + i * 3, 1, &stream_id))) + return FALSE; + + if (!(stream_id & 0x80)) + break; + + if (0xe0 <= stream_id && stream_id <= 0xef) + return FALSE; + if (0xc0 <= stream_id && stream_id <= 0xdf) + return TRUE; + + WARN("Unknown stream type 0x%02x.\n", stream_id); + } + + return FALSE; +} + +static BOOL mpeg_splitter_filter_init_gst(struct parser *filter, const AM_MEDIA_TYPE *mt) { wg_parser_t parser = filter->wg_parser; + wg_parser_stream_t video_stream = 0; + wg_parser_stream_t audio_stream = 0; unsigned int i, stream_count; wg_parser_stream_t stream; struct wg_format fmt; @@ -2364,17 +2406,32 @@ static BOOL mpeg_splitter_filter_init_gst(struct parser *filter) wg_parser_stream_get_preferred_format(stream, &fmt); if (fmt.major_type == WG_MAJOR_TYPE_VIDEO_MPEG1) { - if (!create_pin(filter, wg_parser_get_stream(parser, i), L"Video")) - return FALSE; + if (!video_stream) + video_stream = stream; } else if (fmt.major_type == WG_MAJOR_TYPE_AUDIO_MPEG1) { - if (!create_pin(filter, wg_parser_get_stream(parser, i), L"Audio")) - return FALSE; + if (!audio_stream) + audio_stream = stream; } else FIXME("unexpected format %u\n", fmt.major_type); }
+ if (mpeg_splitter_is_audio_stream_first(filter, mt)) + { + if (audio_stream && !create_pin(filter, audio_stream, L"Audio")) + return FALSE; + if (video_stream && !create_pin(filter, video_stream, L"Video")) + return FALSE; + } + else + { + if (video_stream && !create_pin(filter, video_stream, L"Video")) + return FALSE; + if (audio_stream && !create_pin(filter, audio_stream, L"Audio")) + return FALSE; + } + return TRUE; }