[PATCH 0/7] MR5138: winegstreamer: Support and expose generic audio/video MFT decoders.
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/wg_format.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 6da97685736..82ec024933a 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -394,16 +394,19 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) { const GstStructure *structure = gst_caps_get_structure(caps, 0); const char *name = gst_structure_get_name(structure); + GstAudioInfo audio_info; gboolean parsed; memset(format, 0, sizeof(*format)); - if (!strcmp(name, "audio/x-raw")) + if (g_str_has_prefix(name, "audio/") && gst_audio_info_from_caps(&audio_info, caps)) { - GstAudioInfo info; - - if (gst_audio_info_from_caps(&info, caps)) - wg_format_from_audio_info(format, &info); + if (GST_AUDIO_INFO_FORMAT(&audio_info) != GST_AUDIO_FORMAT_ENCODED) + wg_format_from_audio_info(format, &audio_info); + else if (!strcmp(name, "audio/mpeg") && gst_structure_get_boolean(structure, "parsed", &parsed) && parsed) + 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-raw")) { @@ -412,14 +415,6 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) if (gst_video_info_from_caps(&info, caps)) wg_format_from_video_info(format, &info); } - else if (!strcmp(name, "audio/mpeg") && gst_structure_get_boolean(structure, "parsed", &parsed) && parsed) - { - 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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/wg_format.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 82ec024933a..f7fe3cc92ab 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -395,6 +395,7 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) const GstStructure *structure = gst_caps_get_structure(caps, 0); const char *name = gst_structure_get_name(structure); GstAudioInfo audio_info; + GstVideoInfo video_info; gboolean parsed; memset(format, 0, sizeof(*format)); @@ -408,24 +409,16 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) else if (!strcmp(name, "audio/x-wma")) wg_format_from_caps_audio_wma(format, caps); } - else if (!strcmp(name, "video/x-raw")) + else if (g_str_has_prefix(name, "video/") && gst_video_info_from_caps(&video_info, caps)) { - GstVideoInfo info; - - if (gst_video_info_from_caps(&info, caps)) - wg_format_from_video_info(format, &info); - } - else if (!strcmp(name, "video/x-cinepak")) - { - wg_format_from_caps_video_cinepak(format, caps); - } - else if (!strcmp(name, "video/x-wmv")) - { - wg_format_from_caps_video_wmv(format, caps); - } - else if (!strcmp(name, "video/mpeg") && gst_structure_get_boolean(structure, "parsed", &parsed) && parsed) - { - wg_format_from_caps_video_mpeg1(format, caps); + if (GST_VIDEO_INFO_FORMAT(&video_info) != GST_VIDEO_FORMAT_ENCODED) + wg_format_from_video_info(format, &video_info); + else if (!strcmp(name, "video/x-cinepak")) + wg_format_from_caps_video_cinepak(format, caps); + else if (!strcmp(name, "video/x-wmv")) + wg_format_from_caps_video_wmv(format, caps); + else if (!strcmp(name, "video/mpeg") && gst_structure_get_boolean(structure, "parsed", &parsed) && parsed) + wg_format_from_caps_video_mpeg1(format, caps); } else { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/mfplat.c | 2 ++ dlls/winegstreamer/quartz_parser.c | 4 +++ dlls/winegstreamer/unixlib.h | 15 ++++++++ dlls/winegstreamer/wg_format.c | 56 ++++++++++++++++++++++++++++++ dlls/winegstreamer/wg_parser.c | 2 ++ dlls/winegstreamer/wg_transform.c | 4 +++ dlls/winegstreamer/wm_reader.c | 8 +++++ 7 files changed, 91 insertions(+) diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index e6d9fb9fd2c..38c719bd062 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -570,6 +570,8 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format) FIXME("Format %u not implemented!\n", format->major_type); /* fallthrough */ case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: return NULL; case WG_MAJOR_TYPE_AUDIO: diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 44e13d05c2a..c664c9bd87b 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -463,6 +463,8 @@ unsigned int wg_format_get_max_size(const struct wg_format *format) return 0; case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: FIXME("Cannot guess maximum sample size for unknown format.\n"); return 0; } @@ -721,6 +723,8 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool FIXME("Format %u not implemented!\n", format->major_type); /* fallthrough */ case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: return false; case WG_MAJOR_TYPE_AUDIO: diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 4ec9fce515e..b9b9b7c9dbe 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -33,6 +33,8 @@ typedef UINT32 wg_major_type; enum wg_major_type { WG_MAJOR_TYPE_UNKNOWN = 0, + WG_MAJOR_TYPE_UNKNOWN_AUDIO, + WG_MAJOR_TYPE_UNKNOWN_VIDEO, WG_MAJOR_TYPE_AUDIO, WG_MAJOR_TYPE_AUDIO_MPEG1, WG_MAJOR_TYPE_AUDIO_MPEG4, @@ -95,6 +97,19 @@ struct wg_format union { + struct + { + uint32_t channels; + uint32_t rate; + char caps[512]; + } unknown_audio; + struct + { + int32_t width, height; + uint32_t fps_n, fps_d; + char caps[512]; + } unknown_video; + struct { wg_audio_format format; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index f7fe3cc92ab..7551e6bf1ef 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -265,6 +265,25 @@ static void wg_format_from_caps_audio_wma(struct wg_format *format, const GstCap gst_buffer_unmap(codec_data, &map); } +static void wg_format_from_caps_unknown_audio(struct wg_format *format, const GstCaps *caps, + const GstAudioInfo *info) +{ + gchar *str; + gint len; + + format->major_type = WG_MAJOR_TYPE_UNKNOWN_AUDIO; + format->u.unknown_audio.rate = info->rate; + format->u.unknown_audio.channels = info->channels; + + str = gst_caps_to_string(caps); + len = strlen(str) + 1; + if (len >= ARRAY_SIZE(format->u.unknown_audio.caps)) + GST_FIXME("wg_format.unknown_audio.caps buffer is too small, need %u bytes", len); + else + memcpy(format->u.unknown_audio.caps, str, len); + g_free(str); +} + static void wg_format_from_caps_video_cinepak(struct wg_format *format, const GstCaps *caps) { const GstStructure *structure = gst_caps_get_structure(caps, 0); @@ -390,6 +409,27 @@ static void wg_format_from_caps_video_mpeg1(struct wg_format *format, const GstC format->u.video_mpeg1.fps_d = fps_d; } +static void wg_format_from_caps_unknown_video(struct wg_format *format, const GstCaps *caps, + const GstVideoInfo *info) +{ + gchar *str; + gint len; + + format->major_type = WG_MAJOR_TYPE_UNKNOWN_VIDEO; + format->u.unknown_video.width = info->width; + format->u.unknown_video.height = info->height; + format->u.unknown_video.fps_n = info->fps_n; + format->u.unknown_video.fps_d = info->fps_d; + + str = gst_caps_to_string(caps); + len = strlen(str) + 1; + if (len >= ARRAY_SIZE(format->u.unknown_video.caps)) + GST_FIXME("wg_format.unknown_video.caps buffer is too small, need %u bytes", len); + else + memcpy(format->u.unknown_video.caps, str, len); + g_free(str); +} + void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) { const GstStructure *structure = gst_caps_get_structure(caps, 0); @@ -408,6 +448,11 @@ 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 + { + GST_FIXME("Using fallback for unknown audio caps %" GST_PTR_FORMAT ".", caps); + wg_format_from_caps_unknown_audio(format, caps, &audio_info); + } } else if (g_str_has_prefix(name, "video/") && gst_video_info_from_caps(&video_info, caps)) { @@ -419,6 +464,11 @@ void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) wg_format_from_caps_video_wmv(format, caps); else if (!strcmp(name, "video/mpeg") && gst_structure_get_boolean(structure, "parsed", &parsed) && parsed) wg_format_from_caps_video_mpeg1(format, caps); + else + { + GST_FIXME("Using fallback for unknown video caps %" GST_PTR_FORMAT ".", caps); + wg_format_from_caps_unknown_video(format, caps, &video_info); + } } else { @@ -847,6 +897,10 @@ GstCaps *wg_format_to_caps(const struct wg_format *format) { case WG_MAJOR_TYPE_UNKNOWN: return gst_caps_new_any(); + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + return gst_caps_from_string(format->u.unknown_audio.caps); + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: + return gst_caps_from_string(format->u.unknown_video.caps); case WG_MAJOR_TYPE_AUDIO: return wg_format_to_caps_audio(format); case WG_MAJOR_TYPE_AUDIO_MPEG1: @@ -888,6 +942,8 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) GST_FIXME("Format %u not implemented!", a->major_type); /* fallthrough */ case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: return false; case WG_MAJOR_TYPE_AUDIO: diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index b0a344d5186..9339d9ed8f0 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -133,6 +133,8 @@ static struct wg_parser_stream *get_stream(wg_parser_stream_t stream) static bool format_is_compressed(struct wg_format *format) { return format->major_type != WG_MAJOR_TYPE_UNKNOWN + && format->major_type != WG_MAJOR_TYPE_UNKNOWN_AUDIO + && format->major_type != WG_MAJOR_TYPE_UNKNOWN_VIDEO && format->major_type != WG_MAJOR_TYPE_VIDEO && format->major_type != WG_MAJOR_TYPE_AUDIO; } diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 516b28e82e2..aac2903ba8a 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -400,6 +400,8 @@ NTSTATUS wg_transform_create(void *args) switch (input_format.major_type) { + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: case WG_MAJOR_TYPE_VIDEO_H264: case WG_MAJOR_TYPE_AUDIO_MPEG1: case WG_MAJOR_TYPE_AUDIO_MPEG4: @@ -465,6 +467,8 @@ NTSTATUS wg_transform_create(void *args) break; case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: case WG_MAJOR_TYPE_AUDIO_MPEG1: case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_AUDIO_WMA: diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index e3a2bfc343b..5557803afbf 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1661,6 +1661,10 @@ static const char *get_major_type_string(enum wg_major_type type) return "mpeg1-video"; case WG_MAJOR_TYPE_UNKNOWN: return "unknown"; + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + return "unknown-audio"; + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: + return "unknown-video"; } assert(0); return NULL; @@ -2033,6 +2037,8 @@ static HRESULT WINAPI reader_GetOutputFormat(IWMSyncReader2 *iface, FIXME("Format %u not implemented!\n", format.major_type); break; case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: break; } @@ -2077,6 +2083,8 @@ static HRESULT WINAPI reader_GetOutputFormatCount(IWMSyncReader2 *iface, DWORD o /* fallthrough */ case WG_MAJOR_TYPE_AUDIO: case WG_MAJOR_TYPE_UNKNOWN: + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: *count = 1; break; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/mfplat.c | 138 +++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 38c719bd062..a083915cdbd 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -40,6 +40,8 @@ DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf DEFINE_MEDIATYPE_GUID(MFAudioFormat_RAW_AAC,WAVE_FORMAT_RAW_AAC1); DEFINE_MEDIATYPE_GUID(MFVideoFormat_VC1S,MAKEFOURCC('V','C','1','S')); DEFINE_MEDIATYPE_GUID(MFVideoFormat_IV50,MAKEFOURCC('I','V','5','0')); +DEFINE_MEDIATYPE_GUID(MFAudioFormat_GStreamer,MAKEFOURCC('G','S','T','a')); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_GStreamer,MAKEFOURCC('G','S','T','v')); struct class_factory { @@ -555,6 +557,74 @@ static IMFMediaType *mf_media_type_from_wg_format_video(const struct wg_format * return NULL; } +static IMFMediaType *mf_media_type_from_wg_format_unknown_audio(const struct wg_format *format) +{ + IMFMediaType *type; + UINT32 value; + HRESULT hr; + + if (FAILED(MFCreateMediaType(&type))) + return NULL; + if (FAILED(hr = IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio))) + goto done; + if (FAILED(hr = IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, &MFAudioFormat_GStreamer))) + goto done; + + value = format->u.unknown_audio.rate; + if (value && FAILED(hr = IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, value))) + goto done; + value = format->u.unknown_audio.channels; + if (value && FAILED(hr = IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, value))) + goto done; + if (FAILED(hr = IMFMediaType_SetBlob(type, &MF_MT_USER_DATA, (BYTE *)format->u.unknown_audio.caps, + strlen(format->u.unknown_audio.caps) + 1))) + goto done; + +done: + if (FAILED(hr)) + { + IMFMediaType_Release(type); + return NULL; + } + return type; +} + +static IMFMediaType *mf_media_type_from_wg_format_unknown_video(const struct wg_format *format) +{ + UINT64 frame_rate, frame_size; + IMFMediaType *type; + HRESULT hr; + + if (FAILED(MFCreateMediaType(&type))) + return NULL; + if (FAILED(hr = IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video))) + goto done; + if (FAILED(hr = IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, &MFVideoFormat_GStreamer))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(type, &MF_MT_VIDEO_ROTATION, MFVideoRotationFormat_0))) + goto done; + if (FAILED(hr = IMFMediaType_SetUINT32(type, &MF_MT_COMPRESSED, TRUE))) + goto done; + + frame_size = (UINT64)format->u.unknown_video.width << 32 | format->u.unknown_video.height; + if (FAILED(hr = IMFMediaType_SetUINT64(type, &MF_MT_FRAME_SIZE, frame_size))) + goto done; + frame_rate = (UINT64)format->u.unknown_video.fps_n << 32 | format->u.unknown_video.fps_d; + if (FAILED(hr = IMFMediaType_SetUINT64(type, &MF_MT_FRAME_RATE, frame_rate))) + goto done; + if (FAILED(hr = IMFMediaType_SetBlob(type, &MF_MT_USER_DATA, (BYTE *)format->u.unknown_video.caps, + strlen(format->u.unknown_video.caps) + 1))) + goto done; + +done: + if (FAILED(hr)) + { + IMFMediaType_Release(type); + return NULL; + } + return type; +} + IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format) { switch (format->major_type) @@ -570,15 +640,17 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format) FIXME("Format %u not implemented!\n", format->major_type); /* fallthrough */ case WG_MAJOR_TYPE_UNKNOWN: - case WG_MAJOR_TYPE_UNKNOWN_AUDIO: - case WG_MAJOR_TYPE_UNKNOWN_VIDEO: return NULL; case WG_MAJOR_TYPE_AUDIO: return mf_media_type_from_wg_format_audio(format); + case WG_MAJOR_TYPE_UNKNOWN_AUDIO: + return mf_media_type_from_wg_format_unknown_audio(format); case WG_MAJOR_TYPE_VIDEO: return mf_media_type_from_wg_format_video(format); + case WG_MAJOR_TYPE_UNKNOWN_VIDEO: + return mf_media_type_from_wg_format_unknown_video(format); } assert(0); @@ -670,6 +742,29 @@ static void mf_media_type_to_wg_format_audio_mpeg4(IMFMediaType *type, const GUI format->u.audio_mpeg4.codec_data_len = codec_data_size; } +static void mf_media_type_to_wg_format_unknown_audio(IMFMediaType *type, struct wg_format *format) +{ + UINT32 caps_len; + BYTE *caps; + HRESULT hr; + + memset(format, 0, sizeof(*format)); + format->major_type = WG_MAJOR_TYPE_UNKNOWN_AUDIO; + + if (FAILED(hr = IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &format->u.unknown_audio.rate))) + WARN("Failed to get MF_MT_AUDIO_SAMPLES_PER_SECOND for type %p, hr %#lx.\n", type, hr); + if (FAILED(hr = IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &format->u.unknown_audio.channels))) + WARN("Failed to get MF_MT_AUDIO_NUM_CHANNELS for type %p, hr %#lx.\n", type, hr); + + if (FAILED(hr = IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, &caps, &caps_len))) + WARN("Failed to get MF_MT_USER_DATA for type %p, hr %#lx.\n", type, hr); + else + { + strcpy(format->u.unknown_audio.caps, (char *)caps); + CoTaskMemFree(caps); + } +} + static enum wg_video_format mf_video_format_to_wg(const GUID *subtype) { unsigned int i; @@ -865,6 +960,41 @@ static void mf_media_type_to_wg_format_video_indeo(IMFMediaType *type, uint32_t format->u.video_indeo.version = version; } +static void mf_media_type_to_wg_format_unknown_video(IMFMediaType *type, struct wg_format *format) +{ + UINT64 frame_rate, frame_size; + UINT32 caps_len; + HRESULT hr; + BYTE *caps; + + memset(format, 0, sizeof(*format)); + format->major_type = WG_MAJOR_TYPE_UNKNOWN_VIDEO; + + if (FAILED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) + WARN("Failed to get MF_MT_FRAME_SIZE for type %p, hr %#lx.\n", type, hr); + else + { + format->u.unknown_video.width = frame_size >> 32; + format->u.unknown_video.height = (UINT32)frame_size; + } + + if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate) + WARN("Failed to get MF_MT_FRAME_RATE for type %p, hr %#lx.\n", type, hr); + else + { + format->u.unknown_video.fps_n = frame_rate >> 32; + format->u.unknown_video.fps_d = (UINT32)frame_rate; + } + + if (FAILED(hr = IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, &caps, &caps_len))) + WARN("Failed to get MF_MT_USER_DATA for type %p, hr %#lx.\n", type, hr); + else + { + strcpy(format->u.unknown_video.caps, (char *)caps); + CoTaskMemFree(caps); + } +} + void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) { GUID major_type, subtype; @@ -891,6 +1021,8 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) mf_media_type_to_wg_format_audio_wma(type, &subtype, format); else if (IsEqualGUID(&subtype, &MFAudioFormat_AAC) || IsEqualGUID(&subtype, &MFAudioFormat_RAW_AAC)) mf_media_type_to_wg_format_audio_mpeg4(type, &subtype, format); + else if (IsEqualGUID(&subtype, &MFAudioFormat_GStreamer)) + mf_media_type_to_wg_format_unknown_audio(type, format); else mf_media_type_to_wg_format_audio(type, &subtype, format); } @@ -900,6 +1032,8 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) mf_media_type_to_wg_format_video_h264(type, format); else if (IsEqualGUID(&subtype, &MFVideoFormat_IV50)) mf_media_type_to_wg_format_video_indeo(type, 5, format); + else if (IsEqualGUID(&subtype, &MFVideoFormat_GStreamer)) + mf_media_type_to_wg_format_unknown_video(type, format); else mf_media_type_to_wg_format_video(type, &subtype, format); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/Makefile.in | 2 +- .../{aac_decoder.c => audio_decoder.c} | 50 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) rename dlls/winegstreamer/{aac_decoder.c => audio_decoder.c} (92%) diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 410bbd1dc03..934dee3c7be 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -7,7 +7,7 @@ UNIX_CFLAGS = $(GSTREAMER_CFLAGS) UNIX_LIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS) SOURCES = \ - aac_decoder.c \ + audio_decoder.c \ color_convert.c \ main.c \ media_sink.c \ diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/audio_decoder.c similarity index 92% rename from dlls/winegstreamer/aac_decoder.c rename to dlls/winegstreamer/audio_decoder.c index c0bc57f278e..82af33b671b 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/audio_decoder.c @@ -34,7 +34,7 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); #define NEXT_WAVEFORMATEXTENSIBLE(format) (WAVEFORMATEXTENSIBLE *)((BYTE *)(&(format)->Format + 1) + (format)->Format.cbSize) -static WAVEFORMATEXTENSIBLE const aac_decoder_output_types[] = +static WAVEFORMATEXTENSIBLE const audio_decoder_output_types[] = { {.Format = {.wFormatTag = WAVE_FORMAT_IEEE_FLOAT, .wBitsPerSample = 32, .nSamplesPerSec = 48000, .nChannels = 2}}, {.Format = {.wFormatTag = WAVE_FORMAT_PCM, .wBitsPerSample = 16, .nSamplesPerSec = 48000, .nChannels = 2}}, @@ -51,7 +51,7 @@ static const UINT32 default_channel_mask[7] = KSAUDIO_SPEAKER_5POINT1, }; -struct aac_decoder +struct audio_decoder { IMFTransform IMFTransform_iface; LONG refcount; @@ -66,12 +66,12 @@ struct aac_decoder struct wg_sample_queue *wg_sample_queue; }; -static struct aac_decoder *impl_from_IMFTransform(IMFTransform *iface) +static struct audio_decoder *impl_from_IMFTransform(IMFTransform *iface) { - return CONTAINING_RECORD(iface, struct aac_decoder, IMFTransform_iface); + return CONTAINING_RECORD(iface, struct audio_decoder, IMFTransform_iface); } -static HRESULT try_create_wg_transform(struct aac_decoder *decoder) +static HRESULT try_create_wg_transform(struct audio_decoder *decoder) { struct wg_format input_format, output_format; struct wg_transform_attrs attrs = {0}; @@ -96,7 +96,7 @@ static HRESULT try_create_wg_transform(struct aac_decoder *decoder) static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); @@ -115,7 +115,7 @@ static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, static ULONG WINAPI transform_AddRef(IMFTransform *iface) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); ULONG refcount = InterlockedIncrement(&decoder->refcount); TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); return refcount; @@ -123,7 +123,7 @@ static ULONG WINAPI transform_AddRef(IMFTransform *iface) static ULONG WINAPI transform_Release(IMFTransform *iface) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); ULONG refcount = InterlockedDecrement(&decoder->refcount); TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); @@ -228,7 +228,7 @@ static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD strea static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); const WAVEFORMATEXTENSIBLE *format = decoder->input_types; UINT count = decoder->input_type_count; @@ -245,7 +245,7 @@ static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); UINT32 channel_count, sample_rate; WAVEFORMATEXTENSIBLE wfx = {{0}}; IMFMediaType *media_type; @@ -260,7 +260,7 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR if (!decoder->input_type) return MF_E_TRANSFORM_TYPE_NOT_SET; - wfx = aac_decoder_output_types[index % ARRAY_SIZE(aac_decoder_output_types)]; + wfx = audio_decoder_output_types[index % ARRAY_SIZE(audio_decoder_output_types)]; if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count)) || !channel_count) @@ -271,15 +271,15 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR if (channel_count >= ARRAY_SIZE(default_channel_mask)) return MF_E_INVALIDMEDIATYPE; - if (channel_count > 2 && index >= ARRAY_SIZE(aac_decoder_output_types)) + if (channel_count > 2 && index >= ARRAY_SIZE(audio_decoder_output_types)) { /* If there are more than two channels in the input type GetOutputAvailableType additionally lists * types with 2 channels. */ - index -= ARRAY_SIZE(aac_decoder_output_types); + index -= ARRAY_SIZE(audio_decoder_output_types); channel_count = 2; } - if (index >= ARRAY_SIZE(aac_decoder_output_types)) + if (index >= ARRAY_SIZE(audio_decoder_output_types)) return MF_E_NO_MORE_TYPES; wfx.Format.nChannels = channel_count; @@ -321,7 +321,7 @@ static BOOL matches_format(const WAVEFORMATEXTENSIBLE *a, const WAVEFORMATEXTENS static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); UINT32 size, count = decoder->input_type_count; WAVEFORMATEXTENSIBLE *format, wfx; HRESULT hr; @@ -361,7 +361,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); WAVEFORMATEXTENSIBLE *format, wfx; UINT32 size; HRESULT hr; @@ -380,10 +380,10 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF wfx = *format; CoTaskMemFree(format); - for (i = 0; i < ARRAY_SIZE(aac_decoder_output_types); ++i) - if (matches_format(&aac_decoder_output_types[i], &wfx)) + for (i = 0; i < ARRAY_SIZE(audio_decoder_output_types); ++i) + if (matches_format(&audio_decoder_output_types[i], &wfx)) break; - if (i == ARRAY_SIZE(aac_decoder_output_types)) + if (i == ARRAY_SIZE(audio_decoder_output_types)) return MF_E_INVALIDMEDIATYPE; if (!wfx.Format.wBitsPerSample || !wfx.Format.nChannels || !wfx.Format.nSamplesPerSec) @@ -410,7 +410,7 @@ failed: static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **out) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); IMFMediaType *type; HRESULT hr; @@ -432,7 +432,7 @@ static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD i static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **out) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); IMFMediaType *type; HRESULT hr; @@ -454,7 +454,7 @@ static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); bool accepts_input; TRACE("iface %p, id %#lx, flags %p.\n", iface, id, flags); @@ -495,7 +495,7 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags); @@ -508,7 +508,7 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { - struct aac_decoder *decoder = impl_from_IMFTransform(iface); + struct audio_decoder *decoder = impl_from_IMFTransform(iface); MFT_OUTPUT_STREAM_INFO info; HRESULT hr; @@ -598,7 +598,7 @@ HRESULT aac_decoder_create(REFIID riid, void **ret) static const struct wg_format input_format = {.major_type = WG_MAJOR_TYPE_AUDIO_MPEG4}; struct wg_transform_attrs attrs = {0}; wg_transform_t transform; - struct aac_decoder *decoder; + struct audio_decoder *decoder; HRESULT hr; TRACE("riid %s, ret %p.\n", debugstr_guid(riid), ret); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/audio_decoder.c | 38 ++++++++++++++++++++ dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/mfplat.c | 22 ++++++++++++ dlls/winegstreamer/winegstreamer_classes.idl | 6 ++++ 4 files changed, 67 insertions(+) diff --git a/dlls/winegstreamer/audio_decoder.c b/dlls/winegstreamer/audio_decoder.c index 82af33b671b..771eae465fe 100644 --- a/dlls/winegstreamer/audio_decoder.c +++ b/dlls/winegstreamer/audio_decoder.c @@ -612,6 +612,9 @@ HRESULT aac_decoder_create(REFIID riid, void **ret) if (!(decoder = calloc(1, sizeof(*decoder)))) return E_OUTOFMEMORY; + decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; + decoder->refcount = 1; + decoder->input_types = (WAVEFORMATEXTENSIBLE *)aac_decoder_input_types; decoder->input_type_count = ARRAY_SIZE(aac_decoder_input_types); @@ -621,9 +624,44 @@ HRESULT aac_decoder_create(REFIID riid, void **ret) return hr; } + *ret = &decoder->IMFTransform_iface; + TRACE("Created decoder %p\n", *ret); + return S_OK; +} + +static WAVEFORMATEXTENSIBLE audio_decoder_input_types[] = +{ +#define MAKE_WAVEFORMATEXTENSIBLE(format) \ + {.Format = {.wFormatTag = WAVE_FORMAT_EXTENSIBLE, .nChannels = 6, .nSamplesPerSec = 48000, .nAvgBytesPerSec = 1152000, \ + .nBlockAlign = 24, .wBitsPerSample = 32, .cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)}, \ + .SubFormat = {format,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}}} + + MAKE_WAVEFORMATEXTENSIBLE(MAKEFOURCC('G','S','T','a')), + +#undef MAKE_WAVEFORMATEXTENSIBLE +}; + +HRESULT audio_decoder_create(REFIID riid, void **ret) +{ + struct audio_decoder *decoder; + HRESULT hr; + + TRACE("riid %s, ret %p.\n", debugstr_guid(riid), ret); + + if (!(decoder = calloc(1, sizeof(*decoder)))) + return E_OUTOFMEMORY; decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; decoder->refcount = 1; + decoder->input_types = audio_decoder_input_types; + decoder->input_type_count = ARRAY_SIZE(audio_decoder_input_types); + + if (FAILED(hr = wg_sample_queue_create(&decoder->wg_sample_queue))) + { + free(decoder); + return hr; + } + *ret = &decoder->IMFTransform_iface; TRACE("Created decoder %p\n", *ret); return S_OK; diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 5e6cbbab5d5..b48acd67760 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -170,6 +170,7 @@ unsigned int wg_format_get_stride(const struct wg_format *format); bool wg_video_format_is_rgb(enum wg_video_format format); +HRESULT audio_decoder_create(REFIID riid, void **ret); HRESULT aac_decoder_create(REFIID riid, void **ret); HRESULT h264_decoder_create(REFIID riid, void **ret); HRESULT video_processor_create(REFIID riid, void **ret); diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index a083915cdbd..9e831900cfa 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -119,6 +119,7 @@ static const IClassFactoryVtbl class_factory_vtbl = class_factory_LockServer, }; +static const GUID CLSID_GStreamerAudioDecoder = {0x480b1517, 0xc8e9, 0x4eae, {0xb0, 0x06, 0xe6, 0x30, 0x07, 0x18, 0xd8, 0x5d}}; static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}}; static const struct class_object @@ -128,6 +129,7 @@ static const struct class_object } class_objects[] = { + { &CLSID_GStreamerAudioDecoder, &audio_decoder_create }, { &CLSID_VideoProcessorMFT, &video_processor_create }, { &CLSID_GStreamerByteStreamHandler, &gstreamer_byte_stream_handler_create }, { &CLSID_MSAACDecMFT, &aac_decoder_create }, @@ -327,6 +329,16 @@ HRESULT mfplat_DllRegisterServer(void) {MFMediaType_Video, MFVideoFormat_NV11}, }; + MFT_REGISTER_TYPE_INFO audio_decoder_input_types[] = + { + {MFMediaType_Audio, MFAudioFormat_GStreamer}, + }; + MFT_REGISTER_TYPE_INFO audio_decoder_output_types[] = + { + {MFMediaType_Audio, MFAudioFormat_Float}, + {MFMediaType_Audio, MFAudioFormat_PCM}, + }; + struct mft { GUID clsid; @@ -410,6 +422,16 @@ HRESULT mfplat_DllRegisterServer(void) ARRAY_SIZE(color_convert_output_types), color_convert_output_types, }, + { + CLSID_GStreamerAudioDecoder, + MFT_CATEGORY_AUDIO_DECODER, + L"Wine Audio Decoder MFT", + MFT_ENUM_FLAG_SYNCMFT, + ARRAY_SIZE(audio_decoder_input_types), + audio_decoder_input_types, + ARRAY_SIZE(audio_decoder_output_types), + audio_decoder_output_types, + }, }; unsigned int i; diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index bb727ca8645..0ce6acaceef 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -76,6 +76,12 @@ coclass decodebin_parser {} ] coclass VideoProcessorMFT {} +[ + threading(both), + uuid(480b1517-c8e9-4eae-b006-e6300718d85d) +] +coclass GStreamerAudioDecoder {} + [ helpstring("Generic Decodebin Byte Stream Handler"), threading(both), -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/mfplat.c | 30 ++++++++++++++++++++ dlls/winegstreamer/video_decoder.c | 21 ++++++++++++++ dlls/winegstreamer/winegstreamer_classes.idl | 6 ++++ 4 files changed, 58 insertions(+) diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index b48acd67760..a072dcdb917 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -171,6 +171,7 @@ unsigned int wg_format_get_stride(const struct wg_format *format); bool wg_video_format_is_rgb(enum wg_video_format format); HRESULT audio_decoder_create(REFIID riid, void **ret); +HRESULT video_decoder_create(REFIID riid, void **ret); HRESULT aac_decoder_create(REFIID riid, void **ret); HRESULT h264_decoder_create(REFIID riid, void **ret); HRESULT video_processor_create(REFIID riid, void **ret); diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 9e831900cfa..85a648f465a 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -120,6 +120,7 @@ static const IClassFactoryVtbl class_factory_vtbl = }; static const GUID CLSID_GStreamerAudioDecoder = {0x480b1517, 0xc8e9, 0x4eae, {0xb0, 0x06, 0xe6, 0x30, 0x07, 0x18, 0xd8, 0x5d}}; +static const GUID CLSID_GStreamerVideoDecoder = {0x480b1518, 0xc8e9, 0x4eae, {0xb0, 0x06, 0xe6, 0x30, 0x07, 0x18, 0xd8, 0x5d}}; static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}}; static const struct class_object @@ -130,6 +131,7 @@ static const struct class_object class_objects[] = { { &CLSID_GStreamerAudioDecoder, &audio_decoder_create }, + { &CLSID_GStreamerVideoDecoder, &video_decoder_create }, { &CLSID_VideoProcessorMFT, &video_processor_create }, { &CLSID_GStreamerByteStreamHandler, &gstreamer_byte_stream_handler_create }, { &CLSID_MSAACDecMFT, &aac_decoder_create }, @@ -339,6 +341,24 @@ HRESULT mfplat_DllRegisterServer(void) {MFMediaType_Audio, MFAudioFormat_PCM}, }; + MFT_REGISTER_TYPE_INFO video_decoder_input_types[] = + { + {MFMediaType_Video, MFVideoFormat_GStreamer}, + {MFMediaType_Video, MFVideoFormat_IV50}, + }; + MFT_REGISTER_TYPE_INFO video_decoder_output_types[] = + { + {MFMediaType_Video, MFVideoFormat_YV12}, + {MFMediaType_Video, MFVideoFormat_YUY2}, + {MFMediaType_Video, MFVideoFormat_NV11}, + {MFMediaType_Video, MFVideoFormat_NV12}, + {MFMediaType_Video, MFVideoFormat_RGB32}, + {MFMediaType_Video, MFVideoFormat_RGB24}, + {MFMediaType_Video, MFVideoFormat_RGB565}, + {MFMediaType_Video, MFVideoFormat_RGB555}, + {MFMediaType_Video, MFVideoFormat_RGB8}, + }; + struct mft { GUID clsid; @@ -432,6 +452,16 @@ HRESULT mfplat_DllRegisterServer(void) ARRAY_SIZE(audio_decoder_output_types), audio_decoder_output_types, }, + { + CLSID_GStreamerVideoDecoder, + MFT_CATEGORY_VIDEO_DECODER, + L"Wine Video Decoder MFT", + MFT_ENUM_FLAG_SYNCMFT, + ARRAY_SIZE(video_decoder_input_types), + video_decoder_input_types, + ARRAY_SIZE(video_decoder_output_types), + video_decoder_output_types, + }, }; unsigned int i; diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 0837217e3a6..ddbb75d6789 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -34,6 +34,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DECLARE_DEBUG_CHANNEL(winediag); +extern GUID MFVideoFormat_GStreamer; +static const GUID *const video_decoder_input_types[] = +{ + &MFVideoFormat_GStreamer, +}; static const GUID *const video_decoder_output_types[] = { &MFVideoFormat_NV12, @@ -861,6 +866,22 @@ failed: return hr; } +HRESULT video_decoder_create(REFIID riid, void **out) +{ + IMFTransform *iface; + HRESULT hr; + + TRACE("riid %s, out %p.\n", debugstr_guid(riid), out); + + if (FAILED(hr = video_decoder_create_with_types(video_decoder_input_types, ARRAY_SIZE(video_decoder_input_types), + video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), &iface))) + return hr; + + hr = IMFTransform_QueryInterface(iface, riid, out); + IMFTransform_Release(iface); + return hr; +} + static const GUID *const h264_decoder_input_types[] = { &MFVideoFormat_H264, diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index 0ce6acaceef..63a8e84bc8e 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -82,6 +82,12 @@ coclass VideoProcessorMFT {} ] coclass GStreamerAudioDecoder {} +[ + threading(both), + uuid(480b1518-c8e9-4eae-b006-e6300718d85d) +] +coclass GStreamerVideoDecoder {} + [ helpstring("Generic Decodebin Byte Stream Handler"), threading(both), -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5138
Unrelated test failures in `crypt32:cert`/`crypt32:chain`, and `oleaut32:varformat`. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62299
What's the point of the generic types? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62442
To not have to define conversions and formats for every possible encoded type when they are only needed to connect the media source and MFTs together. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62444
Why do we need to pass unknown encoded types through the PE side at all? I've laid out a design where we avoid this, and it's all but hooked up for Media Foundation. At the risk of reiterating our earlier discussion, is there a reason that won't work? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62451
Again, applications expect to find the individual MFT (decoder, converter, etc) in the MF pipeline and break if they are not there. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62452
Right, but the design is to implement support for stopping at specific compressed formats as they're needed. Is there an application for which this isn't sufficient? E.g. a media player that requires a decoder to exist no matter what file you feed it (but then, how can it correctly deal with uncompressed AVI?) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62461
Yes, pretty much all of them. They do not really care about the compressed format itself, they care about decoder and converter being present to change their properties and enable D3D buffers for instance. This is not even something they request in advance so it's not possible to do it on demand, it *has* to behave like native. In any case I don't think using GStreamer auto plugging, then try to interrupt it somehow, is the right way anyway, but we've discussed that already and clearly we don't agree. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62465
How do these applications work with an uncompressed AVI file? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62466
Probably they don't. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62473
Can you confirm that, then? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62474
I'm sorry, I don't understand. This is about games that have videos in a compressed format and expect the MF pipelines to be created in a specific way. Why should I even try switching these to uncompressed videos, when I debugged it and when it's very clear that they just inspect the pipeline and expect to find transforms in there? Anyway, I'm getting very tired of these pointless discussions. The questions are the same as before and whatever I do it doesn't seem likely to make any difference because we went through this already. There is one very simple reason we should do this, and it's because Windows behaves like this: it creates a pipeline with various transforms in it, and applications don't have to request anything for this to happen. This is now tested in length. Applications are broken because Wine doesn't implement Windows behavior: we tried to take a shortcut and it apparently doesn't work. Like everything else in Wine, we now need to implement Windows behavior more accurately to fix them, period. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62502
Bernhard Kölbl (@besentv) commented about dlls/winegstreamer/audio_decoder.c:
/* AAC Decoder Transform Still says aac decoder. Also I'd advocate for naming this smth like mf_audio_decoder.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62513
I'm sorry, I don't understand. This is about games that have videos in a compressed format and expect the MF pipelines to be created in a specific way.
Why should I even try switching these to uncompressed videos, when I debugged it and when it's very clear that they just inspect the pipeline and expect to find transforms in there?
I'm sorry, I thought you said there were applications which consume *arbitrary* audio files (like media players) and expect a decoder to always be present. I wanted to press that point because it seemed like you were using the assertion that applications always expect a decoder to inform the design or implementation, but that assertion seemed suspicious to me, because not all files have a compressed format. If this is just about games that ship with bundled media files, with known formats, then I'll repeat what I said earlier: as far as I can see, we don't need to feed *every* compressed format through the PE side. We already have support for feeding only a list of known and recognized formats. All it takes, in fact, is to add those formats to the winegstreamer enumeration, and add translation to wg_format.c. The existing logic in autoplug_continue_cb() *already* takes care of the rest. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62525
And then what, do that debugging again and again every time a game uses a new format and expects to see a proper pipeline? What's the point when doing this would fix this category of bugs entirely *and* at the same time, allow to play arbitrary formats? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_62529
Is there anything specific I should do here? Unless we want to implement every individual decoder out there one by one, and I haven't been given any reason for doing that, this is very much the way to go. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5138#note_63177
participants (3)
-
Bernhard Kölbl -
Rémi Bernon -
Zebediah Figura (@zfigura)