-- v2: winegstreamer: Expose the generic video decoder transform. winegstreamer: Introduce a generic audio decoder transform. winegstreamer: Rename aac_decoder to audio_decoder. winegstreamer: Translate generic unknown audio / video media types. winegstreamer: Support generic audio / video unknown formats. winegstreamer: Call gst_video_info_from_caps for all video formats. winegstreamer: Call gst_audio_info_from_caps for all audio formats.
From: Rémi Bernon rbernon@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);
From: Rémi Bernon rbernon@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 {
From: Rémi Bernon rbernon@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; }
From: Rémi Bernon rbernon@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); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/Makefile.in | 2 +- .../{aac_decoder.c => audio_decoder.c} | 52 +++++++++---------- 2 files changed, 27 insertions(+), 27 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..aa7a58734a9 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/audio_decoder.c @@ -1,4 +1,4 @@ -/* AAC Decoder Transform +/* Audio Decoder Transform * * Copyright 2022 Rémi Bernon for CodeWeavers * @@ -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);
From: Rémi Bernon rbernon@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 aa7a58734a9..615c0392ee0 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),
From: Rémi Bernon rbernon@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),
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?
Aren't we going to have to translate real compressed formats to win32 formats anyway?
Not unless applications are actually interested in the compressed format, which I haven't seen any instance of on the MF side yet.
Then ultimately probably. And these unknown formats are still considered a temporary fallback, and reported with a GST_FIXME message. However, it doesn't look tractable to me to do the kind of conversion we do, if we need to support *every* compressed caps (ie: going through an intermediate static representation).
I've been thinking about this, and while I don't dislike the idea of feeding opaque formats through the frontend like this, it's hard for me to particularly want to deviate from the existing design, when it leaves problems that are going to need to be addressed a different way anyway. Especially when it's not really that hard to check if a format is using unrecognized caps. I certainly want to try to make failure modes easy to notice, but this doesn't seem like it should be that hard to debug.
(I kind of do dislike feeding opaque formats through the frontend, mostly because of latency, but I suppose it's not like there's going to be a lot of cases where it matters and we can actually avoid it.)
Also, is there a reason that we need to handle audio and video major types separately? Couldn't we just use the existing WG_MAJOR_TYPE_UNKNOWN and have done? It'd mean a lot less work, which would make it much easier to justify a change like this.
Also, if the caps are unknown, why expose attributes like channels, rate, width, height, FPS?
I support the idea of adding generic video and audio decoders. On native, we can also install new decoders. Except for the default decoder classes that native Windows have, we can treat the gstreamer genric decoders as plugin add-ons.
For the decoders that native windows have, we use the spcific formats. Otherwise, we use the opaque formats and make the generic decoders to handle it.
So the generic decoders are guarantees. We try to find specific decoder first, and fall back to the generic decoders if we fail to find a valid specific decoder.
Also, is there a reason that we need to handle audio and video major types separately? Couldn't we just use the existing WG_MAJOR_TYPE_UNKNOWN and have done? It'd mean a lot less work, which would make it much easier to justify a change like this.
Also, if the caps are unknown, why expose attributes like channels, rate, width, height, FPS?
It looks like the similar situation in !5369
This merge request was closed by Rémi Bernon.