Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/gst_private.h | 3 +++ dlls/winegstreamer/quartz_parser.c | 2 +- dlls/winegstreamer/wm_reader.c | 23 +++++++++++++++++++++-- dlls/wmvcore/tests/wmvcore.c | 6 +++--- 4 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 8b5183a95ee..7d5828a15d6 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -101,6 +101,8 @@ HRESULT decodebin_parser_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; HRESULT wave_parser_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
+bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format); + BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN; @@ -118,6 +120,7 @@ struct wm_stream struct wm_reader *reader; struct wg_parser_stream *wg_stream; WORD index; + struct wg_format format; };
struct wm_reader diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 6d79d2ef129..0862a75b7ef 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -343,7 +343,7 @@ static bool amt_from_wg_format_video(AM_MEDIA_TYPE *mt, const struct wg_format * return true; }
-static bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format) +bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format) { memset(mt, 0, sizeof(*mt));
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 682f9a2ae50..feb000c96ed 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -80,8 +80,26 @@ static ULONG WINAPI stream_config_Release(IWMStreamConfig *iface)
static HRESULT WINAPI stream_config_GetStreamType(IWMStreamConfig *iface, GUID *type) { - FIXME("iface %p, type %p, stub!\n", iface, type); - return E_NOTIMPL; + struct stream_config *config = impl_from_IWMStreamConfig(iface); + struct wm_reader *reader = config->stream->reader; + AM_MEDIA_TYPE mt; + + TRACE("config %p, type %p.\n", config, type); + + EnterCriticalSection(&reader->cs); + + if (!amt_from_wg_format(&mt, &config->stream->format)) + { + LeaveCriticalSection(&reader->cs); + return E_OUTOFMEMORY; + } + + *type = mt.majortype; + FreeMediaType(&mt); + + LeaveCriticalSection(&reader->cs); + + return S_OK; }
static HRESULT WINAPI stream_config_GetStreamNumber(IWMStreamConfig *iface, WORD *number) @@ -1047,6 +1065,7 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream) stream->wg_stream = wg_parser_get_stream(reader->wg_parser, i); stream->reader = reader; stream->index = i; + wg_parser_stream_get_preferred_format(stream->wg_stream, &stream->format); }
LeaveCriticalSection(&reader->cs); diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index 385cda74aba..031a1841360 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -704,11 +704,11 @@ static void test_sync_reader_types(void) ok(stream_number == i + 1, "Got stream number %u.\n", stream_number);
hr = IWMStreamConfig_GetStreamType(config, &majortype); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); if (!i) - todo_wine ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype)); + ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype)); else - todo_wine ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype)); + ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %d.\n", ref);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/gst_private.h | 2 + dlls/winegstreamer/wm_reader.c | 133 +++++++++++++++++++++++++++++ dlls/winegstreamer/wm_syncreader.c | 11 ++- dlls/wmvcore/tests/wmvcore.c | 51 +++++------ 4 files changed, 165 insertions(+), 32 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 7d5828a15d6..db715a9ad70 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -153,6 +153,8 @@ struct wm_reader_ops
void wm_reader_cleanup(struct wm_reader *reader); HRESULT wm_reader_close(struct wm_reader *reader); +HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, + IWMOutputMediaProps **props); void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops); HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index feb000c96ed..2a93e6e1d35 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -20,6 +20,122 @@
WINE_DEFAULT_DEBUG_CHANNEL(wmvcore);
+static struct wm_stream *get_stream_by_output_number(struct wm_reader *reader, DWORD output) +{ + if (output < reader->stream_count) + return &reader->streams[output]; + WARN("Invalid output number %u.\n", output); + return NULL; +} + +struct output_props +{ + IWMOutputMediaProps IWMOutputMediaProps_iface; + LONG refcount; +}; + +static inline struct output_props *impl_from_IWMOutputMediaProps(IWMOutputMediaProps *iface) +{ + return CONTAINING_RECORD(iface, struct output_props, IWMOutputMediaProps_iface); +} + +static HRESULT WINAPI output_props_QueryInterface(IWMOutputMediaProps *iface, REFIID iid, void **out) +{ + struct output_props *props = impl_from_IWMOutputMediaProps(iface); + + TRACE("props %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IWMOutputMediaProps)) + *out = &props->IWMOutputMediaProps_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI output_props_AddRef(IWMOutputMediaProps *iface) +{ + struct output_props *props = impl_from_IWMOutputMediaProps(iface); + ULONG refcount = InterlockedIncrement(&props->refcount); + + TRACE("%p increasing refcount to %u.\n", props, refcount); + + return refcount; +} + +static ULONG WINAPI output_props_Release(IWMOutputMediaProps *iface) +{ + struct output_props *props = impl_from_IWMOutputMediaProps(iface); + ULONG refcount = InterlockedDecrement(&props->refcount); + + TRACE("%p decreasing refcount to %u.\n", props, refcount); + + if (!refcount) + free(props); + + return refcount; +} + +static HRESULT WINAPI output_props_GetType(IWMOutputMediaProps *iface, GUID *major_type) +{ + FIXME("iface %p, major_type %p, stub!\n", iface, major_type); + return E_NOTIMPL; +} + +static HRESULT WINAPI output_props_GetMediaType(IWMOutputMediaProps *iface, WM_MEDIA_TYPE *mt, DWORD *size) +{ + FIXME("iface %p, mt %p, size %p, stub!\n", iface, mt, size); + return E_NOTIMPL; +} + +static HRESULT WINAPI output_props_SetMediaType(IWMOutputMediaProps *iface, WM_MEDIA_TYPE *mt) +{ + FIXME("iface %p, mt %p, stub!\n", iface, mt); + return E_NOTIMPL; +} + +static HRESULT WINAPI output_props_GetStreamGroupName(IWMOutputMediaProps *iface, WCHAR *name, WORD *len) +{ + FIXME("iface %p, name %p, len %p, stub!\n", iface, name, len); + return E_NOTIMPL; +} + +static HRESULT WINAPI output_props_GetConnectionName(IWMOutputMediaProps *iface, WCHAR *name, WORD *len) +{ + FIXME("iface %p, name %p, len %p, stub!\n", iface, name, len); + return E_NOTIMPL; +} + +static const struct IWMOutputMediaPropsVtbl output_props_vtbl = +{ + output_props_QueryInterface, + output_props_AddRef, + output_props_Release, + output_props_GetType, + output_props_GetMediaType, + output_props_SetMediaType, + output_props_GetStreamGroupName, + output_props_GetConnectionName, +}; + +static IWMOutputMediaProps *output_props_create(void) +{ + struct output_props *object; + + if (!(object = calloc(1, sizeof(*object)))) + return NULL; + object->IWMOutputMediaProps_iface.lpVtbl = &output_props_vtbl; + object->refcount = 1; + + TRACE("Created output properties %p.\n", object); + return &object->IWMOutputMediaProps_iface; +} + struct stream_config { IWMStreamConfig IWMStreamConfig_iface; @@ -1116,6 +1232,23 @@ HRESULT wm_reader_close(struct wm_reader *reader) return S_OK; }
+HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOutputMediaProps **props) +{ + struct wm_stream *stream; + + EnterCriticalSection(&reader->cs); + + if (!(stream = get_stream_by_output_number(reader, output))) + { + LeaveCriticalSection(&reader->cs); + return E_INVALIDARG; + } + + *props = output_props_create(); + LeaveCriticalSection(&reader->cs); + return *props ? S_OK : E_OUTOFMEMORY; +} + void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops) { reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl; diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c index cb2e61a25bc..c89fb782a11 100644 --- a/dlls/winegstreamer/wm_syncreader.c +++ b/dlls/winegstreamer/wm_syncreader.c @@ -123,11 +123,14 @@ static HRESULT WINAPI WMSyncReader_GetOutputNumberForStream(IWMSyncReader2 *ifac return S_OK; }
-static HRESULT WINAPI WMSyncReader_GetOutputProps(IWMSyncReader2 *iface, DWORD output_num, IWMOutputMediaProps **output) +static HRESULT WINAPI WMSyncReader_GetOutputProps(IWMSyncReader2 *iface, + DWORD output, IWMOutputMediaProps **props) { - struct sync_reader *This = impl_from_IWMSyncReader2(iface); - FIXME("(%p)->(%u %p): stub!\n", This, output_num, output); - return E_NOTIMPL; + struct sync_reader *reader = impl_from_IWMSyncReader2(iface); + + TRACE("reader %p, output %u, props %p.\n", reader, output, props); + + return wm_reader_get_output_props(&reader->reader, output, props); }
static HRESULT WINAPI WMSyncReader_GetOutputSetting(IWMSyncReader2 *iface, DWORD output_num, const WCHAR *name, diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index 031a1841360..22184c98dc5 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -724,30 +724,28 @@ static void test_sync_reader_types(void) ok(stream_number2 == stream_number, "Expected stream number %u, got %u.\n", stream_number, stream_number2);
hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - if (hr != S_OK) - { - winetest_pop_context(); - continue; - } + ok(hr == S_OK, "Got hr %#x.\n", hr);
ret_size = sizeof(mt_buffer); hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size); - ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
ref = IWMOutputMediaProps_Release(output_props); ok(!ref, "Got outstanding refcount %d.\n", ref);
- if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) + if (hr == S_OK) { - got_audio = true; - check_audio_type(mt); - } - else - { - ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype)); - got_video = true; - check_video_type(mt); + if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) + { + got_audio = true; + check_audio_type(mt); + } + else + { + ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype)); + got_video = true; + check_video_type(mt); + } }
count = 0; @@ -832,19 +830,16 @@ static void test_sync_reader_types(void) todo_wine ok(hr == NS_E_INVALID_OUTPUT_FORMAT, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (hr == S_OK) - { - hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props2); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(output_props2 != output_props, "Expected different objects.\n"); + hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(output_props2 != output_props, "Expected different objects.\n");
- ref = IWMOutputMediaProps_Release(output_props2); - ok(!ref, "Got outstanding refcount %d.\n", ref); - ref = IWMOutputMediaProps_Release(output_props); - ok(!ref, "Got outstanding refcount %d.\n", ref); - } + ref = IWMOutputMediaProps_Release(output_props2); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IWMOutputMediaProps_Release(output_props); + ok(!ref, "Got outstanding refcount %d.\n", ref);
winetest_pop_context(); } @@ -859,7 +854,7 @@ static void test_sync_reader_types(void)
output_props = (void *)0xdeadbeef; hr = IWMSyncReader_GetOutputProps(reader, 2, &output_props); - todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); ok(output_props == (void *)0xdeadbeef, "Got output props %p.\n", output_props);
output_props = (void *)0xdeadbeef;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/wm_reader.c | 49 +++++++++++++++++++++++++++++++--- dlls/wmvcore/tests/wmvcore.c | 27 +++++++++---------- 2 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 2a93e6e1d35..cd08bc96869 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -32,6 +32,8 @@ struct output_props { IWMOutputMediaProps IWMOutputMediaProps_iface; LONG refcount; + + AM_MEDIA_TYPE mt; };
static inline struct output_props *impl_from_IWMOutputMediaProps(IWMOutputMediaProps *iface) @@ -89,8 +91,23 @@ static HRESULT WINAPI output_props_GetType(IWMOutputMediaProps *iface, GUID *maj
static HRESULT WINAPI output_props_GetMediaType(IWMOutputMediaProps *iface, WM_MEDIA_TYPE *mt, DWORD *size) { - FIXME("iface %p, mt %p, size %p, stub!\n", iface, mt, size); - return E_NOTIMPL; + const struct output_props *props = impl_from_IWMOutputMediaProps(iface); + const DWORD req_size = *size; + + TRACE("iface %p, mt %p, size %p.\n", iface, mt, size); + + *size = sizeof(*mt) + props->mt.cbFormat; + if (!mt) + return S_OK; + if (req_size < *size) + return ASF_E_BUFFERTOOSMALL; + + strmbase_dump_media_type(&props->mt); + + memcpy(mt, &props->mt, sizeof(*mt)); + memcpy(mt + 1, props->mt.pbFormat, props->mt.cbFormat); + mt->pbFormat = (BYTE *)(mt + 1); + return S_OK; }
static HRESULT WINAPI output_props_SetMediaType(IWMOutputMediaProps *iface, WM_MEDIA_TYPE *mt) @@ -123,7 +140,7 @@ static const struct IWMOutputMediaPropsVtbl output_props_vtbl = output_props_GetConnectionName, };
-static IWMOutputMediaProps *output_props_create(void) +static IWMOutputMediaProps *output_props_create(const struct wg_format *format) { struct output_props *object;
@@ -132,6 +149,12 @@ static IWMOutputMediaProps *output_props_create(void) object->IWMOutputMediaProps_iface.lpVtbl = &output_props_vtbl; object->refcount = 1;
+ if (!amt_from_wg_format(&object->mt, format)) + { + free(object); + return NULL; + } + TRACE("Created output properties %p.\n", object); return &object->IWMOutputMediaProps_iface; } @@ -1182,6 +1205,24 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream) stream->reader = reader; stream->index = i; wg_parser_stream_get_preferred_format(stream->wg_stream, &stream->format); + if (stream->format.major_type == WG_MAJOR_TYPE_AUDIO) + { + /* R.U.S.E enumerates available audio types, picks the first one it + * likes, and then sets the wrong stream to that type. libav might + * give us WG_AUDIO_FORMAT_F32LE by default, which will result in + * the game incorrectly interpreting float data as integer. + * Therefore just match native and always set our default format to + * S16LE. */ + stream->format.u.audio.format = WG_AUDIO_FORMAT_S16LE; + } + else if (stream->format.major_type == WG_MAJOR_TYPE_VIDEO) + { + /* Call of Juarez: Bound in Blood breaks if I420 is enumerated. + * Some native decoders output I420, but the msmpeg4v3 decoder + * never does. */ + if (stream->format.u.video.format == WG_VIDEO_FORMAT_I420) + stream->format.u.video.format = WG_VIDEO_FORMAT_YV12; + } }
LeaveCriticalSection(&reader->cs); @@ -1244,7 +1285,7 @@ HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOu return E_INVALIDARG; }
- *props = output_props_create(); + *props = output_props_create(&stream->format); LeaveCriticalSection(&reader->cs); return *props ? S_OK : E_OUTOFMEMORY; } diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index 22184c98dc5..6fc74b62dba 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -728,24 +728,21 @@ static void test_sync_reader_types(void)
ret_size = sizeof(mt_buffer); hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr);
ref = IWMOutputMediaProps_Release(output_props); ok(!ref, "Got outstanding refcount %d.\n", ref);
- if (hr == S_OK) + if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) { - if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) - { - got_audio = true; - check_audio_type(mt); - } - else - { - ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype)); - got_video = true; - check_video_type(mt); - } + got_audio = true; + check_audio_type(mt); + } + else + { + ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype)); + got_video = true; + check_video_type(mt); }
count = 0; @@ -844,8 +841,8 @@ static void test_sync_reader_types(void) winetest_pop_context(); }
- todo_wine ok(got_audio, "No audio stream was enumerated.\n"); - todo_wine ok(got_video, "No video stream was enumerated.\n"); + ok(got_audio, "No audio stream was enumerated.\n"); + ok(got_video, "No video stream was enumerated.\n");
count = 0xdeadbeef; hr = IWMSyncReader_GetOutputFormatCount(reader, 2, &count);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/gst_private.h | 2 + dlls/winegstreamer/wm_reader.c | 62 ++++++++++++++++++++++++++++++ dlls/winegstreamer/wm_syncreader.c | 12 +++--- dlls/wmvcore/tests/wmvcore.c | 2 +- 4 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index db715a9ad70..da36d53abff 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -153,6 +153,8 @@ struct wm_reader_ops
void wm_reader_cleanup(struct wm_reader *reader); HRESULT wm_reader_close(struct wm_reader *reader); +HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output, + DWORD index, IWMOutputMediaProps **props); HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOutputMediaProps **props); void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops); diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index cd08bc96869..f6820121bf0 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1290,6 +1290,68 @@ HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOu return *props ? S_OK : E_OUTOFMEMORY; }
+static const enum wg_video_format video_formats[] = +{ + /* Try to prefer YUV formats over RGB ones. Most decoders output in the + * YUV color space, and it's generally much less expensive for + * videoconvert to do YUV -> YUV transformations. */ + WG_VIDEO_FORMAT_NV12, + WG_VIDEO_FORMAT_YV12, + WG_VIDEO_FORMAT_YUY2, + WG_VIDEO_FORMAT_UYVY, + WG_VIDEO_FORMAT_YVYU, + WG_VIDEO_FORMAT_BGRx, + WG_VIDEO_FORMAT_BGR, + WG_VIDEO_FORMAT_RGB16, + WG_VIDEO_FORMAT_RGB15, +}; + +HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output, + DWORD index, IWMOutputMediaProps **props) +{ + struct wm_stream *stream; + struct wg_format format; + + EnterCriticalSection(&reader->cs); + + if (!(stream = get_stream_by_output_number(reader, output))) + { + LeaveCriticalSection(&reader->cs); + return E_INVALIDARG; + } + + wg_parser_stream_get_preferred_format(stream->wg_stream, &format); + + switch (format.major_type) + { + case WG_MAJOR_TYPE_VIDEO: + if (index >= ARRAY_SIZE(video_formats)) + { + LeaveCriticalSection(&reader->cs); + return NS_E_INVALID_OUTPUT_FORMAT; + } + format.u.video.format = video_formats[index]; + break; + + case WG_MAJOR_TYPE_AUDIO: + if (index) + { + LeaveCriticalSection(&reader->cs); + return NS_E_INVALID_OUTPUT_FORMAT; + } + format.u.audio.format = WG_AUDIO_FORMAT_S16LE; + break; + + case WG_MAJOR_TYPE_UNKNOWN: + break; + } + + LeaveCriticalSection(&reader->cs); + + *props = output_props_create(&format); + return *props ? S_OK : E_OUTOFMEMORY; +} + void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops) { reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl; diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c index c89fb782a11..7becd88b63e 100644 --- a/dlls/winegstreamer/wm_syncreader.c +++ b/dlls/winegstreamer/wm_syncreader.c @@ -97,12 +97,14 @@ static HRESULT WINAPI WMSyncReader_GetOutputCount(IWMSyncReader2 *iface, DWORD * return S_OK; }
-static HRESULT WINAPI WMSyncReader_GetOutputFormat(IWMSyncReader2 *iface, DWORD output_num, DWORD format_num, - IWMOutputMediaProps **props) +static HRESULT WINAPI WMSyncReader_GetOutputFormat(IWMSyncReader2 *iface, + DWORD output, DWORD index, IWMOutputMediaProps **props) { - struct sync_reader *This = impl_from_IWMSyncReader2(iface); - FIXME("(%p)->(%u %u %p): stub!\n", This, output_num, format_num, props); - return E_NOTIMPL; + struct sync_reader *reader = impl_from_IWMSyncReader2(iface); + + TRACE("reader %p, output %u, index %u, props %p.\n", reader, output, index, props); + + return wm_reader_get_output_format(&reader->reader, output, index, props); }
static HRESULT WINAPI WMSyncReader_GetOutputFormatCount(IWMSyncReader2 *iface, DWORD output_num, DWORD *formats) diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index 6fc74b62dba..5c1a47b65d1 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -856,7 +856,7 @@ static void test_sync_reader_types(void)
output_props = (void *)0xdeadbeef; hr = IWMSyncReader_GetOutputFormat(reader, 2, 0, &output_props); - todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); ok(output_props == (void *)0xdeadbeef, "Got output props %p.\n", output_props);
IWMProfile_Release(profile);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/wm_reader.c | 30 ++++++++++++++++++++++++++++++ dlls/winegstreamer/wm_syncreader.c | 10 ++++++---- dlls/wmvcore/tests/wmvcore.c | 8 ++++---- 4 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index da36d53abff..9219a86c094 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -155,6 +155,7 @@ void wm_reader_cleanup(struct wm_reader *reader); HRESULT wm_reader_close(struct wm_reader *reader); HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output, DWORD index, IWMOutputMediaProps **props); +HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output, DWORD *count); HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOutputMediaProps **props); void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops); diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index f6820121bf0..79a89c9a332 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1306,6 +1306,36 @@ static const enum wg_video_format video_formats[] = WG_VIDEO_FORMAT_RGB15, };
+HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output, DWORD *count) +{ + struct wm_stream *stream; + struct wg_format format; + + EnterCriticalSection(&reader->cs); + + if (!(stream = get_stream_by_output_number(reader, output))) + { + LeaveCriticalSection(&reader->cs); + return E_INVALIDARG; + } + + wg_parser_stream_get_preferred_format(stream->wg_stream, &format); + switch (format.major_type) + { + case WG_MAJOR_TYPE_VIDEO: + *count = ARRAY_SIZE(video_formats); + break; + + case WG_MAJOR_TYPE_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN: + *count = 1; + break; + } + + LeaveCriticalSection(&reader->cs); + return S_OK; +} + HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output, DWORD index, IWMOutputMediaProps **props) { diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c index 7becd88b63e..54c53dee3bd 100644 --- a/dlls/winegstreamer/wm_syncreader.c +++ b/dlls/winegstreamer/wm_syncreader.c @@ -107,11 +107,13 @@ static HRESULT WINAPI WMSyncReader_GetOutputFormat(IWMSyncReader2 *iface, return wm_reader_get_output_format(&reader->reader, output, index, props); }
-static HRESULT WINAPI WMSyncReader_GetOutputFormatCount(IWMSyncReader2 *iface, DWORD output_num, DWORD *formats) +static HRESULT WINAPI WMSyncReader_GetOutputFormatCount(IWMSyncReader2 *iface, DWORD output, DWORD *count) { - struct sync_reader *This = impl_from_IWMSyncReader2(iface); - FIXME("(%p)->(%u %p): stub!\n", This, output_num, formats); - return E_NOTIMPL; + struct sync_reader *reader = impl_from_IWMSyncReader2(iface); + + TRACE("reader %p, output %u, count %p.\n", reader, output, count); + + return wm_reader_get_output_format_count(&reader->reader, output, count); }
static HRESULT WINAPI WMSyncReader_GetOutputNumberForStream(IWMSyncReader2 *iface, diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index 5c1a47b65d1..ebfdfdf0107 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -747,8 +747,8 @@ static void test_sync_reader_types(void)
count = 0; hr = IWMSyncReader_GetOutputFormatCount(reader, output_number, &count); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(count > 0, "Got count %u.\n", count); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(count > 0, "Got count %u.\n", count);
for (j = 0; j < count; ++j) { @@ -824,7 +824,7 @@ static void test_sync_reader_types(void) }
hr = IWMSyncReader_GetOutputFormat(reader, output_number, count, &output_props); - todo_wine ok(hr == NS_E_INVALID_OUTPUT_FORMAT, "Got hr %#x.\n", hr); + ok(hr == NS_E_INVALID_OUTPUT_FORMAT, "Got hr %#x.\n", hr);
hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -846,7 +846,7 @@ static void test_sync_reader_types(void)
count = 0xdeadbeef; hr = IWMSyncReader_GetOutputFormatCount(reader, 2, &count); - todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); ok(count == 0xdeadbeef, "Got count %#x.\n", count);
output_props = (void *)0xdeadbeef;