According to the tests in 23b72ad, when we are reading a compressed stream, the type returned by `stream_props_GetMediaType()` should reflect compressed format even if we finnally output uncomressed data. For example, if we use wmvcore reader to read a WMV3 stream and output RGB24, the format information returned by `stream_props_GetMediaType()` should be WMV3, not RGB24.
This patch set is marked as draft now, because PATCH 2 and PATCH 3 is affected by 3e8936a2 in MR !2258. So I'll submit a newer version of this after !2258 get merged.
-- v6: winegstreamer: Use stream format in stream_props_GetMediaType. winegstreamer: Implement amt_from_wg_format_video_wmv. winegstreamer: Implement wg_parser_stream_get_stream_format. winegstreamer: Introduce format_is_compressed.
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/wg_parser.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index dfb3da9a4ab..16867c0da7d 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -119,6 +119,13 @@ struct wg_parser_stream gchar *tags[WG_PARSER_TAG_COUNT]; };
+static bool format_is_compressed(struct wg_format *format) +{ + return format->major_type != WG_MAJOR_TYPE_UNKNOWN + && format->major_type != WG_MAJOR_TYPE_VIDEO + && format->major_type != WG_MAJOR_TYPE_AUDIO; +} + static NTSTATUS wg_parser_get_stream_count(void *args) { struct wg_parser_get_stream_count_params *params = args; @@ -475,12 +482,7 @@ static gboolean autoplug_continue_cb(GstElement * decodebin, GstPad *pad, GstCap
wg_format_from_caps(&format, caps);
- if (format.major_type != WG_MAJOR_TYPE_UNKNOWN - && format.major_type != WG_MAJOR_TYPE_VIDEO - && format.major_type != WG_MAJOR_TYPE_AUDIO) - return false; - - return true; + return !format_is_compressed(&format); }
static GstAutoplugSelectResult autoplug_select_cb(GstElement *bin, GstPad *pad, @@ -952,9 +954,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user) gst_caps_unref(caps);
/* For compressed stream, create an extra decodebin to decode it. */ - if (stream->stream_format.major_type != WG_MAJOR_TYPE_UNKNOWN - && stream->stream_format.major_type != WG_MAJOR_TYPE_VIDEO - && stream->stream_format.major_type != WG_MAJOR_TYPE_AUDIO) + if (format_is_compressed(&stream->stream_format)) { if (!stream_decodebin_create(stream)) {
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/main.c | 13 +++++++++++++ dlls/winegstreamer/unixlib.h | 7 +++++++ dlls/winegstreamer/wg_parser.c | 11 +++++++++++ 4 files changed, 32 insertions(+)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 04ec84c7936..fceabaca592 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -82,6 +82,7 @@ uint32_t wg_parser_get_stream_count(struct wg_parser *parser); struct wg_parser_stream *wg_parser_get_stream(struct wg_parser *parser, uint32_t index);
void wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, struct wg_format *format); +void wg_parser_stream_get_stream_format(struct wg_parser_stream *stream, struct wg_format *format); void wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format); void wg_parser_stream_disable(struct wg_parser_stream *stream);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 1e54edb2015..81da2cc7cb6 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -185,6 +185,19 @@ void wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, stru WINE_UNIX_CALL(unix_wg_parser_stream_get_preferred_format, ¶ms); }
+void wg_parser_stream_get_stream_format(struct wg_parser_stream *stream, struct wg_format *format) +{ + struct wg_parser_stream_get_stream_format_params params = + { + .stream = stream, + .format = format, + }; + + TRACE("stream %p, format %p.\n", stream, format); + + WINE_UNIX_CALL(unix_wg_parser_stream_get_stream_format, ¶ms); +} + void wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format) { struct wg_parser_stream_enable_params params = diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index a01efb934f8..ee0bbe60b67 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -240,6 +240,12 @@ struct wg_parser_stream_get_preferred_format_params struct wg_format *format; };
+struct wg_parser_stream_get_stream_format_params +{ + struct wg_parser_stream *stream; + struct wg_format *format; +}; + struct wg_parser_stream_enable_params { struct wg_parser_stream *stream; @@ -350,6 +356,7 @@ enum unix_funcs unix_wg_parser_get_stream,
unix_wg_parser_stream_get_preferred_format, + unix_wg_parser_stream_get_stream_format, unix_wg_parser_stream_enable, unix_wg_parser_stream_disable,
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 16867c0da7d..c0657e0e38a 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -216,6 +216,16 @@ static NTSTATUS wg_parser_stream_get_preferred_format(void *args) return S_OK; }
+static NTSTATUS wg_parser_stream_get_stream_format(void *args) +{ + struct wg_parser_stream_get_stream_format_params *params = args; + + *params->format = format_is_compressed(¶ms->stream->stream_format) ? + params->stream->stream_format : + params->stream->preferred_format; + return S_OK; +} + static NTSTATUS wg_parser_stream_enable(void *args) { const struct wg_parser_stream_enable_params *params = args; @@ -1945,6 +1955,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = X(wg_parser_get_stream),
X(wg_parser_stream_get_preferred_format), + X(wg_parser_stream_get_stream_format), X(wg_parser_stream_enable), X(wg_parser_stream_disable),
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/quartz_parser.c | 57 +++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index de62187cd7d..477235f637b 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -540,6 +540,59 @@ static bool amt_from_wg_format_video_cinepak(AM_MEDIA_TYPE *mt, const struct wg_
return true; } +static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_format *format) +{ + VIDEOINFO *video_format; + uint32_t frame_time; + const GUID *subtype; + + if (!(video_format = CoTaskMemAlloc(sizeof(*video_format)))) + return false; + + switch (format->u.video_wmv.format) + { + case WG_WMV_VIDEO_FORMAT_WMV1: + subtype = &MEDIASUBTYPE_WMV1; + break; + case WG_WMV_VIDEO_FORMAT_WMV2: + subtype = &MEDIASUBTYPE_WMV2; + break; + case WG_WMV_VIDEO_FORMAT_WMV3: + subtype = &MEDIASUBTYPE_WMV3; + break; + case WG_WMV_VIDEO_FORMAT_WMVA: + subtype = &MEDIASUBTYPE_WMVA; + break; + case WG_WMV_VIDEO_FORMAT_WVC1: + subtype = &MEDIASUBTYPE_WVC1; + break; + default: + WARN("Invalid WMV format %u.\n", format->u.video_wmv.format); + return false; + } + + mt->majortype = MEDIATYPE_Video; + mt->subtype = *subtype; + mt->bFixedSizeSamples = FALSE; + mt->bTemporalCompression = TRUE; + mt->lSampleSize = 0; + mt->formattype = FORMAT_VideoInfo; + mt->cbFormat = sizeof(VIDEOINFOHEADER); + mt->pbFormat = (BYTE *)video_format; + + memset(video_format, 0, sizeof(*video_format)); + SetRect(&video_format->rcSource, 0, 0, format->u.video_wmv.width, format->u.video_wmv.height); + video_format->rcTarget = video_format->rcSource; + if ((frame_time = MulDiv(10000000, format->u.video_wmv.fps_d, format->u.video_wmv.fps_n)) != -1) + video_format->AvgTimePerFrame = frame_time; + video_format->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + video_format->bmiHeader.biWidth = format->u.video_wmv.width; + video_format->bmiHeader.biHeight = format->u.video_wmv.height; + video_format->bmiHeader.biPlanes = 1; + video_format->bmiHeader.biCompression = mt->subtype.Data1; + + return true; +}
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm) { @@ -550,7 +603,6 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_AUDIO_WMA: case WG_MAJOR_TYPE_VIDEO_H264: - case WG_MAJOR_TYPE_VIDEO_WMV: case WG_MAJOR_TYPE_VIDEO_INDEO: FIXME("Format %u not implemented!\n", format->major_type); /* fallthrough */ @@ -568,6 +620,9 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
case WG_MAJOR_TYPE_VIDEO_CINEPAK: return amt_from_wg_format_video_cinepak(mt, format); + + case WG_MAJOR_TYPE_VIDEO_WMV: + return amt_from_wg_format_video_wmv(mt, format); }
assert(0);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/wm_reader.c | 6 +++++- dlls/wmvcore/tests/wmvcore.c | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 764774d505b..8ffccede46c 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -544,12 +544,16 @@ static HRESULT WINAPI stream_props_GetType(IWMMediaProps *iface, GUID *major_typ static HRESULT WINAPI stream_props_GetMediaType(IWMMediaProps *iface, WM_MEDIA_TYPE *mt, DWORD *size) { struct stream_config *config = impl_from_IWMMediaProps(iface); + const struct wg_format *format; + struct wg_format stream_format; const DWORD req_size = *size; AM_MEDIA_TYPE stream_mt;
TRACE("iface %p, mt %p, size %p.\n", iface, mt, size);
- if (!amt_from_wg_format(&stream_mt, &config->stream->format, true)) + wg_parser_stream_get_stream_format(config->stream->wg_stream, &stream_format); + format = (stream_format.major_type != WG_MAJOR_TYPE_UNKNOWN) ? &stream_format : &config->stream->format; + if (!amt_from_wg_format(&stream_mt, format, true)) return E_OUTOFMEMORY;
*size = sizeof(stream_mt) + stream_mt.cbFormat; diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index a116d8a1d69..9f755859481 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -1549,7 +1549,7 @@ static void test_sync_reader_types(void) if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE); else - test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, TRUE); + test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE);
ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %ld.\n", ref); @@ -3429,7 +3429,7 @@ static void test_async_reader_types(void) if (IsEqualGUID(&majortype, &MEDIATYPE_Audio)) test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE); else - test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, TRUE); + test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE);
ref = IWMStreamConfig_Release(config); ok(!ref, "Got outstanding refcount %ld.\n", ref);
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=132011
Your paranoid android.
=== debian11 (32 bit report) ===
wmvcore: wmvcore.c:1713: Test failed: Stream 0: Format 2: Got hr 0xc00d0041. wmvcore.c:1730: Test failed: Stream 0: Format 2: Media types didn't match.
Test pipe line is fixed now.
Bikeshedding the naming, but I liked "get_codec_format" better, or perhaps "get_compressed_format"? "stream_format" doesn't seem specific enough; the uncompressed format is also a "stream format".
I realize now I missed bikeshedding the "stream_format" field on a similar basis.
Zebediah Figura (@zfigura) commented about dlls/winegstreamer/quartz_parser.c:
return true;
} +static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_format *format)
Missing space between functions here.
On Wed Apr 26 01:48:41 2023 +0000, Zebediah Figura wrote:
Bikeshedding the naming, but I liked "get_codec_format" better, or perhaps "get_compressed_format"? "stream_format" doesn't seem specific enough; the uncompressed format is also a "stream format". I realize now I missed bikeshedding the "stream_format" field on a similar basis.
I'll rename it to codec_format